]> andersk Git - test.git/commitdiff
Simplify the code that compresses HTTP replies. This also gives us the ability
authorMarkus Gutschke <markus@shellinabox.com>
Sat, 15 Aug 2009 22:55:02 +0000 (22:55 +0000)
committerMarkus Gutschke <markus@shellinabox.com>
Sat, 15 Aug 2009 22:55:02 +0000 (22:55 +0000)
to manipulate headers more easily. We now add "Connection: close" in more cases
where we force a closing of the connection.

config.h
configure
configure.ac
demo/vt100.js
libhttp/httpconnection.c
shellinabox/shell_in_a_box.js
shellinabox/vt100.js

index 27d1e4dcd4cb8e75f4eafc180f915ca61ac0c0ad..ec314355a61d698c58d7a95f96f40e8256b5f58e 100644 (file)
--- a/config.h
+++ b/config.h
 #define STDC_HEADERS 1
 
 /* Most recent revision number in the version control system */
-#define VCS_REVISION "170"
+#define VCS_REVISION "171"
 
 /* Version number of package */
 #define VERSION "2.9"
index 4df37999a052a81d078e3a4e90e06f0d0bf03bbd..932a58b041162b8279a12547f07cef0ee25c760f 100755 (executable)
--- a/configure
+++ b/configure
@@ -2317,7 +2317,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
-VCS_REVISION=170
+VCS_REVISION=171
 
 
 cat >>confdefs.h <<_ACEOF
index 88792b2a45e42b4a7b29fe7060547f3c2e2439a2..d54462c40485f470611f675be176264bb5799d10 100644 (file)
@@ -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=170
+VCS_REVISION=171
 AC_SUBST(VCS_REVISION)
 AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}",
                    [Most recent revision number in the version control system])
index 01073647dd178caa7439233369ed5cc40b79d905..bf064850022be99f7c47f730eb5199bbbbc3d5d9 100644 (file)
@@ -1892,7 +1892,7 @@ VT100.prototype.toggleBell = function() {
 };
 
 VT100.prototype.about = function() {
-  alert("VT100 Terminal Emulator " + "2.9 (revision 170)" +
+  alert("VT100 Terminal Emulator " + "2.9 (revision 171)" +
         "\nCopyright 2008-2009 by Markus Gutschke\n" +
         "For more information check http://shellinabox.com");
 };
index c4a467307551a4852dc00a3bcb6da03da73488f4..972a58cc2a323626f30183b7c38a363b0b262994 100644 (file)
@@ -66,6 +66,8 @@
 #ifdef HAVE_STRLCAT
 #define strncat(a,b,c) ({ char *_a = (a); strlcat(_a, (b), (c)+1); _a; })
 #endif
+#define max(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b);                  \
+                     _a > _b ? _a : _b; })
 
 #include "libhttp/httpconnection.h"
 #include "logging/logging.h"
@@ -488,6 +490,58 @@ static int httpAcceptsEncoding(struct HttpConnection *http,
 }
 #endif
 
