3 static char * indexNames[] =
15 #define NUM_INDEX (sizeof(indexNames) / sizeof(char *))
17 static void WriteFileName(File f, char * fileName)
21 for(c = 0; (ch = fileName[c]); c++)
23 if(ch <= 32 || ch > 128)
27 nibble = (ch & 0xF0) >> 4;
28 f.Putc((nibble > 9) ? (nibble - 10 + 'a') : (nibble + '0'));
30 f.Putc((nibble > 9) ? (nibble - 10 + 'a') : (nibble + '0'));
37 #define CONTENT_PATH "."
39 static void CreateDirectoryListing(File f, char * directory)
41 FileListing listing { directory };
43 f.Puts("<HTML><HEAD></HEAD><BODY>\r\n");
45 if(directory[0] && directory[1] && (directory[1] != ':' || (directory[2] && directory[3])))
46 f.Puts("<A HREF=../>../</A><BR>\r\n");
51 WriteFileName(f, listing.name);
52 if(listing.stats.attribs.isDirectory)
56 f.Puts("</A><BR>\r\n");
59 f.Puts("\r\n</BODY></HTML>\r\n");
62 static char * GetString(char * string, char * what, int count)
66 for(c = 0; what[c]; c++)
68 if((count && c >= count) || (string[c] != what[c] && tolower(string[c]) != tolower(what[c])))
74 class HTTPClient : Socket
79 #define ishexdigit(x) (isdigit(x) || (x >= 'a' && x<='f') || (x >= 'A' && x <= 'F'))
81 uint OnReceive(const byte * buffer, uint count)
84 for(c = 0; c<count-1; c++)
86 if(buffer[c] == '\r' && buffer[c+1] == '\n')
91 char * string = (char *)buffer;
93 if((string = GetString((char *)buffer, "GET ", count)))
96 char path[MAX_LOCATION];
97 char addedPath[MAX_LOCATION];
102 strcpy(path, CONTENT_PATH);
104 for(d = c; d > 0 && string[d] != ' '; d--);
107 if(string[i] == '%' && ishexdigit(string[i+1]) && ishexdigit(string[i+2]))
110 digits[0] = string[i+1];
111 digits[1] = string[i+2];
113 addedPath[len++] = (byte)strtol(digits, null, 16);
117 addedPath[len++] = string[i];
118 addedPath[len] = '\0';
121 PathCat(path, addedPath+1);
123 attribs = FileExists(path);
125 if(attribs.isDirectory)
127 if(addedPath[len-1] != '/')
129 strcpy(reply, "HTTP/1.1 301 Moved Permantently\r\n");
131 strcat(reply, "Location: ");
132 strcat(reply, addedPath);
133 strcat(reply, "/\r\n");
134 strcat(reply, "Content-Length: 0\r\n\r\n");
139 char indexFile[MAX_LOCATION];
140 for(i = 0; i<NUM_INDEX; i++)
142 strcpy(indexFile, path);
143 PathCat(indexFile, indexNames[i]);
144 if(FileExists(indexFile).isFile)
146 f = FileOpen(indexFile, read);
150 // List contents if we didn't find an index
156 CreateDirectoryListing(f, path);
162 else if(attribs.isFile)
163 f = FileOpen(path, read);
165 strcpy(reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
169 char extension[MAX_EXTENSION];
170 uint size = f.GetSize();
171 sprintf(reply, "HTTP/1.1 200 OK\r\n");
173 GetExtension(addedPath, extension);
174 if(attribs.isDirectory || !strcmp(extension, "html") || !strcmp(extension, "htm"))
175 strcat(reply, "Content-Type: text/html\r\n");
177 strcat(reply, "Content-Type: text/plain\r\n");
178 sprintf(strchr(reply, 0), "Content-Length: %d\r\n\r\n", size);
188 class HTTPServer : Service
196 class HTTPApplication : GuiApplication
204 bool Cycle(bool idle)
207 HTTPClient client, next;
208 for(client = (HTTPClient)httpServer.firstClient; client; client = next)
210 next = (HTTPClient)client.next;
213 #define PACKETSIZE 65536
215 static byte buffer[PACKETSIZE];
216 int read = client.f.Read(buffer, 1, PACKETSIZE);
219 client.Send(buffer, read);
224 client.Disconnect(0);
234 HTTPServer httpServer { port = 8080 };
236 Window serverWindow { size = Size { 320, 200 }, text = "ECERE HTTP Server", hasMinimize = true, hasClose = true };