From 727b025799f7c5c37f32c4b57c892faa1e03ba72 Mon Sep 17 00:00:00 2001
From: dscho <dscho>
Date: Thu, 22 Aug 2002 10:13:48 +0000
Subject: synchronized with tightVNC 1.2.5

---
 classes/VncViewer.jar | Bin 37317 -> 45518 bytes
 classes/index.vnc     |   4 +-
 httpd.c               | 133 ++++++++++++++++++++++++++++++++++++++++++++++----
 vncauth.c             |   2 +-
 4 files changed, 127 insertions(+), 12 deletions(-)

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 @@
 <!-- index.vnc - default html page for Java VNC viewer applet.  On any file
      ending in .vnc, the HTTP server embedded in Xvnc will substitute the
      following variables when preceded by a dollar: USER, DESKTOP, DISPLAY,
-     APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT.  Use two dollar signs
-     ($$) to get a dollar sign in the generated html. -->
+     APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT, PARAMS.  Use two dollar
+     signs ($$) to get a dollar sign in the generated html. -->
 
 <HTML>
 <TITLE>
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 <param> 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(&param_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,
+		      "<PARAM NAME=\"%s\" VALUE=\"%s\">\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 */
-- 
cgit v1.2.3