+static void removeHeader(char *header, int *headerLength, const char *id) {
+  check(header);
+  check(headerLength);
+  check(*headerLength >= 0);
+  check(id);
+  check(strchr(id, ':'));
+  int idLength       = strlen(id);
+  if (idLength <= 0) {
+    return;
+  }
+  for (char *ptr = header; header + *headerLength - ptr >= idLength; ) {
+    char *end        = ptr;
+    do {
+      end            = memchr(end, '\n', header + *headerLength - end);
+      if (end == NULL) {
+        end          = header + *headerLength;
+      } else {
+        ++end;
+      }
+    } while (end < header + *headerLength && *end == ' ');
+    if (!strncasecmp(ptr, id, idLength)) {
+      memmove(ptr, end, header + *headerLength - end);
+      *headerLength -= end - ptr;
+    } else {
+      ptr            = end;
+    }
+  }
+}
+
+static void addHeader(char **header, int *headerLength, const char *fmt, ...) {
+  check(header);
+  check(headerLength);
+  check(*headerLength >= 0);
+  check(strstr(fmt, "\r\n"));
+
+  va_list ap;
+  va_start(ap, fmt);
+  char *tmp        = vStringPrintf(NULL, fmt, ap);
+  va_end(ap);
+  int tmpLength    = strlen(tmp);
+
+  if (*headerLength >= 2 && !memcmp(*header + *headerLength - 2, "\r\n", 2)) {
+    *headerLength -= 2;
+  }
+  check(*header    = realloc(*header, *headerLength + tmpLength + 2));
+
+  memcpy(*header + *headerLength, tmp, tmpLength);
+  memcpy(*header + *headerLength + tmpLength, "\r\n", 2);
+  *headerLength   += tmpLength + 2;
+  free(tmp);
+}
+
 void httpTransfer(struct HttpConnection *http, char *msg, int len) {
   check(msg);
   check(len >= 0);
@@ -501,9 +555,12 @@ void httpTransfer(struct HttpConnection *http, char *msg, int len) {
   if (msie && msie[5] >= '4' && msie[5] <= '6') {
     ieBug++;
   }
-      
+
+  char *header              = NULL;
+  int headerLength          = 0;
+  int bodyOffset            = 0;
+
   int compress              = 0;
-  char *contentLength       = NULL;
   if (!http->totalWritten) {
     // Perform some basic sanity checks. This does not necessarily catch all
     // possible problems, though.
@@ -549,12 +606,6 @@ void httpTransfer(struct HttpConnection *http, char *msg, int len) {
         // lines
         if (*line != ' ' && *line != '\t') {
           check(memchr(line, ':', eol - line));
-
-          // Remember where we saw the Content-Length header. We need to edit
-          // it, if we end up sending compressed data
-          if (!strncasecmp(line, "Content-Length:", 15)) {
-            contentLength   = line;
-          }
         }
       }
       lastLine              = line;
@@ -562,41 +613,34 @@ void httpTransfer(struct HttpConnection *http, char *msg, int len) {
       line                  = eol + 1;
     }
 
-    if (compress) {
-      #ifdef HAVE_ZLIB
-      // Create a copy of msg, and edit existing Content-Length line
-      // out of header.
-      char *compressed, *ptr;
-      check(compressed      = malloc(len + 100));
-      if (contentLength) {
-        memcpy(compressed, msg, contentLength - msg);
-        char *part2         = strchr(contentLength, '\n');
-        check(part2++);
-        memcpy(compressed + (contentLength - msg), part2, line - part2);
-        ptr                 = compressed + (contentLength - msg) +
-                                           (line - part2);
-      } else {
-        memcpy(compressed, msg, line - msg);
-        ptr                 = compressed + (line - msg);
+    if (ieBug || compress) {
+      if (l >= 2 && !memcmp(line, "\r\n", 2)) {
+        line               += 2;
+        l                  -= 2;
       }
+      headerLength          = line - msg;
+      bodyOffset            = headerLength;
+      check(header          = malloc(headerLength));
+      memcpy(header, msg, headerLength);
+    }
+    if (ieBug) {
+      removeHeader(header, &headerLength, "connection:");
+      addHeader(&header, &headerLength, "Connection: close\r\n");
+    }
 
-      // Add new Content-Encoding and new Content-Length lines. Leave enough
-      // space to later edit the actual length back in.
-      memcpy(ptr,
-             "Content-Encoding: deflate\r\n"
-             "Content-Length:                    \r\n\r\n",
-             66);
-      contentLength         = ptr + 42;
-      ptr                  += 66;
-      
+    if (compress) {
+      #ifdef HAVE_ZLIB
       // Compress the message
+      char *compressed;
+      check(compressed      = malloc(len));
+      check(len >= bodyOffset + 2);
       z_stream strm         = { .zalloc    = Z_NULL,
                                 .zfree     = Z_NULL,
                                 .opaque    = Z_NULL,
                                 .avail_in  = l - 2,
                                 .next_in   = (unsigned char *)line + 2,
-                                .avail_out = len - (ptr - compressed),
-                                .next_out  = (unsigned char *)ptr
+                                .avail_out = len,
+                                .next_out  = (unsigned char *)compressed
                               };
       if (deflateInit(&strm, Z_DEFAULT_COMPRESSION) == Z_OK) {
         if (deflate(&strm, Z_FINISH) == Z_STREAM_END) {
@@ -605,9 +649,11 @@ void httpTransfer(struct HttpConnection *http, char *msg, int len) {
           free(msg);
           msg               = compressed;
           len              -= strm.avail_out;
-          snprintf(contentLength, 21, "%20lu",
-                   (unsigned long)(len - (ptr - compressed)));
-          contentLength[20] = '\r';
+          bodyOffset        = 0;
+          removeHeader(header, &headerLength, "content-length:");
+          removeHeader(header, &headerLength, "content-encoding:");
+          addHeader(&header, &headerLength, "Content-Length: %d\r\n", len);
+          addHeader(&header, &headerLength, "Content-Encoding: deflate\r\n");
         } else {
           free(compressed);
         }
@@ -619,25 +665,50 @@ void httpTransfer(struct HttpConnection *http, char *msg, int len) {
     }
   }
 
-  http->totalWritten       += len;
-  if (!len) {
+  http->totalWritten       += headerLength + (len - bodyOffset);
+  if (!headerLength) {
+    free(header);
+  } else if (http->msg) {
+    check(http->msg         = realloc(http->msg,
+                                      http->msgLength - http->msgOffset +
+                                      max(http->msgOffset, headerLength)));
+    if (http->msgOffset) {
+      memmove(http->msg, http->msg + http->msgOffset,
+              http->msgLength - http->msgOffset);
+      http->msgLength      -= http->msgOffset;
+      http->msgOffset       = 0;
+    }
+    memcpy(http->msg + http->msgLength, header, headerLength);
+    http->msgLength        += headerLength;
+    free(header);
+  } else {
+    check(!http->msgOffset);
+    http->msg               = header;
+    http->msgLength         = headerLength;
+  }
+
+  if (len <= bodyOffset) {
     free(msg);
   } else if (http->msg) {
     check(http->msg         = realloc(http->msg,
-                                     http->msgLength - http->msgOffset + len));
+                                      http->msgLength - http->msgOffset +
+                                      max(http->msgOffset, len - bodyOffset)));
     if (http->msgOffset) {
       memmove(http->msg, http->msg + http->msgOffset,
               http->msgLength - http->msgOffset);
       http->msgLength      -= http->msgOffset;
       http->msgOffset       = 0;
     }
-    memcpy(http->msg + http->msgLength, msg, len);
-    http->msgLength        += len;
+    memcpy(http->msg + http->msgLength, msg + bodyOffset, len - bodyOffset);
+    http->msgLength        += len - bodyOffset;
     free(msg);
   } else {
     check(!http->msgOffset);
+    if (bodyOffset) {
+      memmove(msg, msg + bodyOffset, len - bodyOffset);
+    }
     http->msg               = msg;
-    http->msgLength         = len;
+    http->msgLength         = len - bodyOffset;
   }
 
   // The caller can suspend the connection, so that it can send an
@@ -686,7 +757,7 @@ void httpTransfer(struct HttpConnection *http, char *msg, int len) {
     }
   }
 
-  if (http->sslHndl && ieBug) {
+  if (ieBug) {
     httpCloseRead(http);
   }
 }
index 12d2bed4da7abf9e7b6786ac98c650e54fbb4164..781870329a20a890fede29246045660b58766a68 100644 (file)
@@ -355,7 +355,7 @@ ShellInABox.prototype.extendContextMenu = function(entries, actions) {
 };
 
 ShellInABox.prototype.about = function() {
-  alert("Shell In A Box version " + "2.9 (revision 170)" +
+  alert("Shell In A Box version " + "2.9 (revision 171)" +
         "\nCopyright 2008-2009 by Markus Gutschke\n" +
         "For more information check http://shellinabox.com" +
         (typeof serverSupportsSSL != 'undefined' && serverSupportsSSL ?
index 01073647dd178caa7439233369ed5cc40b79d905..bf064850022be99f7c47f730eb5199bbbbc3d5d9 100644 (file)
@@ -1892,7 +1892,7 @@ VT100.prototype.toggleBell = function() {
 };
 
 VT100.prototype.about = function() {
-  alert("VT100 Terminal Emulator " + "2.9 (revision 170)" +
+  alert("VT100 Terminal Emulator " + "2.9 (revision 171)" +
         "\nCopyright 2008-2009 by Markus Gutschke\n" +
         "For more information check http://shellinabox.com");
 };
This page took 0.115063 seconds and 5 git commands to generate.