1 /**
2 * Load Post Data
3 *
4 * Copyright (C) 2002-2016 by
5 * Jeffrey Fulmer - <jeff@joedog.org>, et al.
6 * This file is distributed as part of Siege
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (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. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * --
22 *
23 */
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <fcntl.h>
31 #include <load.h>
32 #include <notify.h>
33 #include <memory.h>
34 #include <perl.h>
35 #include <errno.h>
36 #include <util.h>
37 #include <http.h>
38 #include <joedog/boolean.h>
39
40 struct ContentType {
41 char *ext;
42 BOOLEAN ascii;
43 char *type;
44 };
45
46 static const struct ContentType tmap[] = {
47 {"default", TRUE, "application/x-www-form-urlencoded"},
48 {"ai", FALSE, "application/postscript"},
49 {"aif", FALSE, "audio/x-aiff"},
50 {"aifc", FALSE, "audio/x-aiff"},
51 {"aiff", FALSE, "audio/x-aiff"},
52 {"asc", TRUE, "text/plain"},
53 {"au", FALSE, "audio/basic"},
54 {"avi", FALSE, "video/x-msvideo"},
55 {"bcpio", FALSE, "application/x-bcpio"},
56 {"bin", FALSE, "application/octet-stream"},
57 {"c", TRUE, "text/plain"},
58 {"cc", TRUE, "text/plain"},
59 {"ccad", FALSE, "application/clariscad"},
60 {"cdf", FALSE, "application/x-netcdf"},
61 {"class", FALSE, "application/octet-stream"},
62 {"cpio", FALSE, "application/x-cpio"},
63 {"cpt", FALSE, "application/mac-compactpro"},
64 {"csh", FALSE, "application/x-csh"},
65 {"css", TRUE, "text/css"},
66 {"csv", TRUE, "text/csv"},
67 {"dcr", FALSE, "application/x-director"},
68 {"dir", FALSE, "application/x-director"},
69 {"dms", FALSE, "application/octet-stream"},
70 {"doc", FALSE, "application/msword"},
71 {"drw", FALSE, "application/drafting"},
72 {"dvi", FALSE, "application/x-dvi"},
73 {"dwg", FALSE, "application/acad"},
74 {"dxf", FALSE, "application/dxf"},
75 {"dxr", FALSE, "application/x-director"},
76 {"eps", FALSE, "application/postscript"},
77 {"etx", TRUE, "text/x-setext"},
78 {"exe", FALSE, "application/octet-stream"},
79 {"ez", FALSE, "application/andrew-inset"},
80 {"f", TRUE, "text/plain"},
81 {"f90", TRUE, "text/plain"},
82 {"fli", FALSE, "video/x-fli"},
83 {"gif", FALSE, "image/gif"},
84 {"gtar", FALSE, "application/x-gtar"},
85 {"gz", FALSE, "application/x-gzip"},
86 {"h", TRUE, "text/plain"},
87 {"hdf", FALSE, "application/x-hdf"},
88 {"hh", TRUE, "text/plain"},
89 {"hqx", FALSE, "application/mac-binhex40"},
90 {"htm", TRUE, "text/html"},
91 {"html", TRUE, "text/html"},
92 {"ice", FALSE, "x-conference/x-cooltalk"},
93 {"ico", FALSE, "image/x-icon"},
94 {"ief", FALSE, "image/ief"},
95 {"iges", FALSE, "model/iges"},
96 {"igs", FALSE, "model/iges"},
97 {"ips", FALSE, "application/x-ipscript"},
98 {"ipx", FALSE, "application/x-ipix"},
99 {"jpe", FALSE, "image/jpeg"},
100 {"jpeg", FALSE, "image/jpeg"},
101 {"jpg", FALSE, "image/jpeg"},
102 {"js", FALSE, "application/x-javascript"},
103 {"json", FALSE, "application/json"},
104 {"kar", FALSE, "audio/midi"},
105 {"latex", FALSE, "application/x-latex"},
106 {"lha", FALSE, "application/octet-stream"},
107 {"lsp", FALSE, "application/x-lisp"},
108 {"lzh", FALSE, "application/octet-stream"},
109 {"m", TRUE, "text/plain"},
110 {"man", FALSE, "application/x-troff-man"},
111 {"md", TRUE, "text/x-markdown"},
112 {"me", FALSE, "application/x-troff-me"},
113 {"mesh", FALSE, "model/mesh"},
114 {"mid", FALSE, "audio/midi"},
115 {"midi", FALSE, "audio/midi"},
116 {"mif", FALSE, "application/vnd.mif"},
117 {"mime", FALSE, "www/mime"},
118 {"mov", FALSE, "video/quicktime"},
119 {"movie", FALSE, "video/x-sgi-movie"},
120 {"mp2", FALSE, "audio/mpeg"},
121 {"mp3", FALSE, "audio/mpeg"},
122 {"mpe", FALSE, "video/mpeg"},
123 {"mpeg", FALSE, "video/mpeg"},
124 {"mpg", FALSE, "video/mpeg"},
125 {"mpga", FALSE, "audio/mpeg"},
126 {"ms", FALSE, "application/x-troff-ms"},
127 {"msh", FALSE, "model/mesh"},
128 {"nc", FALSE, "application/x-netcdf"},
129 {"oda", FALSE, "application/oda"},
130 {"pbm", FALSE, "image/x-portable-bitmap"},
131 {"pdb", FALSE, "chemical/x-pdb"},
132 {"pdf", FALSE, "application/pdf"},
133 {"pgm", FALSE, "image/x-portable-graymap"},
134 {"pgn", FALSE, "application/x-chess-pgn"},
135 {"png", FALSE, "image/png"},
136 {"pnm", FALSE, "image/x-portable-anymap"},
137 {"pot", FALSE, "application/mspowerpoint"},
138 {"ppm", FALSE, "image/x-portable-pixmap"},
139 {"pps", FALSE, "application/mspowerpoint"},
140 {"ppt", FALSE, "application/mspowerpoint"},
141 {"ppz", FALSE, "application/mspowerpoint"},
142 {"pre", FALSE, "application/x-freelance"},
143 {"proto", FALSE, "application/x-protobuf"},
144 {"prt", FALSE, "application/pro_eng"},
145 {"ps", FALSE, "application/postscript"},
146 {"qt", FALSE, "video/quicktime"},
147 {"ra", FALSE, "audio/x-realaudio"},
148 {"ram", FALSE, "audio/x-pn-realaudio"},
149 {"ras", FALSE, "image/cmu-raster"},
150 {"rgb", FALSE, "image/x-rgb"},
151 {"rm", FALSE, "audio/x-pn-realaudio"},
152 {"roff", FALSE, "application/x-troff"},
153 {"rpm", FALSE, "audio/x-pn-realaudio-plugin"},
154 {"rtf", FALSE, "text/rtf"},
155 {"rtx", FALSE, "text/richtext"},
156 {"scm", FALSE, "application/x-lotusscreencam"},
157 {"set", FALSE, "application/set"},
158 {"sgm", TRUE, "text/sgml"},
159 {"sgml", TRUE, "text/sgml"},
160 {"sh", FALSE, "application/x-sh"},
161 {"shar", FALSE, "application/x-shar"},
162 {"silo", FALSE, "model/mesh"},
163 {"sit", FALSE, "application/x-stuffit"},
164 {"skd", FALSE, "application/x-koan"},
165 {"skm", FALSE, "application/x-koan"},
166 {"skp", FALSE, "application/x-koan"},
167 {"skt", FALSE, "application/x-koan"},
168 {"smi", FALSE, "application/smil"},
169 {"smil", FALSE, "application/smil"},
170 {"snd", FALSE, "audio/basic"},
171 {"sol", FALSE, "application/solids"},
172 {"spl", FALSE, "application/x-futuresplash"},
173 {"src", FALSE, "application/x-wais-source"},
174 {"step", FALSE, "application/STEP"},
175 {"stl", FALSE, "application/SLA"},
176 {"stp", FALSE, "application/STEP"},
177 {"sv4cpio", FALSE, "application/x-sv4cpio"},
178 {"sv4crc", FALSE, "application/x-sv4crc"},
179 {"svg", TRUE, "image/svg+xml"},
180 {"swf", FALSE, "application/x-shockwave-flash"},
181 {"t", FALSE, "application/x-troff"},
182 {"tar", FALSE, "application/x-tar"},
183 {"tcl", FALSE, "application/x-tcl"},
184 {"tex", FALSE, "application/x-tex"},
185 {"texi", FALSE, "application/x-texinfo"},
186 {"texinfo", FALSE, "application/x-texinfo"},
187 {"tif", FALSE, "image/tiff"},
188 {"tiff", FALSE, "image/tiff"},
189 {"tr", FALSE, "application/x-troff"},
190 {"tsi", FALSE, "audio/TSP-audio"},
191 {"tsp", FALSE, "application/dsptype"},
192 {"tsv", TRUE, "text/tab-separated-values"},
193 {"txt", TRUE, "text/plain"},
194 {"unv", FALSE, "application/i-deas"},
195 {"ustar", FALSE, "application/x-ustar"},
196 {"vcd", FALSE, "application/x-cdlink"},
197 {"vda", FALSE, "application/vda"},
198 {"viv", FALSE, "video/vnd.vivo"},
199 {"vivo", FALSE, "video/vnd.vivo"},
200 {"vrml", FALSE, "model/vrml"},
201 {"wav", FALSE, "audio/x-wav"},
202 {"wrl", FALSE, "model/vrml"},
203 {"xbm", FALSE, "image/x-xbitmap"},
204 {"xlc", FALSE, "application/vnd.ms-excel"},
205 {"xll", FALSE, "application/vnd.ms-excel"},
206 {"xlm", FALSE, "application/vnd.ms-excel"},
207 {"xls", FALSE, "application/vnd.ms-excel"},
208 {"xlw", FALSE, "application/vnd.ms-excel"},
209 {"xml", TRUE, "text/xml"},
210 {"xpm", FALSE, "image/x-xpixmap"},
211 {"xwd", FALSE, "image/x-xwindowdump"},
212 {"xyz", FALSE, "chemical/x-pdb"},
213 {"yml", TRUE, "application/x-yaml"},
214 {"zip", FALSE, "application/zip"}
215 };
216
217 char *
get_file_extension(char * file)218 get_file_extension(char *file)
219 {
220 char *dot = strrchr(file, '.');
221 if (!dot || dot == file)
222 return "";
223 return dot + 1;
224 }
225
226 char *
get_content_type(char * file)227 get_content_type(char *file)
228 {
229 int i;
230 char *ext;
231
232 ext = get_file_extension(file);
233 for (i=0; i < (int)sizeof(tmap) / (int)sizeof(tmap[0]); i++) {
234 if (strmatch(ext, tmap[i].ext)) {
235 return tmap[i].type;
236 }
237 }
238 return tmap[0].type;
239 }
240
241 BOOLEAN
is_ascii(char * file)242 is_ascii(char *file)
243 {
244 int i;
245 char *ext;
246
247 ext = get_file_extension(file);
248 for (i=0; i < (int)sizeof(tmap) / (int)sizeof(tmap[0]); i++) {
249 if (strmatch(ext, tmap[i].ext)) {
250 return tmap[i].ascii;
251 }
252 }
253 return tmap[0].ascii;
254 }
255
256 /**
257 * maps a file to our address space
258 * and returns it the calling function.
259 */
260 void
load_file(URL U,char * file)261 load_file(URL U, char *file)
262 {
263 FILE *fp;
264 size_t len;
265 char *buf;
266 char *filename;
267 char mode[8];
268
269 filename = trim(file);
270
271 memset(mode, '\0', sizeof(mode));
272 snprintf(mode, sizeof(mode), "%s", (is_ascii(filename))?"r":"rb");
273 fp = fopen(filename, mode);
274 if (! fp) {
275 NOTIFY(ERROR, "unable to open file: %s", filename );
276 return;
277 }
278
279 fseek(fp, 0, SEEK_END);
280 len = ftell(fp);
281 fseek(fp, 0, SEEK_SET);
282 buf = (char *)xmalloc(len+1);
283
284 if ((fread(buf, 1, len, fp )) == len) {
285 if (is_ascii(filename)) {
286 buf[len] = '\0';
287 trim(buf);
288 len = strlen(buf);
289 }
290 } else {
291 NOTIFY(ERROR, "unable to read file: %s", filename );
292 }
293 fclose(fp);
294
295 if (len > 0) {
296 if (! empty(my.conttype)) {
297 // We're overriding the content-type at the cmd line
298 url_set_conttype(U, my.conttype);
299 } else {
300 url_set_conttype(U, get_content_type(filename));
301 }
302 url_set_postdata(U, buf, len);
303 }
304
305 xfree(buf);
306 return;
307 }
308
309 void
write_file(URL U,char * buf,size_t len)310 write_file(URL U, char *buf, size_t len)
311 {
312 FILE *fp;
313 char mode[8];
314
315 memset(mode, '\0', sizeof(mode));
316 snprintf(mode, sizeof(mode), "%s", (url_get_file(U))?"w":"wb");
317 fp = fopen(url_get_file(U), mode);
318
319 if (fp) {
320 fwrite(buf, len, 1, fp);
321 } else {
322 NOTIFY(ERROR, "unable to write to file");
323 }
324
325 fclose(fp);
326 }
327
328 #if 0
329 void
330 load_file(URL U, char *file)
331 {
332 FILE *fp;
333 size_t len = 0;
334 struct stat st;
335 char *filename;
336 char postdata[POSTBUF];
337 size_t postlen = 0;
338
339 filename = trim(file);
340 memset(postdata, 0, POSTBUF);
341
342 if ((lstat(filename, &st) == 0) || (errno != ENOENT)) {
343 len = (st.st_size >= POSTBUF) ? POSTBUF : st.st_size;
344 if (len < (unsigned)st.st_size) {
345 NOTIFY(WARNING, "Truncated file: %s exceeds the post limit of %d bytes.\n", filename, POSTBUF);
346 }
347 if ((fp = fopen(filename, "r")) == NULL) {
348 NOTIFY(ERROR, "could not open file: %s", filename);
349 return;
350 }
351 if ((fread(postdata, 1, len, fp )) == len) {
352 if (is_ascii(filename)) {
353 trim(postdata);
354 postlen = strlen(postdata);
355 } else {
356 postlen = len;
357 }
358 } else {
359 NOTIFY(ERROR, "unable to read file: %s", filename );
360 }
361 fclose(fp);
362 }
363
364 if (strlen(postdata) > 0) {
365 url_set_conttype(U, get_content_type(filename));
366 url_set_postdata(U, postdata, postlen);
367 }
368 return;
369 }
370 #endif
371
372
373
374