diff options
author | Tatsuya Kinoshita <tats@vega.ocn.ne.jp> | 2011-05-04 07:05:14 +0000 |
---|---|---|
committer | Tatsuya Kinoshita <tats@vega.ocn.ne.jp> | 2011-05-04 07:05:14 +0000 |
commit | 72f72d64a422d6628c4796f5c0bf2e508f134214 (patch) | |
tree | 0c9ea90cc53310832c977265521fb44db24a515e /local.c | |
parent | Adding upstream version 0.3 (diff) | |
download | w3m-72f72d64a422d6628c4796f5c0bf2e508f134214.tar.gz w3m-72f72d64a422d6628c4796f5c0bf2e508f134214.zip |
Adding upstream version 0.5.1upstream/0.5.1
Diffstat (limited to 'local.c')
-rw-r--r-- | local.c | 415 |
1 files changed, 415 insertions, 0 deletions
@@ -0,0 +1,415 @@ +/* $Id: local.c,v 1.31 2003/09/26 17:59:51 ukai Exp $ */ +#include "fm.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <errno.h> +#ifdef HAVE_READLINK +#include <unistd.h> +#endif /* HAVE_READLINK */ +#ifdef __EMX__ +#include <limits.h> /* _MAX_PATH ? */ +#endif /* __EMX__ */ +#include "local.h" +#include "hash.h" + +#define CGIFN_NORMAL 0 +#define CGIFN_LIBDIR 1 +#define CGIFN_CGIBIN 2 + +static Str Local_cookie = NULL; +static char *Local_cookie_file = NULL; + +static void +writeLocalCookie() +{ + FILE *f; + + if (no_rc_dir) + return; + if (Local_cookie_file) + return; + Local_cookie_file = tmpfname(TMPF_COOKIE, NULL)->ptr; + set_environ("LOCAL_COOKIE_FILE", Local_cookie_file); + f = fopen(Local_cookie_file, "wb"); + if (!f) + return; + localCookie(); + fwrite(Local_cookie->ptr, sizeof(char), Local_cookie->length, f); + fclose(f); + chmod(Local_cookie_file, S_IRUSR | S_IWUSR); +} + +/* setup cookie for local CGI */ +Str +localCookie() +{ + char hostname[256]; + + if (Local_cookie) + return Local_cookie; + gethostname(hostname, 256); + srand48((long)New(char) + (long)time(NULL)); + Local_cookie = Sprintf("%ld@%s", lrand48(), hostname); + return Local_cookie; +} + +Str +loadLocalDir(char *dname) +{ + Str tmp; + DIR *d; + Directory *dir; + struct stat st; + char **flist; + char *p, *qdir; + Str fbuf = Strnew(); +#ifdef HAVE_LSTAT + struct stat lst; +#ifdef HAVE_READLINK + char lbuf[1024]; +#endif /* HAVE_READLINK */ +#endif /* HAVE_LSTAT */ + int i, l, nrow = 0, n = 0, maxlen = 0; + int nfile, nfile_max = 100; + Str dirname; + + d = opendir(dname); + if (d == NULL) + return NULL; + dirname = Strnew_charp(dname); + if (Strlastchar(dirname) != '/') + Strcat_char(dirname, '/'); + qdir = html_quote(Str_conv_from_system(dirname)->ptr); + /* FIXME: gettextize? */ + tmp = Strnew_m_charp("<HTML>\n<HEAD>\n<BASE HREF=\"file://", qdir, + "\">\n<TITLE>Directory list of ", qdir, + "</TITLE>\n</HEAD>\n<BODY>\n<H1>Directory list of ", + qdir, "</H1>\n", NULL); + flist = New_N(char *, nfile_max); + nfile = 0; + while ((dir = readdir(d)) != NULL) { + flist[nfile++] = allocStr(dir->d_name, -1); + if (nfile == nfile_max) { + nfile_max *= 2; + flist = New_Reuse(char *, flist, nfile_max); + } + if (multicolList) { + l = strlen(dir->d_name); + if (l > maxlen) + maxlen = l; + n++; + } + } + + if (multicolList) { + l = COLS / (maxlen + 2); + if (!l) + l = 1; + nrow = (n + l - 1) / l; + n = 1; + Strcat_charp(tmp, "<TABLE CELLPADDING=0>\n<TR VALIGN=TOP>\n"); + } + qsort((void *)flist, nfile, sizeof(char *), strCmp); + for (i = 0; i < nfile; i++) { + p = flist[i]; + if (strcmp(p, ".") == 0) + continue; + Strcopy(fbuf, dirname); + if (Strlastchar(fbuf) != '/') + Strcat_char(fbuf, '/'); + Strcat_charp(fbuf, p); +#ifdef HAVE_LSTAT + if (lstat(fbuf->ptr, &lst) < 0) + continue; +#endif /* HAVE_LSTAT */ + if (stat(fbuf->ptr, &st) < 0) + continue; + if (multicolList) { + if (n == 1) + Strcat_charp(tmp, "<TD><NOBR>"); + } + else { +#ifdef HAVE_LSTAT + if (S_ISLNK(lst.st_mode)) + Strcat_charp(tmp, "[LINK] "); + else +#endif /* HAVE_LSTAT */ + if (S_ISDIR(st.st_mode)) + Strcat_charp(tmp, "[DIR] "); + else + Strcat_charp(tmp, "[FILE] "); + } + Strcat_m_charp(tmp, "<A HREF=\"", html_quote(file_quote(p)), NULL); + if (S_ISDIR(st.st_mode)) + Strcat_char(tmp, '/'); + Strcat_m_charp(tmp, "\">", html_quote(conv_from_system(p)), NULL); + if (S_ISDIR(st.st_mode)) + Strcat_char(tmp, '/'); + Strcat_charp(tmp, "</A>"); + if (multicolList) { + if (n++ == nrow) { + Strcat_charp(tmp, "</NOBR></TD>\n"); + n = 1; + } + else { + Strcat_charp(tmp, "<BR>\n"); + } + } + else { +#if defined(HAVE_LSTAT) && defined(HAVE_READLINK) + if (S_ISLNK(lst.st_mode)) { + if ((l = readlink(fbuf->ptr, lbuf, sizeof(lbuf))) > 0) { + lbuf[l] = '\0'; + Strcat_m_charp(tmp, " -> ", + html_quote(conv_from_system(lbuf)), NULL); + if (S_ISDIR(st.st_mode)) + Strcat_char(tmp, '/'); + } + } +#endif /* HAVE_LSTAT && HAVE_READLINK */ + Strcat_charp(tmp, "<br>\n"); + } + } + if (multicolList) { + Strcat_charp(tmp, "</TR>\n</TABLE>\n"); + } + Strcat_charp(tmp, "</BODY>\n</HTML>\n"); + + return tmp; +} + +static int +check_local_cgi(char *file, int status) +{ + struct stat st; + + if (status != CGIFN_LIBDIR && status != CGIFN_CGIBIN) + return -1; + if (stat(file, &st) < 0) + return -1; + if (S_ISDIR(st.st_mode)) + return -1; + if ((st.st_uid == geteuid() && (st.st_mode & S_IXUSR)) || (st.st_gid == getegid() && (st.st_mode & S_IXGRP)) || (st.st_mode & S_IXOTH)) /* executable */ + return 0; + return -1; +} + +void +set_environ(char *var, char *value) +{ +#ifdef HAVE_SETENV + if (var != NULL && value != NULL) + setenv(var, value, 1); +#else /* not HAVE_SETENV */ +#ifdef HAVE_PUTENV + static Hash_sv *env_hash = NULL; + Str tmp = Strnew_m_charp(var, "=", value, NULL); + + if (env_hash == NULL) + env_hash = newHash_sv(20); + putHash_sv(env_hash, var, (void *)tmp->ptr); + putenv(tmp->ptr); +#else /* not HAVE_PUTENV */ + extern char **environ; + char **ne; + char *p; + int i, l, el; + char **e, **newenv; + + /* I have no setenv() nor putenv() */ + /* This part is taken from terms.c of skkfep */ + l = strlen(var); + for (e = environ, i = 0; *e != NULL; e++, i++) { + if (strncmp(e, var, l) == 0 && (*e)[l] == '=') { + el = strlen(*e) - l - 1; + if (el >= strlen(value)) { + strcpy(*e + l + 1, value); + return 0; + } + else { + for (; *e != NULL; e++, i++) { + *e = *(e + 1); + } + i--; + break; + } + } + } + newenv = (char **)GC_malloc((i + 2) * sizeof(char *)); + if (newenv == NULL) + return; + for (e = environ, ne = newenv; *e != NULL; *(ne++) = *(e++)) ; + *(ne++) = p; + *ne = NULL; + environ = newenv; +#endif /* not HAVE_PUTENV */ +#endif /* not HAVE_SETENV */ +} + +static void +set_cgi_environ(char *name, char *fn, char *req_uri) +{ + set_environ("SERVER_SOFTWARE", w3m_version); + set_environ("SERVER_PROTOCOL", "HTTP/1.0"); + set_environ("SERVER_NAME", "localhost"); + set_environ("SERVER_PORT", "80"); /* dummy */ + set_environ("REMOTE_HOST", "localhost"); + set_environ("REMOTE_ADDR", "127.0.0.1"); + set_environ("GATEWAY_INTERFACE", "CGI/1.1"); + + set_environ("SCRIPT_NAME", name); + set_environ("SCRIPT_FILENAME", fn); + set_environ("REQUEST_URI", req_uri); +} + +static Str +checkPath(char *fn, char *path) +{ + char *p; + Str tmp; + struct stat st; + while (*path) { + p = strchr(path, ':'); + tmp = Strnew_charp(expandPath(p ? allocStr(path, p - path) : path)); + if (Strlastchar(tmp) != '/') + Strcat_char(tmp, '/'); + Strcat_charp(tmp, fn); + if (stat(tmp->ptr, &st) == 0) + return tmp; + if (!p) + break; + path = p + 1; + while (*path == ':') + path++; + } + return NULL; +} + +static int +cgi_filename(char *uri, char **fn, char **name, char **path_info) +{ + Str tmp; + int offset; + + *fn = uri; + *name = uri; + *path_info = NULL; + + if (cgi_bin != NULL && strncmp(uri, "/cgi-bin/", 9) == 0) { + offset = 9; + if ((*path_info = strchr(uri + offset, '/'))) + *name = allocStr(uri, *path_info - uri); + tmp = checkPath(*name + offset, cgi_bin); + if (tmp == NULL) + return CGIFN_NORMAL; + *fn = tmp->ptr; + return CGIFN_CGIBIN; + } + +#ifdef __EMX__ + { + char lib[_MAX_PATH]; + _abspath(lib, w3m_lib_dir(), _MAX_PATH); /* Translate '\\' to '/' */ + tmp = Strnew_charp(lib); + } +#else + tmp = Strnew_charp(w3m_lib_dir()); +#endif + if (Strlastchar(tmp) != '/') + Strcat_char(tmp, '/'); + if (strncmp(uri, "/$LIB/", 6) == 0) + offset = 6; + else if (strncmp(uri, tmp->ptr, tmp->length) == 0) + offset = tmp->length; + else if (*uri == '/' && document_root != NULL) { + Str tmp2 = Strnew_charp(document_root); + if (Strlastchar(tmp2) != '/') + Strcat_char(tmp2, '/'); + Strcat_charp(tmp2, uri + 1); + if (strncmp(tmp2->ptr, tmp->ptr, tmp->length) != 0) + return CGIFN_NORMAL; + uri = tmp2->ptr; + *name = uri; + offset = tmp->length; + } + else + return CGIFN_NORMAL; + if ((*path_info = strchr(uri + offset, '/'))) + *name = allocStr(uri, *path_info - uri); + Strcat_charp(tmp, *name + offset); + *fn = tmp->ptr; + return CGIFN_LIBDIR; +} + +FILE * +localcgi_post(char *uri, char *qstr, FormList *request, char *referer) +{ + FILE *fr = NULL, *fw = NULL; + int status; + pid_t pid; + char *file = uri, *name = uri, *path_info = NULL, *tmpf = NULL; + + status = cgi_filename(uri, &file, &name, &path_info); + if (check_local_cgi(file, status) < 0) + return NULL; + writeLocalCookie(); + if (request && request->enctype != FORM_ENCTYPE_MULTIPART) { + tmpf = tmpfname(TMPF_DFL, NULL)->ptr; + fw = fopen(tmpf, "w"); + if (!fw) + return NULL; + } + pid = open_pipe_rw(&fr, NULL); + if (pid < 0) + return NULL; + else if (pid) { + if (fw) + fclose(fw); + return fr; + } + setup_child(TRUE, 2, fw ? fileno(fw) : -1); + + if (qstr) + uri = Strnew_m_charp(uri, "?", qstr, NULL)->ptr; + set_cgi_environ(name, file, uri); + if (path_info) + set_environ("PATH_INFO", path_info); + if (referer && referer != NO_REFERER) + set_environ("HTTP_REFERER", referer); + if (request) { + set_environ("REQUEST_METHOD", "POST"); + if (qstr) + set_environ("QUERY_STRING", qstr); + set_environ("CONTENT_LENGTH", Sprintf("%d", request->length)->ptr); + if (request->enctype == FORM_ENCTYPE_MULTIPART) { + set_environ("CONTENT_TYPE", + Sprintf("multipart/form-data; boundary=%s", + request->boundary)->ptr); + freopen(request->body, "r", stdin); + } + else { + set_environ("CONTENT_TYPE", "application/x-www-form-urlencoded"); + fwrite(request->body, sizeof(char), request->length, fw); + fclose(fw); + freopen(tmpf, "r", stdin); + } + } + else { + set_environ("REQUEST_METHOD", "GET"); + set_environ("QUERY_STRING", qstr ? qstr : ""); + freopen(DEV_NULL_PATH, "r", stdin); + } + +#ifdef HAVE_CHDIR /* ifndef __EMX__ ? */ + chdir(mydirname(file)); +#endif + execl(file, mybasename(file), NULL); + fprintf(stderr, "execl(\"%s\", \"%s\", NULL): %s\n", + file, mybasename(file), strerror(errno)); + exit(1); + return NULL; +} |