file.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 1998,1999  Ross Combs (rocombs@cs.nmsu.edu)
  3.  * Copyright (C) 1999  Rob Crittenden (rcrit@greyoak.com)
  4.  *
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version 2
  8.  * of the License, or (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  */
  19. #include "common/setup_before.h"
  20. #include <stdio.h>
  21. #ifdef HAVE_STDDEF_H
  22. # include <stddef.h>
  23. #else
  24. # ifndef NULL
  25. #  define NULL ((void *)0)
  26. # endif
  27. #endif
  28. #ifdef STDC_HEADERS
  29. # include <stdlib.h>
  30. #else
  31. # ifdef HAVE_MALLOC_H
  32. #  include <malloc.h>
  33. # endif
  34. #endif
  35. #ifdef HAVE_STRING_H
  36. # include <string.h>
  37. #else
  38. # ifdef HAVE_STRINGS_H
  39. #  include <strings.h>
  40. # endif
  41. #endif
  42. #include "compat/strchr.h"
  43. #include <errno.h>
  44. #include "compat/strerror.h"
  45. #ifdef HAVE_SYS_TYPES_H
  46. # include <sys/types.h>
  47. #endif
  48. #ifdef HAVE_SYS_STAT_H
  49. # include <sys/stat.h>
  50. #endif
  51. #include "common/bn_type.h"
  52. #include "common/queue.h"
  53. #include "connection.h"
  54. #include "common/packet.h"
  55. #include "common/file_protocol.h"
  56. #include "common/eventlog.h"
  57. #include "prefs.h"
  58. #include "common/bnettime.h"
  59. #include "file.h"
  60. #include "common/setup_after.h"
  61. static char const * file_get_info(char const * rawname, unsigned int * len, bn_long * modtime);
  62. static char const * file_get_info(char const * rawname, unsigned int * len, bn_long * modtime)
  63. {
  64.     char *filename;
  65.     struct stat  sfile;
  66.     t_bnettime   bt;
  67.     unsigned int i;
  68.     char extension[10];
  69. char pattern[40];
  70. /* Add new default files in this format: "pattern:.extension" */
  71.     char defaultfiles[][50]={"termsofservice-:.txt","newaccount-:.txt","chathelp-war3-:.txt","matchmaking-war3-:.dat"};
  72.         
  73.     if (!rawname)
  74.     {
  75. eventlog(eventlog_level_error,"file_get_info","got NULL rawname");
  76. return NULL;
  77.     }
  78.     if (!len)
  79.     {
  80. eventlog(eventlog_level_error,"file_get_info","got NULL len");
  81. return NULL;
  82.     }
  83.     if (!modtime)
  84.     {
  85. eventlog(eventlog_level_error,"file_get_info","got NULL modtime");
  86. return NULL;
  87.     }
  88.     
  89.     if (strchr(rawname,'/') || strchr(rawname,'\'))
  90.     {
  91. eventlog(eventlog_level_warn,"file_get_info","got rawname containing '/' or '\' "%s"",rawname);
  92. return NULL;
  93.     }
  94.     if (!(filename = malloc(strlen(prefs_get_filedir())+1+strlen(rawname)+1)))
  95.     {
  96. eventlog(eventlog_level_error,"file_get_info","could not allocate memory for filename");
  97. return NULL;
  98.     }
  99.     sprintf(filename,"%s/%s",prefs_get_filedir(),rawname);
  100.     
  101.     /* From here */
  102.     if (stat(filename,&sfile)<0) /* if it doesn't exist, try to replace with default file */
  103.     {
  104.      for (i=0; i < sizeof(defaultfiles)/sizeof(defaultfiles[0]);i++) {
  105.      sscanf(defaultfiles[i],"%[^:]:%[^:]",pattern,extension);
  106.      if (memcmp(rawname, pattern, strlen(pattern)) == 0) { /* Check if there is a default file available for this kind of file */
  107.      eventlog(eventlog_level_warn,"file_get_info","requested file %s not found, trying to send default file instead",rawname);
  108.      // strcpy(rawname,pattern);
  109.      // strcat(rawname,"default");
  110.      // strcat(rawname,extension); /* default files are called e.g. chathelp-war3-default */
  111. free(filename);
  112. if (!(filename = malloc(strlen(prefs_get_filedir()) + 1 +
  113. strlen(pattern) + strlen("default") + strlen(extension) + 1))) {
  114. eventlog(eventlog_level_error,"file_get_info","could not allocate memory for filename [2]");
  115. return NULL;
  116. }
  117.      //sprintf(filename,"%s/%s",prefs_get_filedir(),rawname); /* return default filename instead of original */
  118. strcpy(filename, prefs_get_filedir());
  119. strcat(filename, "/");
  120. strcat(filename, pattern);
  121. strcat(filename, "default");
  122. strcat(filename, extension);
  123.      break;
  124.      }
  125.      }
  126. }
  127. /* to here 
  128. Note: We could use a new config file with the files for which defaults can be sent
  129. format would be: 
  130. matchmaking-war3- matchmaking-war3-default.dat
  131. chathelp-war3- chathelp-war3-default.txt
  132. The number of chars of first coloum would have to be counted so we can compare that part of the string using memcmp
  133. */
  134.     if (stat(filename,&sfile)<0) /* if it doesn't exist */
  135.     {
  136. /* FIXME: check for lower-case version of filename */
  137. free(filename);
  138. return NULL;
  139.     }
  140.     
  141.     *len = (unsigned int)sfile.st_size;
  142.     bt = time_to_bnettime(sfile.st_mtime,0);
  143.     bnettime_to_bn_long(bt,modtime);
  144.     
  145.     return filename;
  146. }
  147. extern int file_to_mod_time(char const * rawname, bn_long * modtime)
  148. {
  149.     char const * filename;
  150.     unsigned int len;
  151.     
  152.     if (!rawname)
  153.     {
  154. eventlog(eventlog_level_error,"file_to_mod_time","got NULL rawname");
  155. return -1;
  156.     }
  157.     if (!modtime)
  158.     {
  159. eventlog(eventlog_level_error,"file_to_mod_time","got NULL modtime");
  160. return -1;
  161.     }
  162.     
  163.     if (!(filename = file_get_info(rawname, &len, modtime)))
  164. return -1;
  165.     
  166.     free((void *)filename); /* avoid warning */
  167.     
  168.     return 0;
  169. }
  170. /* Send a file.  If the file doesn't exist we still need to respond
  171.  * to the file request.  This will set filelen to 0 and send the server
  172.  * reply message and the client will be happy and not hang.
  173.  */
  174. extern int file_send(t_connection * c, char const * rawname, unsigned int adid, unsigned int etag, unsigned int startoffset, int need_header)
  175. {
  176.     char const * filename;
  177.     t_packet *   rpacket;
  178.     FILE *       fp;
  179.     unsigned int filelen;
  180.     int          nbytes;
  181.     
  182.     if (!c)
  183.     {
  184. eventlog(eventlog_level_error,"file_send","got NULL connection");
  185. return -1;
  186.     }
  187.     if (!rawname)
  188.     {
  189. eventlog(eventlog_level_error,"file_send","got NULL rawname");
  190. return -1;
  191.     }
  192.     
  193.     if (!(rpacket = packet_create(packet_class_file)))
  194.     {
  195. eventlog(eventlog_level_error,"file_send","could not create file packet");
  196. return -1;
  197.     }
  198.     packet_set_size(rpacket,sizeof(t_server_file_reply));
  199.     packet_set_type(rpacket,SERVER_FILE_REPLY);
  200.     
  201.     if ((filename = file_get_info(rawname,&filelen,&rpacket->u.server_file_reply.timestamp)))
  202.     {
  203. if (!(fp = fopen(filename,"rb")))
  204. {
  205.     /* FIXME: check for lower-case version of filename */
  206.     eventlog(eventlog_level_error,"file_send","stat() succeeded yet could not open file "%s" for reading (fclose: %s)",filename,strerror(errno));
  207.     filelen = 0;
  208. }
  209. free((void *)filename); /* avoid warning */
  210.     }
  211.     else
  212.     {
  213. fp = NULL;
  214. filelen = 0;
  215. bn_long_set_a_b(&rpacket->u.server_file_reply.timestamp,0,0);
  216.     }
  217.     
  218.     if (fp)
  219.     {
  220. if (startoffset<filelen) {
  221.     fseek(fp,startoffset,SEEK_SET);
  222. } else {
  223.     eventlog(eventlog_level_warn,"file_send","[%d] startoffset is beyond end of file (%u>%u)",conn_get_socket(c),startoffset,filelen);
  224.     /* Keep the real filesize. Battle.net does it the same way ... */
  225.     fclose(fp);
  226.     fp = NULL;
  227. }
  228.     }
  229.     if (need_header)
  230.     {
  231. /* send the header from the server with the rawname and length. */
  232. bn_int_set(&rpacket->u.server_file_reply.filelen,filelen);
  233. bn_int_set(&rpacket->u.server_file_reply.adid,adid);
  234. bn_int_set(&rpacket->u.server_file_reply.extensiontag,etag);
  235. /* rpacket->u.server_file_reply.timestamp is set above */
  236. packet_append_string(rpacket,rawname);
  237. conn_push_outqueue(c,rpacket);
  238.     }
  239.     packet_del_ref(rpacket);
  240.     /* Now send the data. Since it may be longer than a packet; we use
  241.      * the raw packet class.
  242.      */
  243.     if (!fp)
  244.     {
  245. eventlog(eventlog_level_warn,"file_send","[%d] sending no data for file "%s"",conn_get_socket(c),rawname);
  246. return -1;
  247.     }
  248.     
  249.     eventlog(eventlog_level_info,"file_send","[%d] sending file "%s" of length %d",conn_get_socket(c),rawname,filelen);
  250.     for (;;)
  251.     {
  252. if (!(rpacket = packet_create(packet_class_raw)))
  253. {
  254.     eventlog(eventlog_level_error,"file_send","could not create raw packet");
  255.     if (fclose(fp)<0)
  256. eventlog(eventlog_level_error,"file_send","could not close file "%s" after reading (fclose: %s)",rawname,strerror(errno));
  257.     return -1;
  258. }
  259. if ((nbytes = fread(packet_get_raw_data_build(rpacket,0),1,MAX_PACKET_SIZE,fp))<(int)MAX_PACKET_SIZE)
  260. {
  261.     if (nbytes>0) /* send out last portion */
  262.     {
  263. packet_set_size(rpacket,nbytes);
  264. conn_push_outqueue(c,rpacket);
  265.     }
  266.     packet_del_ref(rpacket);
  267.     if (ferror(fp))
  268. eventlog(eventlog_level_error,"file_send","read failed before EOF on file "%s" (fread: %s)",rawname,strerror(errno));
  269.     break;
  270. }
  271. packet_set_size(rpacket,nbytes);
  272. conn_push_outqueue(c,rpacket);
  273. packet_del_ref(rpacket);
  274.     }
  275.     
  276.     if (fclose(fp)<0)
  277. eventlog(eventlog_level_error,"file_send","could not close file "%s" after reading (fclose: %s)",rawname,strerror(errno));
  278.     return 0;
  279. }