aboutsummaryrefslogtreecommitdiffstats
path: root/local.c
diff options
context:
space:
mode:
authorTatsuya Kinoshita <tats@vega.ocn.ne.jp>2011-05-04 07:05:14 +0000
committerTatsuya Kinoshita <tats@vega.ocn.ne.jp>2011-05-04 07:05:14 +0000
commit72f72d64a422d6628c4796f5c0bf2e508f134214 (patch)
tree0c9ea90cc53310832c977265521fb44db24a515e /local.c
parentAdding upstream version 0.3 (diff)
downloadw3m-1ef51c20e0ea7b35c8c9cad6f9d9bc1e16664cc5.tar.gz
w3m-1ef51c20e0ea7b35c8c9cad6f9d9bc1e16664cc5.zip
Adding upstream version 0.5.1upstream/0.5.1
Diffstat (limited to 'local.c')
-rw-r--r--local.c415
1 files changed, 415 insertions, 0 deletions
diff --git a/local.c b/local.c
new file mode 100644
index 0000000..b1e388d
--- /dev/null
+++ b/local.c
@@ -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]&nbsp; ");
+ 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;
+}