#include <stdlib.h>
#include <string.h>
-int cm_sort(const void* _a, const void* _b){
+int cm_sort(const void* _a, const void* _b) {
char* a = *(char**)_a;
char* b = *(char**)_b;
return strcmp(a, b);
}
-char** cm_scandir(const char* path){
+char** cm_scandir(const char* path) {
DIR* dir = opendir(path);
- if(dir != NULL){
+ if(dir != NULL) {
char** r = malloc(sizeof(*r));
r[0] = NULL;
struct dirent* d;
- while((d = readdir(dir)) != NULL){
- if(strcmp(d->d_name, ".") != 0){
+ while((d = readdir(dir)) != NULL) {
+ if(strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
struct stat s;
char* p = cm_strcat3(path, "/", d->d_name);
stat(p, &s);
char** old = r;
int i;
- for(i = 0; old[i] != NULL; i++);
+ for(i = 0; old[i] != NULL; i++)
+ ;
r = malloc(sizeof(*r) * (i + 2));
for(i = 0; old[i] != NULL; i++) r[i] = old[i];
r[i] = cm_strcat(d->d_name, S_ISDIR(s.st_mode) ? "/" : "");
}
}
int len;
- for(len = 0; r[len] != NULL; len++);
+ for(len = 0; r[len] != NULL; len++)
+ ;
qsort(r, len, sizeof(char*), cm_sort);
+
+ char** old = r;
+ int i;
+ for(i = 0; old[i] != NULL; i++)
+ ;
+ r = malloc(sizeof(*r) * (i + 2));
+ for(i = 0; old[i] != NULL; i++) r[i + 1] = old[i];
+ r[0] = cm_strdup("../");
+ r[i + 1] = NULL;
+ free(old);
+
return r;
- }else{
+ } else {
return NULL;
}
}
return &config.root;
}
-bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost){
+bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost) {
int i;
bool found = false;
bool pathstart = false;
bool perm = false;
again:
- for(i = 0; i < vhost->dir_count; i++){
+ for(i = 0; i < vhost->dir_count; i++) {
struct tw_dir_entry* e = &vhost->dirs[i];
pathstart = false;
- if(strlen(path) >= strlen(e->dir)){
+ if(strlen(path) >= strlen(e->dir)) {
pathstart = true;
int j;
- for(j = 0; path[j] != 0 && e->dir[j] != 0; j++){
- if(path[j] != e->dir[j]){
+ for(j = 0; path[j] != 0 && e->dir[j] != 0; j++) {
+ if(path[j] != e->dir[j]) {
pathstart = false;
break;
}
}
char* noslash = cm_strdup(e->dir);
noslash[strlen(noslash) - 1] = 0;
- if(strcmp(e->dir, path) == 0 || strcmp(noslash, path) == 0 || pathstart){
+ if(strcmp(e->dir, path) == 0 || strcmp(noslash, path) == 0 || pathstart) {
found = true;
- if(strcmp(e->name, "all") == 0){
+ if(strcmp(e->name, "all") == 0) {
perm = e->type == TW_DIR_ALLOW;
}
}
free(noslash);
}
- if(!found && vhost != &config.root){
+ if(!found && vhost != &config.root) {
vhost = &config.root;
goto again;
}
config.root.root = NULL;
config.root.mime_count = 0;
config.root.dir_count = 0;
+ config.root.icon_count = 0;
config.vhost_count = 0;
config.module_count = 0;
config.extension = NULL;
current = &config.vhosts[config.vhost_count++];
current->dir_count = 0;
current->mime_count = 0;
+ current->icon_count = 0;
int i;
current->name = cm_strdup(vhost);
current->port = -1;
if(r[1] == NULL) {
cm_log("Config", "Missing extension at line %d", ln);
stop = 1;
- }else if(r[2] == NULL) {
+ } else if(r[2] == NULL) {
cm_log("Config", "Missing MIME at line %d", ln);
stop = 1;
} else {
e->ext = cm_strdup(r[1]);
e->mime = cm_strdup(r[2]);
}
+ } else if(cm_strcaseequ(r[0], "Icon")) {
+ if(r[1] == NULL) {
+ cm_log("Config", "Missing MIME at line %d", ln);
+ stop = 1;
+ } else if(r[2] == NULL) {
+ cm_log("Config", "Missing path at line %d", ln);
+ stop = 1;
+ } else {
+ struct tw_icon_entry* e = ¤t->icons[current->icon_count++];
+ e->mime = cm_strdup(r[1]);
+ e->icon = cm_strdup(r[2]);
+ }
} else if(cm_strcaseequ(r[0], "LoadModule")) {
for(i = 1; r[i] != NULL; i++) {
void* mod = tw_module_load(r[i]);
tw_write(ssl, sock, "\r\n", 2);
size_t incr = 0;
while(1) {
- if(f != NULL){
+ if(f != NULL) {
char buffer[128];
fread(buffer, size < 128 ? size : 128, 1, f);
tw_write(ssl, sock, buffer, size < 128 ? size : 128);
- }else{
+ } else {
tw_write(ssl, sock, (unsigned char*)doc + incr, size < 128 ? size : 128);
}
incr += 128;
}
}
+char* tw_get_mime(const char* ext, struct tw_config_entry* vhost_entry) {
+ char* mime = "application/octet-stream";
+ if(ext == NULL) return mime;
+ bool set = false;
+ int i;
+ for(i = 0; i < vhost_entry->mime_count; i++) {
+ if(strcmp(vhost_entry->mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(vhost_entry->mimes[i].ext, ext) == 0)) {
+ mime = vhost_entry->mimes[i].mime;
+ set = true;
+ }
+ }
+ if(!set) {
+ for(i = 0; i < config.root.mime_count; i++) {
+ if(strcmp(config.root.mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(config.root.mimes[i].ext, ext) == 0)) {
+ mime = config.root.mimes[i].mime;
+ }
+ }
+ }
+ return mime;
+}
+
+char* tw_get_icon(const char* mime, struct tw_config_entry* vhost_entry) {
+ char* icon = "";
+ if(mime == NULL) return "";
+ bool set = false;
+ int i;
+ for(i = 0; i < vhost_entry->icon_count; i++) {
+ if(strcmp(vhost_entry->icons[i].mime, "all") == 0 || (mime != NULL && strcmp(vhost_entry->icons[i].mime, mime) == 0)) {
+ icon = vhost_entry->icons[i].icon;
+ set = true;
+ }
+ }
+ if(!set) {
+ for(i = 0; i < config.root.icon_count; i++) {
+ if(strcmp(config.root.icons[i].mime, "all") == 0 || (mime != NULL && strcmp(config.root.icons[i].mime, mime) == 0)) {
+ icon = config.root.icons[i].icon;
+ }
+ }
+ }
+ return icon;
+}
+
#ifdef __MINGW32__
struct pass_entry {
int sock;
if(ret == 0) {
char* vhost = cm_strdup(config.hostname);
int i;
- for(i = 0; req.headers[i] != NULL; i += 2){
- if(cm_strcaseequ(req.headers[i], "Host")){
+ for(i = 0; req.headers[i] != NULL; i += 2) {
+ if(cm_strcaseequ(req.headers[i], "Host")) {
free(vhost);
vhost = req.headers[i + 1];
break;
cm_log("Server", "Host is %s", vhost);
int port = s == NULL ? 80 : 443;
char* host = cm_strdup(vhost);
- for(i = 0; vhost[i] != 0; i++){
- if(vhost[i] == ':'){
+ for(i = 0; vhost[i] != 0; i++) {
+ if(vhost[i] == ':') {
host[i] = 0;
port = atoi(host + i + 1);
break;
char* path = cm_strcat(vhost_entry->root == NULL ? "" : vhost_entry->root, req.path);
cm_log("Server", "Filesystem path is %s", path);
struct stat st;
- if(stat(path, &st) == 0){
- if(!tw_permission_allowed(path, addr, req, vhost_entry)){
+ if(stat(path, &st) == 0) {
+ if(!tw_permission_allowed(path, addr, req, vhost_entry)) {
tw_http_error(s, sock, 403, name, port);
- }else if(S_ISDIR(st.st_mode)){
+ } else if(S_ISDIR(st.st_mode)) {
char* str = malloc(1);
str[0] = 0;
char** items = cm_scandir(path);
addstring(&str, " <th></th>\n");
addstring(&str, " <th>Filename</th>\n");
addstring(&str, " </tr>\n");
- if(items != NULL){
- for(i = 0; items[i] != NULL; i++){
+ if(items != NULL) {
+ for(i = 0; items[i] != NULL; i++) {
+ char* ext = NULL;
+ int j;
+ for(j = strlen(items[i]) - 1; j >= 0; j--) {
+ if(items[i][j] == '.') {
+ ext = cm_strdup(items[i] + j);
+ break;
+ }
+ }
+ char* mime = tw_get_mime(ext, vhost_entry);
+ if(strcmp(items[i], "../") == 0) {
+ mime = "misc/parent";
+ } else if(items[i][strlen(items[i]) - 1] == '/') {
+ mime = "misc/dir";
+ }
+ char* icon = tw_get_icon(mime, vhost_entry);
+ if(ext != NULL) free(ext);
+ char* itm = cm_strdup(items[i]);
+ if(strlen(itm) >= 32) {
+ if(itm[strlen(itm) - 1] == '/') {
+ itm[31] = 0;
+ itm[30] = '/';
+ itm[29] = '.';
+ itm[28] = '.';
+ itm[27] = '.';
+ } else {
+ itm[31] = 0;
+ itm[30] = '.';
+ itm[29] = '.';
+ itm[28] = '.';
+ }
+ }
addstring(&str, "<tr>\n");
- addstring(&str, " <td></td>\n");
- addstring(&str, " <td><a href=\"%l\">%h</a></td>\n", items[i], items[i]);
+ addstring(&str, " <td><img src=\"%s\" alt=\"icon\"></td>\n", icon);
+ addstring(&str, " <td><a href=\"%l\"><code>%h</code></a></td>\n", items[i], itm);
addstring(&str, "</tr>\n");
+ free(itm);
}
}
addstring(&str, " </table>\n");
addstring(&str, "</html>\n");
tw_process_page(s, sock, tw_http_status(200), "text/html", NULL, str, strlen(str));
free(str);
- }else{
- char* mime = "application/octet-stream";
- bool set = false;
+ } else {
char* ext = NULL;
- for(i = strlen(req.path) - 1; i >= 0; i--){
- if(req.path[i] == '.'){
+ for(i = strlen(req.path) - 1; i >= 0; i--) {
+ if(req.path[i] == '.') {
ext = cm_strdup(req.path + i);
break;
}
}
- for(i = 0; i < vhost_entry->mime_count; i++){
- if(strcmp(vhost_entry->mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(vhost_entry->mimes[i].ext, ext) == 0)){
- mime = vhost_entry->mimes[i].mime;
- set = true;
- }
- }
- if(!set){
- for(i = 0; i < config.root.mime_count; i++){
- if(strcmp(config.root.mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(config.root.mimes[i].ext, ext) == 0)){
- mime = config.root.mimes[i].mime;
- set = true;
- }
- }
- }
+ char* mime = tw_get_mime(ext, vhost_entry);
if(ext != NULL) free(ext);
FILE* f = fopen(path, "rb");
tw_process_page(s, sock, tw_http_status(200), mime, f, NULL, st.st_size);
fclose(f);
}
- }else{
+ } else {
tw_http_error(s, sock, 404, name, port);
}
free(path);
}
free(vhost);
free(host);
+ } else if(ret == -1) {
} else {
tw_http_error(s, sock, 400, name, port);
}