/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/file.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/bnetd/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:37 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) 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 "common/util.h"
60 #include "common/xalloc.h"
61 #include "file.h"
62 #include "common/setup_after.h"
63
64
65 static char const * file_get_info(char const * rawname, unsigned int * len, bn_long * modtime);
66
67 static char * file_find_default(const char *rawname)
68 {
69 /* Add new default files here */
70 const char * defaultfiles[]={"termsofservice-",".txt",
71 "newaccount-",".txt",
72 "chathelp-war3-",".txt",
73 "matchmaking-war3-",".dat",
74 NULL,NULL};
75 const char ** pattern, **extension;
76 char *filename = NULL;
77
78 for (pattern = defaultfiles, extension = defaultfiles + 1; *pattern; pattern+=2, extension+=2)
79 if (!strncmp(rawname, *pattern,strlen(*pattern))) { /* Check if there is a default file available for this kind of file */
80 filename = (char*)xmalloc(strlen(prefs_get_filedir()) + 1 + strlen(*pattern) + 7 + strlen(*extension) + 1);
81
82 strcpy(filename, prefs_get_filedir());
83 strcat(filename, "/");
84 strcat(filename, *pattern);
85 strcat(filename, "default");
86 strcat(filename, *extension);
87
88 break;
89 }
90
91 return filename;
92 }
93
94 static char const * file_get_info(char const * rawname, unsigned int * len, bn_long * modtime)
95 {
96 char *filename;
97 struct stat sfile;
98 t_bnettime bt;
99
100 if (!rawname) {
101 eventlog(eventlog_level_error,__FUNCTION__,"got NULL rawname");
102 return NULL;
103 }
104
105 if (!len) {
106 eventlog(eventlog_level_error,__FUNCTION__,"got NULL len");
107 return NULL;
108 }
109
110 if (!modtime) {
111 eventlog(eventlog_level_error,__FUNCTION__,"got NULL modtime");
112 return NULL;
113 }
114
115 if (strchr(rawname,'/') || strchr(rawname,'\\')) {
116 eventlog(eventlog_level_warn,__FUNCTION__,"got rawname containing '/' or '\\' \"%s\"",rawname);
117 return NULL;
118 }
119
120 filename = buildpath(prefs_get_filedir(), rawname);
121
122 if (stat(filename,&sfile)<0) { /* if it doesn't exist, try to replace with default file */
123 xfree((void*)filename);
124 filename = file_find_default(rawname);
125 if (!filename) return NULL; /* no default version */
126
127 if (stat(filename,&sfile)<0) { /* try again */
128 /* FIXME: check for lower-case version of filename */
129 xfree(filename);
130 return NULL;
131 }
132 }
133
134 *len = (unsigned int)sfile.st_size;
135 bt = time_to_bnettime(sfile.st_mtime,0);
136 bnettime_to_bn_long(bt,modtime);
137
138 return filename;
139 }
140
141
142 extern int file_to_mod_time(char const * rawname, bn_long * modtime)
143 {
144 char const * filename;
145 unsigned int len;
146
147 if (!rawname)
148 {
149 eventlog(eventlog_level_error,__FUNCTION__,"got NULL rawname");
150 return -1;
151 }
152 if (!modtime)
153 {
154 eventlog(eventlog_level_error,__FUNCTION__,"got NULL modtime");
155 return -1;
156 }
157
158 if (!(filename = file_get_info(rawname, &len, modtime)))
159 return -1;
160
161 xfree((void *)filename); /* avoid warning */
162
163 return 0;
164 }
165
166
167 /* Send a file. If the file doesn't exist we still need to respond
168 * to the file request. This will set filelen to 0 and send the server
169 * reply message and the client will be happy and not hang.
170 */
171 extern int file_send(t_connection * c, char const * rawname, unsigned int adid, unsigned int etag, unsigned int startoffset, int need_header)
172 {
173 char const * filename;
174 t_packet * rpacket;
175 FILE * fp;
176 unsigned int filelen;
177 int nbytes;
178
179 if (!c)
180 {
181 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
182 return -1;
183 }
184 if (!rawname)
185 {
186 eventlog(eventlog_level_error,__FUNCTION__,"got NULL rawname");
187 return -1;
188 }
189
190 if (!(rpacket = packet_create(packet_class_file)))
191 {
192 eventlog(eventlog_level_error,__FUNCTION__,"could not create file packet");
193 return -1;
194 }
195 packet_set_size(rpacket,sizeof(t_server_file_reply));
196 packet_set_type(rpacket,SERVER_FILE_REPLY);
197
198 if ((filename = file_get_info(rawname,&filelen,&rpacket->u.server_file_reply.timestamp)))
199 {
200 if (!(fp = fopen(filename,"rb")))
201 {
202 /* FIXME: check for lower-case version of filename */
203 eventlog(eventlog_level_error,__FUNCTION__,"stat() succeeded yet could not open file \"%s\" for reading (fclose: %s)",filename,pstrerror(errno));
204 filelen = 0;
205 }
206 xfree((void *)filename); /* avoid warning */
207 }
208 else
209 {
210 fp = NULL;
211 filelen = 0;
212 bn_long_set_a_b(&rpacket->u.server_file_reply.timestamp,0,0);
213 }
214
215 if (fp)
216 {
217 if (startoffset<filelen) {
218 fseek(fp,startoffset,SEEK_SET);
219 } else {
220 eventlog(eventlog_level_warn,__FUNCTION__,"[%d] startoffset is beyond end of file (%u>%u)",conn_get_socket(c),startoffset,filelen);
221 /* Keep the real filesize. Battle.net does it the same way ... */
222 fclose(fp);
223 fp = NULL;
224 }
225 }
226
227 if (need_header)
228 {
229 /* send the header from the server with the rawname and length. */
230 bn_int_set(&rpacket->u.server_file_reply.filelen,filelen);
231 bn_int_set(&rpacket->u.server_file_reply.adid,adid);
232 bn_int_set(&rpacket->u.server_file_reply.extensiontag,etag);
233 /* rpacket->u.server_file_reply.timestamp is set above */
234 packet_append_string(rpacket,rawname);
235 conn_push_outqueue(c,rpacket);
236 }
237 packet_del_ref(rpacket);
238
239 /* Now send the data. Since it may be longer than a packet; we use
240 * the raw packet class.
241 */
242 if (!fp)
243 {
244 eventlog(eventlog_level_warn,__FUNCTION__,"[%d] sending no data for file \"%s\"",conn_get_socket(c),rawname);
245 return -1;
246 }
247
248 eventlog(eventlog_level_info,__FUNCTION__,"[%d] sending file \"%s\" of length %d",conn_get_socket(c),rawname,filelen);
249 for (;;)
250 {
251 if (!(rpacket = packet_create(packet_class_raw)))
252 {
253 eventlog(eventlog_level_error,__FUNCTION__,"could not create raw packet");
254 if (fclose(fp)<0)
255 eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (fclose: %s)",rawname,pstrerror(errno));
256 return -1;
257 }
258 if ((nbytes = fread(packet_get_raw_data_build(rpacket,0),1,MAX_PACKET_SIZE,fp))<(int)MAX_PACKET_SIZE)
259 {
260 if (nbytes>0) /* send out last portion */
261 {
262 packet_set_size(rpacket,nbytes);
263 conn_push_outqueue(c,rpacket);
264 }
265 packet_del_ref(rpacket);
266 if (ferror(fp))
267 eventlog(eventlog_level_error,__FUNCTION__,"read failed before EOF on file \"%s\" (fread: %s)",rawname,pstrerror(errno));
268 break;
269 }
270 packet_set_size(rpacket,nbytes);
271 conn_push_outqueue(c,rpacket);
272 packet_del_ref(rpacket);
273 }
274
275 if (fclose(fp)<0)
276 eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (fclose: %s)",rawname,pstrerror(errno));
277 return 0;
278 }

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