diff --git a/ChangeLog b/ChangeLog index c3e1cfe..13edcd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-07-06 Markus Gutschke + + * Making it easier to host the terminal on non-root URLs by always + redirecting to a URL that includes a trailing slash. + 2009-07-05 Markus Gutschke * Released version 2.9 diff --git a/config.h b/config.h index 1851d33..14545c9 100644 --- a/config.h +++ b/config.h @@ -132,7 +132,7 @@ #define STDC_HEADERS 1 /* Most recent revision number in the version control system */ -#define VCS_REVISION "139" +#define VCS_REVISION "140" /* Version number of package */ #define VERSION "2.9" diff --git a/configure b/configure index 1cd015c..607b501 100755 --- a/configure +++ b/configure @@ -2037,7 +2037,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -VCS_REVISION=139 +VCS_REVISION=140 cat >>confdefs.h <<_ACEOF diff --git a/configure.ac b/configure.ac index 2080858..3f31db3 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ(2.57) dnl This is the one location where the authoritative version number is stored AC_INIT(shellinabox, 2.9, markus@shellinabox.com) -VCS_REVISION=139 +VCS_REVISION=140 AC_SUBST(VCS_REVISION) AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}", [Most recent revision number in the version control system]) diff --git a/demo/vt100.js b/demo/vt100.js index 740bfd4..9dce1b3 100644 --- a/demo/vt100.js +++ b/demo/vt100.js @@ -1693,7 +1693,7 @@ VT100.prototype.toggleBell = function() { }; VT100.prototype.about = function() { - alert("VT100 Terminal Emulator " + "2.9 (revision 139)" + + alert("VT100 Terminal Emulator " + "2.9 (revision 140)" + "\nCopyright 2008-2009 by Markus Gutschke\n" + "For more information check http://shellinabox.com"); }; diff --git a/libhttp/http.h b/libhttp/http.h index 3235eab..e7840fa 100644 --- a/libhttp/http.h +++ b/libhttp/http.h @@ -128,6 +128,7 @@ const char *urlGetPath(URL *url); const char *urlGetPathInfo(URL *url); const char *urlGetQuery(URL *url); const char *urlGetAnchor(URL *url); +const char *urlGetURL(URL *url); const HashMap *urlGetArgs(URL *url); HashMap *newHashMap(void (*destructor)(void *arg, char *key, char *value), void *arg); diff --git a/libhttp/libhttp.sym b/libhttp/libhttp.sym index afa641d..4eb0bbc 100644 --- a/libhttp/libhttp.sym +++ b/libhttp/libhttp.sym @@ -42,6 +42,7 @@ urlGetPath urlGetPathInfo urlGetQuery urlGetAnchor +urlGetURL urlGetArgs newHashMap deleteHashMap diff --git a/libhttp/url.c b/libhttp/url.c index 7dae646..e12fa76 100644 --- a/libhttp/url.c +++ b/libhttp/url.c @@ -327,6 +327,7 @@ void initURL(struct URL *url, const struct HttpConnection *http, url->pathinfo = strdup(httpGetPathInfo(http)); url->query = strdup(httpGetQuery(http)); url->anchor = NULL; + url->url = NULL; initHashMap(&url->args, urlDestroyHashMapEntry, NULL); if (!strcmp(http->method, "GET")) { urlParseQueryString(url, url->query, strlen(url->query)); @@ -345,6 +346,7 @@ void destroyURL(struct URL *url) { free(url->pathinfo); free(url->query); free(url->anchor); + free(url->url); destroyHashMap(&url->args); } } @@ -390,6 +392,23 @@ const char *urlGetAnchor(struct URL *url) { return url->anchor; } +const char *urlGetURL(struct URL *url) { + if (!url->url) { + const char *host = urlGetHost(url); + int s_size = 8 + strlen(host) + 25 + strlen(url->path); + check(*(char **)&url->url = malloc(s_size + 1)); + *url->url = '\000'; + strncat(url->url, url->protocol, s_size); + strncat(url->url, "://", s_size); + strncat(url->url, host, s_size); + if (url->port != (strcmp(url->protocol, "http") ? 443 : 80)) { + snprintf(strrchr(url->url, '\000'), 25, ":%d", url->port); + } + strncat(url->url, url->path, s_size); + } + return url->url; +} + const struct HashMap *urlGetArgs(struct URL *url) { return &url->args; } diff --git a/libhttp/url.h b/libhttp/url.h index 3df8bb5..7af8367 100644 --- a/libhttp/url.h +++ b/libhttp/url.h @@ -61,6 +61,7 @@ struct URL { char *pathinfo; char *query; char *anchor; + char *url; struct HashMap args; }; @@ -79,6 +80,7 @@ const char *urlGetPath(struct URL *url); const char *urlGetPathInfo(struct URL *url); const char *urlGetQuery(struct URL *url); const char *urlGetAnchor(struct URL *url); +const char *urlGetURL(struct URL *url); const struct HashMap *urlGetArgs(struct URL *url); #endif /* URL_H__ */ diff --git a/shellinabox/shell_in_a_box.js b/shellinabox/shell_in_a_box.js index f584688..3833c35 100644 --- a/shellinabox/shell_in_a_box.js +++ b/shellinabox/shell_in_a_box.js @@ -355,7 +355,7 @@ ShellInABox.prototype.extendContextMenu = function(entries, actions) { }; ShellInABox.prototype.about = function() { - alert("Shell In A Box version " + "2.9 (revision 139)" + + alert("Shell In A Box version " + "2.9 (revision 140)" + "\nCopyright 2008-2009 by Markus Gutschke\n" + "For more information check http://shellinabox.com" + (typeof serverSupportsSSL != 'undefined' && serverSupportsSSL ? diff --git a/shellinabox/shellinaboxd.c b/shellinabox/shellinaboxd.c index 853fe3c..db28faf 100644 --- a/shellinabox/shellinaboxd.c +++ b/shellinabox/shellinaboxd.c @@ -468,6 +468,7 @@ static int shellInABoxHttpHandler(HttpConnection *http, void *arg, // Normalize the path info const char *pathInfo = urlGetPathInfo(url); + int trailingSlash = *pathInfo == '/'; while (*pathInfo == '/') { pathInfo++; } @@ -478,10 +479,23 @@ static int shellInABoxHttpHandler(HttpConnection *http, void *arg, } int pathInfoLength = endPathInfo - pathInfo; - // The root page either serves the AJAX application or redirects to the - // secure HTTPS URL. - if (!pathInfoLength || + // The root page should always have a trailing slash. If it doesn't do so, + // the JavaScript code cannot easily find related resources. + if (!pathInfoLength && !trailingSlash) { + char *redir = stringPrintf(NULL, + "HTTP/1.1 302 Temporary Relocation\r\n" + "Connection: close\r\n" + "Content-Length: 0\r\n" + "Content-Type: text/html\r\n" + "Location: %s/\r\n" + "\r\n", + urlGetURL(url)); + debug("Redirecting to %s/", urlGetURL(url)); + httpTransfer(http, redir, strlen(redir)); + } else if (!pathInfoLength || (pathInfoLength == 5 && !memcmp(pathInfo, "plain", 5))) { + // The root page either serves the AJAX application or redirects to the + // secure HTTPS URL. if (contentType && !strncasecmp(contentType, "application/x-www-form-urlencoded", 33)) { // XMLHttpRequest carrying data between the AJAX application and the diff --git a/shellinabox/vt100.js b/shellinabox/vt100.js index 740bfd4..9dce1b3 100644 --- a/shellinabox/vt100.js +++ b/shellinabox/vt100.js @@ -1693,7 +1693,7 @@ VT100.prototype.toggleBell = function() { }; VT100.prototype.about = function() { - alert("VT100 Terminal Emulator " + "2.9 (revision 139)" + + alert("VT100 Terminal Emulator " + "2.9 (revision 140)" + "\nCopyright 2008-2009 by Markus Gutschke\n" + "For more information check http://shellinabox.com"); };