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