New developer version 0.6.8; added select () function; added demonstrating example...
[ZeXOS.git] / apps / websrv / http.c
blob2f7a6e02565f996a962ef33236f728243250bd72
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #ifdef LINUX
28 # include <dirent.h>
29 # include <sys/stat.h>
30 # include <sys/types.h>
31 # include <sys/param.h>
32 #endif
34 #include "net.h"
35 #include "client.h"
37 typedef struct {
38 char *name;
39 unsigned attrib;
40 unsigned char next;
41 unsigned char unused;
42 } __attribute__ ((__packed__)) dirent_t;
44 #define VFS_FILEATTR_FILE 0x1
46 typedef struct web_context {
47 struct web_context *next, *prev;
49 char *name;
50 char *page;
51 unsigned page_len;
52 } web_t;
54 web_t web_list;
56 web_t *web_find (char *name)
58 web_t *web;
59 for (web = web_list.next; web != &web_list; web = web->next)
60 if (!strcmp (web->name, name))
61 return web;
63 return 0;
66 web_t *web_register (char *name)
68 unsigned page_len = 0;
70 char *page = (char *) malloc (sizeof (char) * 80);
72 if (!page)
73 return 0;
76 HTTP/1.0 200 OK
77 Content-Type: text/html
78 Content-Length: 1354
81 // http header
82 memcpy (page, "HTTP/1.0 200 OK\n", 16);
83 memcpy (page+16, "Content-Type: text/html\n", 24);
84 memcpy (page+40, "Content-Length: ", 16);
85 memcpy (page+56, " ", 5);
86 page[61] = '\n';
87 page[62] = '\n';
89 page_len = 63;
91 FILE *f = fopen (name, "r");
93 if (!f) {
94 printf ("error -> file '%s' not found\n", name);
95 return 0;
98 fseek (f, 0, SEEK_END);
99 unsigned flen = ftell (f);
100 fseek (f, 0, SEEK_SET);
102 page = (char *) realloc ((void *) page, sizeof (char) * (flen + 80));
104 if (!page)
105 return 0;
107 fread (page+page_len, flen, 1, f);
109 page_len += flen;
111 page[page_len] = '\0';
113 char num[11];
114 memset (num, 0, 11);
115 sprintf (num, "%d", page_len-63); // convert int to char *
116 unsigned num_len = strlen (num);
118 memcpy (page+56, num, num_len);
120 fclose (f);
122 web_t *web = (web_t *) malloc (sizeof (web_t));
124 if (!web)
125 return 0;
127 web->name = strdup (name);
128 web->page = page;
129 web->page_len = page_len;
131 /* add into list */
132 web->next = &web_list;
133 web->prev = web_list.prev;
134 web->prev->next = web;
135 web->next->prev = web;
137 printf ("> adding to cache: '%s'\n", name);
139 return web;
142 dirent_t *getdir ()
144 dirent_t *dirent;
146 asm volatile (
147 "movl $25, %%eax;"
148 "int $0x80;"
149 "movl %%eax, %0;"
150 : "=g" (dirent) :: "%eax");
152 return dirent;
155 int http_loadfiles ()
157 #ifndef LINUX
158 dirent_t *dir = getdir ();
160 if (!dir)
161 return 0;
163 unsigned id;
165 for (id = 0; dir[id].next; id ++) {
166 if (dir[id].attrib & VFS_FILEATTR_FILE) {
167 if (strstr (dir[id].name, ".htm"))
168 if (!web_register (dir[id].name))
169 return 0;
172 #else
173 struct dirent *entry; /* Only used as a pointer - see dirent.h */
174 struct stat statbuf; /* So we can check which files are directories. */
175 char *pathname = ".";
177 /* Open a directory for directory reads. */
178 DIR *directory = opendir (pathname);
180 if (!directory) {
181 printf ("ERROR -> cannot open %s\n", pathname);
182 return 0;
185 while ((entry = readdir (directory))) {
186 /* Skip if . or .. */
187 if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
188 continue;
190 /* stat it to see if it is a regular file. */
191 int retval = stat (entry->d_name, &statbuf);
193 if (retval == 0 && statbuf.st_mode & S_IFREG)
194 if (strstr (entry->d_name, ".htm"))
195 if (!web_register (entry->d_name))
196 return 0;
200 closedir (directory);
201 #endif
203 return 1;
206 int http_init ()
208 web_list.next = &web_list;
209 web_list.prev = &web_list;
211 if (!http_loadfiles ())
212 return 0;
214 return 1;
217 int http_transfer (client_t *c)
219 web_t *web = web_find (strlen (c->page) == 0 ? "i.htm" : c->page);
221 if (web) {
222 printf ("> sending '%s' web page\n", web->name);
224 send_to_socket (c->fd, web->page, web->page_len);
225 } else
226 printf ("> web page '%s' not found\n", c->page);
228 c->state = CLIENT_STATE_DONE;
230 return 1;
233 int http_destroy ()
235 web_t *web;
236 for (web = web_list.next; web != &web_list; web = web->next)
237 free (web->page);
239 return 1;