1 /*
2 bi_file.c
3
4 CSQC file builtins
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stdlib.h>
32 #ifdef HAVE_STRING_H
33 # include <string.h>
34 #endif
35 #ifdef HAVE_STRINGS_H
36 # include <strings.h>
37 #endif
38
39 #ifdef HAVE_FNMATCH_H
40 # define model_t sunmodel_t
41 # include <fnmatch.h>
42 # undef model_t
43 #else
44 # ifdef _WIN32
45 # include "fnmatch.h"
46 # endif
47 #endif
48
49 #ifndef HAVE_FNMATCH_PROTO
50 int fnmatch (const char *__pattern, const char *__string, int __flags);
51 #endif
52
53 #include "QF/cvar.h"
54 #include "QF/progs.h"
55 #include "QF/quakefs.h"
56 #include "QF/va.h"
57 #include "QF/zone.h"
58
59 #include "rua_internal.h"
60
61 static const char *file_ban_list[] = {
62 "default.cfg{,.gz}",
63 "demo1.dem{,.gz}",
64 "demo2.dem{,.gz}",
65 "demo3.dem{,.gz}",
66 "end1.bin{,.gz}",
67 "end2.bin{,.gz}",
68 "gfx.wad{,.gz}",
69 "progs.dat{,.gz}",
70 "quake.rc{,.gz}",
71 0,
72 };
73
74 static const char *dir_ban_list[] = {
75 "gfx",
76 "maps",
77 "progs",
78 "skins",
79 "sound",
80 0,
81 };
82
83 static int
file_readable(char * path)84 file_readable (char *path)
85 {
86 char t;
87 char *p = strchr (path, '/');
88 const char **match;
89
90 if (p) {
91 t = *p;
92 *p = 0;
93 for (match = dir_ban_list; *match; match++) {
94 if (fnmatch (*match, path, FNM_PATHNAME) == 0) {
95 *p = t;
96 return 0;
97 }
98 }
99 } else {
100 for (match = file_ban_list; *match; match++) {
101 if (fnmatch (*match, path, FNM_PATHNAME) == 0) {
102 return 0;
103 }
104 }
105 }
106 return 1;
107 }
108
109 static int
file_writeable(char * path)110 file_writeable (char *path)
111 {
112 return file_readable (path);
113 }
114
115 static void
bi_File_Open(progs_t * pr)116 bi_File_Open (progs_t *pr)
117 {
118 QFile *file;
119 const char *pth = P_GSTRING (pr, 0);
120 const char *mode = P_GSTRING (pr, 1);
121 char *path;
122 char *p;
123 int do_write = 0;
124 int do_read = 0;
125
126 p = strchr (mode, 'r');
127 if (p) {
128 do_read |= 1;
129 if (p[1] == '+')
130 do_write |= 1;
131 }
132
133 p = strchr (mode, 'w');
134 if (p) {
135 do_write |= 1;
136 if (p[1] == '+')
137 do_read |= 1;
138 }
139
140 p = strchr (mode, 'a');
141 if (p) {
142 do_write |= 1;
143 if (p[1] == '+')
144 do_read |= 1;
145 }
146
147 path = QFS_CompressPath (pth);
148 //printf ("'%s' '%s'\n", P_GSTRING (pr, 0), path);
149 if (!path[0])
150 goto error;
151 if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || path [2] == 0))
152 goto error;
153 if (path[strlen (path) - 1] =='/')
154 goto error;
155 if (!do_read && !do_write)
156 goto error;
157 if (do_read && !file_readable (path))
158 goto error;
159 if (do_write && !file_writeable (path))
160 goto error;
161
162 file = QFS_Open (va ("%s/%s", qfs_gamedir->dir.def, path), mode);
163 if (!file)
164 goto error;
165 free (path);
166 if ((R_INT (pr) = QFile_AllocHandle (pr, file)))
167 return;
168 Qclose (file);
169 error:
170 free (path);
171 R_INT (pr) = 0;
172 }
173
174 static builtin_t builtins[] = {
175 {"File_Open", bi_File_Open, -1},
176 {0}
177 };
178
179 void
RUA_File_Init(progs_t * pr,int secure)180 RUA_File_Init (progs_t *pr, int secure)
181 {
182 PR_RegisterBuiltins (pr, builtins);
183 }
184