diff --git a/classes/VncViewer.jar b/classes/VncViewer.jar
index cf4c124..5f3fbc6 100644
Binary files a/classes/VncViewer.jar and b/classes/VncViewer.jar differ
diff --git a/classes/index.vnc b/classes/index.vnc
index 6cab43e..63b2f56 100644
--- a/classes/index.vnc
+++ b/classes/index.vnc
@@ -1,8 +1,8 @@
+ APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT, PARAMS. Use two dollar
+ signs ($$) to get a dollar sign in the generated html. -->
diff --git a/httpd.c b/httpd.c
index dc49870..1e65658 100644
--- a/httpd.c
+++ b/httpd.c
@@ -54,6 +54,8 @@
static void httpProcessInput();
static Bool compareAndSkip(char **ptr, const char *str);
+static Bool parseParams(const char *request, char *result, int max_bytes);
+static Bool validateString(char *str);
/*
int httpPort = 0;
@@ -153,7 +155,7 @@ httpCheckFds(rfbScreenInfoPtr rfbScreen)
#ifdef USE_LIBWRAP
if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
STRING_UNKNOWN)) {
- rfbLog("Rejected connection from client %s\n",
+ rfbLog("Rejected HTTP connection from client %s\n",
inet_ntoa(addr.sin_addr));
#else
if ((rfbScreen->httpFP = fdopen(rfbScreen->httpSock, "r+")) == NULL) {
@@ -197,7 +199,9 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
{
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
- char fullFname[256];
+ char fullFname[512];
+ char params[1024];
+ char *ptr;
char *fname;
unsigned int maxFnameLen;
FILE* fd;
@@ -209,14 +213,14 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
cl.sock=rfbScreen->httpSock;
- if (strlen(rfbScreen->httpDir) > 200) {
+ if (strlen(rfbScreen->httpDir) > 255) {
rfbLog("-httpd directory too long\n");
httpCloseSock(rfbScreen);
return;
}
strcpy(fullFname, rfbScreen->httpDir);
fname = &fullFname[strlen(fullFname)];
- maxFnameLen = 255 - strlen(fullFname);
+ maxFnameLen = 511 - strlen(fullFname);
buf_filled=0;
@@ -250,7 +254,7 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
/* Process the request. */
if (strncmp(buf, "GET ", 4)) {
- rfbLog("no GET line\n");
+ rfbLog("httpd: no GET line\n");
httpCloseSock(rfbScreen);
return;
} else {
@@ -259,26 +263,26 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
}
if (strlen(buf) > maxFnameLen) {
- rfbLog("GET line too long\n");
+ rfbLog("httpd: GET line too long\n");
httpCloseSock(rfbScreen);
return;
}
if (sscanf(buf, "GET %s HTTP/1.0", fname) != 1) {
- rfbLog("couldn't parse GET line\n");
+ rfbLog("httpd: couldn't parse GET line\n");
httpCloseSock(rfbScreen);
return;
}
if (fname[0] != '/') {
- rfbLog("filename didn't begin with '/'\n");
+ rfbLog("httpd: filename didn't begin with '/'\n");
WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
httpCloseSock(rfbScreen);
return;
}
if (strchr(fname+1, '/') != NULL) {
- rfbLog("asking for file in other directory\n");
+ rfbLog("httpd: asking for file in other directory\n");
WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
httpCloseSock(rfbScreen);
return;
@@ -288,6 +292,19 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
rfbLog("httpd: get '%s' for %s\n", fname+1,
inet_ntoa(addr.sin_addr));
+ /* Extract parameters from the URL string if necessary */
+
+ params[0] = '\0';
+ ptr = strchr(fname, '?');
+ if (ptr != NULL) {
+ *ptr = '\0';
+ if (!parseParams(&ptr[1], params, 1024)) {
+ params[0] = '\0';
+ rfbLog("httpd: bad parameters in the URL\n");
+ }
+ }
+
+
/* If we were asked for '/', actually read the file index.vnc */
if (strcmp(fname, "/") == 0) {
@@ -382,6 +399,11 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
} else
#endif
WriteExact(&cl, "?", 1);
+ } else if (compareAndSkip(&ptr, "$PARAMS")) {
+
+ if (params[0] != '\0')
+ WriteExact(httpSock, params, strlen(params));
+
} else {
if (!compareAndSkip(&ptr, "$$"))
ptr++;
@@ -420,3 +442,96 @@ compareAndSkip(char **ptr, const char *str)
return FALSE;
}
+
+/*
+ * Parse the request tail after the '?' character, and format a sequence
+ * of tags for inclusion into an HTML page with embedded applet.
+ */
+
+static Bool
+parseParams(const char *request, char *result, int max_bytes)
+{
+ char param_request[128];
+ char param_formatted[196];
+ const char *tail;
+ char *delim_ptr;
+ char *value_str;
+ int cur_bytes, len;
+
+ result[0] = '\0';
+ cur_bytes = 0;
+
+ tail = request;
+ for (;;) {
+ /* Copy individual "name=value" string into a buffer */
+ delim_ptr = strchr((char *)tail, '&');
+ if (delim_ptr == NULL) {
+ if (strlen(tail) >= sizeof(param_request)) {
+ return FALSE;
+ }
+ strcpy(param_request, tail);
+ } else {
+ len = delim_ptr - tail;
+ if (len >= sizeof(param_request)) {
+ return FALSE;
+ }
+ memcpy(param_request, tail, len);
+ param_request[len] = '\0';
+ }
+
+ /* Split the request into parameter name and value */
+ value_str = strchr(¶m_request[1], '=');
+ if (value_str == NULL) {
+ return FALSE;
+ }
+ *value_str++ = '\0';
+ if (strlen(value_str) == 0) {
+ return FALSE;
+ }
+
+ /* Validate both parameter name and value */
+ if (!validateString(param_request) || !validateString(value_str)) {
+ return FALSE;
+ }
+
+ /* Prepare HTML-formatted representation of the name=value pair */
+ len = sprintf(param_formatted,
+ "\n",
+ param_request, value_str);
+ if (cur_bytes + len + 1 > max_bytes) {
+ return FALSE;
+ }
+ strcat(result, param_formatted);
+ cur_bytes += len;
+
+ /* Go to the next parameter */
+ if (delim_ptr == NULL) {
+ break;
+ }
+ tail = delim_ptr + 1;
+ }
+ return TRUE;
+}
+
+/*
+ * Check if the string consists only of alphanumeric characters, '+'
+ * signs, underscores, and dots. Replace all '+' signs with spaces.
+ */
+
+static Bool
+validateString(char *str)
+{
+ char *ptr;
+
+ for (ptr = str; *ptr != '\0'; ptr++) {
+ if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') {
+ if (*ptr == '+') {
+ *ptr = ' ';
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
diff --git a/vncauth.c b/vncauth.c
index 48e5f6e..64e8cbe 100644
--- a/vncauth.c
+++ b/vncauth.c
@@ -63,7 +63,7 @@ vncEncryptAndStorePasswd(char *passwd, char *fname)
/* windows security sux */
#ifndef WIN32
- chmod(fname, S_IRUSR|S_IWUSR);
+ fchmod(fp, S_IRUSR|S_IWUSR);
#endif
/* pad password with nulls */