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