commit e54c8687b8d11a12a8ddc8495f6d3d286a057f61
parent a62709b092ed85e24f0b7fc6c860f5ff40075a42
Author: ukai <ukai>
Date: Fri, 31 Jan 2003 16:25:02 +0000
[w3m-dev 03721] PATH_INFO support of local CGI
* local.c (CGIFN_DROOT): deleted
(CGIFN_LIBDIR): added
(CGIFN_MODE): deleted
(CGIFN_CONTAIN_SLASH): deleted
(check_local_cgi): rewrite
(cgi_filename): rewrite
(localcgi_post): support PATH_INFO
* url.c (openURL): rewrite
* Bonus/smb.cgi: use PATH_INFO
From: Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
Diffstat:
M | Bonus/smb.cgi | | | 28 | ++++++++++++++++++++++------ |
M | ChangeLog | | | 13 | +++++++++++++ |
M | local.c | | | 138 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
M | url.c | | | 44 | ++++++++------------------------------------ |
4 files changed, 105 insertions(+), 118 deletions(-)
diff --git a/Bonus/smb.cgi b/Bonus/smb.cgi
@@ -3,9 +3,12 @@
# Workgroup list: file:/$LIB/smb.cgi
# Server list: file:/$LIB/smb.cgi?workgroup
# Sahre list: file:/$LIB/smb.cgi?//server
+# file:/$LIB/smb.cgi/server
# Directory: file:/$LIB/smb.cgi?//server/share
# file:/$LIB/smb.cgi?//server/share/dir...
+# file:/$LIB/smb.cgi/server/share
# Get file: file:/$LIB/smb.cgi?//server/share/dir.../file
+# file:/$LIB/smb.cgi/server/share/dir.../file
#
# ----- ~/.w3m/smb -----
# workgroup = <workgroup>
@@ -64,9 +67,22 @@ $FILE = "F000";
$CGI = "file://" . &file_encode($ENV{"SCRIPT_NAME"} || $0);
$QUERY = $ENV{"QUERY_STRING"};
+$PATH_INFO = $ENV{"PATH_INFO"};
-$_ = &file_decode($QUERY);
-$DEBUG && print "DEBUG: QUERY_STRING=\"$_\"\n";
+if ($PATH_INFO =~ m@^/@) {
+ $_ = $PATH_INFO;
+ if (! m@^//@) {
+ $_ = "/$_";
+ }
+ s@[\r\n\0\\"]@@g;
+ $DEBUG && print "DEBUG: PATH_INFO=\"$_\"\n";
+ $Q = "";
+}
+else {
+ $_ = &file_decode($QUERY);
+ $DEBUG && print "DEBUG: QUERY_STRING=\"$_\"\n";
+ $Q = "?";
+}
if (s@^//([^/]+)@@) {
$server = $1;
# if (!$USE_OPT_A && !defined($PASSWD)) {
@@ -138,7 +154,7 @@ $DEBUG && print "DEBUG: $_";
$c = $&;
s/^ //;
$_ eq "." && next;
- print "<a href=\"$CGI?$service"
+ print "<a href=\"$CGI$Q$service"
. &cleanup("$file/" . &file_encode($_)) . "\">"
. &html_quote($_) . "</a>"
. &html_quote($c) . "\n";
@@ -183,7 +199,7 @@ sub share_list {
for (sort @share) {
($_, $d, @c) = split(" ");
if ($d eq 'Disk') {
- print "<tr><td>+ <a href=\"$CGI?//$server/"
+ print "<tr><td>+ <a href=\"$CGI$Q//$server/"
. &file_encode($_) . "\">"
. &html_quote($_) . "</a>";
} else {
@@ -213,7 +229,7 @@ sub server_list {
print "<tr><td colspan=3><b>$group</b>\n";
for (sort @server) {
($_, @c) = split(" ");
- print "<tr><td>+ <a href=\"$CGI?//"
+ print "<tr><td>+ <a href=\"$CGI$Q//"
. &file_encode($_) . "\">"
. &html_quote($_) . "</a><td><td>"
. &html_quote("@c") . "\n";
@@ -335,7 +351,7 @@ sub print_form {
Content-Type: text/html
<h1>$q</h1>
-<form action="$CGI?$_" method=POST>
+<form action="$CGI$Q$_" method=POST>
<table>
<tr><td>Workgroup <td>User <td>Password
<tr><td><input type=text size=8 name=group value="$WORKGROUP">
diff --git a/ChangeLog b/ChangeLog
@@ -1,5 +1,18 @@
2003-02-01 Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
+ * [w3m-dev 03721] PATH_INFO support of local CGI
+ * local.c (CGIFN_DROOT): deleted
+ (CGIFN_LIBDIR): added
+ (CGIFN_MODE): deleted
+ (CGIFN_CONTAIN_SLASH): deleted
+ (check_local_cgi): rewrite
+ (cgi_filename): rewrite
+ (localcgi_post): support PATH_INFO
+ * url.c (openURL): rewrite
+ * Bonus/smb.cgi: use PATH_INFO
+
+2003-02-01 Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
+
* [w3m-dev 03720] mark remains
* main.c (srchcore): PREC_NUM
diff --git a/local.c b/local.c
@@ -17,11 +17,8 @@
#include "hash.h"
#define CGIFN_NORMAL 0
-#define CGIFN_DROOT 1
+#define CGIFN_LIBDIR 1
#define CGIFN_CGIBIN 2
-#define CGIFN_MODE(x) ((x)&3)
-
-#define CGIFN_CONTAIN_SLASH 4
static char *Local_cookie_file = NULL;
@@ -183,45 +180,16 @@ check_local_cgi(char *file, int status)
{
struct stat st;
- if (status & CGIFN_CONTAIN_SLASH) {
- /* local CGI file must be just under /cgi-bin/
- * or /$LIB/
- */
+ if (status != CGIFN_LIBDIR && status != CGIFN_CGIBIN)
return -1;
- }
-#ifdef __EMX__
- if (CGIFN_MODE(status) != CGIFN_CGIBIN) {
- char tmp[_MAX_PATH];
- int len;
-
- _abspath(tmp, w3m_lib_dir(), _MAX_PATH); /* Translate '\\' to '/' */
- len = strlen(tmp);
- while (len > 1 && tmp[len - 1] == '/')
- len--;
- if (strnicmp(file, tmp, len) || /* and ignore case */
- (file[len] != '/'))
- return -1;
- }
-#else /* not __EMX__ */
- if (CGIFN_MODE(status) != CGIFN_CGIBIN) {
- char *tmp = Strnew_charp(w3m_lib_dir())->ptr;
- int len = strlen(tmp);
-
- while (len > 1 && tmp[len - 1] == '/')
- len--;
- if (strncmp(file, tmp, len) || (file[len] != '/'))
- /*
- * a local-CGI script should be located on either
- * /cgi-bin/ directory or LIB_DIR (typically /usr/local/lib/w3m).
- */
- return -1;
- }
-#endif /* not __EMX__ */
if (stat(file, &st) < 0)
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 */
+ 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;
}
@@ -316,43 +284,60 @@ checkPath(char *fn, char *path)
return NULL;
}
-static char *
-cgi_filename(char *fn, int *status)
+static int
+cgi_filename(char *uri, char **fn, char **name, char **path_info)
{
Str tmp;
- struct stat st;
- if (cgi_bin != NULL && strncmp(fn, "/cgi-bin/", 9) == 0) {
- *status = CGIFN_CGIBIN;
- if (strchr(fn + 9, '/'))
- *status |= CGIFN_CONTAIN_SLASH;
- tmp = checkPath(fn + 9, cgi_bin);
+ 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 fn;
- return tmp->ptr;
+ return CGIFN_NORMAL;
+ *fn = tmp->ptr;
+ return CGIFN_CGIBIN;
}
- if (strncmp(fn, "/$LIB/", 6) == 0) {
- *status = CGIFN_NORMAL;
- tmp = Strnew_charp(w3m_lib_dir());
- fn += 5;
- if (strchr(fn + 1, '/'))
- *status |= CGIFN_CONTAIN_SLASH;
- if (Strlastchar(tmp) == '/')
- fn++;
- Strcat_charp(tmp, fn);
- return tmp->ptr;
+
+#ifdef __EMX__
+ {
+ char lib[_MAX_PATH];
+ _abspath(lib, w3m_lib_dir(), _MAX_PATH); /* Translate '\\' to '/' */
+ tmp = Strnew_charp(lib);
}
- if (*fn == '/' && document_root != NULL && stat(fn, &st) < 0) {
- *status = CGIFN_DROOT;
- if (strchr(fn + 1, '/'))
- *status |= CGIFN_CONTAIN_SLASH;
- tmp = Strnew_charp(document_root);
- if (Strlastchar(tmp) != '/')
- Strcat_char(tmp, '/');
- Strcat_charp(tmp, fn);
- return tmp->ptr;
+#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;
}
- *status = CGIFN_NORMAL;
- return fn;
+ 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 *
@@ -361,9 +346,9 @@ localcgi_post(char *uri, char *qstr, FormList *request, char *referer)
FILE *fr = NULL, *fw = NULL;
int status;
pid_t pid;
- char *file;
+ char *file = uri, *name = uri, *path_info = NULL;
- file = cgi_filename(uri, &status);
+ status = cgi_filename(uri, &file, &name, &path_info);
if (check_local_cgi(file, status) < 0)
return NULL;
writeLocalCookie();
@@ -382,10 +367,11 @@ localcgi_post(char *uri, char *qstr, FormList *request, char *referer)
}
setup_child(TRUE, 2, -1);
- if (qstr == NULL)
- set_cgi_environ(uri, file, uri);
- else
- set_cgi_environ(uri, file, Strnew_m_charp(uri, "?", qstr, NULL)->ptr);
+ 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) {
diff --git a/url.c b/url.c
@@ -1463,14 +1463,13 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
URLFile *ouf, HRequest *hr, unsigned char *status)
{
Str tmp;
- int i, sock, scheme;
+ int sock, scheme;
char *p, *q, *u;
URLFile uf;
HRequest hr0;
#ifdef USE_SSL
SSL *sslh = NULL;
#endif /* USE_SSL */
- int extlen = strlen(CGI_EXTENSION);
if (hr == NULL)
hr = &hr0;
@@ -1521,49 +1520,22 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
switch (pu->scheme) {
case SCM_LOCAL:
case SCM_LOCAL_CGI:
- if (request && request->body) {
+ if (request && request->body)
/* local CGI: POST */
- if ((q = strchr(pu->file, '?')) != NULL) {
- p = Strnew_charp_n(pu->file, (int)(q - pu->file))->ptr;
- pu->real_file = cleanupName(file_unquote(p));
- q++;
- }
- uf.stream = newFileStream(localcgi_post(pu->real_file,
- pu->query,
- request,
- option->referer),
+ uf.stream = newFileStream(localcgi_post(pu->real_file, pu->query,
+ request, option->referer),
(void (*)())pclose);
- if (uf.stream == NULL)
- goto ordinary_local_file;
- uf.is_cgi = TRUE;
- uf.scheme = pu->scheme = SCM_LOCAL_CGI;
- }
- else if (pu->query != NULL) {
+ else
/* lodal CGI: GET */
uf.stream = newFileStream(localcgi_get(pu->real_file, pu->query,
option->referer),
(void (*)())pclose);
- if (uf.stream == NULL) {
- goto ordinary_local_file;
- }
+ if (uf.stream) {
uf.is_cgi = TRUE;
uf.scheme = pu->scheme = SCM_LOCAL_CGI;
+ return uf;
}
- else if ((i = strlen(pu->file)) > extlen &&
- !strncmp(pu->file + i - extlen, CGI_EXTENSION, extlen)) {
- /* lodal CGI: GET */
- uf.stream = newFileStream(localcgi_get(pu->real_file, NULL,
- option->referer),
- (void (*)())pclose);
- if (uf.stream == NULL)
- goto ordinary_local_file;
- uf.is_cgi = TRUE;
- uf.scheme = pu->scheme = SCM_LOCAL_CGI;
- }
- else {
- ordinary_local_file:
- examineFile(pu->real_file, &uf);
- }
+ examineFile(pu->real_file, &uf);
if (uf.stream == NULL) {
if (dir_exist(pu->real_file)) {
add_index_file(pu, &uf);