[tor-commits] [stegotorus/master] Renames after the merge; drop the old x_http.

zwol at torproject.org zwol at torproject.org
Fri Jul 20 23:17:06 UTC 2012


commit 0382170797b7ddadfd91b292d35da0a08627e57e
Author: Zack Weinberg <zackw at cmu.edu>
Date:   Thu Dec 1 23:30:00 2011 +0000

    Renames after the merge; drop the old x_http.
---
 Makefile.am            |   17 +-
 run-autogen.csh        |    3 -
 src/steg/cookies.c     |  234 -------
 src/steg/cookies.cc    |  234 +++++++
 src/steg/crc32.c       |   82 ---
 src/steg/crc32.cc      |   82 +++
 src/steg/http.cc       |  857 +++++++++++++++++++++++++
 src/steg/jsSteg.c      | 1163 ---------------------------------
 src/steg/jsSteg.cc     | 1163 +++++++++++++++++++++++++++++++++
 src/steg/payloads.c    | 1669 ------------------------------------------------
 src/steg/payloads.cc   | 1669 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/steg/pdfSteg.c     |  630 ------------------
 src/steg/pdfSteg.cc    |  630 ++++++++++++++++++
 src/steg/swfSteg.c     |  282 --------
 src/steg/swfSteg.c.old |  264 --------
 src/steg/swfSteg.cc    |  282 ++++++++
 src/steg/x_http.c.old  |  337 ----------
 src/steg/x_http.cc     |  360 -----------
 src/steg/x_http2.c     |  857 -------------------------
 src/steg/zpack.c       |  408 ------------
 src/steg/zpack.cc      |  408 ++++++++++++
 21 files changed, 5333 insertions(+), 6298 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index ebf44d9..bbd89a6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,15 +19,14 @@ PROTOCOLS = \
 	src/protocol/x_null.cc
 
 STEGANOGRAPHERS = \
-	src/steg/x_http.cc \
-	src/steg/x_http2.c \
-	src/steg/payloads.c \
-	src/steg/cookies.c \
-	src/steg/jsSteg.c \
-	src/steg/swfSteg.c \
-	src/steg/zpack.c \
-	src/steg/crc32.c \
-	src/steg/pdfSteg.c
+	src/steg/http.cc \
+	src/steg/payloads.cc \
+	src/steg/cookies.cc \
+	src/steg/jsSteg.cc \
+	src/steg/swfSteg.cc \
+	src/steg/zpack.cc \
+	src/steg/crc32.cc \
+	src/steg/pdfSteg.cc
 
 libstegotorus_a_SOURCES = \
 	src/connections.cc \
diff --git a/run-autogen.csh b/run-autogen.csh
deleted file mode 100644
index 9fe8c44..0000000
--- a/run-autogen.csh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/csh
-setenv PATH /usr/local/bin:`echo $PATH`
-./autogen.sh
diff --git a/src/steg/cookies.c b/src/steg/cookies.c
deleted file mode 100644
index c773386..0000000
--- a/src/steg/cookies.c
+++ /dev/null
@@ -1,234 +0,0 @@
-
-#include "cookies.h"
-
-int unwrap_cookie(unsigned char* inbuf, unsigned char* outbuf, int buflen) {
-  int i,j;
-  j = 0;
-
-  for (i=0; i < buflen; i++) {
-    char c  = inbuf[i];
-
-    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
-      outbuf[j++] = c; 
-  }
-
-  return j;
-
-}
-
-
-
-
-
-
-/* valid cookie characters: anything between between 33 and 126, with the exception of "=" and ';'*/
-/* writes a line of the form XXXX=YYYYY of length cookielen to outbuf, outbuf length >= cookielen */
-/* returns data consumed if success.  datalen assumed to be greater than cookielen*/
-
-
-int gen_one_cookie(unsigned char* outbuf, int cookielen, unsigned char* data, int datalen) {
-  int sofar = 0;
-  unsigned char c;
-  int namelen, vlen;
-  int data_consumed = 0;
-
-  if (cookielen < 4)
-    return -1;
-
-
-
-  if (cookielen > 13)
-    namelen = rand() % 10 + 1;
-  else 
-    namelen = rand() % (cookielen - 3) + 1;
-
-  vlen = cookielen - namelen;
-
-
-
-  while (sofar < namelen) {
-    c = rand() % (127 - 33) + 33;
-    if (c == '=' || c == ';' || c == '`' || c == '\'' || c == '%' || c == '+' || c == '{' || c == '}' ||
-	c == '<' || c == '>' || c == '?' || c == '#')
-      continue;
-
-    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (rand () % 4 != 0)) {
-      if (data_consumed < datalen) 
-	outbuf[sofar++] = data[data_consumed++];
-    }
-    else
-      outbuf[sofar++] = c;
-  }
-
-
-  outbuf[sofar++] = '=';
-
-
-  while (sofar < cookielen) {
-    c = rand() % (127 - 33) + 33;
-    if (c == '=' || c == ';' || c == '`' || c == '\'' || c == '%' || c == '+' || c == '{' || c == '}' ||
-	c == '<' || c == '>' || c == '?' || c == '#')
-      continue;
-
-
-
-    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (rand() % 4 != 0)) {
-      if (data_consumed < datalen) 
-	outbuf[sofar++] = data[data_consumed++];
-    }
-    else
-      outbuf[sofar++] = c;
-  }
-
-
-  
-  return data_consumed;
-
-}
-
-
-
-
-/* dummy version for testing */
-int gen_one_cookie2(unsigned char* outbuf, int cookielen, unsigned char* data, int datalen) {
-  int i;
-
-  if (cookielen < 4)
-    return -1;
-
-  if (datalen >= cookielen) {
-    memcpy(outbuf, data, cookielen);
-    return cookielen;
-  }
-
-  memcpy(outbuf, data, datalen);
-  for (i=datalen; i < cookielen; i++)
-    outbuf[i] = '+';
-
-  return datalen;
-
-}
-
-/* returns data consumed */
-int gen_cookie_field(unsigned char* outbuf, int total_cookie_len, unsigned char* data, int datalen) {
-  int rem_cookie_len = total_cookie_len;
-  int consumed = 0;
-
-
-  if (total_cookie_len < 4) {
-    fprintf(stderr, "error: cookie length too small\n");
-    return -1;
-  }
-
-  while (rem_cookie_len > 4) {
-    int cookielen = 4 + rand() % (rem_cookie_len - 3);
-
-    int cnt =  gen_one_cookie(outbuf, cookielen, data + consumed, datalen - consumed);
-
-    if (cnt < 0) {
-      fprintf(stderr, "error: couldn't create cookie %d\n", cnt);
-      return cnt;
-    }
-
-
-
-    consumed += cnt;
-    //    fprintf(stderr, "cnt = %d %d %d; consumed = %d\n", cnt, rem_cookie_len, cookielen, consumed);
-    rem_cookie_len = rem_cookie_len - cookielen;
-    outbuf += cookielen;
-
-
- 
-   if (rem_cookie_len == 0) {
-      break;
-    }
-    else if (rem_cookie_len <= 5) {
-      int i = 0;
-      if ((consumed < datalen) && (consumed % 2 == 1)) {
-	outbuf[0] = data[consumed];
-	consumed++;
-	outbuf++;
-	rem_cookie_len--;
-      }
-
-      for (i=0; i < rem_cookie_len; i++) 
-	outbuf[i] = "ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ"[rand() % 40];
-      
-      return consumed;
-    }
-    
-    
-    outbuf[0] = ';';
-    outbuf++;
-    rem_cookie_len--;
-  }
-
-
-  if (consumed % 2 == 1) {
-    if ((outbuf[-1] >= '0' && outbuf[-1] <= '9') || (outbuf[-1] >= 'a' && outbuf[-1] <= 'f')) {
-      outbuf[-1] = '*';
-      consumed--;
-    }
-    else {
-      outbuf[-1] = data[consumed];
-      consumed++;
-    }	  
-  }
-
-
-  return consumed;
-}
-
-
-/* dummy version for testing */
-int gen_cookie_field2(unsigned char* outbuf, int total_cookie_len, unsigned char* data, int datalen) {
-  int i;
-  if (datalen >= total_cookie_len) {
-    memcpy(outbuf, data, total_cookie_len);
-    return total_cookie_len;
-  }
-
-  memcpy(outbuf, data, datalen);
-  for (i=datalen; i < total_cookie_len; i++)
-    outbuf[i] = '*';
-
-  return datalen;
-}
-
-
-
-
-/*
-
-int main () {
-  char outbuf[200];
-  char data[52] = "1a239023820389023802380389abc2322132321932847203aedf";
-  char data2[200];
-  //  srand(time(NULL));
-  srand (20);
-
-
-
-  int i=0;
-
-  for (i=0; i < 1000000; i++) {
-    int cookielen = rand()%50 + 5;
-    bzero(outbuf, sizeof(outbuf));
-    int len = gen_cookie_field(outbuf, cookielen, data, sizeof(data));
-    //    printf("len = %d cookie = %s %d\n", len, outbuf, cookielen);
-    bzero(data2, sizeof(data2));
-    int len2 = unwrap_cookie(outbuf, data2, cookielen);
-    //    printf("unwrapped datalen = %d data = %s\n", len, data2);
-
-    if (len != len2)
-      printf("hello %d\n", i);
-  }
-  
-
-
-
-}
-
-*/
-
-
diff --git a/src/steg/cookies.cc b/src/steg/cookies.cc
new file mode 100644
index 0000000..c773386
--- /dev/null
+++ b/src/steg/cookies.cc
@@ -0,0 +1,234 @@
+
+#include "cookies.h"
+
+int unwrap_cookie(unsigned char* inbuf, unsigned char* outbuf, int buflen) {
+  int i,j;
+  j = 0;
+
+  for (i=0; i < buflen; i++) {
+    char c  = inbuf[i];
+
+    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
+      outbuf[j++] = c; 
+  }
+
+  return j;
+
+}
+
+
+
+
+
+
+/* valid cookie characters: anything between between 33 and 126, with the exception of "=" and ';'*/
+/* writes a line of the form XXXX=YYYYY of length cookielen to outbuf, outbuf length >= cookielen */
+/* returns data consumed if success.  datalen assumed to be greater than cookielen*/
+
+
+int gen_one_cookie(unsigned char* outbuf, int cookielen, unsigned char* data, int datalen) {
+  int sofar = 0;
+  unsigned char c;
+  int namelen, vlen;
+  int data_consumed = 0;
+
+  if (cookielen < 4)
+    return -1;
+
+
+
+  if (cookielen > 13)
+    namelen = rand() % 10 + 1;
+  else 
+    namelen = rand() % (cookielen - 3) + 1;
+
+  vlen = cookielen - namelen;
+
+
+
+  while (sofar < namelen) {
+    c = rand() % (127 - 33) + 33;
+    if (c == '=' || c == ';' || c == '`' || c == '\'' || c == '%' || c == '+' || c == '{' || c == '}' ||
+	c == '<' || c == '>' || c == '?' || c == '#')
+      continue;
+
+    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (rand () % 4 != 0)) {
+      if (data_consumed < datalen) 
+	outbuf[sofar++] = data[data_consumed++];
+    }
+    else
+      outbuf[sofar++] = c;
+  }
+
+
+  outbuf[sofar++] = '=';
+
+
+  while (sofar < cookielen) {
+    c = rand() % (127 - 33) + 33;
+    if (c == '=' || c == ';' || c == '`' || c == '\'' || c == '%' || c == '+' || c == '{' || c == '}' ||
+	c == '<' || c == '>' || c == '?' || c == '#')
+      continue;
+
+
+
+    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (rand() % 4 != 0)) {
+      if (data_consumed < datalen) 
+	outbuf[sofar++] = data[data_consumed++];
+    }
+    else
+      outbuf[sofar++] = c;
+  }
+
+
+  
+  return data_consumed;
+
+}
+
+
+
+
+/* dummy version for testing */
+int gen_one_cookie2(unsigned char* outbuf, int cookielen, unsigned char* data, int datalen) {
+  int i;
+
+  if (cookielen < 4)
+    return -1;
+
+  if (datalen >= cookielen) {
+    memcpy(outbuf, data, cookielen);
+    return cookielen;
+  }
+
+  memcpy(outbuf, data, datalen);
+  for (i=datalen; i < cookielen; i++)
+    outbuf[i] = '+';
+
+  return datalen;
+
+}
+
+/* returns data consumed */
+int gen_cookie_field(unsigned char* outbuf, int total_cookie_len, unsigned char* data, int datalen) {
+  int rem_cookie_len = total_cookie_len;
+  int consumed = 0;
+
+
+  if (total_cookie_len < 4) {
+    fprintf(stderr, "error: cookie length too small\n");
+    return -1;
+  }
+
+  while (rem_cookie_len > 4) {
+    int cookielen = 4 + rand() % (rem_cookie_len - 3);
+
+    int cnt =  gen_one_cookie(outbuf, cookielen, data + consumed, datalen - consumed);
+
+    if (cnt < 0) {
+      fprintf(stderr, "error: couldn't create cookie %d\n", cnt);
+      return cnt;
+    }
+
+
+
+    consumed += cnt;
+    //    fprintf(stderr, "cnt = %d %d %d; consumed = %d\n", cnt, rem_cookie_len, cookielen, consumed);
+    rem_cookie_len = rem_cookie_len - cookielen;
+    outbuf += cookielen;
+
+
+ 
+   if (rem_cookie_len == 0) {
+      break;
+    }
+    else if (rem_cookie_len <= 5) {
+      int i = 0;
+      if ((consumed < datalen) && (consumed % 2 == 1)) {
+	outbuf[0] = data[consumed];
+	consumed++;
+	outbuf++;
+	rem_cookie_len--;
+      }
+
+      for (i=0; i < rem_cookie_len; i++) 
+	outbuf[i] = "ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ"[rand() % 40];
+      
+      return consumed;
+    }
+    
+    
+    outbuf[0] = ';';
+    outbuf++;
+    rem_cookie_len--;
+  }
+
+
+  if (consumed % 2 == 1) {
+    if ((outbuf[-1] >= '0' && outbuf[-1] <= '9') || (outbuf[-1] >= 'a' && outbuf[-1] <= 'f')) {
+      outbuf[-1] = '*';
+      consumed--;
+    }
+    else {
+      outbuf[-1] = data[consumed];
+      consumed++;
+    }	  
+  }
+
+
+  return consumed;
+}
+
+
+/* dummy version for testing */
+int gen_cookie_field2(unsigned char* outbuf, int total_cookie_len, unsigned char* data, int datalen) {
+  int i;
+  if (datalen >= total_cookie_len) {
+    memcpy(outbuf, data, total_cookie_len);
+    return total_cookie_len;
+  }
+
+  memcpy(outbuf, data, datalen);
+  for (i=datalen; i < total_cookie_len; i++)
+    outbuf[i] = '*';
+
+  return datalen;
+}
+
+
+
+
+/*
+
+int main () {
+  char outbuf[200];
+  char data[52] = "1a239023820389023802380389abc2322132321932847203aedf";
+  char data2[200];
+  //  srand(time(NULL));
+  srand (20);
+
+
+
+  int i=0;
+
+  for (i=0; i < 1000000; i++) {
+    int cookielen = rand()%50 + 5;
+    bzero(outbuf, sizeof(outbuf));
+    int len = gen_cookie_field(outbuf, cookielen, data, sizeof(data));
+    //    printf("len = %d cookie = %s %d\n", len, outbuf, cookielen);
+    bzero(data2, sizeof(data2));
+    int len2 = unwrap_cookie(outbuf, data2, cookielen);
+    //    printf("unwrapped datalen = %d data = %s\n", len, data2);
+
+    if (len != len2)
+      printf("hello %d\n", i);
+  }
+  
+
+
+
+}
+
+*/
+
+
diff --git a/src/steg/crc32.c b/src/steg/crc32.c
deleted file mode 100644
index 7fdc847..0000000
--- a/src/steg/crc32.c
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "crc32.h"
-
-#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
-
-static const unsigned int crc_c[256] = {
-	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
-	0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
-	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
-	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
-	0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
-	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
-	0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
-	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
-	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-	0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
-	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
-	0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
-	0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
-	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
-	0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
-	0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
-	0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-	0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
-	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
-	0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
-	0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
-	0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
-	0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
-	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
-	0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
-	0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
-	0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
-	0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
-	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
-	0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
-	0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
-	0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
-	0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
-	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-	0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
-	0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
-	0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
-	0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
-	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
-	0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
-	0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
-	0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-	0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
-	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
-	0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
-	0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
-	0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
-	0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
-	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
-	0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
-	0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
-	0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
-	0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
-	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
-};
-
-
-unsigned int generate_crc32c(char *buffer, size_t length) {
-  size_t i;
-  unsigned int crc32 = ~0L;
-
-  for (i = 0; i < length; i++){
-      CRC32C(crc32, (unsigned char)buffer[i]);
-  }
-  return ~crc32;
-}
-
diff --git a/src/steg/crc32.cc b/src/steg/crc32.cc
new file mode 100644
index 0000000..7fdc847
--- /dev/null
+++ b/src/steg/crc32.cc
@@ -0,0 +1,82 @@
+#include "crc32.h"
+
+#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
+
+static const unsigned int crc_c[256] = {
+	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+	0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+	0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+	0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+	0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+	0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+	0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+	0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+	0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+	0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+	0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+	0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+	0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+	0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+	0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+	0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+	0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+	0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+	0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+	0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+	0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+	0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+	0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+	0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+	0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+	0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+	0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+	0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+	0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+	0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+	0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+	0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+	0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+	0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+	0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+	0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+	0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+	0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+	0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+
+unsigned int generate_crc32c(char *buffer, size_t length) {
+  size_t i;
+  unsigned int crc32 = ~0L;
+
+  for (i = 0; i < length; i++){
+      CRC32C(crc32, (unsigned char)buffer[i]);
+  }
+  return ~crc32;
+}
+
diff --git a/src/steg/http.cc b/src/steg/http.cc
new file mode 100644
index 0000000..7377196
--- /dev/null
+++ b/src/steg/http.cc
@@ -0,0 +1,857 @@
+/*  Copyright (c) 2011, SRI International
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+    * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    Contributors: Zack Weinberg, Vinod Yegneswaran
+    See LICENSE for other credits and copying information
+*/
+
+
+
+#include "util.h"
+#include "connections.h"
+#include "steg.h"
+#include "payloads.h"
+#include "cookies.h"
+#include "swfSteg.h"
+#include "pdfSteg.h"
+#include "jsSteg.h"
+
+#include <event2/buffer.h>
+#include <stdio.h>
+
+
+
+
+
+
+#define MIN_COOKIE_SIZE 24
+#define MAX_COOKIE_SIZE 1024
+
+
+int 
+x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source);
+
+int
+lookup_peer_name_from_ip(char* p_ip, char* p_name);
+
+
+static int has_peer_name = 0;
+static char peername[512];
+
+
+struct x_http2_steg_t
+{
+  steg_t super;
+  
+  int have_transmitted;
+  int have_received;
+  int type;
+};
+
+
+STEG_DEFINE_MODULE(x_http2,
+                   1024,  /* client-server max data rate - made up */
+                   10240, /* server-client max data rate - ditto */
+                   1,     /* max concurrent connections per IP */
+                   1);     /* max concurrent IPs */
+
+
+
+
+
+
+int x_http2_client_uri_transmit (steg_t *s, struct evbuffer *source, conn_t *conn);
+int x_http2_client_cookie_transmit (steg_t *s, struct evbuffer *source, conn_t *conn);
+
+void evbuffer_dump(struct evbuffer *buf, FILE *out);
+void buf_dump(unsigned char* buf, int len, FILE *out);
+int gen_uri_field(char* uri, unsigned int uri_sz, char* data, int datalen);
+
+
+void 
+evbuffer_dump(struct evbuffer *buf, FILE *out) 
+{
+  int nextent = evbuffer_peek(buf, SSIZE_MAX, 0, 0, 0);
+  struct evbuffer_iovec v[nextent];
+  int i;
+  const unsigned char *p, *limit;
+  
+  if (evbuffer_peek(buf, -1, 0, v, nextent) != nextent)
+    abort();
+  
+  for (i = 0; i < nextent; i++) {
+    p = v[i].iov_base;
+    limit = p + v[i].iov_len;
+    
+    putc('|', out);
+    while (p < limit) {
+      if (*p < 0x20 || *p >= 0x7F || *p == '\\' || *p == '|')
+	fprintf(out, "\\x%02x", *p);
+      else
+	putc(*p, out);
+      p++;
+    }
+  }
+  putc('|', out);
+}
+
+
+
+
+
+void 
+buf_dump(unsigned char* buf, int len, FILE *out) 
+{
+  int i=0;
+  putc('|', out);
+  while (i < len) {
+    if (buf[i] < 0x20 || buf[i] >= 0x7F || buf[i] == '\\' || buf[i]== '|')
+      fprintf(out, "\\x%02x", buf[i]);
+    else
+      putc(buf[i], out);
+    i++;
+  }
+  putc('|', out);
+  putc('\n', out);
+}
+
+
+
+
+
+steg_t * 
+x_http2_new(rng_t *rng, unsigned int is_clientside)
+{
+
+  STEG_NEW(x_http2, state, rng, is_clientside);
+
+  if (is_clientside)
+    load_payloads("traces/client.out");
+  else {
+    load_payloads("traces/server.out");
+    init_JS_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, JS_MIN_AVAIL_SIZE);
+    //   init_JS_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, JS_MIN_AVAIL_SIZE, HTTP_CONTENT_HTML);
+    init_HTML_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, HTML_MIN_AVAIL_SIZE);
+    init_PDF_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, PDF_MIN_AVAIL_SIZE);
+    init_SWF_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, 0);
+  }
+
+
+  /* if there were extra stuff to fill in, you would do it here */
+  return upcast_steg(state);
+}
+
+void
+x_http2_del(steg_t *s)
+{
+  x_http2_steg_t *state = downcast_steg(s);
+
+  STEG_DEL(s);
+
+  /* if there were extra stuff to deallocate, you would do it here */
+  free(state);
+}
+
+
+// x_http2_detect determines if a packet should be processed by the http2 steg module 
+unsigned int
+x_http2_detect(conn_t *conn)
+{
+  struct evbuffer *buf = conn_get_inbound(conn);
+  unsigned char *data;
+
+  //return 0;
+/*****
+ Here is a list of HTTP response codes extracted from the server-portals.out trace
+
+7369 HTTP/1.1 200 OK
+ 470 HTTP/1.1 302 Found
+ 350 HTTP/1.1 304 Not Modified
+ 212 HTTP/1.1 302 Moved Temporarily
+ 184 HTTP/1.1 204 No Content
+ 451 HTTP/1.0 200 OK
+  36 HTTP/1.0 204 No Content
+  21 HTTP/1.1 301 Moved Permanently
+  19 HTTP/1.1 302 Object moved
+  15 HTTP/1.1 404 Not Found
+
+   7 HTTP/1.0 304 Not Modified
+   6 HTTP/1.1 302 Redirect
+   3 HTTP/1.0 200 Ok
+   2 HTTP/1.1 303 Object Moved
+   2 HTTP/1.0 301 Moved Permanently
+   2 HTTP/1.0 302 Moved Temporarily
+   2 HTTP/1.0 400 Bad request
+   2 HTTP/1.0 403 Forbidden
+   1 HTTP/1.0 404 Not Found
+   1 HTTP/1.1 200
+   1 HTTP/1.1 302 FOUND
+   1 HTTP/1.1 304
+   1 HTTP/1.1 400 Bad Request
+   1 HTTP/1.1 403 Forbidden
+   1 HTTP/1.1 503 Service Unavailable.
+ *****/
+
+  // The first part of a valid HTTP response should be of the form
+  // HTTP/1.x nnn
+
+  if (evbuffer_get_length(buf) >= 12) {
+    data = evbuffer_pullup(buf, 12);
+    
+    if (data != NULL &&
+         ((!memcmp(data, "HTTP/1.1 200", 12)) ||
+          (!memcmp(data, "HTTP/1.1 302", 12)) ||
+          (!memcmp(data, "HTTP/1.1 304", 12)) ||
+          (!memcmp(data, "HTTP/1.1 204", 12)) ||
+          (!memcmp(data, "HTTP/1.0 200", 12)) ||
+          (!memcmp(data, "HTTP/1.0 204", 12)) ||
+          (!memcmp(data, "HTTP/1.1 301", 12)) ||
+          (!memcmp(data, "HTTP/1.1 302", 12)) ||
+          (!memcmp(data, "HTTP/1.1 404", 12)))) {
+      log_debug("x_http2_detect: valid response");
+      return 1;
+    }
+  }
+
+
+
+
+
+  // SC: if we are only interested in jsSteg, we may want to
+  // consider HTTP/1.1 and HTTP/1.0 responses whose code is 200 only
+
+  // check to see if this is a valid HTTP request
+  //
+  // the following is for HTTP requests used by the http2 steg module
+  // The client always transmits "GET /" followed by at least four
+  // characters that are either lowercase hex digits or equals
+  // signs, so we need nine bytes of incoming data.
+
+
+
+  if (evbuffer_get_length(buf) >= 9) {
+    data = evbuffer_pullup(buf, 9);
+    if (data != NULL && (!memcmp(data, "GET /", 5) || !memcmp(data, "POST /", 5) || !memcmp(data, "Cookie", 6))) {
+      log_debug("x_http2_detect: valid request");
+      return 1;
+    }
+  }
+ 
+  log_debug("x_http2_detect: didn't find either HTTP request or response");
+  /* Didn't find either the client or the server pattern. */
+  return 0;
+}
+
+size_t
+x_http2_transmit_room(steg_t *s, conn_t *conn)
+{
+  unsigned int mjc;
+
+  if (downcast_steg(s)->have_transmitted)
+    /* can't send any more on this connection */
+    return 0;
+  
+
+  if (s->is_clientside) {
+    /* per http://www.boutell.com/newfaq/misc/urllength.html,
+       IE<9 can handle no more than 2048 characters in the path
+       component of a URL; we're not talking to IE, but this limit
+       means longer paths look fishy; we hex-encode the path, so
+       we have to cut the number in half. */
+    return (MIN_COOKIE_SIZE + rand() % (MAX_COOKIE_SIZE - MIN_COOKIE_SIZE)) / 4;
+    // return 1024;
+  } 
+  else {
+
+    if (!downcast_steg(s)->have_received)
+      return 0;
+
+    switch(downcast_steg(s)->type) {
+
+    case HTTP_CONTENT_SWF:
+      return 1024;
+
+    case HTTP_CONTENT_JAVASCRIPT:
+      mjc = get_max_JS_capacity() / 2;
+      if (mjc > 1024) {
+	// it should be 1024 + ...., but seems like we need to be a little bit smaller (chopper bug?)
+	int rval = 512 + rand()%(mjc - 1024);  
+	//	fprintf(stderr, "returning rval %d, mjc  %d\n", rval, mjc);
+	return rval;
+      }
+      log_warn("js capacity too small\n");
+      exit(-1);
+
+    case HTTP_CONTENT_HTML:
+      mjc = get_max_HTML_capacity() / 2;
+      if (mjc > 1024) {
+	// it should be 1024 + ...., but seems like we need to be a little bit smaller (chopper bug?)
+	int rval = 512 + rand()%(mjc - 1024);  
+	//	fprintf(stderr, "returning rval %d, mjc  %d\n", rval, mjc);
+	return rval;
+      }
+      log_warn("js capacity too small\n");
+      exit(-1);
+
+    case HTTP_CONTENT_PDF:
+      // return 1024 + rand()%(get_max_PDF_capacity() - 1024)
+      return PDF_MIN_AVAIL_SIZE;
+    }
+
+    return SIZE_MAX;
+  }
+}
+
+
+
+
+
+
+int
+lookup_peer_name_from_ip(char* p_ip, char* p_name)  {
+  struct addrinfo* ailist;
+  struct addrinfo* aip;
+  struct addrinfo hint;
+  char buf[128];
+     
+  hint.ai_flags = AI_CANONNAME;
+  hint.ai_family = 0;
+  hint.ai_socktype = 0;
+  hint.ai_protocol = 0;
+  hint.ai_addrlen = 0;
+  hint.ai_canonname = NULL;
+  hint.ai_addr = NULL;
+  hint.ai_next = NULL;
+  
+  strcpy(buf, p_ip);
+  buf[strchr(buf, ':') - buf] = 0;
+
+  
+  if (getaddrinfo(buf, NULL, &hint, &ailist)) {
+    fprintf(stderr, "error: getaddrinfo() %s\n", p_ip);
+    exit(1);
+  }
+ 
+  for (aip = ailist; aip != NULL; aip = aip->ai_next) {
+    char buf[512];
+    if (getnameinfo(aip->ai_addr, sizeof(struct sockaddr), buf, 512, NULL, 0, 0) == 0) {
+      sprintf(p_name, "%s", buf);
+      return 1;
+    }
+  }
+  
+  return 0;
+}
+
+
+
+
+
+
+
+
+int 
+x_http2_client_cookie_transmit (steg_t *s, struct evbuffer *source, conn_t *conn) {
+
+  /* On the client side, we have to embed the data in a GET query somehow;
+     the only plausible places to put it are the URL and cookies.  This
+     presently uses the URL. And it can't be binary. */
+  // struct evbuffer *scratch;
+  struct evbuffer_iovec *iv;
+  int i, nv;
+  struct evbuffer *dest = conn_get_outbound(conn);
+  size_t sbuflen = evbuffer_get_length(source);
+  char buf[10000];
+  unsigned char data[(int) sbuflen*2];
+  //  unsigned char outbuf[MAX_COOKIE_SIZE];
+
+  unsigned char outbuf[(int) sbuflen*8];
+  int datalen;
+
+
+  //  size_t sofar = 0;
+  size_t cookie_len;
+  
+
+  /* Convert all the data in 'source' to hexadecimal and write it to
+     'scratch'. Data is padded to a multiple of four characters with
+     equals signs. */
+
+
+  unsigned int len = 0;
+  unsigned int cnt = 0;
+
+
+
+  datalen = 0;    
+  cookie_len = 4 * sbuflen + rand() % 4;
+  
+
+  nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0);
+  iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
+
+  if (evbuffer_peek(source, sbuflen, NULL, iv, nv) != nv) {
+    free(iv);
+    return -1;
+  }
+
+  // retry up to 10 times
+  while (!len) {
+    len = find_client_payload(buf, sizeof(buf), TYPE_HTTP_REQUEST);
+    if (cnt++ == 10) return -1;
+  }
+
+
+  if (has_peer_name == 0 && lookup_peer_name_from_ip((char*) conn->peername, peername))
+    has_peer_name = 1;
+
+  // if (find_uri_type(buf) != HTTP_CONTENT_SWF) {
+  //   fprintf(stderr, "%s\n", buf);
+  //   exit(-1);
+  // }
+    
+
+  
+  cnt = 0;
+  
+  for (i = 0; i < nv; i++) {
+    const unsigned char *p = iv[i].iov_base;
+    const unsigned char *limit = p + iv[i].iov_len;
+    char c;
+    while (p < limit && cnt < sbuflen) {
+      c = *p++;
+      data[datalen] = "0123456789abcdef"[(c & 0xF0) >> 4];
+      data[datalen+1] = "0123456789abcdef"[(c & 0x0F) >> 0];
+      datalen += 2;
+      cnt++;
+    }
+  }
+  
+  free(iv);
+
+  if (cookie_len < 4) cookie_len = 4;
+
+  datalen = gen_cookie_field(outbuf, cookie_len, data, datalen);
+  log_debug("CLIENT: sending cookie of length = %d %d\n", datalen, (int) cookie_len);
+  //  fprintf(stderr, "CLIENT: sending cookie of length = %d %d\n", datalen, (int) cookie_len);
+
+  if (datalen < 0) {
+    log_debug("cookie generation failed\n");
+    return -1;
+  }
+
+
+  if (evbuffer_add(dest, buf, strstr(buf, "\r\n") - buf + 2)  ||  // add uri field
+      evbuffer_add(dest, "Host: ", 6) ||
+      evbuffer_add(dest, peername, strlen(peername)) ||
+      evbuffer_add(dest, strstr(buf, "\r\n"), len - (unsigned int) (strstr(buf, "\r\n") - buf))  ||  // add everything but first line
+      evbuffer_add(dest, "Cookie: ", 8) ||
+      evbuffer_add(dest, outbuf, cookie_len) ||
+      evbuffer_add(dest, "\r\n\r\n", 4)) {
+      log_debug("error ***********************");
+      return -1;
+    }
+ 
+  // debug
+  // log_warn("CLIENT HTTP request header:");
+  // buf_dump((unsigned char*)buf, len, stderr);
+ 
+  //  sofar += datalen/2;
+  evbuffer_drain(source, datalen/2);
+  
+  log_debug("CLIENT TRANSMITTED payload %d\n", (int) sbuflen);
+  
+  conn_cease_transmission(conn);
+
+  downcast_steg(s)->type = find_uri_type(buf, sizeof(buf));
+  downcast_steg(s)->have_transmitted = 1;
+  return 0;
+}
+
+
+
+
+int gen_uri_field(char* uri, unsigned int uri_sz, char* data, int datalen) {
+  unsigned int so_far = 0;
+  uri[0] = 0;
+
+  strcat(uri, "GET /");
+  so_far = 5;
+
+  while (datalen > 0) {
+    unsigned int r = rand() % 4;
+
+    if (r == 1) {
+      r = rand() % 46;
+      if (r < 20) 
+	uri[so_far++] = 'g' + r;      
+      else 
+	uri[so_far++] = 'A' + r - 20;
+    }
+    else {
+      uri[so_far++] = data[0];
+      data++;
+      datalen--;
+    }
+
+
+
+    r = rand() % 8;
+
+    if (r == 0 && datalen > 0)
+      uri[so_far++] = '/';
+
+    if (r == 2 && datalen > 0)
+      uri[so_far++] = '_';
+
+
+    if (so_far > uri_sz - 6) {
+      fprintf(stderr, "too small\n");
+      return 0;
+    }
+  }
+
+  switch(rand()%4){
+  case 1:
+    memcpy(uri+so_far, ".htm ", 6);
+    break;
+  case 2:
+    memcpy(uri+so_far, ".html ", 7);
+    break;
+  case 3:
+    memcpy(uri+so_far, ".js ", 5);
+    break;
+  case 0:
+    memcpy(uri+so_far, ".swf ", 6);
+    break;
+
+  }
+
+  return strlen(uri);
+
+}
+
+
+
+
+
+int 
+x_http2_client_uri_transmit (steg_t *s, struct evbuffer *source, conn_t *conn) {
+
+
+  struct evbuffer *dest = conn_get_outbound(conn);
+
+  
+  struct evbuffer_iovec *iv;
+  int i, nv;
+  
+  /* Convert all the data in 'source' to hexadecimal and write it to
+     'scratch'. Data is padded to a multiple of four characters with
+     equals signs. */
+  size_t slen = evbuffer_get_length(source);
+  size_t datalen = 0;
+  int cnt = 0;
+  char data[2*slen];
+  
+  char outbuf[1024];
+  int len =0;
+  char buf[10000];
+  
+  
+  if (has_peer_name == 0 && lookup_peer_name_from_ip((char*) conn->peername, peername))
+    has_peer_name = 1;
+  
+  
+
+  nv = evbuffer_peek(source, slen, NULL, NULL, 0);
+  iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
+  if (evbuffer_peek(source, slen, NULL, iv, nv) != nv) {
+    free(iv);
+    return -1;
+  }
+  
+  for (i = 0; i < nv; i++) {
+    const unsigned char *p = iv[i].iov_base;
+    const unsigned char *limit = p + iv[i].iov_len;
+    char c;
+    while (p < limit) {
+      c = *p++;
+      data[datalen++] = "0123456789abcdef"[(c & 0xF0) >> 4];
+      data[datalen++] = "0123456789abcdef"[(c & 0x0F) >> 0];
+      }
+  }
+  free(iv);
+  
+
+
+  do {
+    datalen = gen_uri_field(outbuf, sizeof(outbuf), data, datalen);
+  } while (datalen == 0);
+  
+
+
+
+  // retry up to 10 times
+  while (!len) {
+    len = find_client_payload(buf, sizeof(buf), TYPE_HTTP_REQUEST);
+    if (cnt++ == 10) return -1;
+  }
+  
+  
+  //  fprintf(stderr, "outbuf = %s\n", outbuf);
+
+  if (evbuffer_add(dest, outbuf, datalen)  ||  // add uri field
+      evbuffer_add(dest, "HTTP/1.1\r\nHost: ", 19) ||
+      evbuffer_add(dest, peername, strlen(peername)) ||
+      evbuffer_add(dest, strstr(buf, "\r\n"), len - (unsigned int) (strstr(buf, "\r\n") - buf))  ||  // add everything but first line
+      evbuffer_add(dest, "\r\n", 2)) {
+      log_debug("error ***********************");
+      return -1;
+  }
+
+
+
+  evbuffer_drain(source, slen);
+  conn_cease_transmission(conn);
+  downcast_steg(s)->type = find_uri_type(outbuf, sizeof(outbuf));
+  downcast_steg(s)->have_transmitted = 1;
+  return 0;
+ 
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+int
+x_http2_transmit(steg_t *s, struct evbuffer *source, conn_t *conn)
+{
+  //  struct evbuffer *dest = conn_get_outbound(conn);
+
+  //  fprintf(stderr, "in x_http2_ transmit %d\n", downcast_steg(s)->type);
+    
+
+
+  if (s->is_clientside) {
+        /* On the client side, we have to embed the data in a GET query somehow;
+       the only plausible places to put it are the URL and cookies.  This
+       presently uses the URL. And it can't be binary. */
+
+    if (evbuffer_get_length(source) < 72)
+      return x_http2_client_uri_transmit(s, source, conn); //@@
+    return x_http2_client_cookie_transmit(s, source, conn); //@@
+  } 
+  else {
+    int rval = -1;
+    switch(downcast_steg(s)->type) {
+      
+    case HTTP_CONTENT_SWF: 
+      rval = x_http2_server_SWF_transmit(s, source, conn);
+      break;
+
+    case HTTP_CONTENT_JAVASCRIPT:
+      rval = x_http2_server_JS_transmit(s, source, conn, HTTP_CONTENT_JAVASCRIPT);
+      break;
+
+    case HTTP_CONTENT_HTML:
+      rval = x_http2_server_JS_transmit(s, source, conn, HTTP_CONTENT_HTML);
+      break;
+
+    case HTTP_CONTENT_PDF:
+      rval = x_http2_server_PDF_transmit(s, source, conn);
+      break;
+    }
+
+    if (rval == 0) downcast_steg(s)->have_transmitted = 1;
+    return rval;
+  }
+}
+
+
+
+
+
+
+int 
+x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
+
+  int cnt = 0;
+  unsigned char* data;
+  int type;
+
+  do {
+    struct evbuffer_ptr s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
+    unsigned char *p;
+    unsigned char c, h, secondhalf;
+    char outbuf[MAX_COOKIE_SIZE];
+    int sofar = 0;
+    int cookie_mode = 0;
+
+
+    if (s2.pos == -1) {
+      log_debug("Did not find end of request %d", (int) evbuffer_get_length(source));
+      //      evbuffer_dump(source, stderr);
+      return RECV_INCOMPLETE;
+    }
+
+    log_debug("SERVER received request header of length %d", (int)s2.pos);
+
+    data = evbuffer_pullup(source, s2.pos+4);
+
+    if (data == NULL) {
+      log_debug("SERVER evbuffer_pullup fails");
+      return RECV_BAD;
+    }
+
+
+    data[s2.pos+3] = 0;
+
+    type = find_uri_type((char *)data, s2.pos+4);
+
+    if (strstr((char*) data, "Cookie") != NULL) {
+      p = (unsigned char*) strstr((char*) data, "Cookie:") + sizeof "Cookie: "-1;
+      cookie_mode = 1;
+    }
+    else
+      p = data + sizeof "GET /" -1;
+
+
+    secondhalf = 0;
+    c = 0;
+   
+
+    while (strncmp((char*) p, "\r\n", 2) != 0 && (cookie_mode != 0 || p[0] != '.')) {
+      if (!secondhalf) 
+	c = 0;
+      if ('0' <= *p && *p <= '9') 
+	h = *p - '0';
+      else if ('a' <= *p && *p <= 'f') 
+	h = *p - 'a' + 10;
+      else {
+	p++;
+	continue;
+      }
+
+      c = (c << 4) + h;
+      if (secondhalf) {
+	outbuf[sofar++] = c;
+	cnt++;
+      }
+      secondhalf = !secondhalf;
+      p++;
+    }
+
+    outbuf[sofar] = 0;
+
+    if (secondhalf) {
+      fprintf(stderr, "incorrect cookie or uri recovery \n");
+      exit(-1);
+    }
+
+
+
+    if (evbuffer_add(dest, outbuf, sofar)) {
+      log_debug("Failed to transfer buffer");
+      return RECV_BAD;
+    } 
+    evbuffer_drain(source, s2.pos + sizeof("\r\n\r\n") - 1);
+  } while (evbuffer_get_length(source));
+  
+
+  downcast_steg(s)->have_received = 1;
+  downcast_steg(s)->type = type;
+  //  fprintf(stderr, "SERVER RECEIVED payload %d %d\n", cnt, type);
+    
+  conn_transmit_soon(conn, 100);
+  return RECV_GOOD;
+}
+
+
+
+
+
+
+
+
+
+
+
+static int
+x_http2_receive(steg_t *s, conn_t *conn, struct evbuffer *dest)
+{
+  struct evbuffer *source = conn_get_inbound(conn);
+  // unsigned int type;
+  int rval = RECV_BAD;
+
+
+  if (s->is_clientside) {
+
+    //    fprintf(stderr, "client type = %d\n", downcast_steg(s)->type);
+
+    switch(downcast_steg(s)->type) {
+      
+    case HTTP_CONTENT_SWF: 
+      rval = x_http2_handle_client_SWF_receive(s, conn, dest, source);
+      break;
+
+    case HTTP_CONTENT_JAVASCRIPT:
+    case HTTP_CONTENT_HTML:
+      rval = x_http2_handle_client_JS_receive(s, conn, dest, source);
+      break;
+
+    case HTTP_CONTENT_PDF:
+      rval = x_http2_handle_client_PDF_receive(s, conn, dest, source);
+      break;
+    }
+
+    if (rval == RECV_GOOD) downcast_steg(s)->have_received = 1;
+    return rval;
+
+  } else {
+    return x_http2_server_receive(s, conn, dest, source);
+  }
+
+   
+}
diff --git a/src/steg/jsSteg.c b/src/steg/jsSteg.c
deleted file mode 100644
index 1486255..0000000
--- a/src/steg/jsSteg.c
+++ /dev/null
@@ -1,1163 +0,0 @@
-#include "payloads.h"
-#include "jsSteg.h"
-#include "cookies.h"
-
-void buf_dump(unsigned char* buf, int len, FILE *out);
-
-
-/*
- * jsSteg: A Javascript-based steganography module
- *
- */
-
-
-/*
- * int isxString(char *str)
- *
- * description:
- *   return 1 if all char in str are hexadecimal
- *   return 0 otherwise
- *
- */
-int isxString(char *str) {
-  unsigned int i;
-  char *dp = str;
-  for (i=0; i<strlen(str); i++) {
-    if (! isxdigit(*dp) ) {
-      return 0;
-    }
-  }
-  return 1;
-}
-
-
-/*
- * isGzipContent(char *msg)
- *
- * If the HTTP header of msg specifies that the content is gzipped,
- * this function returns 1; otherwise, it returns 0
- *
- * Assumptions:
- * msg is null terminated 
- *
- */
-int isGzipContent (char *msg) {
-  char *ptr = msg, *end;
-  int gzipFlag = 0;
-
-  if (!strstr(msg, "\r\n\r\n"))
-    return 0;
-
-  while (1) {
-    end = strstr(ptr, "\r\n");
-    if (end == NULL) {
-      break;
-    }
-
-    if (!strncmp(ptr, "Content-Encoding: gzip", 22)) {
-      gzipFlag = 1;
-      break;
-    }
-   
-    if (!strncmp(end, "\r\n\r\n", 4)){
-      break;
-    }
-    ptr = end+2;
-  }
-
-  return gzipFlag;
-}
-
-
-/*
- * findContentType(char *msg)
- *
- * If the HTTP header of msg specifies that the content type:
- * case (content type)
- *   javascript: return HTTP_CONTENT_JAVASCRIPT
- *   pdf:        return HTTP_CONTENT_PDF
- *   shockwave:  return HTTP_CONTENT_SWF
- *   html:       return HTTP_CONTENT_HTML
- *   otherwise:  return 0
- *
- * Assumptions:
- * msg is null terminated 
- *
- */
-int findContentType (char *msg) {
-  char *ptr = msg, *end;
-
-  if (!strstr(msg, "\r\n\r\n"))
-    return 0;
-
-  while (1) {
-    end = strstr(ptr, "\r\n");
-    if (end == NULL) {
-      break;
-    }
-
-    if (!strncmp(ptr, "Content-Type:", 13)) {
-        
-      if (!strncmp(ptr+14, "text/javascript", 15) || 
-          !strncmp(ptr+14, "application/javascript", 22) || 
-          !strncmp(ptr+14, "application/x-javascript", 24)) {
-        return HTTP_CONTENT_JAVASCRIPT;
-      }
-      if (!strncmp(ptr+14, "text/html", 9)) {
-        return HTTP_CONTENT_HTML;
-      }
-      if (!strncmp(ptr+14, "application/pdf", 15) || 
-          !strncmp(ptr+14, "application/x-pdf", 17)) {
-        return HTTP_CONTENT_PDF;
-      }
-      if (!strncmp(ptr+14, "application/x-shockwave-flash", strlen("application/x-shockwave-flash"))) {
-        return HTTP_CONTENT_SWF;
-      }
-    }
- 
-    if (!strncmp(end, "\r\n\r\n", 4)){
-      break;
-    }
-    ptr = end+2;
-  }
-
-  return 0;
-}
-
-
-
-/*
- * int encode(char *data, char *jTemplate, char *jData,
- *            unsigned int dlen, unsigned int jtlen, unsigned int jdlen)
- *
- * description:
- *   embed hex-encoded data (data) in the input Javascript (jTemplate)
- *   and put the result in jData
- *   function returns the number of characters in data successfully
- *   embedded in jData, or returns one of the error codes
- *
- * approach: 
- *   replaces characters in jTemplate that are hexadecimal (i.e., {0-9,a-f,A-F})
- *   with those in data, and leave the non-hex char in place
- *
- * input:
- *   - data[] : hex data to hide
- *   - dlen   : size of data
- *   - jTemplate[] : Javascript
- *   - jlen   : size of jTemplate
- *   - jdlen  : size of jData, output buffer
- *
- * output:
- *   - jData  : result of encoding data in jTemplate
- *
- * assumptions:
- *   - data is hex-encoded
- *
- * exceptions:
- *   - if (jdlen < jtlen) return INVALID_BUF_SIZE
- *   - if (data contains non-hex char) return INVALID_DATA_CHAR
- *
- * example:
- *   data      = "0123456789ABCDEF"
- *   jTemplate = "dfp_ord=Math.random()*10000000000000000; dfp_tile = 1;"
- *   encode() returns 16
- *   jData     = "01p_or2=M3th.r4n5om()*6789ABCDEF0000000; dfp_tile = 1;"
- *
- */
-int encode(char *data, char *jTemplate, char *jData,
-	   unsigned int dlen, unsigned int jtlen, unsigned int jdlen )
-{
-  unsigned int encCnt = 0;  /* num of data encoded in jData */
-  char *dp, *jtp, *jdp; /* current pointers for data, jTemplate, and jData */
-  
-  unsigned int j;
-
-  /* 
-   *  insanity checks
-   */
-  if (jdlen < jtlen) { return INVALID_BUF_SIZE; }
-
-  dp = data; jtp = jTemplate; jdp = jData;
-
-  if (! isxString(dp) ) { return INVALID_DATA_CHAR; }
-
-  /* handling boundary case: dlen == 0 */
-  if (dlen < 1) { return 0; }
-
-
-  for (j=0; j<jtlen; j++) {
-    /* found a hex char in jTemplate that can be used for encoding data */
-    if ( isxdigit(*jtp) ) {
-      *jdp = *dp;
-      dp++;
-      encCnt++;
-      if (encCnt == dlen) { 
-	jtp++; jdp++;
-	break; 
-      }
-    } else {
-      *jdp = *jtp;
-    }
-    jtp++; jdp++;
-  }
-
-
-  /* copying the rest of jTemplate to jdata */
-  while (jtp < (jTemplate+jtlen)) {
-    *jdp++ = *jtp++;
-  }
-
-  return encCnt;
-}
-
-
-#define startScriptTypeJS "<script type=\"text/javascript\">"
-#define endScriptTypeJS "</script>"
-// #define JS_DELIMITER "?"
-// #define JS_DELIMITER_REPLACEMENT "."
-
-
-/*
- * similar to encode(), but uses offset2Hex to look for usable hex char
- * in JS for encoding. See offset2Hex for what hex char are considered
- * usable. encode() also converts JS_DELIMITER that appears in the
- * the JS to JS_DELIMITER_REPLACEMENT, before all the data is encoded.
- *
- * Output:
- * fin - signal the caller whether all data has been encoded and 
- *       a JS_DELIMITER has been added
- */
-int  encode2(char *data, char *jTemplate, char *jData,
-	     unsigned int dlen, unsigned int jtlen,
-	     unsigned int jdlen, int *fin)
-{
-  unsigned int encCnt = 0;  /* num of data encoded in jData */
-  char *dp, *jtp, *jdp; /* current pointers for data, jTemplate, and jData */
-  int i,j;
-
-  /*
-   *  insanity checks
-   */
-  if (jdlen < jtlen) { return INVALID_BUF_SIZE; }
-
-  dp = data; jtp = jTemplate; jdp = jData;
-
-  if (! isxString(dp) ) { return INVALID_DATA_CHAR; }
-
-  /* handling boundary case: dlen == 0 */
-  if (dlen < 1) { return 0; }
-
-
-  i = offset2Hex(jtp, (jTemplate+jtlen)-jtp, 0);
-  while (encCnt < dlen && i != -1) {
-    // copy next i char from jtp to jdp,
-    // except that if *jtp==JS_DELIMITER, copy
-    // JS_DELIMITER_REPLACEMENT to jdp instead
-    j = 0;
-    while (j < i) {
-      if (*jtp == JS_DELIMITER) {
-        *jdp = JS_DELIMITER_REPLACEMENT;
-      } else {
-        *jdp = *jtp;
-      }
-      jtp = jtp + 1; jdp = jdp + 1; j++;
-    }
-
-    *jdp = *dp;
-    encCnt++;
-    dp = dp + 1; jtp = jtp + 1; jdp = jdp + 1;
-
-    i = offset2Hex(jtp, (jTemplate+jtlen)-jtp, 1);
-  }
-
-
-
-  // copy the rest of jTemplate to jdata
-  // if we've encoded all data, replace the first
-  // char in jTemplate by JS_DELIMITER, if needed,
-  // to signal the end of data encoding
-
-#ifdef DEBUG2
-  printf("encode2: encCnt = %d; dlen = %d\n", encCnt, dlen);
-#endif
-
-  *fin = 0;
-  if (encCnt == dlen) {
-    // replace the next char in jTemplate by JS_DELIMITER
-    if (jtp < (jTemplate+jtlen)) {
-      *jdp = JS_DELIMITER;
-    }
-    jdp = jdp+1; jtp = jtp+1;
-    *fin = 1;
-  }
-
-  while (jtp < (jTemplate+jtlen)) {
-    if (*jtp == JS_DELIMITER) {
-      if (encCnt < dlen) {
-        *jdp = JS_DELIMITER_REPLACEMENT;
-      } else {
-        *jdp = *jtp;
-      }
-      // else if (isxdigit(*jtp)) {
-      //   if (encCnt < dlen && *fin == 0) {
-      //     *jdp = JS_DELIMITER;
-      //     *fin = 1;
-      //   } else {
-      //     *jdp = *jtp;
-      //   }
-      // }
-    } else {
-      *jdp = *jtp;
-    }
-    jdp = jdp+1; jtp = jtp+1;
-  }
-
-#ifdef DEBUG2
-  printf("encode2: encCnt = %d; dlen = %d\n", encCnt, dlen);
-  printf("encode2: fin= %d\n", *fin);
-#endif
-
-  return encCnt;
-
-}
-
-
-
-int encodeHTTPBody(char *data, char *jTemplate, char *jData,
-		   unsigned int dlen, unsigned int jtlen,
-		   unsigned int jdlen, int mode)
-{
-  char *dp, *jtp, *jdp; // current pointers for data, jTemplate, and jData
-  unsigned int encCnt = 0;  // num of data encoded in jData
-  int n; // tmp for updating encCnt
-  char *jsStart, *jsEnd;
-  int skip;
-  int scriptLen;
-  int fin;
-  unsigned int dlen2 = dlen;
-  dp = data; 
-  jtp = jTemplate; 
-  jdp = jData;
-
-
-  if (mode == CONTENT_JAVASCRIPT) {
-    // assumption: the javascript pertaining to jTemplate has enough capacity
-    // to encode jData. thus, we only invoke encode() once here.
-    encCnt = encode2(dp, jtp, jdp, dlen, jtlen, jdlen, &fin);
-    // ensure that all dlen char from data have been encoded in jData
-#ifdef DEBUG
-    if (encCnt != dlen || fin == 0) {
-      printf("Problem encoding all data to the JS\n");
-    }
-#endif
-    return encCnt;
-
-  } 
-
-  else if (mode == CONTENT_HTML_JAVASCRIPT) {
-    while (encCnt < dlen2) {
-      jsStart = strstr(jtp, startScriptTypeJS);
-      if (jsStart == NULL) { 
-#ifdef DEBUG
-	printf("lack of usable JS; can't find startScriptType\n");
-#endif
-	return encCnt; 
-      }
-      skip = strlen(startScriptTypeJS)+jsStart-jtp;
-#ifdef DEBUG2
-      printf("copying %d (skip) char from jtp to jdp\n", skip);
-#endif
-      memcpy(jdp, jtp, skip);
-      jtp = jtp+skip; jdp = jdp+skip;
-      jsEnd = strstr(jtp, endScriptTypeJS);
-      if (jsEnd == NULL) { 
-#ifdef DEBUG
-	printf("lack of usable JS; can't find endScriptType\n");
-#endif
-	return encCnt; 
-      }
-
-      // the JS for encoding data is between jsStart and jsEnd
-      scriptLen = jsEnd - jtp;
-      // n = encode2(dp, jtp, jdp, dlen, jtlen, jdlen, &fin);
-      n = encode2(dp, jtp, jdp, dlen, scriptLen, jdlen, &fin);
-      // update encCnt, dp, and dlen based on n
-      if (n > 0) {
-	encCnt = encCnt+n; dp = dp+n; dlen = dlen-n;
-      }
-      // update jtp, jdp, jdlen
-      skip = jsEnd-jtp;
-      jtp = jtp+skip; jdp = jdp+skip; jdlen = jdlen-skip;
-      skip = strlen(endScriptTypeJS);
-      memcpy(jdp, jtp, skip);
-      jtp = jtp+skip; jdp = jdp+skip; jdlen = jdlen-skip;
-    }
-
-    // copy the rest of jTemplate to jdp
-    skip = jTemplate+jtlen-jtp;
-
-    // handling the boundary case in which JS_DELIMITER hasn't been
-    // added by encode()
-    if (fin == 0 && dlen == 0) {
-      if (skip > 0) {
-	*jtp = JS_DELIMITER;
-	jtp = jtp+1; jdp = jdp+1;
-	skip--;
-      }
-    }
-    memcpy(jdp, jtp, skip);
-    return encCnt;
-
-  } else {
-    log_warn("Unknown mode (%d) for encode2()", mode);
-    return 0;
-  }
-
-
-}
-
-/*
- * int decode(char *jData, char *dataBuf,
- *            unsigned int jdlen, unsigned int dlen, unsigned int dataBufSize)
- *
- * description:
- *   extract hex char from Javascript embedded with data (jData)
- *   and put the result in dataBuf
- *   function returns the number of hex char extracted from jData
- *   to dataBuf, or returns one of the error codes
- *
- * input:
- *   - jData[]: Javascript embedded with hex-encoded data
- *   - jdlen  : size of jData
- *   - dlen   : size of data to recover
- *   - dataBufSize : size of output data buffer (dataBuf)
- *
- * output:
- *   - dataBuf[] : output buffer for recovered data
- *
- * assumptions:
- *   - data is hex-encoded
- *
- * exceptions:
- *   - if (dlen > dataBufSize) return INVALID_BUF_SIZE
- *
- * example:
- *   jData  = "01p_or2=M3th.r4n5om()*6789ABCDEF0000000; dfp_tile = 1;"
- *   jdlen  = 54
- *   dlen   = 16
- *   dataBufSize = 1000 
- *   decode() returns 16
- *   dataBuf= "0123456789ABCDEF"
- *
- */
-int decode (char *jData, char *dataBuf, unsigned int jdlen,
-	    unsigned int dlen, unsigned int dataBufSize )
-{
-  unsigned int decCnt = 0;  /* num of data decoded */
-  char *dp, *jdp; /* current pointers for dataBuf and jData */
-  unsigned int j;
-
-  if (dlen > dataBufSize) { return INVALID_BUF_SIZE; }
-
-  dp = dataBuf; jdp = jData;
-  for (j=0; j<jdlen; j++) {
-    if ( isxdigit(*jdp) ) {
-      if (decCnt < dlen) {
-	decCnt++;
-	*dp++ = *jdp++;
-      } else {
-	break;
-      }
-    } else {
-      jdp++;
-    }
-  }
-  return decCnt;
-}
-
-
-/*
- * decode2() is similar to decode(), but uses offset2Hex to look for
- * applicable hex char in JS for decoding. Also, the decoding process
- * stops when JS_DELIMITER is encountered.
- */
-int decode2 (char *jData, char *dataBuf, unsigned int jdlen,
-	     unsigned int dataBufSize, int *fin )
-{
-  unsigned int decCnt = 0;  /* num of data decoded */
-  char *dp, *jdp; /* current pointers for dataBuf and jData */
-  int i,j;
-  int cjdlen = jdlen;
-  
-  *fin = 0;
-  dp = dataBuf; jdp = jData;
-  
-  i = offset2Hex(jdp, cjdlen, 0);
-  while (i != -1) {
-    // return if JS_DELIMITER exists between jdp and jdp+i
-    for (j=0; j<i; j++) {
-      if (*jdp == JS_DELIMITER) {
-        *fin = 1;
-        return decCnt;
-      }
-      jdp = jdp+1; cjdlen--;
-    }
-    // copy hex data from jdp to dp
-    if (dataBufSize <= 0) {
-      return decCnt;
-    }
-    *dp = *jdp;
-    jdp = jdp+1; cjdlen--;
-    dp = dp+1; dataBufSize--;
-    decCnt++;
-   
-    // find the next hex char
-    i = offset2Hex(jdp, cjdlen, 1); 
-  }
-
-  // look for JS_DELIMITER between jdp to jData+jdlen
-  while (jdp < jData+jdlen) {
-    if (*jdp == JS_DELIMITER) {
-      *fin = 1;
-      break;
-    }
-    jdp = jdp+1; 
-  }
-
-  return decCnt;
-}
-
-
-int decodeHTTPBody (char *jData, char *dataBuf, unsigned int jdlen,
-		    unsigned int dataBufSize, int *fin, int mode )
-{
-  char *jsStart, *jsEnd;
-  char *dp, *jdp; // current pointers for data and jData
-  int scriptLen;
-  int decCnt = 0;
-  int n;
-  int dlen = dataBufSize;
-  dp = dataBuf; jdp = jData; 
-
-  if (mode == CONTENT_JAVASCRIPT) {
-    decCnt = decode2(jData, dataBuf, jdlen, dataBufSize, fin);
-    if (*fin == 0) {
-      log_warn("Unable to find JS_DELIMITER");
-    }
-  } 
-  else if (mode == CONTENT_HTML_JAVASCRIPT) {
-    *fin = 0;
-    while (*fin == 0) {
-      jsStart = strstr(jdp, startScriptTypeJS);
-      if (jsStart == NULL) {
-#ifdef DEBUG
-	printf("Can't find startScriptType for decoding data inside script type JS\n");
-#endif
-        return decCnt; 
-      }
-      jdp = jsStart+strlen(startScriptTypeJS);
-      jsEnd = strstr(jdp, endScriptTypeJS);
-      if (jsEnd == NULL) { 
-#ifdef DEBUG
-	printf("Can't find endScriptType for decoding data inside script type JS\n");
-#endif
-        return decCnt; 
-      }
-
-      // the JS for decoding data is between jsStart and jsEnd
-      scriptLen = jsEnd - jdp;
-      n = decode2(jdp, dp, scriptLen, dlen, fin);
-      if (n > 0) {
-        decCnt = decCnt+n; dlen=dlen-n; dp=dp+n;
-      }
-      jdp = jsEnd+strlen(endScriptTypeJS);
-    } // while (*fin==0)
-  } else {
-    log_warn("Unknown mode (%d) for encode2()", mode);
-    return 0;
-  }
-
-  return decCnt;
-}
-
-
-
-
-
-void printerr(int errno) {
-  if (errno == INVALID_BUF_SIZE) {
-    printf ("Error: Output buffer too small\n");
-  } 
-  else if (errno == INVALID_DATA_CHAR) {
-    printf ("Error: Non-hex char in data\n");
-  } 
-  else {
-    printf ("Unknown error: %i\n", errno);
-  }
-}
-
-
-int testEncode(char *data, char *js, char *outBuf, unsigned int dlen, unsigned int jslen, 
-	       unsigned int outBufLen, int testNum) {
-  int r;
-
-  printf ("***** Start of testEncode (%i) *****\n", testNum);
-  printf ("Input:\n");
-  printf ("data         = %s\n", data);
-  printf ("data len     = %i\n", dlen);
-  printf ("js           = %s\n", js);
-  printf ("js len       = %i\n", jslen);
-  r = encode (data, js, outBuf, dlen, jslen, outBufLen);
-  if (r < 0) {
-    printerr(r);
-  } else {
-    printf ("\nOutput:\n");
-    printf ("%i char of data embedded in outBuf\n", r);
-    outBuf[jslen]    = '\0';
-    printf ("outBuf       = %s\n", outBuf);
-  }
-  printf ("***** End of testEncode (%i) *****\n", testNum);
-  return r;
-}
-
-int testDecode(char *inBuf, char *outBuf, unsigned int inBufSize, unsigned int dlen, 
-	       unsigned int outBufSize, int testNum) {
-
-  int r;
-
-  printf ("***** Start of testDecode (%i) *****\n", testNum);
-  printf ("Input:\n");
-  printf ("inBuf       = %s\n", inBuf);
-  printf ("inBuf size  = %i\n", inBufSize);
-  printf ("data len    = %i\n", dlen);
-  printf ("outBuf size = %i\n", outBufSize);
-  r = decode(inBuf, outBuf, inBufSize, dlen, outBufSize);
-  if (r < 0) {
-    printerr(r);
-  } else {
-    printf ("\nOutput:\n");
-    printf ("%i char of data recovered from inBuf (to outBuf)\n", r);
-    outBuf[r] = '\0';
-    printf ("outBuf   = %s\n", outBuf);
-  }
-  printf ("***** End of testDecode (%i) *****\n", testNum);
-  return r;
-}
-
-
-int testEncode2(char *data, char *js, char *outBuf, 
-		unsigned int dlen, unsigned int jslen, unsigned int outBufLen,
-		int mode, int testNum) {
-  int r;
-  // int fin;
-
-  printf ("***** Start of testEncode2 (%i) *****\n", testNum);
-  printf ("Input:\n");
-  printf ("data         = %s\n", data);
-  printf ("data len     = %i\n", dlen);
-  printf ("js           = %s\n", js);
-  printf ("js len       = %i\n", jslen);
-  // r = encode2(data, js, outBuf, dlen, jslen, outBufLen, &fin);
-  r = encodeHTTPBody(data, js, outBuf, dlen, jslen, outBufLen, mode);
-
-  if (r < 0) {
-    printerr(r);
-  } 
-  else {
-    printf ("\nOutput:\n");
-    printf ("%i char of data embedded in outBuf\n", r);
-    //    printf ("fin          = %d\n", fin);
-    outBuf[jslen]    = '\0';
-    printf ("outBuf       = %s\n", outBuf);
-    
-    if ((unsigned int) r < dlen) {
-      printf ("Incomplete data encoding\n");
-    }
-  }
-  printf ("***** End of testEncode (%i) *****\n", testNum);
-  return r;
-}
-
-
-
-
-int testDecode2(char *inBuf, char *outBuf, 
-	     unsigned int inBufSize, unsigned int outBufSize,
-	     int mode, int testNum) {
-  int r;
-  int fin;
-
-  printf ("***** Start of testDecode2 (%i) *****\n", testNum);
-  printf ("Input:\n");
-  printf ("inBuf       = %s\n", inBuf);
-  printf ("inBuf size  = %i\n", inBufSize);
-  printf ("outBuf size = %i\n", outBufSize);
-  r = decodeHTTPBody(inBuf, outBuf, inBufSize, outBufSize, &fin, mode);
-  if (r < 0) {
-    printerr(r);
-  } else {
-    printf ("\nOutput:\n");
-    printf ("%i char of data recovered from inBuf (to outBuf)\n", r);
-    outBuf[r] = '\0';
-    printf ("outBuf   = %s\n", outBuf);
-  }
-  printf ("***** End of testDecode2 (%i) *****\n", testNum);
-  return r;
-}
-
-
-int 
-x_http2_server_JS_transmit (steg_t* s, struct evbuffer *source, conn_t *conn, unsigned int content_type) {
-
-  struct evbuffer_iovec *iv;
-  int nv;
-  struct evbuffer *dest = conn_get_outbound(conn);
-  size_t sbuflen = evbuffer_get_length(source);
-  char *hend, *jsTemplate = NULL, *outbuf, *outbuf2;
-  char data[(int) sbuflen*2];
-  char newHdr[MAX_RESP_HDR_SIZE];
-  unsigned int datalen = 0, cnt = 0, mjs = 0;
-  int r, i, mode, jsLen, hLen, cLen, newHdrLen = 0, outbuf2len;
-  
-  int gzipMode = JS_GZIP_RESP;
-
-
-  log_debug("sbuflen = %d\n", (int) sbuflen);
-
-  if (content_type != HTTP_CONTENT_JAVASCRIPT &&
-      content_type != HTTP_CONTENT_HTML) {
-    log_warn("SERVER ERROR: Unknown content type (%d)", content_type);
-    return -1;
-  }
-
-  // log_debug("SERVER: dumping data with length %d:", (int) sbuflen);
-  // evbuffer_dump(source, stderr);
-
-  nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0);
-  iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
-
-  if (evbuffer_peek(source, sbuflen, NULL, iv, nv) != nv) {
-    free(iv);
-    return -1;
-  }
-
-  if (content_type == HTTP_CONTENT_JAVASCRIPT) {
-    mjs = get_max_JS_capacity();
-  } else if (content_type == HTTP_CONTENT_HTML) {
-    mjs = get_max_HTML_capacity();
-  }
-
-  if (mjs <= 0) {
-    log_warn("SERVER ERROR: No JavaScript found in jsTemplate");
-    return -1;
-  }
-
-  if (sbuflen > (size_t) mjs) {
-    log_warn("SERVER ERROR: jsTemplate cannot accommodate data %d %dn",
-             (int) sbuflen, (int) mjs);
-    return -1;
-  }
-    
-  // Convert data in 'source' to hexadecimal and write it to data
-  cnt = 0;
-  for (i = 0; i < nv; i++) {
-    const unsigned char *p = iv[i].iov_base;
-    const unsigned char *limit = p + iv[i].iov_len;
-    char c;
-
-    while (p < limit && cnt < sbuflen) {
-      c = *p++;
-      data[datalen] = "0123456789abcdef"[(c & 0xF0) >> 4];
-      data[datalen+1] = "0123456789abcdef"[(c & 0x0F) >> 0];
-      datalen += 2;
-      cnt++;
-    }
-  }
-
-  free(iv);
-
-  log_debug("SERVER encoded data in hex string (len %d):", datalen);
-  //    buf_dump((unsigned char*)data, datalen, stderr);
-
-
-
-  if (get_payload(content_type, datalen, &jsTemplate, &jsLen) == 1) {
-    log_debug("SERVER found the applicable HTTP response template with size %d", jsLen);
-  } else {
-    log_warn("SERVER couldn't find the applicable HTTP response template");
-    return -1;
-  }
-
-  // log_debug("MJS %d %d", datalen, mjs);
-  if (jsTemplate == NULL) {
-    log_warn("NO suitable payload found %d %d", datalen, mjs);
-    return -1;
-  }
-
-  // assumption: jsTemplate is null-terminated
-  hend = strstr(jsTemplate, "\r\n\r\n");
-  if (hend == NULL) {
-    log_warn("Unable to find end of header in the HTTP template");
-    return -1;
-  }
-
-  mode = has_eligible_HTTP_content (jsTemplate, jsLen, HTTP_CONTENT_JAVASCRIPT);
-
-  // log_debug("SERVER: using HTTP resp template of length = %d", jsLen);
-  // log_debug("HTTP resp tempmlate:");
-  // buf_dump((unsigned char*)jsTemplate, jsLen, stderr);
-
-  hLen = hend+4-jsTemplate;
-  cLen = jsLen - hLen;
-  outbuf = malloc(cLen);
-  if (outbuf == NULL) {
-    log_warn("malloc for outbuf fails");
-    return -1;
-  }
-
-  r = encodeHTTPBody(data, hend+4, outbuf, datalen, cLen, cLen, mode);
-
-  if (r < 0 || ((unsigned int) r < datalen)) {
-    log_warn("SERVER ERROR: Incomplete data encoding");
-    return -1;
-  }
-
-  // work in progress
-  if (gzipMode == 1) {
-    // conservative estimate:
-    // sizeof outbuf2 = cLen + 10-byte for gzip header + 8-byte for crc 
-    outbuf2 = malloc(cLen+18);  
-    if (outbuf2 == NULL) {
-      log_warn("malloc for outbuf2 fails");
-      return -1;
-    }
-
-    outbuf2len = gzDeflate(outbuf, cLen, outbuf2, cLen+18, time(NULL));
-
-    if (outbuf2len <= 0) {
-      log_warn("gzDeflate for outbuf fails");
-      free(outbuf2);
-      return -1;
-    }
-    free(outbuf);
-
-  } else {
-    outbuf2 = outbuf;
-    outbuf2len = cLen;
-  }
-
-  // outbuf2 points to the HTTP payload (of length outbuf2len) to be sent 
-
-  if (mode == CONTENT_JAVASCRIPT) { // JavaScript in HTTP body
-    newHdrLen = gen_response_header((char*) "application/x-javascript", gzipMode,
-                                    outbuf2len, newHdr, sizeof(newHdr));
-  } else if (mode == CONTENT_HTML_JAVASCRIPT) { // JavaScript(s) embedded in HTML doc
-    newHdrLen = gen_response_header((char*) "text/html", gzipMode,
-                                    outbuf2len, newHdr, sizeof(newHdr));
-  } else { // unknown mode
-    log_warn("SERVER ERROR: unknown mode for creating the HTTP response header");
-    free(outbuf2);
-    return -1;
-  }
-  if (newHdrLen < 0) {
-    log_warn("SERVER ERROR: gen_response_header fails for jsSteg");
-    free(outbuf2);
-    return -1;
-  }
-
-  // newHdr points to the HTTP header (of length newHdrLen) to be sent 
-
-  if (evbuffer_add(dest, newHdr, newHdrLen)) {
-    log_warn("SERVER ERROR: evbuffer_add() fails for newHdr");
-    free(outbuf2);
-    return -1;
-  }
-
-  if (evbuffer_add(dest, outbuf2, outbuf2len)) {
-    log_warn("SERVER ERROR: evbuffer_add() fails for outbuf2");
-    free(outbuf2);
-    return -1;
-  }
-
-  evbuffer_drain(source, sbuflen);
-
-  free(outbuf2);
-  conn_close_after_transmit(conn);
-  //  downcast_steg(s)->have_transmitted = 1;
-  return 0;
-}
-
-
-
-
-
-
-int
-x_http2_handle_client_JS_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
-  struct evbuffer_ptr s2;
-  unsigned int response_len = 0;
-  unsigned int content_len = 0;
-  unsigned int hdrLen;
-  char buf[10];
-  char respMsg[HTTP_MSG_BUF_SIZE];
-  char data[HTTP_MSG_BUF_SIZE];
-  char buf2[HTTP_MSG_BUF_SIZE];
-
-  unsigned char *field, *fieldStart, *fieldEnd, *fieldValStart;
-  char *httpBody;
- 
-  int decCnt, fin, i, j, k, gzipMode=0, httpBodyLen, buf2len, contentType = 0;
-  ev_ssize_t r;
-  struct evbuffer * scratch;
-  char c;
-  
-  
-  s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
-  if (s2.pos == -1) {
-    log_debug("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
-    //      evbuffer_dump(source, stderr);
-    return RECV_INCOMPLETE;
-    }
-  
-  log_debug("CLIENT received response header with len %d", (int)s2.pos);
-  
-  response_len = 0;
-  hdrLen = s2.pos + strlen("\r\n\r\n"); 
-  response_len += hdrLen;
-  
-  // get content length, e.g., Content-Length: 22417
-  field = evbuffer_pullup(source, s2.pos);
-  if (field == NULL) {
-    log_debug("CLIENT unable to pullup the complete HTTP header");
-    return RECV_BAD;
-  }
-  
-  fieldStart = (unsigned char*) strstr((char*) field, "Content-Length: ");
-  if (fieldStart == NULL) {
-    log_debug("CLIENT unable to find Content-Length in the header");
-    return RECV_BAD;
-  }
-  
-  fieldEnd = (unsigned char*) strstr((char *)fieldStart, "\r\n");
-  if (fieldEnd == NULL) {
-    log_debug("CLIENT unable to find end of line for Content-Length");
-    return RECV_BAD;
-  }
-
-  fieldValStart = fieldStart+strlen("Content-Length: ");
-  if ((unsigned int) (fieldEnd-fieldValStart) > (sizeof(buf)-1)) {
-    log_debug("CLIENT: Value of Content-Length too large");
-    return RECV_BAD;
-  }
-  memcpy(buf, fieldValStart, fieldEnd-fieldValStart);
-  buf[fieldEnd-fieldValStart] = 0;
-  
-  content_len = atoi(buf);
-  log_debug("CLIENT received Content-Length = %d\n", content_len);
-  
-  response_len += content_len;
-
-  if (response_len > evbuffer_get_length(source))
-    return RECV_INCOMPLETE;
- 
-  // read the entire HTTP resp
-  if (response_len < HTTP_MSG_BUF_SIZE) {
-    r = evbuffer_copyout(source, respMsg, response_len);
-    log_debug("CLIENT %d char copied from source to respMsg (expected %d)", (int)r, response_len);
-    if (r < 0) {
-      log_debug("CLIENT ERROR: evbuffer_copyout fails");
-      return RECV_INCOMPLETE;
-    }
-    if (r < response_len) {
-      log_debug("CLIENT: evbuffer_copyout incomplete; got %d instead of %d", (int)r, response_len);
-      return RECV_INCOMPLETE;
-    }
-    respMsg[response_len] = 0;
-  } else {
-    log_debug("CLIENT: HTTP response too large to handle");
-    return RECV_BAD;
-  }
-  
-  log_debug("CLIENT received HTTP response with length %d\n", response_len);
-  // buf_dump((unsigned char*)respMsg, response_len, stderr);
-  // log_debug("HTTP response header:");
-  // buf_dump((unsigned char*)respMsg, hdrLen+80, stderr);
- 
-  contentType = findContentType (respMsg);
-  if (contentType != HTTP_CONTENT_JAVASCRIPT && contentType != HTTP_CONTENT_HTML) {
-    log_warn("ERROR: Invalid content type (%d)", contentType);
-    return RECV_BAD;
-  }
-
-  httpBody = respMsg + hdrLen;
-  httpBodyLen = response_len - hdrLen;
-
-  gzipMode = isGzipContent(respMsg);
-  if (gzipMode) {
-    log_debug("gzip content encoding detected");
-    buf2len = gzInflate(httpBody, httpBodyLen, buf2, HTTP_MSG_BUF_SIZE);
-    if (buf2len <= 0) {
-      log_warn("gzInflate for httpBody fails");
-      fprintf(stderr, "gzInflate for httpBody fails");
-      exit(-1);
-      return RECV_BAD;
-    }
-    buf2[buf2len] = 0;
-    httpBody = buf2;
-    httpBodyLen = buf2len;
-  }
- 
-  if (contentType == HTTP_CONTENT_JAVASCRIPT) { 
-    decCnt = decodeHTTPBody(httpBody, data, httpBodyLen, HTTP_MSG_BUF_SIZE,
-                            &fin, CONTENT_JAVASCRIPT);
-  } else {
-    decCnt = decodeHTTPBody(httpBody, data, httpBodyLen, HTTP_MSG_BUF_SIZE,
-                            &fin, CONTENT_HTML_JAVASCRIPT);
-  }
-  data[decCnt] = 0;
-  
-  log_debug("After decodeHTTPBody; decCnt: %d\n", decCnt);
-
-  // decCnt is an odd number or data is not a hex string
-  if (decCnt % 2) {
-    fprintf(stderr, "CLIENT ERROR: An odd number of hex characters received\n");
-    //      buf_dump((unsigned char*)data, decCnt, stderr);
-    return RECV_BAD;
-  }
-  
-  if (! isxString(data)) {
-    log_warn("CLIENT ERROR: Data received not hex");
-    //      buf_dump((unsigned char*)data, decCnt, stderr);
-    return RECV_BAD;
-  }
-  
-  // log_debug("Hex data received:");
-  //    buf_dump ((unsigned char*)data, decCnt, stderr);
-  
-  // get a scratch buffer
-  scratch = evbuffer_new();
-  if (!scratch) return RECV_BAD;
-  
-  if (evbuffer_expand(scratch, decCnt/2)) {
-    log_warn("CLIENT ERROR: Evbuffer expand failed \n");
-    evbuffer_free(scratch);
-    return RECV_BAD;
-  }
-  
-  // convert hex data back to binary
-  for (i=0, j=0; i< decCnt; i=i+2, ++j) {
-    sscanf(&data[i], "%2x", (unsigned int*) &k);
-    c = (char)k;
-    evbuffer_add(scratch, &c, 1);
-  }
-  
-  // log_debug("CLIENT Done converting hex data to binary:\n");
-  // evbuffer_dump(scratch, stderr);
-  
- 
-  //  fprintf(stderr, "CLIENT RECEIVED payload of size %d\n", (int) evbuffer_get_length(scratch));
-  // add the scratch buffer (which contains the data) to dest
-  
-  if (evbuffer_add_buffer(dest, scratch)) {
-    evbuffer_free(scratch);
-    log_warn("CLIENT ERROR: Failed to transfer buffer");
-    return RECV_BAD;
-  }
-  log_debug("Added scratch (buffer) to dest\n");
-  
-  evbuffer_free(scratch);
-  
-  
-  if (response_len <= evbuffer_get_length(source)) {
-    if (evbuffer_drain(source, response_len) == -1) {
-      log_warn("CLIENT ERROR: Failed to drain source");
-      return RECV_BAD;
-    }
-  }
-  else {
-    log_warn("response_len > buffer size... can't drain");
-    exit(-1);
-  }
-  
-    
-  log_debug("Drained source for %d char\n", response_len);
-   
-  //  downcast_steg(s)->have_received = 1;
-  conn_expect_close(conn);
-  
-  return RECV_GOOD;
-}
-
-
-/*****
-      int
-      main() {
-      int jDataSize = 1000; 
-      char jData[jDataSize];
-      int outDataBufSize = 1000; 
-      char outDataBuf[outDataBufSize];
-
-      int r;
-      // test case 1: data embedded in javascript
-      r = testEncode2(data1, js1, jData, strlen(data1), strlen(js1), jDataSize,
-      CONTENT_JAVASCRIPT, 1); 
-      if (r > 0) { testDecode2(jData, outDataBuf, strlen(js1), outDataBufSize, CONTENT_JAVASCRIPT, 1); }
-    
-      // test case 4: data embedded in one script type javascript
-      r = testEncode2(data1, js4, jData, strlen(data1), strlen(js4), jDataSize,
-      CONTENT_HTML_JAVASCRIPT, 4); 
-      if (r > 0) { testDecode2(jData, outDataBuf, strlen(js4), outDataBufSize, CONTENT_HTML_JAVASCRIPT, 4); }
-
-      // test case 5: data embedded in one script type javascript
-      r = testEncode2(data1, js5, jData, strlen(data1), strlen(js5), jDataSize,
-      CONTENT_HTML_JAVASCRIPT, 5); 
-      if (r > 0) { testDecode2(jData, outDataBuf, strlen(js5), outDataBufSize, CONTENT_HTML_JAVASCRIPT, 5); }
-
-
-      return 0;
-      }
-*****/
-
-/*****
-      int
-      main() {
-      int jDataSize = 1000; 
-      char jData[jDataSize];
-      int jDataSmallSize = 5; 
-      char jDataSmall[jDataSmallSize];
-
-      int outDataBufSize = 1000; 
-      char outDataBuf[outDataBufSize];
-      int outDataSmallSize = 5; 
-      char outDataSmall[outDataSmallSize];
-
-      int r;
-
-      // test case 1: data embedded in javascript
-      r = testEncode(data1, js1, jData, strlen(data1), strlen(js1), jDataSize, 1); 
-      if (r > 0) { testDecode(jData, outDataBuf, strlen(js1), r, outDataBufSize, 1); }
-
-      // test case 2: data embedded in javascript
-      r = testEncode(data1, js2, jData, strlen(data1), strlen(js2), jDataSize, 2); 
-      if (r > 0) { testDecode(jData, outDataBuf, strlen(js2), r, outDataBufSize, 2); }
-
-      // test case 3: data partially embedded in javascript; num of hex char in js < data len
-      r = testEncode(data1, js3, jData, strlen(data1), strlen(js3), jDataSize, 3); 
-      if (r > 0) { testDecode(jData, outDataBuf, strlen(js3), r, outDataBufSize, 3); }
-
-      // test case 4: data embedded in javascript; larger data
-      r = testEncode(data2, js1, jData, strlen(data2), strlen(js1), jDataSize, 4); 
-      if (r > 0) { testDecode(jData, outDataBuf, strlen(js1), r, outDataBufSize, 4); }
-
-      // test case 5 (for encode): err for non-hex data
-      testEncode(nonhexstr, js1, jData, strlen(nonhexstr), strlen(js1), jDataSize, 5); 
- 
-      // test case 6 (for encode): err for small output buf
-      testEncode(data1, js1, jDataSmall, strlen(data1), strlen(js1), jDataSmallSize, 6); 
-
-      // test case 7 (for decode): err for small output buf
-      r = testEncode(data1, js1, jData, strlen(data1), strlen(js1), jDataSize, 7); 
-      if (r > 0) { testDecode(jData, outDataSmall, strlen(js1), r, outDataSmallSize, 7); }
-      }
-*****/
-
diff --git a/src/steg/jsSteg.cc b/src/steg/jsSteg.cc
new file mode 100644
index 0000000..1486255
--- /dev/null
+++ b/src/steg/jsSteg.cc
@@ -0,0 +1,1163 @@
+#include "payloads.h"
+#include "jsSteg.h"
+#include "cookies.h"
+
+void buf_dump(unsigned char* buf, int len, FILE *out);
+
+
+/*
+ * jsSteg: A Javascript-based steganography module
+ *
+ */
+
+
+/*
+ * int isxString(char *str)
+ *
+ * description:
+ *   return 1 if all char in str are hexadecimal
+ *   return 0 otherwise
+ *
+ */
+int isxString(char *str) {
+  unsigned int i;
+  char *dp = str;
+  for (i=0; i<strlen(str); i++) {
+    if (! isxdigit(*dp) ) {
+      return 0;
+    }
+  }
+  return 1;
+}
+
+
+/*
+ * isGzipContent(char *msg)
+ *
+ * If the HTTP header of msg specifies that the content is gzipped,
+ * this function returns 1; otherwise, it returns 0
+ *
+ * Assumptions:
+ * msg is null terminated 
+ *
+ */
+int isGzipContent (char *msg) {
+  char *ptr = msg, *end;
+  int gzipFlag = 0;
+
+  if (!strstr(msg, "\r\n\r\n"))
+    return 0;
+
+  while (1) {
+    end = strstr(ptr, "\r\n");
+    if (end == NULL) {
+      break;
+    }
+
+    if (!strncmp(ptr, "Content-Encoding: gzip", 22)) {
+      gzipFlag = 1;
+      break;
+    }
+   
+    if (!strncmp(end, "\r\n\r\n", 4)){
+      break;
+    }
+    ptr = end+2;
+  }
+
+  return gzipFlag;
+}
+
+
+/*
+ * findContentType(char *msg)
+ *
+ * If the HTTP header of msg specifies that the content type:
+ * case (content type)
+ *   javascript: return HTTP_CONTENT_JAVASCRIPT
+ *   pdf:        return HTTP_CONTENT_PDF
+ *   shockwave:  return HTTP_CONTENT_SWF
+ *   html:       return HTTP_CONTENT_HTML
+ *   otherwise:  return 0
+ *
+ * Assumptions:
+ * msg is null terminated 
+ *
+ */
+int findContentType (char *msg) {
+  char *ptr = msg, *end;
+
+  if (!strstr(msg, "\r\n\r\n"))
+    return 0;
+
+  while (1) {
+    end = strstr(ptr, "\r\n");
+    if (end == NULL) {
+      break;
+    }
+
+    if (!strncmp(ptr, "Content-Type:", 13)) {
+        
+      if (!strncmp(ptr+14, "text/javascript", 15) || 
+          !strncmp(ptr+14, "application/javascript", 22) || 
+          !strncmp(ptr+14, "application/x-javascript", 24)) {
+        return HTTP_CONTENT_JAVASCRIPT;
+      }
+      if (!strncmp(ptr+14, "text/html", 9)) {
+        return HTTP_CONTENT_HTML;
+      }
+      if (!strncmp(ptr+14, "application/pdf", 15) || 
+          !strncmp(ptr+14, "application/x-pdf", 17)) {
+        return HTTP_CONTENT_PDF;
+      }
+      if (!strncmp(ptr+14, "application/x-shockwave-flash", strlen("application/x-shockwave-flash"))) {
+        return HTTP_CONTENT_SWF;
+      }
+    }
+ 
+    if (!strncmp(end, "\r\n\r\n", 4)){
+      break;
+    }
+    ptr = end+2;
+  }
+
+  return 0;
+}
+
+
+
+/*
+ * int encode(char *data, char *jTemplate, char *jData,
+ *            unsigned int dlen, unsigned int jtlen, unsigned int jdlen)
+ *
+ * description:
+ *   embed hex-encoded data (data) in the input Javascript (jTemplate)
+ *   and put the result in jData
+ *   function returns the number of characters in data successfully
+ *   embedded in jData, or returns one of the error codes
+ *
+ * approach: 
+ *   replaces characters in jTemplate that are hexadecimal (i.e., {0-9,a-f,A-F})
+ *   with those in data, and leave the non-hex char in place
+ *
+ * input:
+ *   - data[] : hex data to hide
+ *   - dlen   : size of data
+ *   - jTemplate[] : Javascript
+ *   - jlen   : size of jTemplate
+ *   - jdlen  : size of jData, output buffer
+ *
+ * output:
+ *   - jData  : result of encoding data in jTemplate
+ *
+ * assumptions:
+ *   - data is hex-encoded
+ *
+ * exceptions:
+ *   - if (jdlen < jtlen) return INVALID_BUF_SIZE
+ *   - if (data contains non-hex char) return INVALID_DATA_CHAR
+ *
+ * example:
+ *   data      = "0123456789ABCDEF"
+ *   jTemplate = "dfp_ord=Math.random()*10000000000000000; dfp_tile = 1;"
+ *   encode() returns 16
+ *   jData     = "01p_or2=M3th.r4n5om()*6789ABCDEF0000000; dfp_tile = 1;"
+ *
+ */
+int encode(char *data, char *jTemplate, char *jData,
+	   unsigned int dlen, unsigned int jtlen, unsigned int jdlen )
+{
+  unsigned int encCnt = 0;  /* num of data encoded in jData */
+  char *dp, *jtp, *jdp; /* current pointers for data, jTemplate, and jData */
+  
+  unsigned int j;
+
+  /* 
+   *  insanity checks
+   */
+  if (jdlen < jtlen) { return INVALID_BUF_SIZE; }
+
+  dp = data; jtp = jTemplate; jdp = jData;
+
+  if (! isxString(dp) ) { return INVALID_DATA_CHAR; }
+
+  /* handling boundary case: dlen == 0 */
+  if (dlen < 1) { return 0; }
+
+
+  for (j=0; j<jtlen; j++) {
+    /* found a hex char in jTemplate that can be used for encoding data */
+    if ( isxdigit(*jtp) ) {
+      *jdp = *dp;
+      dp++;
+      encCnt++;
+      if (encCnt == dlen) { 
+	jtp++; jdp++;
+	break; 
+      }
+    } else {
+      *jdp = *jtp;
+    }
+    jtp++; jdp++;
+  }
+
+
+  /* copying the rest of jTemplate to jdata */
+  while (jtp < (jTemplate+jtlen)) {
+    *jdp++ = *jtp++;
+  }
+
+  return encCnt;
+}
+
+
+#define startScriptTypeJS "<script type=\"text/javascript\">"
+#define endScriptTypeJS "</script>"
+// #define JS_DELIMITER "?"
+// #define JS_DELIMITER_REPLACEMENT "."
+
+
+/*
+ * similar to encode(), but uses offset2Hex to look for usable hex char
+ * in JS for encoding. See offset2Hex for what hex char are considered
+ * usable. encode() also converts JS_DELIMITER that appears in the
+ * the JS to JS_DELIMITER_REPLACEMENT, before all the data is encoded.
+ *
+ * Output:
+ * fin - signal the caller whether all data has been encoded and 
+ *       a JS_DELIMITER has been added
+ */
+int  encode2(char *data, char *jTemplate, char *jData,
+	     unsigned int dlen, unsigned int jtlen,
+	     unsigned int jdlen, int *fin)
+{
+  unsigned int encCnt = 0;  /* num of data encoded in jData */
+  char *dp, *jtp, *jdp; /* current pointers for data, jTemplate, and jData */
+  int i,j;
+
+  /*
+   *  insanity checks
+   */
+  if (jdlen < jtlen) { return INVALID_BUF_SIZE; }
+
+  dp = data; jtp = jTemplate; jdp = jData;
+
+  if (! isxString(dp) ) { return INVALID_DATA_CHAR; }
+
+  /* handling boundary case: dlen == 0 */
+  if (dlen < 1) { return 0; }
+
+
+  i = offset2Hex(jtp, (jTemplate+jtlen)-jtp, 0);
+  while (encCnt < dlen && i != -1) {
+    // copy next i char from jtp to jdp,
+    // except that if *jtp==JS_DELIMITER, copy
+    // JS_DELIMITER_REPLACEMENT to jdp instead
+    j = 0;
+    while (j < i) {
+      if (*jtp == JS_DELIMITER) {
+        *jdp = JS_DELIMITER_REPLACEMENT;
+      } else {
+        *jdp = *jtp;
+      }
+      jtp = jtp + 1; jdp = jdp + 1; j++;
+    }
+
+    *jdp = *dp;
+    encCnt++;
+    dp = dp + 1; jtp = jtp + 1; jdp = jdp + 1;
+
+    i = offset2Hex(jtp, (jTemplate+jtlen)-jtp, 1);
+  }
+
+
+
+  // copy the rest of jTemplate to jdata
+  // if we've encoded all data, replace the first
+  // char in jTemplate by JS_DELIMITER, if needed,
+  // to signal the end of data encoding
+
+#ifdef DEBUG2
+  printf("encode2: encCnt = %d; dlen = %d\n", encCnt, dlen);
+#endif
+
+  *fin = 0;
+  if (encCnt == dlen) {
+    // replace the next char in jTemplate by JS_DELIMITER
+    if (jtp < (jTemplate+jtlen)) {
+      *jdp = JS_DELIMITER;
+    }
+    jdp = jdp+1; jtp = jtp+1;
+    *fin = 1;
+  }
+
+  while (jtp < (jTemplate+jtlen)) {
+    if (*jtp == JS_DELIMITER) {
+      if (encCnt < dlen) {
+        *jdp = JS_DELIMITER_REPLACEMENT;
+      } else {
+        *jdp = *jtp;
+      }
+      // else if (isxdigit(*jtp)) {
+      //   if (encCnt < dlen && *fin == 0) {
+      //     *jdp = JS_DELIMITER;
+      //     *fin = 1;
+      //   } else {
+      //     *jdp = *jtp;
+      //   }
+      // }
+    } else {
+      *jdp = *jtp;
+    }
+    jdp = jdp+1; jtp = jtp+1;
+  }
+
+#ifdef DEBUG2
+  printf("encode2: encCnt = %d; dlen = %d\n", encCnt, dlen);
+  printf("encode2: fin= %d\n", *fin);
+#endif
+
+  return encCnt;
+
+}
+
+
+
+int encodeHTTPBody(char *data, char *jTemplate, char *jData,
+		   unsigned int dlen, unsigned int jtlen,
+		   unsigned int jdlen, int mode)
+{
+  char *dp, *jtp, *jdp; // current pointers for data, jTemplate, and jData
+  unsigned int encCnt = 0;  // num of data encoded in jData
+  int n; // tmp for updating encCnt
+  char *jsStart, *jsEnd;
+  int skip;
+  int scriptLen;
+  int fin;
+  unsigned int dlen2 = dlen;
+  dp = data; 
+  jtp = jTemplate; 
+  jdp = jData;
+
+
+  if (mode == CONTENT_JAVASCRIPT) {
+    // assumption: the javascript pertaining to jTemplate has enough capacity
+    // to encode jData. thus, we only invoke encode() once here.
+    encCnt = encode2(dp, jtp, jdp, dlen, jtlen, jdlen, &fin);
+    // ensure that all dlen char from data have been encoded in jData
+#ifdef DEBUG
+    if (encCnt != dlen || fin == 0) {
+      printf("Problem encoding all data to the JS\n");
+    }
+#endif
+    return encCnt;
+
+  } 
+
+  else if (mode == CONTENT_HTML_JAVASCRIPT) {
+    while (encCnt < dlen2) {
+      jsStart = strstr(jtp, startScriptTypeJS);
+      if (jsStart == NULL) { 
+#ifdef DEBUG
+	printf("lack of usable JS; can't find startScriptType\n");
+#endif
+	return encCnt; 
+      }
+      skip = strlen(startScriptTypeJS)+jsStart-jtp;
+#ifdef DEBUG2
+      printf("copying %d (skip) char from jtp to jdp\n", skip);
+#endif
+      memcpy(jdp, jtp, skip);
+      jtp = jtp+skip; jdp = jdp+skip;
+      jsEnd = strstr(jtp, endScriptTypeJS);
+      if (jsEnd == NULL) { 
+#ifdef DEBUG
+	printf("lack of usable JS; can't find endScriptType\n");
+#endif
+	return encCnt; 
+      }
+
+      // the JS for encoding data is between jsStart and jsEnd
+      scriptLen = jsEnd - jtp;
+      // n = encode2(dp, jtp, jdp, dlen, jtlen, jdlen, &fin);
+      n = encode2(dp, jtp, jdp, dlen, scriptLen, jdlen, &fin);
+      // update encCnt, dp, and dlen based on n
+      if (n > 0) {
+	encCnt = encCnt+n; dp = dp+n; dlen = dlen-n;
+      }
+      // update jtp, jdp, jdlen
+      skip = jsEnd-jtp;
+      jtp = jtp+skip; jdp = jdp+skip; jdlen = jdlen-skip;
+      skip = strlen(endScriptTypeJS);
+      memcpy(jdp, jtp, skip);
+      jtp = jtp+skip; jdp = jdp+skip; jdlen = jdlen-skip;
+    }
+
+    // copy the rest of jTemplate to jdp
+    skip = jTemplate+jtlen-jtp;
+
+    // handling the boundary case in which JS_DELIMITER hasn't been
+    // added by encode()
+    if (fin == 0 && dlen == 0) {
+      if (skip > 0) {
+	*jtp = JS_DELIMITER;
+	jtp = jtp+1; jdp = jdp+1;
+	skip--;
+      }
+    }
+    memcpy(jdp, jtp, skip);
+    return encCnt;
+
+  } else {
+    log_warn("Unknown mode (%d) for encode2()", mode);
+    return 0;
+  }
+
+
+}
+
+/*
+ * int decode(char *jData, char *dataBuf,
+ *            unsigned int jdlen, unsigned int dlen, unsigned int dataBufSize)
+ *
+ * description:
+ *   extract hex char from Javascript embedded with data (jData)
+ *   and put the result in dataBuf
+ *   function returns the number of hex char extracted from jData
+ *   to dataBuf, or returns one of the error codes
+ *
+ * input:
+ *   - jData[]: Javascript embedded with hex-encoded data
+ *   - jdlen  : size of jData
+ *   - dlen   : size of data to recover
+ *   - dataBufSize : size of output data buffer (dataBuf)
+ *
+ * output:
+ *   - dataBuf[] : output buffer for recovered data
+ *
+ * assumptions:
+ *   - data is hex-encoded
+ *
+ * exceptions:
+ *   - if (dlen > dataBufSize) return INVALID_BUF_SIZE
+ *
+ * example:
+ *   jData  = "01p_or2=M3th.r4n5om()*6789ABCDEF0000000; dfp_tile = 1;"
+ *   jdlen  = 54
+ *   dlen   = 16
+ *   dataBufSize = 1000 
+ *   decode() returns 16
+ *   dataBuf= "0123456789ABCDEF"
+ *
+ */
+int decode (char *jData, char *dataBuf, unsigned int jdlen,
+	    unsigned int dlen, unsigned int dataBufSize )
+{
+  unsigned int decCnt = 0;  /* num of data decoded */
+  char *dp, *jdp; /* current pointers for dataBuf and jData */
+  unsigned int j;
+
+  if (dlen > dataBufSize) { return INVALID_BUF_SIZE; }
+
+  dp = dataBuf; jdp = jData;
+  for (j=0; j<jdlen; j++) {
+    if ( isxdigit(*jdp) ) {
+      if (decCnt < dlen) {
+	decCnt++;
+	*dp++ = *jdp++;
+      } else {
+	break;
+      }
+    } else {
+      jdp++;
+    }
+  }
+  return decCnt;
+}
+
+
+/*
+ * decode2() is similar to decode(), but uses offset2Hex to look for
+ * applicable hex char in JS for decoding. Also, the decoding process
+ * stops when JS_DELIMITER is encountered.
+ */
+int decode2 (char *jData, char *dataBuf, unsigned int jdlen,
+	     unsigned int dataBufSize, int *fin )
+{
+  unsigned int decCnt = 0;  /* num of data decoded */
+  char *dp, *jdp; /* current pointers for dataBuf and jData */
+  int i,j;
+  int cjdlen = jdlen;
+  
+  *fin = 0;
+  dp = dataBuf; jdp = jData;
+  
+  i = offset2Hex(jdp, cjdlen, 0);
+  while (i != -1) {
+    // return if JS_DELIMITER exists between jdp and jdp+i
+    for (j=0; j<i; j++) {
+      if (*jdp == JS_DELIMITER) {
+        *fin = 1;
+        return decCnt;
+      }
+      jdp = jdp+1; cjdlen--;
+    }
+    // copy hex data from jdp to dp
+    if (dataBufSize <= 0) {
+      return decCnt;
+    }
+    *dp = *jdp;
+    jdp = jdp+1; cjdlen--;
+    dp = dp+1; dataBufSize--;
+    decCnt++;
+   
+    // find the next hex char
+    i = offset2Hex(jdp, cjdlen, 1); 
+  }
+
+  // look for JS_DELIMITER between jdp to jData+jdlen
+  while (jdp < jData+jdlen) {
+    if (*jdp == JS_DELIMITER) {
+      *fin = 1;
+      break;
+    }
+    jdp = jdp+1; 
+  }
+
+  return decCnt;
+}
+
+
+int decodeHTTPBody (char *jData, char *dataBuf, unsigned int jdlen,
+		    unsigned int dataBufSize, int *fin, int mode )
+{
+  char *jsStart, *jsEnd;
+  char *dp, *jdp; // current pointers for data and jData
+  int scriptLen;
+  int decCnt = 0;
+  int n;
+  int dlen = dataBufSize;
+  dp = dataBuf; jdp = jData; 
+
+  if (mode == CONTENT_JAVASCRIPT) {
+    decCnt = decode2(jData, dataBuf, jdlen, dataBufSize, fin);
+    if (*fin == 0) {
+      log_warn("Unable to find JS_DELIMITER");
+    }
+  } 
+  else if (mode == CONTENT_HTML_JAVASCRIPT) {
+    *fin = 0;
+    while (*fin == 0) {
+      jsStart = strstr(jdp, startScriptTypeJS);
+      if (jsStart == NULL) {
+#ifdef DEBUG
+	printf("Can't find startScriptType for decoding data inside script type JS\n");
+#endif
+        return decCnt; 
+      }
+      jdp = jsStart+strlen(startScriptTypeJS);
+      jsEnd = strstr(jdp, endScriptTypeJS);
+      if (jsEnd == NULL) { 
+#ifdef DEBUG
+	printf("Can't find endScriptType for decoding data inside script type JS\n");
+#endif
+        return decCnt; 
+      }
+
+      // the JS for decoding data is between jsStart and jsEnd
+      scriptLen = jsEnd - jdp;
+      n = decode2(jdp, dp, scriptLen, dlen, fin);
+      if (n > 0) {
+        decCnt = decCnt+n; dlen=dlen-n; dp=dp+n;
+      }
+      jdp = jsEnd+strlen(endScriptTypeJS);
+    } // while (*fin==0)
+  } else {
+    log_warn("Unknown mode (%d) for encode2()", mode);
+    return 0;
+  }
+
+  return decCnt;
+}
+
+
+
+
+
+void printerr(int errno) {
+  if (errno == INVALID_BUF_SIZE) {
+    printf ("Error: Output buffer too small\n");
+  } 
+  else if (errno == INVALID_DATA_CHAR) {
+    printf ("Error: Non-hex char in data\n");
+  } 
+  else {
+    printf ("Unknown error: %i\n", errno);
+  }
+}
+
+
+int testEncode(char *data, char *js, char *outBuf, unsigned int dlen, unsigned int jslen, 
+	       unsigned int outBufLen, int testNum) {
+  int r;
+
+  printf ("***** Start of testEncode (%i) *****\n", testNum);
+  printf ("Input:\n");
+  printf ("data         = %s\n", data);
+  printf ("data len     = %i\n", dlen);
+  printf ("js           = %s\n", js);
+  printf ("js len       = %i\n", jslen);
+  r = encode (data, js, outBuf, dlen, jslen, outBufLen);
+  if (r < 0) {
+    printerr(r);
+  } else {
+    printf ("\nOutput:\n");
+    printf ("%i char of data embedded in outBuf\n", r);
+    outBuf[jslen]    = '\0';
+    printf ("outBuf       = %s\n", outBuf);
+  }
+  printf ("***** End of testEncode (%i) *****\n", testNum);
+  return r;
+}
+
+int testDecode(char *inBuf, char *outBuf, unsigned int inBufSize, unsigned int dlen, 
+	       unsigned int outBufSize, int testNum) {
+
+  int r;
+
+  printf ("***** Start of testDecode (%i) *****\n", testNum);
+  printf ("Input:\n");
+  printf ("inBuf       = %s\n", inBuf);
+  printf ("inBuf size  = %i\n", inBufSize);
+  printf ("data len    = %i\n", dlen);
+  printf ("outBuf size = %i\n", outBufSize);
+  r = decode(inBuf, outBuf, inBufSize, dlen, outBufSize);
+  if (r < 0) {
+    printerr(r);
+  } else {
+    printf ("\nOutput:\n");
+    printf ("%i char of data recovered from inBuf (to outBuf)\n", r);
+    outBuf[r] = '\0';
+    printf ("outBuf   = %s\n", outBuf);
+  }
+  printf ("***** End of testDecode (%i) *****\n", testNum);
+  return r;
+}
+
+
+int testEncode2(char *data, char *js, char *outBuf, 
+		unsigned int dlen, unsigned int jslen, unsigned int outBufLen,
+		int mode, int testNum) {
+  int r;
+  // int fin;
+
+  printf ("***** Start of testEncode2 (%i) *****\n", testNum);
+  printf ("Input:\n");
+  printf ("data         = %s\n", data);
+  printf ("data len     = %i\n", dlen);
+  printf ("js           = %s\n", js);
+  printf ("js len       = %i\n", jslen);
+  // r = encode2(data, js, outBuf, dlen, jslen, outBufLen, &fin);
+  r = encodeHTTPBody(data, js, outBuf, dlen, jslen, outBufLen, mode);
+
+  if (r < 0) {
+    printerr(r);
+  } 
+  else {
+    printf ("\nOutput:\n");
+    printf ("%i char of data embedded in outBuf\n", r);
+    //    printf ("fin          = %d\n", fin);
+    outBuf[jslen]    = '\0';
+    printf ("outBuf       = %s\n", outBuf);
+    
+    if ((unsigned int) r < dlen) {
+      printf ("Incomplete data encoding\n");
+    }
+  }
+  printf ("***** End of testEncode (%i) *****\n", testNum);
+  return r;
+}
+
+
+
+
+int testDecode2(char *inBuf, char *outBuf, 
+	     unsigned int inBufSize, unsigned int outBufSize,
+	     int mode, int testNum) {
+  int r;
+  int fin;
+
+  printf ("***** Start of testDecode2 (%i) *****\n", testNum);
+  printf ("Input:\n");
+  printf ("inBuf       = %s\n", inBuf);
+  printf ("inBuf size  = %i\n", inBufSize);
+  printf ("outBuf size = %i\n", outBufSize);
+  r = decodeHTTPBody(inBuf, outBuf, inBufSize, outBufSize, &fin, mode);
+  if (r < 0) {
+    printerr(r);
+  } else {
+    printf ("\nOutput:\n");
+    printf ("%i char of data recovered from inBuf (to outBuf)\n", r);
+    outBuf[r] = '\0';
+    printf ("outBuf   = %s\n", outBuf);
+  }
+  printf ("***** End of testDecode2 (%i) *****\n", testNum);
+  return r;
+}
+
+
+int 
+x_http2_server_JS_transmit (steg_t* s, struct evbuffer *source, conn_t *conn, unsigned int content_type) {
+
+  struct evbuffer_iovec *iv;
+  int nv;
+  struct evbuffer *dest = conn_get_outbound(conn);
+  size_t sbuflen = evbuffer_get_length(source);
+  char *hend, *jsTemplate = NULL, *outbuf, *outbuf2;
+  char data[(int) sbuflen*2];
+  char newHdr[MAX_RESP_HDR_SIZE];
+  unsigned int datalen = 0, cnt = 0, mjs = 0;
+  int r, i, mode, jsLen, hLen, cLen, newHdrLen = 0, outbuf2len;
+  
+  int gzipMode = JS_GZIP_RESP;
+
+
+  log_debug("sbuflen = %d\n", (int) sbuflen);
+
+  if (content_type != HTTP_CONTENT_JAVASCRIPT &&
+      content_type != HTTP_CONTENT_HTML) {
+    log_warn("SERVER ERROR: Unknown content type (%d)", content_type);
+    return -1;
+  }
+
+  // log_debug("SERVER: dumping data with length %d:", (int) sbuflen);
+  // evbuffer_dump(source, stderr);
+
+  nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0);
+  iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
+
+  if (evbuffer_peek(source, sbuflen, NULL, iv, nv) != nv) {
+    free(iv);
+    return -1;
+  }
+
+  if (content_type == HTTP_CONTENT_JAVASCRIPT) {
+    mjs = get_max_JS_capacity();
+  } else if (content_type == HTTP_CONTENT_HTML) {
+    mjs = get_max_HTML_capacity();
+  }
+
+  if (mjs <= 0) {
+    log_warn("SERVER ERROR: No JavaScript found in jsTemplate");
+    return -1;
+  }
+
+  if (sbuflen > (size_t) mjs) {
+    log_warn("SERVER ERROR: jsTemplate cannot accommodate data %d %dn",
+             (int) sbuflen, (int) mjs);
+    return -1;
+  }
+    
+  // Convert data in 'source' to hexadecimal and write it to data
+  cnt = 0;
+  for (i = 0; i < nv; i++) {
+    const unsigned char *p = iv[i].iov_base;
+    const unsigned char *limit = p + iv[i].iov_len;
+    char c;
+
+    while (p < limit && cnt < sbuflen) {
+      c = *p++;
+      data[datalen] = "0123456789abcdef"[(c & 0xF0) >> 4];
+      data[datalen+1] = "0123456789abcdef"[(c & 0x0F) >> 0];
+      datalen += 2;
+      cnt++;
+    }
+  }
+
+  free(iv);
+
+  log_debug("SERVER encoded data in hex string (len %d):", datalen);
+  //    buf_dump((unsigned char*)data, datalen, stderr);
+
+
+
+  if (get_payload(content_type, datalen, &jsTemplate, &jsLen) == 1) {
+    log_debug("SERVER found the applicable HTTP response template with size %d", jsLen);
+  } else {
+    log_warn("SERVER couldn't find the applicable HTTP response template");
+    return -1;
+  }
+
+  // log_debug("MJS %d %d", datalen, mjs);
+  if (jsTemplate == NULL) {
+    log_warn("NO suitable payload found %d %d", datalen, mjs);
+    return -1;
+  }
+
+  // assumption: jsTemplate is null-terminated
+  hend = strstr(jsTemplate, "\r\n\r\n");
+  if (hend == NULL) {
+    log_warn("Unable to find end of header in the HTTP template");
+    return -1;
+  }
+
+  mode = has_eligible_HTTP_content (jsTemplate, jsLen, HTTP_CONTENT_JAVASCRIPT);
+
+  // log_debug("SERVER: using HTTP resp template of length = %d", jsLen);
+  // log_debug("HTTP resp tempmlate:");
+  // buf_dump((unsigned char*)jsTemplate, jsLen, stderr);
+
+  hLen = hend+4-jsTemplate;
+  cLen = jsLen - hLen;
+  outbuf = malloc(cLen);
+  if (outbuf == NULL) {
+    log_warn("malloc for outbuf fails");
+    return -1;
+  }
+
+  r = encodeHTTPBody(data, hend+4, outbuf, datalen, cLen, cLen, mode);
+
+  if (r < 0 || ((unsigned int) r < datalen)) {
+    log_warn("SERVER ERROR: Incomplete data encoding");
+    return -1;
+  }
+
+  // work in progress
+  if (gzipMode == 1) {
+    // conservative estimate:
+    // sizeof outbuf2 = cLen + 10-byte for gzip header + 8-byte for crc 
+    outbuf2 = malloc(cLen+18);  
+    if (outbuf2 == NULL) {
+      log_warn("malloc for outbuf2 fails");
+      return -1;
+    }
+
+    outbuf2len = gzDeflate(outbuf, cLen, outbuf2, cLen+18, time(NULL));
+
+    if (outbuf2len <= 0) {
+      log_warn("gzDeflate for outbuf fails");
+      free(outbuf2);
+      return -1;
+    }
+    free(outbuf);
+
+  } else {
+    outbuf2 = outbuf;
+    outbuf2len = cLen;
+  }
+
+  // outbuf2 points to the HTTP payload (of length outbuf2len) to be sent 
+
+  if (mode == CONTENT_JAVASCRIPT) { // JavaScript in HTTP body
+    newHdrLen = gen_response_header((char*) "application/x-javascript", gzipMode,
+                                    outbuf2len, newHdr, sizeof(newHdr));
+  } else if (mode == CONTENT_HTML_JAVASCRIPT) { // JavaScript(s) embedded in HTML doc
+    newHdrLen = gen_response_header((char*) "text/html", gzipMode,
+                                    outbuf2len, newHdr, sizeof(newHdr));
+  } else { // unknown mode
+    log_warn("SERVER ERROR: unknown mode for creating the HTTP response header");
+    free(outbuf2);
+    return -1;
+  }
+  if (newHdrLen < 0) {
+    log_warn("SERVER ERROR: gen_response_header fails for jsSteg");
+    free(outbuf2);
+    return -1;
+  }
+
+  // newHdr points to the HTTP header (of length newHdrLen) to be sent 
+
+  if (evbuffer_add(dest, newHdr, newHdrLen)) {
+    log_warn("SERVER ERROR: evbuffer_add() fails for newHdr");
+    free(outbuf2);
+    return -1;
+  }
+
+  if (evbuffer_add(dest, outbuf2, outbuf2len)) {
+    log_warn("SERVER ERROR: evbuffer_add() fails for outbuf2");
+    free(outbuf2);
+    return -1;
+  }
+
+  evbuffer_drain(source, sbuflen);
+
+  free(outbuf2);
+  conn_close_after_transmit(conn);
+  //  downcast_steg(s)->have_transmitted = 1;
+  return 0;
+}
+
+
+
+
+
+
+int
+x_http2_handle_client_JS_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
+  struct evbuffer_ptr s2;
+  unsigned int response_len = 0;
+  unsigned int content_len = 0;
+  unsigned int hdrLen;
+  char buf[10];
+  char respMsg[HTTP_MSG_BUF_SIZE];
+  char data[HTTP_MSG_BUF_SIZE];
+  char buf2[HTTP_MSG_BUF_SIZE];
+
+  unsigned char *field, *fieldStart, *fieldEnd, *fieldValStart;
+  char *httpBody;
+ 
+  int decCnt, fin, i, j, k, gzipMode=0, httpBodyLen, buf2len, contentType = 0;
+  ev_ssize_t r;
+  struct evbuffer * scratch;
+  char c;
+  
+  
+  s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
+  if (s2.pos == -1) {
+    log_debug("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
+    //      evbuffer_dump(source, stderr);
+    return RECV_INCOMPLETE;
+    }
+  
+  log_debug("CLIENT received response header with len %d", (int)s2.pos);
+  
+  response_len = 0;
+  hdrLen = s2.pos + strlen("\r\n\r\n"); 
+  response_len += hdrLen;
+  
+  // get content length, e.g., Content-Length: 22417
+  field = evbuffer_pullup(source, s2.pos);
+  if (field == NULL) {
+    log_debug("CLIENT unable to pullup the complete HTTP header");
+    return RECV_BAD;
+  }
+  
+  fieldStart = (unsigned char*) strstr((char*) field, "Content-Length: ");
+  if (fieldStart == NULL) {
+    log_debug("CLIENT unable to find Content-Length in the header");
+    return RECV_BAD;
+  }
+  
+  fieldEnd = (unsigned char*) strstr((char *)fieldStart, "\r\n");
+  if (fieldEnd == NULL) {
+    log_debug("CLIENT unable to find end of line for Content-Length");
+    return RECV_BAD;
+  }
+
+  fieldValStart = fieldStart+strlen("Content-Length: ");
+  if ((unsigned int) (fieldEnd-fieldValStart) > (sizeof(buf)-1)) {
+    log_debug("CLIENT: Value of Content-Length too large");
+    return RECV_BAD;
+  }
+  memcpy(buf, fieldValStart, fieldEnd-fieldValStart);
+  buf[fieldEnd-fieldValStart] = 0;
+  
+  content_len = atoi(buf);
+  log_debug("CLIENT received Content-Length = %d\n", content_len);
+  
+  response_len += content_len;
+
+  if (response_len > evbuffer_get_length(source))
+    return RECV_INCOMPLETE;
+ 
+  // read the entire HTTP resp
+  if (response_len < HTTP_MSG_BUF_SIZE) {
+    r = evbuffer_copyout(source, respMsg, response_len);
+    log_debug("CLIENT %d char copied from source to respMsg (expected %d)", (int)r, response_len);
+    if (r < 0) {
+      log_debug("CLIENT ERROR: evbuffer_copyout fails");
+      return RECV_INCOMPLETE;
+    }
+    if (r < response_len) {
+      log_debug("CLIENT: evbuffer_copyout incomplete; got %d instead of %d", (int)r, response_len);
+      return RECV_INCOMPLETE;
+    }
+    respMsg[response_len] = 0;
+  } else {
+    log_debug("CLIENT: HTTP response too large to handle");
+    return RECV_BAD;
+  }
+  
+  log_debug("CLIENT received HTTP response with length %d\n", response_len);
+  // buf_dump((unsigned char*)respMsg, response_len, stderr);
+  // log_debug("HTTP response header:");
+  // buf_dump((unsigned char*)respMsg, hdrLen+80, stderr);
+ 
+  contentType = findContentType (respMsg);
+  if (contentType != HTTP_CONTENT_JAVASCRIPT && contentType != HTTP_CONTENT_HTML) {
+    log_warn("ERROR: Invalid content type (%d)", contentType);
+    return RECV_BAD;
+  }
+
+  httpBody = respMsg + hdrLen;
+  httpBodyLen = response_len - hdrLen;
+
+  gzipMode = isGzipContent(respMsg);
+  if (gzipMode) {
+    log_debug("gzip content encoding detected");
+    buf2len = gzInflate(httpBody, httpBodyLen, buf2, HTTP_MSG_BUF_SIZE);
+    if (buf2len <= 0) {
+      log_warn("gzInflate for httpBody fails");
+      fprintf(stderr, "gzInflate for httpBody fails");
+      exit(-1);
+      return RECV_BAD;
+    }
+    buf2[buf2len] = 0;
+    httpBody = buf2;
+    httpBodyLen = buf2len;
+  }
+ 
+  if (contentType == HTTP_CONTENT_JAVASCRIPT) { 
+    decCnt = decodeHTTPBody(httpBody, data, httpBodyLen, HTTP_MSG_BUF_SIZE,
+                            &fin, CONTENT_JAVASCRIPT);
+  } else {
+    decCnt = decodeHTTPBody(httpBody, data, httpBodyLen, HTTP_MSG_BUF_SIZE,
+                            &fin, CONTENT_HTML_JAVASCRIPT);
+  }
+  data[decCnt] = 0;
+  
+  log_debug("After decodeHTTPBody; decCnt: %d\n", decCnt);
+
+  // decCnt is an odd number or data is not a hex string
+  if (decCnt % 2) {
+    fprintf(stderr, "CLIENT ERROR: An odd number of hex characters received\n");
+    //      buf_dump((unsigned char*)data, decCnt, stderr);
+    return RECV_BAD;
+  }
+  
+  if (! isxString(data)) {
+    log_warn("CLIENT ERROR: Data received not hex");
+    //      buf_dump((unsigned char*)data, decCnt, stderr);
+    return RECV_BAD;
+  }
+  
+  // log_debug("Hex data received:");
+  //    buf_dump ((unsigned char*)data, decCnt, stderr);
+  
+  // get a scratch buffer
+  scratch = evbuffer_new();
+  if (!scratch) return RECV_BAD;
+  
+  if (evbuffer_expand(scratch, decCnt/2)) {
+    log_warn("CLIENT ERROR: Evbuffer expand failed \n");
+    evbuffer_free(scratch);
+    return RECV_BAD;
+  }
+  
+  // convert hex data back to binary
+  for (i=0, j=0; i< decCnt; i=i+2, ++j) {
+    sscanf(&data[i], "%2x", (unsigned int*) &k);
+    c = (char)k;
+    evbuffer_add(scratch, &c, 1);
+  }
+  
+  // log_debug("CLIENT Done converting hex data to binary:\n");
+  // evbuffer_dump(scratch, stderr);
+  
+ 
+  //  fprintf(stderr, "CLIENT RECEIVED payload of size %d\n", (int) evbuffer_get_length(scratch));
+  // add the scratch buffer (which contains the data) to dest
+  
+  if (evbuffer_add_buffer(dest, scratch)) {
+    evbuffer_free(scratch);
+    log_warn("CLIENT ERROR: Failed to transfer buffer");
+    return RECV_BAD;
+  }
+  log_debug("Added scratch (buffer) to dest\n");
+  
+  evbuffer_free(scratch);
+  
+  
+  if (response_len <= evbuffer_get_length(source)) {
+    if (evbuffer_drain(source, response_len) == -1) {
+      log_warn("CLIENT ERROR: Failed to drain source");
+      return RECV_BAD;
+    }
+  }
+  else {
+    log_warn("response_len > buffer size... can't drain");
+    exit(-1);
+  }
+  
+    
+  log_debug("Drained source for %d char\n", response_len);
+   
+  //  downcast_steg(s)->have_received = 1;
+  conn_expect_close(conn);
+  
+  return RECV_GOOD;
+}
+
+
+/*****
+      int
+      main() {
+      int jDataSize = 1000; 
+      char jData[jDataSize];
+      int outDataBufSize = 1000; 
+      char outDataBuf[outDataBufSize];
+
+      int r;
+      // test case 1: data embedded in javascript
+      r = testEncode2(data1, js1, jData, strlen(data1), strlen(js1), jDataSize,
+      CONTENT_JAVASCRIPT, 1); 
+      if (r > 0) { testDecode2(jData, outDataBuf, strlen(js1), outDataBufSize, CONTENT_JAVASCRIPT, 1); }
+    
+      // test case 4: data embedded in one script type javascript
+      r = testEncode2(data1, js4, jData, strlen(data1), strlen(js4), jDataSize,
+      CONTENT_HTML_JAVASCRIPT, 4); 
+      if (r > 0) { testDecode2(jData, outDataBuf, strlen(js4), outDataBufSize, CONTENT_HTML_JAVASCRIPT, 4); }
+
+      // test case 5: data embedded in one script type javascript
+      r = testEncode2(data1, js5, jData, strlen(data1), strlen(js5), jDataSize,
+      CONTENT_HTML_JAVASCRIPT, 5); 
+      if (r > 0) { testDecode2(jData, outDataBuf, strlen(js5), outDataBufSize, CONTENT_HTML_JAVASCRIPT, 5); }
+
+
+      return 0;
+      }
+*****/
+
+/*****
+      int
+      main() {
+      int jDataSize = 1000; 
+      char jData[jDataSize];
+      int jDataSmallSize = 5; 
+      char jDataSmall[jDataSmallSize];
+
+      int outDataBufSize = 1000; 
+      char outDataBuf[outDataBufSize];
+      int outDataSmallSize = 5; 
+      char outDataSmall[outDataSmallSize];
+
+      int r;
+
+      // test case 1: data embedded in javascript
+      r = testEncode(data1, js1, jData, strlen(data1), strlen(js1), jDataSize, 1); 
+      if (r > 0) { testDecode(jData, outDataBuf, strlen(js1), r, outDataBufSize, 1); }
+
+      // test case 2: data embedded in javascript
+      r = testEncode(data1, js2, jData, strlen(data1), strlen(js2), jDataSize, 2); 
+      if (r > 0) { testDecode(jData, outDataBuf, strlen(js2), r, outDataBufSize, 2); }
+
+      // test case 3: data partially embedded in javascript; num of hex char in js < data len
+      r = testEncode(data1, js3, jData, strlen(data1), strlen(js3), jDataSize, 3); 
+      if (r > 0) { testDecode(jData, outDataBuf, strlen(js3), r, outDataBufSize, 3); }
+
+      // test case 4: data embedded in javascript; larger data
+      r = testEncode(data2, js1, jData, strlen(data2), strlen(js1), jDataSize, 4); 
+      if (r > 0) { testDecode(jData, outDataBuf, strlen(js1), r, outDataBufSize, 4); }
+
+      // test case 5 (for encode): err for non-hex data
+      testEncode(nonhexstr, js1, jData, strlen(nonhexstr), strlen(js1), jDataSize, 5); 
+ 
+      // test case 6 (for encode): err for small output buf
+      testEncode(data1, js1, jDataSmall, strlen(data1), strlen(js1), jDataSmallSize, 6); 
+
+      // test case 7 (for decode): err for small output buf
+      r = testEncode(data1, js1, jData, strlen(data1), strlen(js1), jDataSize, 7); 
+      if (r > 0) { testDecode(jData, outDataSmall, strlen(js1), r, outDataSmallSize, 7); }
+      }
+*****/
+
diff --git a/src/steg/payloads.c b/src/steg/payloads.c
deleted file mode 100644
index 2b82451..0000000
--- a/src/steg/payloads.c
+++ /dev/null
@@ -1,1669 +0,0 @@
-#include "util.h"
-#include "payloads.h"
-#include "swfSteg.h"
-
-
-/* These variables below are write-once, hence they should be race-safe */
-
-static int initTypePayload[MAX_CONTENT_TYPE];
-static int typePayloadCount[MAX_CONTENT_TYPE];
-static int typePayload[MAX_CONTENT_TYPE][MAX_PAYLOADS];
-static int typePayloadCap[MAX_CONTENT_TYPE][MAX_PAYLOADS];
-
-
-static unsigned int max_JS_capacity = 0;
-static unsigned int max_HTML_capacity = 0;
-static unsigned int max_PDF_capacity = 0;
-
-
-
-pentry_header payload_hdrs[MAX_PAYLOADS];
-char* payloads[MAX_PAYLOADS];
-int payload_count = 0;
-
-
-unsigned int get_max_JS_capacity() {
-  return max_JS_capacity;
-}
-
-unsigned int get_max_HTML_capacity() {
-  return max_HTML_capacity;
-}
-
-unsigned int get_max_PDF_capacity() {
-  return max_PDF_capacity;
-}
-
-
-
-/*
- * fixContentLen corrects the Content-Length for an HTTP msg that
- * has been ungzipped, and removes the "Content-Encoding: gzip"
- * field from the header.
- *
- * The function returns -1 if no change to the HTTP msg has been made,
- * when the msg wasn't gzipped or an error has been encountered
- * If fixContentLen changes the msg header, it will put the new HTTP
- * msg in buf and returns the length of the new msg
- *
- * Input:
- * payload - pointer to the (input) HTTP msg
- * payloadLen - length of the (input) HTTP msg
- *
- * Ouptut:
- * buf - pointer to the buffer containing the new HTTP msg
- * bufLen - length of buf
- * 
- */
-int fixContentLen (char* payload, int payloadLen, char *buf, int bufLen) {
-
-  int gzipFlag=0, clFlag=0, clZeroFlag=0;
-  char* ptr = payload;
-  char* clPtr = payload;
-  char* gzipPtr = payload;
-  char* end;
-
-
-  char *cp, *clEndPtr;
-  int hdrLen, bodyLen, r, len;
-
-
-
-
-
-  // note that the ordering between the Content-Length and the Content-Encoding
-  // in an HTTP msg may be different for different msg 
-
-  // if payloadLen is larger than the size of our buffer,
-  // stop and return -1
-  if (payloadLen > bufLen) { return -1; }
-
-  while (1) {
-    end = strstr(ptr, "\r\n");
-    if (end == NULL) {
-      // log_debug("invalid header %d %d %s \n", payloadLen, (int) (ptr - payload), payload);
-      return -1;
-    }
-
-    if (!strncmp(ptr, "Content-Encoding: gzip\r\n", 24)) {
-        gzipFlag = 1;
-        gzipPtr = ptr;     
-    } else if (!strncmp(ptr, "Content-Length: 0", 17)) {
-        clZeroFlag = 1;
-    } else if (!strncmp(ptr, "Content-Length:", 15)) {
-        clFlag = 1;
-        clPtr = ptr;
-    }
-
-    if (!strncmp(end, "\r\n\r\n", 4)){
-      break;
-    }
-    ptr = end+2;
-  }
-
-  // stop if zero Content-Length or Content-Length not found
-  if (clZeroFlag || ! clFlag) return -1;
-  
-  // end now points to the end of the header, before "\r\n\r\n"
-  cp=buf;
-  bodyLen = (int)(payloadLen - (end+4-payload));
-
-  clEndPtr = strstr(clPtr, "\r\n");
-  if (clEndPtr == NULL) {
-    log_debug("unable to find end of line for Content-Length");
-    return -1;
-  }
-  if (gzipFlag && clFlag) {
-    if (gzipPtr < clPtr) { // Content-Encoding appears before Content-Length
-
-      // copy the part of the header before Content-Encoding
-      len = (int)(gzipPtr-payload);
-      memcpy(cp, payload, len);
-      cp = cp+len;
-
-      // copy the part of the header between Content-Encoding and Content-Length
-      // skip 24 char, the len of "Content-Encoding: gzip\r\n"
-      // *** this is temporary; we'll remove this after the obfsproxy can perform gzip
-      len = (int)(clPtr-(gzipPtr+24));  
-      memcpy(cp, gzipPtr+24, len);
-      cp = cp+len;
-
-      // put the new Content-Length
-      memcpy(cp, "Content-Length: ", 16);
-      cp = cp+16;
-      r = sprintf(cp, "%d\r\n", bodyLen);
-      if (r < 0) {
-        log_debug("sprintf fails");
-        return -1;
-      }
-      cp = cp+r;
-
-      // copy the part of the header after Content-Length, if any
-      if (clEndPtr != end) { // there is header info after Content-Length
-        len = (int)(end-(clEndPtr+2));
-        memcpy(cp, clEndPtr+2, len);
-        cp = cp+len;
-        memcpy(cp, "\r\n\r\n", 4);
-        cp = cp+4;
-      } else { // Content-Length is the last hdr field
-        memcpy(cp, "\r\n", 2);
-        cp = cp+2;
-      }
-
-      hdrLen = cp-buf;
-
-/****
-log_debug("orig: hdrLen = %d, bodyLen = %d, payloadLen = %d", (int)(end+4-payload), bodyLen, payloadLen);
-log_debug("new: hdrLen = %d, bodyLen = %d, payloadLen = %d", hdrLen, bodyLen, hdrLen+bodyLen);
- ****/
-
-      // copy the HTTP body
-      memcpy(cp, end+4, bodyLen);
-      return (hdrLen+bodyLen);
-
-    } else { // Content-Length before Content-Encoding
-      // copy the part of the header before Content-Length
-      len = (int)(clPtr-payload);
-      memcpy(cp, payload, len);
-      cp = cp+len;
-
-      // put the new Content-Length
-      memcpy(cp, "Content-Length: ", 16);
-      cp = cp+16;
-      r = sprintf(cp, "%d\r\n", bodyLen);
-      if (r < 0) {
-        log_debug("sprintf fails");
-        return -1;
-      }
-      cp = cp+r;
-
-      // copy the part of the header between Content-Length and Content-Encoding
-      len = (int)(gzipPtr-(clEndPtr+2));
-      memcpy(cp, clEndPtr+2, len);
-      cp = cp+len;
-      
-      // copy the part of the header after Content-Encoding
-      // skip 24 char, the len of "Content-Encoding: gzip\r\n"
-      // *** this is temporary; we'll remove this after the obfsproxy can perform gzip
-      if (end > (gzipPtr+24)) { // there is header info after Content-Encoding
-        len = (int)(end-(gzipPtr+24));
-        memcpy(cp, gzipPtr+24, len);
-        cp = cp+len;
-        memcpy(cp, "\r\n\r\n", 4);
-        cp = cp+4;
-      } else { // Content-Encoding is the last field in the hdr
-        memcpy(cp, "\r\n", 2);
-        cp = cp+2;
-      }
-      hdrLen = cp-buf;
-
-/****
-log_debug("orig: hdrLen = %d, bodyLen = %d, payloadLen = %d", (int)(end+4-payload), bodyLen, payloadLen);
-log_debug("new: hdrLen = %d, bodyLen = %d, payloadLen = %d", hdrLen, bodyLen, hdrLen+bodyLen);
- ****/
-
-      // copy the HTTP body
-      memcpy(cp, end+4, bodyLen);
-      return (hdrLen+bodyLen);
-    }
-  }
-  return -1;
-}
-
-void load_payloads(const char* fname) {
-  FILE* f;
-  char buf[HTTP_MSG_BUF_SIZE];
-  char buf2[HTTP_MSG_BUF_SIZE];
-  pentry_header pentry;
-  int pentryLen;
-  int r;
-
-  if (payload_count != 0)
-    return;
-
-  srand(time(NULL));
-  f = fopen(fname, "r");
-  if (f == NULL) {
-    fprintf(stderr, "Cannot open trace file %s. Exiting\n", fname);
-    exit(1);
-  }
-
-  bzero(payload_hdrs, sizeof(payload_hdrs));
-
-  while (payload_count < MAX_PAYLOADS) {
-
-    if (fread(&pentry, 1, sizeof(pentry_header), f) < sizeof(pentry_header)) {
-      break;
-    }
-   
-    pentryLen = ntohl(pentry.length);
-    if((unsigned int) pentryLen > sizeof(buf)) {
-#ifdef DEBUG
-      // fprintf(stderr, "pentry too big %d %d\n", pentry.length, ntohl(pentry.length));
-      fprintf(stderr, "pentry too big %d\n", pentryLen);
-#endif
-      // skip to the next pentry
-      if (fseek(f, pentryLen, SEEK_CUR)) {
-        fprintf(stderr, "skipping to next pentry fails\n");
-      }
-      continue;
-      // exit(0);
-    }
-
-    pentry.length = pentryLen;
-    pentry.ptype = ntohs(pentry.ptype);
-
-    if (fread(buf, 1, pentry.length, f) < (unsigned int) pentry.length)
-      break;
-
-    // todo:
-    // fixed content length for gzip'd HTTP msg
-    // fixContentLen returns -1, if no change to the msg
-    // otherwise, it put the new HTTP msg (with hdr changed) in buf2
-    // and returns the size of the new msg
-
-    r = -1;
-    if (pentry.ptype == TYPE_HTTP_RESPONSE) {
-      r = fixContentLen (buf, pentry.length, buf2, HTTP_MSG_BUF_SIZE);
-      // log_debug("for payload_count %d, fixContentLen returns %d", payload_count, r);
-    }
-    // else {
-    // log_debug("for payload_count %d, pentry.ptype = %d", payload_count, pentry.ptype);
-    // }
-
-    if (r < 0) {
-      payloads[payload_count] = malloc(pentry.length + 1);
-      memcpy(payloads[payload_count], buf, pentry.length);
-    } else {
-      pentry.length = r;
-      payloads[payload_count] = malloc(pentry.length + 1);
-      memcpy(payloads[payload_count], buf2, pentry.length);
-    }
-    payload_hdrs[payload_count] = pentry;
-    payloads[payload_count][pentry.length] = 0;
-    payload_count++;
-  } // while
-
-#ifdef DEBUG
-  printf("loading payload count = %d\n", payload_count);
-#endif
-  
-  fclose(f);
-}
-
-
-
-
-
-void gen_rfc_1123_date(char* buf, int buf_size) {
-  time_t t = time(NULL);
-  struct tm *my_tm = gmtime(&t);
-  strftime(buf, buf_size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", my_tm);
-}
-
-
-
-void gen_rfc_1123_expiry_date(char* buf, int buf_size) {
-  time_t t = time(NULL) + rand() % 10000;
-  struct tm *my_tm = gmtime(&t);
-  strftime(buf, buf_size, "Expires: %a, %d %b %Y %H:%M:%S GMT\r\n", my_tm);
-}
-
-
-
-
-
-int gen_response_header(char* content_type, int gzip, int length, char* buf, int buflen) {
-  char* ptr;
-
-  // conservative assumption here.... 
-  if (buflen < 400) {
-    fprintf(stderr, "gen_response_header: buflen too small\n");
-    return -1;
-  }
-
-  sprintf(buf, "HTTP/1.1 200 OK\r\n");
-  ptr = buf + strlen("HTTP/1.1 200 OK\r\n");
-  gen_rfc_1123_date(ptr, buflen - (ptr - buf));
-  ptr = ptr + strlen(ptr);
-
-  sprintf(ptr, "Server: Apache\r\n");
-  ptr = ptr + strlen(ptr);
-
-  switch(rand() % 9) {
-  case 1:
-    sprintf(ptr, "Vary: Cookie\r\n");
-    ptr = ptr + strlen(ptr);
-    break;
-
-  case 2:
-    sprintf(ptr, "Vary: Accept-Encoding, User-Agent\r\n");
-    ptr = ptr + strlen(ptr);
-    break;
-
-  case 3:
-    sprintf(ptr, "Vary: *\r\n");
-    ptr = ptr + strlen(ptr);
-    break;
-
-  }
-
-
-  switch(rand() % 4) {
-  case 2:
-    gen_rfc_1123_expiry_date(ptr, buflen - (ptr - buf));
-    ptr = ptr + strlen(ptr);
-  }
-
-
-  
-
-  if (gzip) 
-    sprintf(ptr, "Content-Length: %d\r\nContent-Encoding: gzip\r\nContent-Type: %s\r\n", length, content_type);
-  else
-    sprintf(ptr, "Content-Length: %d\r\nContent-Type: %s\r\n", length, content_type);
-    
-  ptr += strlen(ptr);
-
-  switch(rand() % 4) {
-  case 2:
-  case 3:
-  case 4:
-    sprintf(ptr, "Connection: Keep-Alive\r\n\r\n");
-    break;
-  default:
-    sprintf(ptr, "Connection: close\r\n\r\n");
-    break;    
-  }
-
-  ptr += strlen(ptr);
-
-  return ptr - buf;
-}
-
-
-
-
-
-
-int parse_client_headers(char* inbuf, char* outbuf, int len) {
-  // client-side
-  // remove Host: field
-  // remove referrer fields?
-
-  char* ptr = inbuf;
-  int outlen = 0;
-
-  while (1) {
-    // char* end = strstr(ptr, "\r\n", len - (ptr - inbuf));
-    char* end = strstr(ptr, "\r\n");
-    if (end == NULL) {
-      fprintf(stderr, "invalid client header %d %d %s \n PTR = %s\n", len, (int) (len - (ptr - inbuf)), inbuf, ptr);
-      // fprintf(stderr, "HERE %s\n", ptr);
-      break;
-    }
-
-    if (!strncmp(ptr, "Host:", 5) ||
-	!strncmp(ptr, "Referer:", 8) ||
-	!strncmp(ptr, "Cookie:", 7)) {
-      goto next;
-    }
-
-    memcpy(outbuf + outlen, ptr, end - ptr + 2);
-    outlen += end - ptr + 2;
-
-  next:
-    if (!strncmp(end, "\r\n\r\n", 4)){
-      break;
-    }
-    ptr = end+2;
-  }
-  
-  return outlen;
-
-  // server-side
-  // fix date fields
-  // fix content-length
-
-
-
-}
-
-
-
-
-/* first line is of the form....
-   GET /XX/XXXX.swf[?YYYY] HTTP/1.1\r\n
-*/
-
-
-int 
-find_uri_type(char* buf_orig, int buflen) {
-
-  char* uri;
-  char* ext;
-
-  char* buf = malloc(buflen+1);
-  char* uri_end;
-
-
-  memcpy(buf, buf_orig, buflen);
-  buf[buflen] = 0;
-
-  
-  if (strncmp(buf, "GET", 3) != 0
-      && strncmp(buf, "POST", 4) != 0) {
-    fprintf(stderr, "HERE %s\n", buf);
-    return -1;
-  }
-  
-
-
-  uri = strchr(buf, ' ') + 1;
-
-  if (uri == NULL) {
-    fprintf(stderr, "Invalid URL\n");
-    return -1;
-  }
-
-  uri_end = strchr(uri, ' ');
-
-  if (uri_end == NULL) {
-    fprintf(stderr, "unterminated uri\n");
-    return -1;
-  }
-
-  uri_end[0] = 0;
-  
-
-
-
-
-  ext = strrchr(uri, '/');
-
-  if (ext == NULL) {
-    fprintf(stderr, "no / in url: find_uri_type...");
-    return -1;
-  }
-
-  ext = strchr(ext, '.');
-
-
-  if (ext == NULL || !strncmp(ext, ".html", 5) || !strncmp(ext, ".htm", 4) || !strncmp(ext, ".php", 4)
-      || !strncmp(ext, ".jsp", 4) || !strncmp(ext, ".asp", 4))
-    return HTTP_CONTENT_HTML;
-
-
-  if (!strncmp(ext, ".js", 3) || !strncmp(ext, ".JS", 3))
-    return HTTP_CONTENT_JAVASCRIPT;
-
-  if (!strncmp(ext, ".pdf", 4) || !strncmp(ext, ".PDF", 4))
-    return HTTP_CONTENT_PDF;
-
-
-  if (!strncmp(ext, ".swf", 4) || !strncmp(ext, ".SWF", 4))
-    return HTTP_CONTENT_SWF;
-
-
-
-  free(buf);
-  return -1;
-  
-}
-
-/*
-int 
-find_uri_type(char* buf) {
-
-  char* uri;
-  int uri_len;
-  char* ext;
-
-  if (strncmp(buf, "GET", 3) != 0 && strncmp(buf, "POST", 4) != 0) 
-    return -1;
-
-  buf = strchr(buf, ' ') + 1;
-  uri_len = strchr(buf, ' ') - buf;
-  uri = malloc(uri_len + 1);
-
-  strncpy(uri, buf, uri_len);
-  uri[uri_len] = 0;
-
-  if (strchr(uri, '?'))
-    ext = strchr(uri, '?') - 4;
-  else
-    ext = uri + uri_len - 4;
-
-
-  if (!strncmp(ext, ".pdf", 4) || !strncmp(ext, ".PDF", 4))
-    return HTTP_CONTENT_PDF;
-
-  if (!strncmp(ext, ".swf", 4) || !strncmp(ext, ".SWF", 4))
-    return HTTP_CONTENT_SWF;
-
-  if (!strncmp(ext, ".js", 3) || !strncmp(ext, ".JS", 3))
-    return HTTP_CONTENT_JAVASCRIPT;
-
-  if (!strncmp(ext-1, "html", 4) || !strncmp(ext, "htm", 3) || strchr(ext-1, '.') == NULL)
-    return HTTP_CONTENT_HTML;
-
-  // default type
-  return HTTP_CONTENT_HTML;
-  // return HTTP_CONTENT_JAVASCRIPT;
-  return -1;
-  
-}
-
-*/
-
-
-
-
-
-
-
-
-unsigned int find_client_payload(char* buf, int len, int type) {
-  int r = rand() % payload_count;
-  int cnt = 0;
-  char* inbuf;
-
-#ifdef DEBUG
-  fprintf(stderr, "TRYING payload %d \n", r);
-#endif
-  while (1) {
-    pentry_header* p = &payload_hdrs[r];
-    if (p->ptype == type) {
-      inbuf = payloads[r];
-      if (find_uri_type(inbuf, p->length) != HTTP_CONTENT_SWF &&
-          find_uri_type(inbuf, p->length) != HTTP_CONTENT_HTML &&
-	  find_uri_type(inbuf, p->length) != HTTP_CONTENT_JAVASCRIPT &&
-	  find_uri_type(inbuf, p->length) != HTTP_CONTENT_PDF) {
-	goto next;
-      }
-      if (p->length > len) {
-	fprintf(stderr, "BUFFER TOO SMALL... \n");
-	goto next;
-      }
-      else
-	len = p->length;
-      break;
-    }
-  next:
-    r = (r+1) % payload_count;
-    
-
-    // no matching payloads...
-    if (cnt++ == payload_count) {
-      fprintf(stderr, "NO MATCHING PAYLOADS... \n");
-      return 0;
-    }
-  }
-
-  inbuf[len] = 0;
-
-  // clean up the buffer...
-  return parse_client_headers(inbuf, buf, len);
-  
-}
-
-
-/*
- * skipJSPattern returns the number of characters to skip when
- * the input pointer matches the start of a common JavaScript
- * keyword 
- *
- * todo: 
- * Use a more efficient regular expression matching algo
- */
-
-
-
-int skipJSPattern(char *cp, int len) {
-  int i,j;
-
-
-  char keywords [21][10]= {"function", "return", "var", "int", "random", "Math", "while",
-			   "else", "for", "document", "write", "writeln", "true",
-			   "false", "True", "False", "window", "indexOf", "navigator", "case", "if"};
-
-
-  if (len < 1) return 0;
-
-  // change the limit to 21 to enable if as a keyword
-  for (i=0; i < 20; i++) {
-    char* word = keywords[i];
-    
-    if (len <= (int) strlen(word))
-      continue;
-
-    if (word[0] != cp[0])
-      continue;
-
-    for (j=1; j < (int) strlen(word); j++) {
-      if (isxdigit(word[j])) {
-	if (!isxdigit(cp[j]))
-	  goto next_word;
-	else
-	  continue;
-      }
-      
-      if (cp[j] != word[j])
-	goto next_word;
-    }
-    if (!isalnum(cp[j]))
-      return strlen(word)+1;
-      
-  next_word:
-    continue;
-  }
-
-  return 0;
-}
-
-
-
-
-/* int skipJSPattern (char *cp, int len) { */
-
-/*   // log_debug("Turning off skipJSPattern for debugging"); */
-/*   //  return 0; */
-
-/*   if (len < 1) return 0; */
-
-/*   if (len > 8) { */
-/*     // "function " and "function(" */
-/*     if (cp[0] == 'f' && */
-/*         !strncmp(cp+1, "un", 2) && */
-/*         isxdigit(cp[3]) && */
-/*         !strncmp(cp+4, "tion", 4) && */
-/*         (cp[8] == ' ' || cp[8] == '(')) */
-/*     return 9; */
-/*   } */
-
-/*   if (len > 6) { */
-/*     // "return " */
-/*     if (cp[0] == 'r' && */
-/*         isxdigit(cp[1]) && */
-/*         !strncmp(cp+2, "turn ", 5))  */
-/*     return 7; */
-/*     // "switch " */
-/*     if (cp[0] == 's' && */
-/*         !strncmp(cp+1, "wit", 3) && */
-/*         isxdigit(cp[4]) && */
-/*         !strncmp(cp+5, "h ", 2))  */
-/*     return 7; */
-/*   } */
-
-/*   if (len > 5) { */
-/*     // "while " and "while(" */
-/*     if (cp[0] == 'w' && */
-/*         !strncmp(cp+1, "hil", 3) && */
-/*         isxdigit(cp[4]) && */
-/*         (cp[5] == ' ' || cp[5] == '(')) */
-/*     return 6; */
-/*   } */
-
-/*   if (len > 4) { */
-/*     // "else " and "else{" */
-/*     if (cp[0] == 'e' && */
-/*         !strncmp(cp, "ls", 2) && */
-/*         isxdigit(cp[3]) && */
-/*         (cp[4] == ' ' || cp[4] == '{')) */
-/*     return 5; */
-/*   } */
-
-/*   if (len > 3) { */
-/*     // "var " */
-/*     if (cp[0] == 'v' && */
-/*         isxdigit(cp[1]) && */
-/*         cp[2] == 'r' && */
-/*         cp[3] == ' ') */
-/*     return 4; */
-/*   } */
-
-/*   return 0; */
-/* } */
-
-
-
-int isalnum_ (char c) {
-  if (isalnum(c) || c == '_') return 1;
-  else return 0;
-}
-
-int offset2Alnum_ (char *p, int range) {
-  char *cp = p;
-
-  while ((cp < (p+range)) && !isalnum_(*cp)) {
-    cp++;
-  }
-
-  if (cp < (p+range)) {
-    return (cp-p);
-  } else {
-    return -1;
-  }
-}
-
-
-
-/*
- * offset2Hex returns the offset to the next usable hex char.
- * usable here refer to char that our steg module can use to encode
- * data. in particular, words that correspond to common JavaScript keywords
- * are not used for data encoding (see skipJSPattern). Also, because
- * JS var name must start with an underscore or a letter (but not a digit)
- * we don't use the first char of a word for encoding data
- *
- * e.g., the JS statement "var a;" won't be used for encoding data
- * because "var" is a common JS keyword and "a" is the first char of a word
- *
- * Input:
- * p - ptr to the starting pos 
- * range - max number of char to look
- * isLastCharHex - is the char pointed to by (p-1) a hex char 
- *
- * Output:
- * offset2Hex returns the offset to the next usable hex char
- * between p and (p+range), if it exists;
- * otherwise, it returns -1
- *
- */
-int offset2Hex (char *p, int range, int isLastCharHex) {
-  char *cp = p;
-  int i,j;
-  int isFirstWordChar = 1;
-
-  if (range < 1) return -1;
-
-  // case 1: last char is hexadecimal
-  if (isLastCharHex) {
-    if (isxdigit(*cp)) return 0; // base case
-    else {
-      while (cp < (p+range) && isalnum_(*cp)) {
-        cp++;
-        if (isxdigit(*cp)) return (cp-p);
-      }
-      if (cp >= (p+range)) return -1;
-      // non-alnum_ found
-      // fallthru and handle case 2
-    }
-  }
- 
-  // case 2:
-  // find the next word that starts with alnum or underscore,
-  // which could be a variable, keyword, or literal inside a string
-
-  i = offset2Alnum_(cp, p+range-cp);
-  if (i == -1) return -1;
-
-  while (cp < (p+range) && i != -1) {
-
-    if (i == 0) { 
-      if (isFirstWordChar) {
-        j = skipJSPattern(cp, p+range-cp); 
-        if (j > 0) {
-          cp = cp+j;
-        } else {
-          cp++; isFirstWordChar = 0; // skip the 1st char of a word
-        }
-      } else { // we are in the middle of a word; no need to invoke skipJSPattern
-        if (isxdigit(*cp)) return (cp-p);
-        if (! isalnum_(*cp)) {
-          isFirstWordChar = 1;
-        }
-        cp++;
-     }
-   } else {
-     cp += i; isFirstWordChar = 1;
-   }
-   i = offset2Alnum_(cp, p+range-cp);
-
-  } // while
-
-  // cannot find next usable hex char 
-  return -1;
- 
-}
-
-/*
- * capacityJS3 is the next iteration for capacityJS
- */
-unsigned int capacityJS3 (char* buf, int len, int mode) {
-  char *hEnd, *bp, *jsStart, *jsEnd;
-  int cnt=0;
-  int j;
-
-  // jump to the beginning of the body of the HTTP message
-  hEnd = strstr(buf, "\r\n\r\n");
-  if (hEnd == NULL) {
-    // cannot find the separator between HTTP header and HTTP body
-    return 0;
-  }
-  bp = hEnd + 4;
-
-
-  if (mode == CONTENT_JAVASCRIPT) {
-    j = offset2Hex(bp, (buf+len)-bp, 0);
-    while (j != -1) {
-      cnt++;
-      if (j == 0) {
-        bp = bp+1;
-      } else {
-        bp = bp+j+1;
-      }
-
-      if (len < buf + len - bp) {
-	fprintf(stderr, "HERE\n");
-      }
-      j = offset2Hex(bp, (buf+len)-bp, 1);
-    } // while
-    return cnt;
-  } else if (mode == CONTENT_HTML_JAVASCRIPT) {
-     while (bp < (buf+len)) {
-       jsStart = strstr(bp, "<script type=\"text/javascript\">");
-       if (jsStart == NULL) break;
-       bp = jsStart+31;
-       jsEnd = strstr(bp, "</script>");
-       if (jsEnd == NULL) break;
-       // count the number of usable hex char between jsStart+31 and jsEnd
-
-       j = offset2Hex(bp, jsEnd-bp, 0);
-       while (j != -1) {
-         cnt++;
-         if (j == 0) {
-           bp = bp+1;
-         } else {
-           bp = bp+j+1;
-         }
-
-	 if (len < jsEnd - buf || len < jsEnd - bp) {
-	   fprintf(stderr, "HERE2\n");
-	 }
-
-
-         j = offset2Hex(bp, jsEnd-bp, 1);
-       } // while (j != -1)
-
-       if (buf + len < bp + 9) {
-	 fprintf(stderr, "HERE3\n");
-       }
-
-
-       bp += 9;
-     } // while (bp < (buf+len))
-     return cnt;
-  } else {
-    fprintf(stderr, "Unknown mode (%d) for capacityJS() ... \n", mode);
-    return 0;
-  }
-}
-
-
-/*
- * strInBinary looks for char array pattern of length patternLen in a char array
- * blob of length blobLen
- *
- * return a pointer for the first occurrence of pattern in blob, if found
- * otherwise, return NULL
- * 
- */
-char *
-strInBinary (const char *pattern, unsigned int patternLen, 
-             const char *blob, unsigned int blobLen) {
-  int found = 0;
-  char *cp = (char *)blob;
-
-  while (1) {
-    if (blob+blobLen-cp < patternLen) break;
-    if (*cp == pattern[0]) {
-      if (memcmp(cp, pattern, patternLen) == 0) {
-        found = 1;
-        break;
-      }
-    }
-    cp++; 
-  }
-  if (found) return cp;
-  else return NULL;
-}
-
-
-/*
- * has_eligible_HTTP_content() identifies if the input HTTP message 
- * contains a specified type of content, used by a steg module to
- * select candidate HTTP message as cover traffic
- */
-
-// for JavaScript, there are two cases:
-// 1) If Content-Type: has one of the following values
-//       text/javascript 
-//       application/x-javascript
-//       application/javascript
-// 2) Content-Type: text/html and 
-//    HTTP body contains <script type="text/javascript"> ... </script>
-// #define CONTENT_JAVASCRIPT		1 (for case 1)
-// #define CONTENT_HTML_JAVASCRIPT	2 (for case 2)
-//
-// for pdf, we look for the msgs whose Content-Type: has one of the
-// following values
-// 1) application/pdf
-// 2) application/x-pdf
-// 
-
-int has_eligible_HTTP_content (char* buf, int len, int type) {
-  char* ptr = buf;
-  char* matchptr;
-  int tjFlag=0, thFlag=0, ceFlag=0, teFlag=0, http304Flag=0, clZeroFlag=0, pdfFlag=0, swfFlag=0, gzipFlag=0;
-  char* end, *cp;
-
-#ifdef DEBUG
-  fprintf(stderr, "TESTING availabilty of js in payload ... \n");
-#endif
-
-  if (type != HTTP_CONTENT_JAVASCRIPT &&
-      type != HTTP_CONTENT_HTML &&
-      type != HTTP_CONTENT_PDF && type != HTTP_CONTENT_SWF)
-    return 0;
-
-  // assumption: buf is null-terminated
-  if (!strstr(buf, "\r\n\r\n"))
-    return 0;
-
-
-  while (1) {
-    end = strstr(ptr, "\r\n");
-    if (end == NULL) {
-      break;
-    }
-
-    if (!strncmp(ptr, "Content-Type:", 13)) {
-	
-      if (!strncmp(ptr+14, "text/javascript", 15) || 
-	  !strncmp(ptr+14, "application/javascript", 22) || 
-	  !strncmp(ptr+14, "application/x-javascript", 24)) {
-	tjFlag = 1;
-      }
-      if (!strncmp(ptr+14, "text/html", 9)) {
-	thFlag = 1;
-      }
-      if (!strncmp(ptr+14, "application/pdf", 15) || 
-	  !strncmp(ptr+14, "application/x-pdf", 17)) {
-	pdfFlag = 1;
-      }
-      if (!strncmp(ptr+14, "application/x-shockwave-flash", strlen("application/x-shockwave-flash"))) {
-	swfFlag = 1;
-      }
-
-    } else if (!strncmp(ptr, "Content-Encoding: gzip", 22)) {
-      gzipFlag = 1;
-    } else if (!strncmp(ptr, "Content-Encoding:", 17)) { // Content-Encoding that is not gzip
-      ceFlag = 1;
-    } else if (!strncmp(ptr, "Transfer-Encoding:", 18)) {
-      teFlag = 1;
-    } else if (!strncmp(ptr, "HTTP/1.1 304 ", 13)) {
-      http304Flag = 1;
-    } else if (!strncmp(ptr, "Content-Length: 0", 17)) {
-      clZeroFlag = 1;
-    }
-    
-    if (!strncmp(end, "\r\n\r\n", 4)){
-      break;
-    }
-    ptr = end+2;
-  }
-
-#ifdef DEBUG
-  printf("tjFlag=%d; thFlag=%d; gzipFlag=%d; ceFlag=%d; teFlag=%d; http304Flag=%d; clZeroFlag=%d\n", 
-    tjFlag, thFlag, gzipFlag, ceFlag, teFlag, http304Flag, clZeroFlag);
-#endif
-
-  // if (type == HTTP_CONTENT_JAVASCRIPT)
-  if (type == HTTP_CONTENT_JAVASCRIPT || type == HTTP_CONTENT_HTML) {
-    // empty body if it's HTTP not modified (304) or zero Content-Length
-    if (http304Flag || clZeroFlag) return 0; 
-
-    // for now, we're not dealing with Transfer-Encoding (e.g., chunked)
-    // or Content-Encoding that is not gzip
-    // if (teFlag) return 0;
-    if (teFlag || ceFlag) return 0;
-
-    if (tjFlag && ceFlag && end != NULL) {
-      log_debug("(JS) gzip flag detected with hdr len %d", (int)(end-buf+4));
-    } else if (thFlag && ceFlag && end != NULL) {
-      log_debug("(HTML) gzip flag detected with hdr len %d", (int)(end-buf+4));
-    }
-
-    // case 1
-    if (tjFlag) return 1; 
-
-    // case 2: check if HTTP body contains <script type="text/javascript">
-    if (thFlag) {
-      matchptr = strstr(ptr, "<script type=\"text/javascript\">");
-      if (matchptr != NULL) {
-        return 2;
-      }
-    }
-  }
-
-  if (type == HTTP_CONTENT_PDF && pdfFlag) {
-    // reject msg with empty body: HTTP not modified (304) or zero Content-Length
-    if (http304Flag || clZeroFlag) return 0; 
-
-    // for now, we're not dealing with Transfer-Encoding (e.g., chunked)
-    // or Content-Encoding that is not gzip
-    // if (teFlag) return 0;
-    if (teFlag || ceFlag) return 0;
-
-    // check if HTTP body contains "endstream";
-    // strlen("endstream") == 9
-    
-    cp = strInBinary("endstream", 9, ptr, buf+len-ptr);
-    if (cp != NULL) {
-      // log_debug("Matched endstream!");
-      return 1;
-    }
-  }
-  
-  if (type == HTTP_CONTENT_SWF && swfFlag == 1 && 
-      ((len + buf - end) > SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 8))
-    return 1;
-
-  return 0;
-}
-
-
-
-unsigned int capacityPDF (char* buf, int len) {
-  char *hEnd, *bp, *streamStart, *streamEnd;
-  int cnt=0;
-  int size;
-
-  // jump to the beginning of the body of the HTTP message
-  hEnd = strstr(buf, "\r\n\r\n");
-  if (hEnd == NULL) {
-    // cannot find the separator between HTTP header and HTTP body
-    return 0;
-  }
-  bp = hEnd + 4;
-
-  while (bp < (buf+len)) {
-     streamStart = strInBinary("stream", 6, bp, (buf+len)-bp);
-     // streamStart = strstr(bp, "stream");
-     if (streamStart == NULL) break;
-     bp = streamStart+6;
-     streamEnd = strInBinary("endstream", 9, bp, (buf+len)-bp);
-     // streamEnd = strstr(bp, "endstream");
-     if (streamEnd == NULL) break;
-     // count the number of char between streamStart+6 and streamEnd
-     size = streamEnd - (streamStart+6) - 2; // 2 for \r\n before streamEnd
-     if (size > 0) {
-       cnt = cnt + size;
-       log_debug("capacity of pdf increase by %d", size);
-     }
-     bp += 9;
-  }
-  return cnt;
-}
-
-
-
-
-
-
-
-
-
-/*
- * init_payload_pool initializes the arrays pertaining to 
- * message payloads for the specified content type
- *
- * Specifically, it populates the following arrays
- * static int initTypePayload[MAX_CONTENT_TYPE];
- * static int typePayloadCount[MAX_CONTENT_TYPE];
- * static int typePayload[MAX_CONTENT_TYPE][MAX_PAYLOADS];
- * static int typePayloadCap[MAX_CONTENT_TYPE][MAX_PAYLOADS];
- *
- * Input:
- * len - max length of payload
- * type - ptype field value in pentry_header
- * contentType - (e.g, HTTP_CONTENT_JAVASCRIPT for JavaScript content)
- */
-
-
-
-
-int  init_JS_payload_pool(int len, int type, int minCapacity) {
-
-  // stat for usable payload
-  int minPayloadSize = 0, maxPayloadSize = 0; 
-  int sumPayloadSize = 0;
-  int minPayloadCap = 0, maxPayloadCap = 0;
-  int sumPayloadCap = 0;
-
-  unsigned int contentType = HTTP_CONTENT_JAVASCRIPT;
-
-  int cnt = 0;
-  int r;
-  pentry_header* p;
-  char* msgbuf;
-  int cap;
-  int mode;
-
-
-
-  if (payload_count == 0) {
-    log_debug("payload_count == 0; forgot to run load_payloads()?\n");
-    return 0;
-  }
-  
-  if (initTypePayload[contentType] != 0) return 1; // init is done already
-
-
-  for (r = 0; r < payload_count; r++) {
-    p = &payload_hdrs[r];
-    if (p->ptype != type || p->length > len) {
-      continue;
-    }
-
-    msgbuf = payloads[r];
-
-    mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_JAVASCRIPT);
-    if (mode == CONTENT_JAVASCRIPT) {
-      
-      cap = capacityJS3(msgbuf, p->length, mode);
-      if (cap <  JS_DELIMITER_SIZE) 
-	continue;
-
-      cap = (cap - JS_DELIMITER_SIZE)/2;
-
-      if (cap > minCapacity) {
-	typePayloadCap[contentType][cnt] = cap; // (cap-JS_DELIMITER_SIZE)/2;
-	// because we use 2 hex char to encode every data byte, the available
-	// capacity for encoding data is divided by 2
-	typePayload[contentType][cnt] = r;
-	cnt++;
-	
-	// update stat
-	if (cnt == 1) {
-	  minPayloadSize = p->length; maxPayloadSize = p->length;
-	  minPayloadCap = cap; maxPayloadCap = cap;
-	} 
-	else {
-	  if (minPayloadSize > p->length) minPayloadSize = p->length; 
-	  if (maxPayloadSize < p->length) maxPayloadSize = p->length; 
-	  if (minPayloadCap > cap) minPayloadCap = cap;
-	  if (maxPayloadCap < cap) {
-	    maxPayloadCap = cap;
-	  }
-	  
-	}
-	sumPayloadSize += p->length; sumPayloadCap += cap;
-      }
-    }
-  }
-
-  
-  max_JS_capacity = maxPayloadCap;
-
-
-  initTypePayload[contentType] = 1;
-  typePayloadCount[contentType] = cnt;
-  log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
-     contentType, typePayloadCount[contentType]); 
-  log_debug("minPayloadSize = %d", minPayloadSize); 
-  log_debug("maxPayloadSize = %d", maxPayloadSize); 
-  log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt); 
-  log_debug("minPayloadCap  = %d", minPayloadCap); 
-  log_debug("maxPayloadCap  = %d", maxPayloadCap); 
-  log_debug("avgPayloadCap  = %f", (float)sumPayloadCap/(float)cnt); 
-  return 1;
-}
-
-
-int  init_HTML_payload_pool(int len, int type, int minCapacity) {
-
-  // stat for usable payload
-  int minPayloadSize = 0, maxPayloadSize = 0; 
-  int sumPayloadSize = 0;
-  int minPayloadCap = 0, maxPayloadCap = 0;
-  int sumPayloadCap = 0;
-
-  unsigned int contentType = HTTP_CONTENT_HTML;
-
-  int cnt = 0;
-  int r;
-  pentry_header* p;
-  char* msgbuf;
-  int cap;
-  int mode;
-
-
-
-  if (payload_count == 0) {
-    log_debug("payload_count == 0; forgot to run load_payloads()?\n");
-    return 0;
-  }
-  
-  if (initTypePayload[contentType] != 0) return 1; // init is done already
-
-
-  for (r = 0; r < payload_count; r++) {
-    p = &payload_hdrs[r];
-    if (p->ptype != type || p->length > len) {
-      continue;
-    }
-
-    msgbuf = payloads[r];
-
-    mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_HTML);
-    if (mode == CONTENT_HTML_JAVASCRIPT) {
-      
-      cap = capacityJS3(msgbuf, p->length, mode);
-      if (cap <  JS_DELIMITER_SIZE) 
-	continue;
-
-      cap = (cap - JS_DELIMITER_SIZE)/2;
-
-      if (cap > minCapacity) {
-	typePayloadCap[contentType][cnt] = cap; // (cap-JS_DELIMITER_SIZE)/2;
-	// because we use 2 hex char to encode every data byte, the available
-	// capacity for encoding data is divided by 2
-	typePayload[contentType][cnt] = r;
-	cnt++;
-	
-	// update stat
-	if (cnt == 1) {
-	  minPayloadSize = p->length; maxPayloadSize = p->length;
-	  minPayloadCap = cap; maxPayloadCap = cap;
-	} 
-	else {
-	  if (minPayloadSize > p->length) minPayloadSize = p->length; 
-	  if (maxPayloadSize < p->length) maxPayloadSize = p->length; 
-	  if (minPayloadCap > cap) minPayloadCap = cap;
-	  if (maxPayloadCap < cap) {
-	    maxPayloadCap = cap;
-	  }
-	  
-	}
-	sumPayloadSize += p->length; sumPayloadCap += cap;
-      }
-    }
-  }
-
-  
-  max_HTML_capacity = maxPayloadCap;
-
-
-  initTypePayload[contentType] = 1;
-  typePayloadCount[contentType] = cnt;
-  log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
-     contentType, typePayloadCount[contentType]); 
-  log_debug("minPayloadSize = %d", minPayloadSize); 
-  log_debug("maxPayloadSize = %d", maxPayloadSize); 
-  log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt); 
-  log_debug("minPayloadCap  = %d", minPayloadCap); 
-  log_debug("maxPayloadCap  = %d", maxPayloadCap); 
-  log_debug("avgPayloadCap  = %f", (float)sumPayloadCap/(float)cnt); 
-  return 1;
-}
-
-
-
-
-
-
-
-
-int  init_PDF_payload_pool(int len, int type, int minCapacity) {
-
-  // stat for usable payload
-  int minPayloadSize = 0, maxPayloadSize = 0; 
-  int sumPayloadSize = 0;
-  int minPayloadCap = 0, maxPayloadCap = 0;
-  int sumPayloadCap = 0;
-
-  int cnt = 0;
-  int r;
-  pentry_header* p;
-  char* msgbuf;
-  int cap;
-  int mode;
-  unsigned int contentType = HTTP_CONTENT_PDF;
-  
-
-  if (payload_count == 0) {
-     fprintf(stderr, "payload_count == 0; forgot to run load_payloads()?\n");
-     return 0;
-  }
-  
-  if (initTypePayload[contentType] != 0) return 1; // init is done already
-
-
-  for (r = 0; r < payload_count; r++) {
-    p = &payload_hdrs[r];
-    if (p->ptype != type || p->length > len) {
-      continue;
-    }
-
-    msgbuf = payloads[r];
-
-    mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_PDF);
-    if (mode > 0) {
-      // use capacityPDF() to find out the amount of data that we
-      // can encode in the pdf doc 
-      // cap = minCapacity+1;
-      cap = capacityPDF(msgbuf, p->length);
-      log_debug("got pdf (index %d) with capacity %d", r, cap);
-      if (cap > minCapacity) {
-	log_debug("pdf (index %d) greater than mincapacity %d", cnt, minCapacity);
-	typePayloadCap[contentType][cnt] = (cap-PDF_DELIMITER_SIZE)/2;
-	typePayload[contentType][cnt] = r;
-	cnt++;
-	
-	// update stat
-	if (cnt == 1) {
-	  minPayloadSize = p->length; maxPayloadSize = p->length;
-	  minPayloadCap = cap; maxPayloadCap = cap;
-	} 
-	else {
-	  if (minPayloadSize > p->length) minPayloadSize = p->length; 
-	  if (maxPayloadSize < p->length) maxPayloadSize = p->length; 
-	  if (minPayloadCap > cap) minPayloadCap = cap;
-	  if (maxPayloadCap < cap) maxPayloadCap = cap;
-	}
-	sumPayloadSize += p->length; sumPayloadCap += cap;
-      }
-    }
-  }
-
-  max_PDF_capacity = maxPayloadCap;
-  initTypePayload[contentType] = 1;
-  typePayloadCount[contentType] = cnt;
-  log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
-     contentType, typePayloadCount[contentType]); 
-  log_debug("minPayloadSize = %d", minPayloadSize); 
-  log_debug("maxPayloadSize = %d", maxPayloadSize); 
-  log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt); 
-  log_debug("minPayloadCap  = %d", minPayloadCap); 
-  log_debug("maxPayloadCap  = %d", maxPayloadCap); 
-  log_debug("avgPayloadCap  = %f", (float)sumPayloadCap/(float)cnt); 
-  return 1;
-}
-
-
-
-
-
-int  init_SWF_payload_pool(int len, int type, int minCapacity) {
-
-  // stat for usable payload
-  int minPayloadSize = 0, maxPayloadSize = 0; 
-  int sumPayloadSize = 0;
-
-  int cnt = 0;
-  int r;
-  pentry_header* p;
-  char* msgbuf;
-  int mode;
-  unsigned int contentType = HTTP_CONTENT_SWF;
-
-
-  if (payload_count == 0) {
-     fprintf(stderr, "payload_count == 0; forgot to run load_payloads()?\n");
-     return 0;
-  }
-  
-  if (initTypePayload[contentType] != 0) return 1; // init is done already
-
-
-  for (r = 0; r < payload_count; r++) {
-    p = &payload_hdrs[r];
-    if (p->ptype != type || p->length > len) {
-      continue;
-    }
-
-    msgbuf = payloads[r];
-    // found a payload corr to the specified contentType
-
-    mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_SWF);
-    if (mode > 0) {
-      typePayload[contentType][cnt] = r;
-      cnt++;
-      // update stat
-      if (cnt == 1) {
-	minPayloadSize = p->length; 
-	maxPayloadSize = p->length;
-      } 
-      else {
-	if (minPayloadSize > p->length) 
-	  minPayloadSize = p->length; 
-	if (maxPayloadSize < p->length) 
-	  maxPayloadSize = p->length; 
-      }
-      sumPayloadSize += p->length;
-    }
-  }
-    
-  initTypePayload[contentType] = 1;
-  typePayloadCount[contentType] = cnt;
-  log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
-     contentType, typePayloadCount[contentType]); 
-  log_debug("minPayloadSize = %d", minPayloadSize); 
-  log_debug("maxPayloadSize = %d", maxPayloadSize); 
-  log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt); 
-  return 1;
-}
-
-
-
-
-
-
-
-
-
-int get_next_payload (int contentType, char** buf, int* size, int* cap) {
-  int r;
-
-  log_debug("get_next_payload: contentType = %d, initTypePayload = %d, typePayloadCount = %d",
-      contentType, initTypePayload[contentType], typePayloadCount[contentType]);
-
-
-  if (contentType <= 0 ||
-      contentType >= MAX_CONTENT_TYPE ||
-      initTypePayload[contentType] == 0 ||
-      typePayloadCount[contentType] == 0)
-    return 0;
-
-  r = rand() % typePayloadCount[contentType];
-//  int r = 1;
-//  log_debug("SERVER: *** always choose the same payload ***");
-
-  log_debug("SERVER: picked payload with index %d", r);
-  *buf = payloads[typePayload[contentType][r]];
-  *size = payload_hdrs[typePayload[contentType][r]].length;
-  *cap = typePayloadCap[contentType][r];
-  return 1;
-}
-
-
-
-
-
-
-
-
-int get_payload (int contentType, int cap, char** buf, int* size) {
-  int r;
-  unsigned int i = 0;
-  unsigned int cnt = 0;
-
-  log_debug("get_payload: contentType = %d, initTypePayload = %d, typePayloadCount = %d",
-      contentType, initTypePayload[contentType], typePayloadCount[contentType]);
-
-
-  if (contentType <= 0 ||
-      contentType >= MAX_CONTENT_TYPE ||
-      initTypePayload[contentType] == 0 ||
-      typePayloadCount[contentType] == 0)
-    return 0;
-
-
-  cnt = typePayloadCount[contentType];
-   r = rand() % cnt;
-
-  for (i=0; i < cnt; i++) {
-
-    if (typePayloadCap[contentType][(r+i) % cnt] <= cap)
-      continue;
-
-    *buf = payloads[typePayload[contentType][(r+i)%cnt]];
-    *size = payload_hdrs[typePayload[contentType][(r+i)%cnt]].length;
-    return 1;
-  }
-
-
-
-  return 0;
-
-}
-
-
-
-
-int
-find_content_length (char *hdr, int hlen) {
-  char *clStart;
-  char* clEnd;
-  char *clValStart;
-  int valLen;
-  int contentLen;
-  char buf[10];
-
-  clStart = strstr(hdr, "Content-Length: ");
-  if (clStart == NULL) {
-    log_debug("Unable to find Content-Length in the header");
-    return -1;
-  }
-
-  clEnd = strstr((char *)clStart, "\r\n");
-  if (clEnd == NULL) {
-    log_debug("Unable to find end of line for Content-Length");
-    return -1;
-  }
-
-  // clValStart = clStart+strlen("Content-Length: ");
-  clValStart = clStart+16;
-
-  valLen = clEnd-clValStart;
-  if (valLen > 9) return -1;
-  memcpy(buf, clValStart, valLen);
-  buf[valLen] = 0;
-  contentLen = atoi(buf);
-  return contentLen;
-}
-
-
-
-
-
-
-/*
-
-void testOffset2Alnum_skipJSPattern () {
-  char s1[] = "for (i=0; i<10; i++) { print i; }";
-
-  char s2[] = "***abcde*****";
-  int d, i;
-
-  printf("s1 = %s\n", s1);
-  printf("s2 = %s\n", s2);
-
-
-  d = offset2Alnum_(s1, strlen(s1));
-  printf ("offset2Alnum_ for s1 = %d\n", d);
-  d = offset2Alnum_(s2, strlen(s2));
-  printf ("offset2Alnum_ for s2 = %d\n", d);
-
-  i = skipJSPattern (s1, strlen(s1));
-  printf ("skipJSPattern for s1 = %d\n", i);
-  i = skipJSPattern (s2, strlen(s2));
-  printf ("skipJSPattern for s2 = %d\n", i);
-}
-
-
-
-
-void testOffset2Hex () {
-  int d;
-  char s3[] = "for (bc=0; bc<10; bc++) { ad=2*bc+ad; }";
-  printf("len(s3)=%d; s3 = |%s|\n", (int)strlen(s3), s3);
-
-  d = offset2Alnum_(s3, strlen(s3));
-  printf ("offset2Alnum_ for s3 = %d\n", d);
-  d = offset2Hex(s3, strlen(s3), 0);
-  printf ("offset2Hex for s3 = %d\n", d);
-}
-
-
-void testCapacityJS () {
-  int d;
-  char s4[] = "\r\n\r\n abc = abc + 1;";
-  char s6[] = "\r\n\r\n <script type=\"text/javascript\">abc = abc + 1;</script>";
-
-  printf("\nTest for CONTENT_JAVASCRIPT:\n");
-  printf("len(s4)=%d; s4 = |%s|\n", (int)strlen(s4), s4);
-
-  d = offset2Alnum_(s4, strlen(s4));
-  printf ("offset2Alnum_ for s4 = %d\n", d);
-  d = offset2Hex(s4, strlen(s4), 0);
-  printf ("offset2Hex for s4 = %d\n", d);
-
-  printf("capacityJS  (JS) returns %d\n", capacityJS(s4, strlen(s4), CONTENT_JAVASCRIPT));
-  printf("capacityJS3 (JS) returns %d\n", capacityJS3(s4, strlen(s4), CONTENT_JAVASCRIPT));
-
-  printf("\nTest for CONTENT_HTML_JAVASCRIPT:\n");
-  printf("len(s6)=%d; s6 = |%s|\n", (int)strlen(s6), s6);
-
-  d = offset2Alnum_(s6, strlen(s6));
-  printf ("offset2Alnum_ for s6 = %d\n", d);
-  d = offset2Hex(s6, strlen(s6), 0);
-  printf ("offset2Hex for s6 = %d\n", d);
-
-  printf("capacityJS  (HTML) returns %d\n", capacityJS(s6, strlen(s6), CONTENT_HTML_JAVASCRIPT));
-  printf("capacityJS3 (HTML) returns %d\n", capacityJS3(s6, strlen(s6), CONTENT_HTML_JAVASCRIPT));
-}
-*/
-
-
-/*****
-int main() {
-  char buf[HTTP_MSG_BUF_SIZE];
-  bzero(buf, sizeof(buf));
-  // test for TYPE_HTTP_REQUEST
-  // load_payloads("../../traces/client.out");
-  // int len = find_client_payload(buf, 10000, TYPE_HTTP_REQUEST);
-  // printf("%s\n", buf);
-
-  // test for TYPE_HTTP_RESPONSE
-  // load_payloads("../../traces/server-cnn-nogzip.out");
-  // load_payloads("../../traces/server-portals.out"); // ptype==1?
-
-  // testOffset2Alnum_skipJSPattern();
-  // testOffset2Hex();
-  // testCapacityJS();
-  
-  load_payloads("../../traces/server.out");
-  // int r;
-  // r = find_server_payload(&buf, sizeof(buf), TYPE_HTTP_RESPONSE, HTTP_CONTENT_JAVASCRIPT);
-  // if (r > 0) {
-  //   printf("Available payload capablity %d\n", r);
-  // }
-  // return r;
-
-  return 0;
-}
- *****/
-
diff --git a/src/steg/payloads.cc b/src/steg/payloads.cc
new file mode 100644
index 0000000..2b82451
--- /dev/null
+++ b/src/steg/payloads.cc
@@ -0,0 +1,1669 @@
+#include "util.h"
+#include "payloads.h"
+#include "swfSteg.h"
+
+
+/* These variables below are write-once, hence they should be race-safe */
+
+static int initTypePayload[MAX_CONTENT_TYPE];
+static int typePayloadCount[MAX_CONTENT_TYPE];
+static int typePayload[MAX_CONTENT_TYPE][MAX_PAYLOADS];
+static int typePayloadCap[MAX_CONTENT_TYPE][MAX_PAYLOADS];
+
+
+static unsigned int max_JS_capacity = 0;
+static unsigned int max_HTML_capacity = 0;
+static unsigned int max_PDF_capacity = 0;
+
+
+
+pentry_header payload_hdrs[MAX_PAYLOADS];
+char* payloads[MAX_PAYLOADS];
+int payload_count = 0;
+
+
+unsigned int get_max_JS_capacity() {
+  return max_JS_capacity;
+}
+
+unsigned int get_max_HTML_capacity() {
+  return max_HTML_capacity;
+}
+
+unsigned int get_max_PDF_capacity() {
+  return max_PDF_capacity;
+}
+
+
+
+/*
+ * fixContentLen corrects the Content-Length for an HTTP msg that
+ * has been ungzipped, and removes the "Content-Encoding: gzip"
+ * field from the header.
+ *
+ * The function returns -1 if no change to the HTTP msg has been made,
+ * when the msg wasn't gzipped or an error has been encountered
+ * If fixContentLen changes the msg header, it will put the new HTTP
+ * msg in buf and returns the length of the new msg
+ *
+ * Input:
+ * payload - pointer to the (input) HTTP msg
+ * payloadLen - length of the (input) HTTP msg
+ *
+ * Ouptut:
+ * buf - pointer to the buffer containing the new HTTP msg
+ * bufLen - length of buf
+ * 
+ */
+int fixContentLen (char* payload, int payloadLen, char *buf, int bufLen) {
+
+  int gzipFlag=0, clFlag=0, clZeroFlag=0;
+  char* ptr = payload;
+  char* clPtr = payload;
+  char* gzipPtr = payload;
+  char* end;
+
+
+  char *cp, *clEndPtr;
+  int hdrLen, bodyLen, r, len;
+
+
+
+
+
+  // note that the ordering between the Content-Length and the Content-Encoding
+  // in an HTTP msg may be different for different msg 
+
+  // if payloadLen is larger than the size of our buffer,
+  // stop and return -1
+  if (payloadLen > bufLen) { return -1; }
+
+  while (1) {
+    end = strstr(ptr, "\r\n");
+    if (end == NULL) {
+      // log_debug("invalid header %d %d %s \n", payloadLen, (int) (ptr - payload), payload);
+      return -1;
+    }
+
+    if (!strncmp(ptr, "Content-Encoding: gzip\r\n", 24)) {
+        gzipFlag = 1;
+        gzipPtr = ptr;     
+    } else if (!strncmp(ptr, "Content-Length: 0", 17)) {
+        clZeroFlag = 1;
+    } else if (!strncmp(ptr, "Content-Length:", 15)) {
+        clFlag = 1;
+        clPtr = ptr;
+    }
+
+    if (!strncmp(end, "\r\n\r\n", 4)){
+      break;
+    }
+    ptr = end+2;
+  }
+
+  // stop if zero Content-Length or Content-Length not found
+  if (clZeroFlag || ! clFlag) return -1;
+  
+  // end now points to the end of the header, before "\r\n\r\n"
+  cp=buf;
+  bodyLen = (int)(payloadLen - (end+4-payload));
+
+  clEndPtr = strstr(clPtr, "\r\n");
+  if (clEndPtr == NULL) {
+    log_debug("unable to find end of line for Content-Length");
+    return -1;
+  }
+  if (gzipFlag && clFlag) {
+    if (gzipPtr < clPtr) { // Content-Encoding appears before Content-Length
+
+      // copy the part of the header before Content-Encoding
+      len = (int)(gzipPtr-payload);
+      memcpy(cp, payload, len);
+      cp = cp+len;
+
+      // copy the part of the header between Content-Encoding and Content-Length
+      // skip 24 char, the len of "Content-Encoding: gzip\r\n"
+      // *** this is temporary; we'll remove this after the obfsproxy can perform gzip
+      len = (int)(clPtr-(gzipPtr+24));  
+      memcpy(cp, gzipPtr+24, len);
+      cp = cp+len;
+
+      // put the new Content-Length
+      memcpy(cp, "Content-Length: ", 16);
+      cp = cp+16;
+      r = sprintf(cp, "%d\r\n", bodyLen);
+      if (r < 0) {
+        log_debug("sprintf fails");
+        return -1;
+      }
+      cp = cp+r;
+
+      // copy the part of the header after Content-Length, if any
+      if (clEndPtr != end) { // there is header info after Content-Length
+        len = (int)(end-(clEndPtr+2));
+        memcpy(cp, clEndPtr+2, len);
+        cp = cp+len;
+        memcpy(cp, "\r\n\r\n", 4);
+        cp = cp+4;
+      } else { // Content-Length is the last hdr field
+        memcpy(cp, "\r\n", 2);
+        cp = cp+2;
+      }
+
+      hdrLen = cp-buf;
+
+/****
+log_debug("orig: hdrLen = %d, bodyLen = %d, payloadLen = %d", (int)(end+4-payload), bodyLen, payloadLen);
+log_debug("new: hdrLen = %d, bodyLen = %d, payloadLen = %d", hdrLen, bodyLen, hdrLen+bodyLen);
+ ****/
+
+      // copy the HTTP body
+      memcpy(cp, end+4, bodyLen);
+      return (hdrLen+bodyLen);
+
+    } else { // Content-Length before Content-Encoding
+      // copy the part of the header before Content-Length
+      len = (int)(clPtr-payload);
+      memcpy(cp, payload, len);
+      cp = cp+len;
+
+      // put the new Content-Length
+      memcpy(cp, "Content-Length: ", 16);
+      cp = cp+16;
+      r = sprintf(cp, "%d\r\n", bodyLen);
+      if (r < 0) {
+        log_debug("sprintf fails");
+        return -1;
+      }
+      cp = cp+r;
+
+      // copy the part of the header between Content-Length and Content-Encoding
+      len = (int)(gzipPtr-(clEndPtr+2));
+      memcpy(cp, clEndPtr+2, len);
+      cp = cp+len;
+      
+      // copy the part of the header after Content-Encoding
+      // skip 24 char, the len of "Content-Encoding: gzip\r\n"
+      // *** this is temporary; we'll remove this after the obfsproxy can perform gzip
+      if (end > (gzipPtr+24)) { // there is header info after Content-Encoding
+        len = (int)(end-(gzipPtr+24));
+        memcpy(cp, gzipPtr+24, len);
+        cp = cp+len;
+        memcpy(cp, "\r\n\r\n", 4);
+        cp = cp+4;
+      } else { // Content-Encoding is the last field in the hdr
+        memcpy(cp, "\r\n", 2);
+        cp = cp+2;
+      }
+      hdrLen = cp-buf;
+
+/****
+log_debug("orig: hdrLen = %d, bodyLen = %d, payloadLen = %d", (int)(end+4-payload), bodyLen, payloadLen);
+log_debug("new: hdrLen = %d, bodyLen = %d, payloadLen = %d", hdrLen, bodyLen, hdrLen+bodyLen);
+ ****/
+
+      // copy the HTTP body
+      memcpy(cp, end+4, bodyLen);
+      return (hdrLen+bodyLen);
+    }
+  }
+  return -1;
+}
+
+void load_payloads(const char* fname) {
+  FILE* f;
+  char buf[HTTP_MSG_BUF_SIZE];
+  char buf2[HTTP_MSG_BUF_SIZE];
+  pentry_header pentry;
+  int pentryLen;
+  int r;
+
+  if (payload_count != 0)
+    return;
+
+  srand(time(NULL));
+  f = fopen(fname, "r");
+  if (f == NULL) {
+    fprintf(stderr, "Cannot open trace file %s. Exiting\n", fname);
+    exit(1);
+  }
+
+  bzero(payload_hdrs, sizeof(payload_hdrs));
+
+  while (payload_count < MAX_PAYLOADS) {
+
+    if (fread(&pentry, 1, sizeof(pentry_header), f) < sizeof(pentry_header)) {
+      break;
+    }
+   
+    pentryLen = ntohl(pentry.length);
+    if((unsigned int) pentryLen > sizeof(buf)) {
+#ifdef DEBUG
+      // fprintf(stderr, "pentry too big %d %d\n", pentry.length, ntohl(pentry.length));
+      fprintf(stderr, "pentry too big %d\n", pentryLen);
+#endif
+      // skip to the next pentry
+      if (fseek(f, pentryLen, SEEK_CUR)) {
+        fprintf(stderr, "skipping to next pentry fails\n");
+      }
+      continue;
+      // exit(0);
+    }
+
+    pentry.length = pentryLen;
+    pentry.ptype = ntohs(pentry.ptype);
+
+    if (fread(buf, 1, pentry.length, f) < (unsigned int) pentry.length)
+      break;
+
+    // todo:
+    // fixed content length for gzip'd HTTP msg
+    // fixContentLen returns -1, if no change to the msg
+    // otherwise, it put the new HTTP msg (with hdr changed) in buf2
+    // and returns the size of the new msg
+
+    r = -1;
+    if (pentry.ptype == TYPE_HTTP_RESPONSE) {
+      r = fixContentLen (buf, pentry.length, buf2, HTTP_MSG_BUF_SIZE);
+      // log_debug("for payload_count %d, fixContentLen returns %d", payload_count, r);
+    }
+    // else {
+    // log_debug("for payload_count %d, pentry.ptype = %d", payload_count, pentry.ptype);
+    // }
+
+    if (r < 0) {
+      payloads[payload_count] = malloc(pentry.length + 1);
+      memcpy(payloads[payload_count], buf, pentry.length);
+    } else {
+      pentry.length = r;
+      payloads[payload_count] = malloc(pentry.length + 1);
+      memcpy(payloads[payload_count], buf2, pentry.length);
+    }
+    payload_hdrs[payload_count] = pentry;
+    payloads[payload_count][pentry.length] = 0;
+    payload_count++;
+  } // while
+
+#ifdef DEBUG
+  printf("loading payload count = %d\n", payload_count);
+#endif
+  
+  fclose(f);
+}
+
+
+
+
+
+void gen_rfc_1123_date(char* buf, int buf_size) {
+  time_t t = time(NULL);
+  struct tm *my_tm = gmtime(&t);
+  strftime(buf, buf_size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", my_tm);
+}
+
+
+
+void gen_rfc_1123_expiry_date(char* buf, int buf_size) {
+  time_t t = time(NULL) + rand() % 10000;
+  struct tm *my_tm = gmtime(&t);
+  strftime(buf, buf_size, "Expires: %a, %d %b %Y %H:%M:%S GMT\r\n", my_tm);
+}
+
+
+
+
+
+int gen_response_header(char* content_type, int gzip, int length, char* buf, int buflen) {
+  char* ptr;
+
+  // conservative assumption here.... 
+  if (buflen < 400) {
+    fprintf(stderr, "gen_response_header: buflen too small\n");
+    return -1;
+  }
+
+  sprintf(buf, "HTTP/1.1 200 OK\r\n");
+  ptr = buf + strlen("HTTP/1.1 200 OK\r\n");
+  gen_rfc_1123_date(ptr, buflen - (ptr - buf));
+  ptr = ptr + strlen(ptr);
+
+  sprintf(ptr, "Server: Apache\r\n");
+  ptr = ptr + strlen(ptr);
+
+  switch(rand() % 9) {
+  case 1:
+    sprintf(ptr, "Vary: Cookie\r\n");
+    ptr = ptr + strlen(ptr);
+    break;
+
+  case 2:
+    sprintf(ptr, "Vary: Accept-Encoding, User-Agent\r\n");
+    ptr = ptr + strlen(ptr);
+    break;
+
+  case 3:
+    sprintf(ptr, "Vary: *\r\n");
+    ptr = ptr + strlen(ptr);
+    break;
+
+  }
+
+
+  switch(rand() % 4) {
+  case 2:
+    gen_rfc_1123_expiry_date(ptr, buflen - (ptr - buf));
+    ptr = ptr + strlen(ptr);
+  }
+
+
+  
+
+  if (gzip) 
+    sprintf(ptr, "Content-Length: %d\r\nContent-Encoding: gzip\r\nContent-Type: %s\r\n", length, content_type);
+  else
+    sprintf(ptr, "Content-Length: %d\r\nContent-Type: %s\r\n", length, content_type);
+    
+  ptr += strlen(ptr);
+
+  switch(rand() % 4) {
+  case 2:
+  case 3:
+  case 4:
+    sprintf(ptr, "Connection: Keep-Alive\r\n\r\n");
+    break;
+  default:
+    sprintf(ptr, "Connection: close\r\n\r\n");
+    break;    
+  }
+
+  ptr += strlen(ptr);
+
+  return ptr - buf;
+}
+
+
+
+
+
+
+int parse_client_headers(char* inbuf, char* outbuf, int len) {
+  // client-side
+  // remove Host: field
+  // remove referrer fields?
+
+  char* ptr = inbuf;
+  int outlen = 0;
+
+  while (1) {
+    // char* end = strstr(ptr, "\r\n", len - (ptr - inbuf));
+    char* end = strstr(ptr, "\r\n");
+    if (end == NULL) {
+      fprintf(stderr, "invalid client header %d %d %s \n PTR = %s\n", len, (int) (len - (ptr - inbuf)), inbuf, ptr);
+      // fprintf(stderr, "HERE %s\n", ptr);
+      break;
+    }
+
+    if (!strncmp(ptr, "Host:", 5) ||
+	!strncmp(ptr, "Referer:", 8) ||
+	!strncmp(ptr, "Cookie:", 7)) {
+      goto next;
+    }
+
+    memcpy(outbuf + outlen, ptr, end - ptr + 2);
+    outlen += end - ptr + 2;
+
+  next:
+    if (!strncmp(end, "\r\n\r\n", 4)){
+      break;
+    }
+    ptr = end+2;
+  }
+  
+  return outlen;
+
+  // server-side
+  // fix date fields
+  // fix content-length
+
+
+
+}
+
+
+
+
+/* first line is of the form....
+   GET /XX/XXXX.swf[?YYYY] HTTP/1.1\r\n
+*/
+
+
+int 
+find_uri_type(char* buf_orig, int buflen) {
+
+  char* uri;
+  char* ext;
+
+  char* buf = malloc(buflen+1);
+  char* uri_end;
+
+
+  memcpy(buf, buf_orig, buflen);
+  buf[buflen] = 0;
+
+  
+  if (strncmp(buf, "GET", 3) != 0
+      && strncmp(buf, "POST", 4) != 0) {
+    fprintf(stderr, "HERE %s\n", buf);
+    return -1;
+  }
+  
+
+
+  uri = strchr(buf, ' ') + 1;
+
+  if (uri == NULL) {
+    fprintf(stderr, "Invalid URL\n");
+    return -1;
+  }
+
+  uri_end = strchr(uri, ' ');
+
+  if (uri_end == NULL) {
+    fprintf(stderr, "unterminated uri\n");
+    return -1;
+  }
+
+  uri_end[0] = 0;
+  
+
+
+
+
+  ext = strrchr(uri, '/');
+
+  if (ext == NULL) {
+    fprintf(stderr, "no / in url: find_uri_type...");
+    return -1;
+  }
+
+  ext = strchr(ext, '.');
+
+
+  if (ext == NULL || !strncmp(ext, ".html", 5) || !strncmp(ext, ".htm", 4) || !strncmp(ext, ".php", 4)
+      || !strncmp(ext, ".jsp", 4) || !strncmp(ext, ".asp", 4))
+    return HTTP_CONTENT_HTML;
+
+
+  if (!strncmp(ext, ".js", 3) || !strncmp(ext, ".JS", 3))
+    return HTTP_CONTENT_JAVASCRIPT;
+
+  if (!strncmp(ext, ".pdf", 4) || !strncmp(ext, ".PDF", 4))
+    return HTTP_CONTENT_PDF;
+
+
+  if (!strncmp(ext, ".swf", 4) || !strncmp(ext, ".SWF", 4))
+    return HTTP_CONTENT_SWF;
+
+
+
+  free(buf);
+  return -1;
+  
+}
+
+/*
+int 
+find_uri_type(char* buf) {
+
+  char* uri;
+  int uri_len;
+  char* ext;
+
+  if (strncmp(buf, "GET", 3) != 0 && strncmp(buf, "POST", 4) != 0) 
+    return -1;
+
+  buf = strchr(buf, ' ') + 1;
+  uri_len = strchr(buf, ' ') - buf;
+  uri = malloc(uri_len + 1);
+
+  strncpy(uri, buf, uri_len);
+  uri[uri_len] = 0;
+
+  if (strchr(uri, '?'))
+    ext = strchr(uri, '?') - 4;
+  else
+    ext = uri + uri_len - 4;
+
+
+  if (!strncmp(ext, ".pdf", 4) || !strncmp(ext, ".PDF", 4))
+    return HTTP_CONTENT_PDF;
+
+  if (!strncmp(ext, ".swf", 4) || !strncmp(ext, ".SWF", 4))
+    return HTTP_CONTENT_SWF;
+
+  if (!strncmp(ext, ".js", 3) || !strncmp(ext, ".JS", 3))
+    return HTTP_CONTENT_JAVASCRIPT;
+
+  if (!strncmp(ext-1, "html", 4) || !strncmp(ext, "htm", 3) || strchr(ext-1, '.') == NULL)
+    return HTTP_CONTENT_HTML;
+
+  // default type
+  return HTTP_CONTENT_HTML;
+  // return HTTP_CONTENT_JAVASCRIPT;
+  return -1;
+  
+}
+
+*/
+
+
+
+
+
+
+
+
+unsigned int find_client_payload(char* buf, int len, int type) {
+  int r = rand() % payload_count;
+  int cnt = 0;
+  char* inbuf;
+
+#ifdef DEBUG
+  fprintf(stderr, "TRYING payload %d \n", r);
+#endif
+  while (1) {
+    pentry_header* p = &payload_hdrs[r];
+    if (p->ptype == type) {
+      inbuf = payloads[r];
+      if (find_uri_type(inbuf, p->length) != HTTP_CONTENT_SWF &&
+          find_uri_type(inbuf, p->length) != HTTP_CONTENT_HTML &&
+	  find_uri_type(inbuf, p->length) != HTTP_CONTENT_JAVASCRIPT &&
+	  find_uri_type(inbuf, p->length) != HTTP_CONTENT_PDF) {
+	goto next;
+      }
+      if (p->length > len) {
+	fprintf(stderr, "BUFFER TOO SMALL... \n");
+	goto next;
+      }
+      else
+	len = p->length;
+      break;
+    }
+  next:
+    r = (r+1) % payload_count;
+    
+
+    // no matching payloads...
+    if (cnt++ == payload_count) {
+      fprintf(stderr, "NO MATCHING PAYLOADS... \n");
+      return 0;
+    }
+  }
+
+  inbuf[len] = 0;
+
+  // clean up the buffer...
+  return parse_client_headers(inbuf, buf, len);
+  
+}
+
+
+/*
+ * skipJSPattern returns the number of characters to skip when
+ * the input pointer matches the start of a common JavaScript
+ * keyword 
+ *
+ * todo: 
+ * Use a more efficient regular expression matching algo
+ */
+
+
+
+int skipJSPattern(char *cp, int len) {
+  int i,j;
+
+
+  char keywords [21][10]= {"function", "return", "var", "int", "random", "Math", "while",
+			   "else", "for", "document", "write", "writeln", "true",
+			   "false", "True", "False", "window", "indexOf", "navigator", "case", "if"};
+
+
+  if (len < 1) return 0;
+
+  // change the limit to 21 to enable if as a keyword
+  for (i=0; i < 20; i++) {
+    char* word = keywords[i];
+    
+    if (len <= (int) strlen(word))
+      continue;
+
+    if (word[0] != cp[0])
+      continue;
+
+    for (j=1; j < (int) strlen(word); j++) {
+      if (isxdigit(word[j])) {
+	if (!isxdigit(cp[j]))
+	  goto next_word;
+	else
+	  continue;
+      }
+      
+      if (cp[j] != word[j])
+	goto next_word;
+    }
+    if (!isalnum(cp[j]))
+      return strlen(word)+1;
+      
+  next_word:
+    continue;
+  }
+
+  return 0;
+}
+
+
+
+
+/* int skipJSPattern (char *cp, int len) { */
+
+/*   // log_debug("Turning off skipJSPattern for debugging"); */
+/*   //  return 0; */
+
+/*   if (len < 1) return 0; */
+
+/*   if (len > 8) { */
+/*     // "function " and "function(" */
+/*     if (cp[0] == 'f' && */
+/*         !strncmp(cp+1, "un", 2) && */
+/*         isxdigit(cp[3]) && */
+/*         !strncmp(cp+4, "tion", 4) && */
+/*         (cp[8] == ' ' || cp[8] == '(')) */
+/*     return 9; */
+/*   } */
+
+/*   if (len > 6) { */
+/*     // "return " */
+/*     if (cp[0] == 'r' && */
+/*         isxdigit(cp[1]) && */
+/*         !strncmp(cp+2, "turn ", 5))  */
+/*     return 7; */
+/*     // "switch " */
+/*     if (cp[0] == 's' && */
+/*         !strncmp(cp+1, "wit", 3) && */
+/*         isxdigit(cp[4]) && */
+/*         !strncmp(cp+5, "h ", 2))  */
+/*     return 7; */
+/*   } */
+
+/*   if (len > 5) { */
+/*     // "while " and "while(" */
+/*     if (cp[0] == 'w' && */
+/*         !strncmp(cp+1, "hil", 3) && */
+/*         isxdigit(cp[4]) && */
+/*         (cp[5] == ' ' || cp[5] == '(')) */
+/*     return 6; */
+/*   } */
+
+/*   if (len > 4) { */
+/*     // "else " and "else{" */
+/*     if (cp[0] == 'e' && */
+/*         !strncmp(cp, "ls", 2) && */
+/*         isxdigit(cp[3]) && */
+/*         (cp[4] == ' ' || cp[4] == '{')) */
+/*     return 5; */
+/*   } */
+
+/*   if (len > 3) { */
+/*     // "var " */
+/*     if (cp[0] == 'v' && */
+/*         isxdigit(cp[1]) && */
+/*         cp[2] == 'r' && */
+/*         cp[3] == ' ') */
+/*     return 4; */
+/*   } */
+
+/*   return 0; */
+/* } */
+
+
+
+int isalnum_ (char c) {
+  if (isalnum(c) || c == '_') return 1;
+  else return 0;
+}
+
+int offset2Alnum_ (char *p, int range) {
+  char *cp = p;
+
+  while ((cp < (p+range)) && !isalnum_(*cp)) {
+    cp++;
+  }
+
+  if (cp < (p+range)) {
+    return (cp-p);
+  } else {
+    return -1;
+  }
+}
+
+
+
+/*
+ * offset2Hex returns the offset to the next usable hex char.
+ * usable here refer to char that our steg module can use to encode
+ * data. in particular, words that correspond to common JavaScript keywords
+ * are not used for data encoding (see skipJSPattern). Also, because
+ * JS var name must start with an underscore or a letter (but not a digit)
+ * we don't use the first char of a word for encoding data
+ *
+ * e.g., the JS statement "var a;" won't be used for encoding data
+ * because "var" is a common JS keyword and "a" is the first char of a word
+ *
+ * Input:
+ * p - ptr to the starting pos 
+ * range - max number of char to look
+ * isLastCharHex - is the char pointed to by (p-1) a hex char 
+ *
+ * Output:
+ * offset2Hex returns the offset to the next usable hex char
+ * between p and (p+range), if it exists;
+ * otherwise, it returns -1
+ *
+ */
+int offset2Hex (char *p, int range, int isLastCharHex) {
+  char *cp = p;
+  int i,j;
+  int isFirstWordChar = 1;
+
+  if (range < 1) return -1;
+
+  // case 1: last char is hexadecimal
+  if (isLastCharHex) {
+    if (isxdigit(*cp)) return 0; // base case
+    else {
+      while (cp < (p+range) && isalnum_(*cp)) {
+        cp++;
+        if (isxdigit(*cp)) return (cp-p);
+      }
+      if (cp >= (p+range)) return -1;
+      // non-alnum_ found
+      // fallthru and handle case 2
+    }
+  }
+ 
+  // case 2:
+  // find the next word that starts with alnum or underscore,
+  // which could be a variable, keyword, or literal inside a string
+
+  i = offset2Alnum_(cp, p+range-cp);
+  if (i == -1) return -1;
+
+  while (cp < (p+range) && i != -1) {
+
+    if (i == 0) { 
+      if (isFirstWordChar) {
+        j = skipJSPattern(cp, p+range-cp); 
+        if (j > 0) {
+          cp = cp+j;
+        } else {
+          cp++; isFirstWordChar = 0; // skip the 1st char of a word
+        }
+      } else { // we are in the middle of a word; no need to invoke skipJSPattern
+        if (isxdigit(*cp)) return (cp-p);
+        if (! isalnum_(*cp)) {
+          isFirstWordChar = 1;
+        }
+        cp++;
+     }
+   } else {
+     cp += i; isFirstWordChar = 1;
+   }
+   i = offset2Alnum_(cp, p+range-cp);
+
+  } // while
+
+  // cannot find next usable hex char 
+  return -1;
+ 
+}
+
+/*
+ * capacityJS3 is the next iteration for capacityJS
+ */
+unsigned int capacityJS3 (char* buf, int len, int mode) {
+  char *hEnd, *bp, *jsStart, *jsEnd;
+  int cnt=0;
+  int j;
+
+  // jump to the beginning of the body of the HTTP message
+  hEnd = strstr(buf, "\r\n\r\n");
+  if (hEnd == NULL) {
+    // cannot find the separator between HTTP header and HTTP body
+    return 0;
+  }
+  bp = hEnd + 4;
+
+
+  if (mode == CONTENT_JAVASCRIPT) {
+    j = offset2Hex(bp, (buf+len)-bp, 0);
+    while (j != -1) {
+      cnt++;
+      if (j == 0) {
+        bp = bp+1;
+      } else {
+        bp = bp+j+1;
+      }
+
+      if (len < buf + len - bp) {
+	fprintf(stderr, "HERE\n");
+      }
+      j = offset2Hex(bp, (buf+len)-bp, 1);
+    } // while
+    return cnt;
+  } else if (mode == CONTENT_HTML_JAVASCRIPT) {
+     while (bp < (buf+len)) {
+       jsStart = strstr(bp, "<script type=\"text/javascript\">");
+       if (jsStart == NULL) break;
+       bp = jsStart+31;
+       jsEnd = strstr(bp, "</script>");
+       if (jsEnd == NULL) break;
+       // count the number of usable hex char between jsStart+31 and jsEnd
+
+       j = offset2Hex(bp, jsEnd-bp, 0);
+       while (j != -1) {
+         cnt++;
+         if (j == 0) {
+           bp = bp+1;
+         } else {
+           bp = bp+j+1;
+         }
+
+	 if (len < jsEnd - buf || len < jsEnd - bp) {
+	   fprintf(stderr, "HERE2\n");
+	 }
+
+
+         j = offset2Hex(bp, jsEnd-bp, 1);
+       } // while (j != -1)
+
+       if (buf + len < bp + 9) {
+	 fprintf(stderr, "HERE3\n");
+       }
+
+
+       bp += 9;
+     } // while (bp < (buf+len))
+     return cnt;
+  } else {
+    fprintf(stderr, "Unknown mode (%d) for capacityJS() ... \n", mode);
+    return 0;
+  }
+}
+
+
+/*
+ * strInBinary looks for char array pattern of length patternLen in a char array
+ * blob of length blobLen
+ *
+ * return a pointer for the first occurrence of pattern in blob, if found
+ * otherwise, return NULL
+ * 
+ */
+char *
+strInBinary (const char *pattern, unsigned int patternLen, 
+             const char *blob, unsigned int blobLen) {
+  int found = 0;
+  char *cp = (char *)blob;
+
+  while (1) {
+    if (blob+blobLen-cp < patternLen) break;
+    if (*cp == pattern[0]) {
+      if (memcmp(cp, pattern, patternLen) == 0) {
+        found = 1;
+        break;
+      }
+    }
+    cp++; 
+  }
+  if (found) return cp;
+  else return NULL;
+}
+
+
+/*
+ * has_eligible_HTTP_content() identifies if the input HTTP message 
+ * contains a specified type of content, used by a steg module to
+ * select candidate HTTP message as cover traffic
+ */
+
+// for JavaScript, there are two cases:
+// 1) If Content-Type: has one of the following values
+//       text/javascript 
+//       application/x-javascript
+//       application/javascript
+// 2) Content-Type: text/html and 
+//    HTTP body contains <script type="text/javascript"> ... </script>
+// #define CONTENT_JAVASCRIPT		1 (for case 1)
+// #define CONTENT_HTML_JAVASCRIPT	2 (for case 2)
+//
+// for pdf, we look for the msgs whose Content-Type: has one of the
+// following values
+// 1) application/pdf
+// 2) application/x-pdf
+// 
+
+int has_eligible_HTTP_content (char* buf, int len, int type) {
+  char* ptr = buf;
+  char* matchptr;
+  int tjFlag=0, thFlag=0, ceFlag=0, teFlag=0, http304Flag=0, clZeroFlag=0, pdfFlag=0, swfFlag=0, gzipFlag=0;
+  char* end, *cp;
+
+#ifdef DEBUG
+  fprintf(stderr, "TESTING availabilty of js in payload ... \n");
+#endif
+
+  if (type != HTTP_CONTENT_JAVASCRIPT &&
+      type != HTTP_CONTENT_HTML &&
+      type != HTTP_CONTENT_PDF && type != HTTP_CONTENT_SWF)
+    return 0;
+
+  // assumption: buf is null-terminated
+  if (!strstr(buf, "\r\n\r\n"))
+    return 0;
+
+
+  while (1) {
+    end = strstr(ptr, "\r\n");
+    if (end == NULL) {
+      break;
+    }
+
+    if (!strncmp(ptr, "Content-Type:", 13)) {
+	
+      if (!strncmp(ptr+14, "text/javascript", 15) || 
+	  !strncmp(ptr+14, "application/javascript", 22) || 
+	  !strncmp(ptr+14, "application/x-javascript", 24)) {
+	tjFlag = 1;
+      }
+      if (!strncmp(ptr+14, "text/html", 9)) {
+	thFlag = 1;
+      }
+      if (!strncmp(ptr+14, "application/pdf", 15) || 
+	  !strncmp(ptr+14, "application/x-pdf", 17)) {
+	pdfFlag = 1;
+      }
+      if (!strncmp(ptr+14, "application/x-shockwave-flash", strlen("application/x-shockwave-flash"))) {
+	swfFlag = 1;
+      }
+
+    } else if (!strncmp(ptr, "Content-Encoding: gzip", 22)) {
+      gzipFlag = 1;
+    } else if (!strncmp(ptr, "Content-Encoding:", 17)) { // Content-Encoding that is not gzip
+      ceFlag = 1;
+    } else if (!strncmp(ptr, "Transfer-Encoding:", 18)) {
+      teFlag = 1;
+    } else if (!strncmp(ptr, "HTTP/1.1 304 ", 13)) {
+      http304Flag = 1;
+    } else if (!strncmp(ptr, "Content-Length: 0", 17)) {
+      clZeroFlag = 1;
+    }
+    
+    if (!strncmp(end, "\r\n\r\n", 4)){
+      break;
+    }
+    ptr = end+2;
+  }
+
+#ifdef DEBUG
+  printf("tjFlag=%d; thFlag=%d; gzipFlag=%d; ceFlag=%d; teFlag=%d; http304Flag=%d; clZeroFlag=%d\n", 
+    tjFlag, thFlag, gzipFlag, ceFlag, teFlag, http304Flag, clZeroFlag);
+#endif
+
+  // if (type == HTTP_CONTENT_JAVASCRIPT)
+  if (type == HTTP_CONTENT_JAVASCRIPT || type == HTTP_CONTENT_HTML) {
+    // empty body if it's HTTP not modified (304) or zero Content-Length
+    if (http304Flag || clZeroFlag) return 0; 
+
+    // for now, we're not dealing with Transfer-Encoding (e.g., chunked)
+    // or Content-Encoding that is not gzip
+    // if (teFlag) return 0;
+    if (teFlag || ceFlag) return 0;
+
+    if (tjFlag && ceFlag && end != NULL) {
+      log_debug("(JS) gzip flag detected with hdr len %d", (int)(end-buf+4));
+    } else if (thFlag && ceFlag && end != NULL) {
+      log_debug("(HTML) gzip flag detected with hdr len %d", (int)(end-buf+4));
+    }
+
+    // case 1
+    if (tjFlag) return 1; 
+
+    // case 2: check if HTTP body contains <script type="text/javascript">
+    if (thFlag) {
+      matchptr = strstr(ptr, "<script type=\"text/javascript\">");
+      if (matchptr != NULL) {
+        return 2;
+      }
+    }
+  }
+
+  if (type == HTTP_CONTENT_PDF && pdfFlag) {
+    // reject msg with empty body: HTTP not modified (304) or zero Content-Length
+    if (http304Flag || clZeroFlag) return 0; 
+
+    // for now, we're not dealing with Transfer-Encoding (e.g., chunked)
+    // or Content-Encoding that is not gzip
+    // if (teFlag) return 0;
+    if (teFlag || ceFlag) return 0;
+
+    // check if HTTP body contains "endstream";
+    // strlen("endstream") == 9
+    
+    cp = strInBinary("endstream", 9, ptr, buf+len-ptr);
+    if (cp != NULL) {
+      // log_debug("Matched endstream!");
+      return 1;
+    }
+  }
+  
+  if (type == HTTP_CONTENT_SWF && swfFlag == 1 && 
+      ((len + buf - end) > SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 8))
+    return 1;
+
+  return 0;
+}
+
+
+
+unsigned int capacityPDF (char* buf, int len) {
+  char *hEnd, *bp, *streamStart, *streamEnd;
+  int cnt=0;
+  int size;
+
+  // jump to the beginning of the body of the HTTP message
+  hEnd = strstr(buf, "\r\n\r\n");
+  if (hEnd == NULL) {
+    // cannot find the separator between HTTP header and HTTP body
+    return 0;
+  }
+  bp = hEnd + 4;
+
+  while (bp < (buf+len)) {
+     streamStart = strInBinary("stream", 6, bp, (buf+len)-bp);
+     // streamStart = strstr(bp, "stream");
+     if (streamStart == NULL) break;
+     bp = streamStart+6;
+     streamEnd = strInBinary("endstream", 9, bp, (buf+len)-bp);
+     // streamEnd = strstr(bp, "endstream");
+     if (streamEnd == NULL) break;
+     // count the number of char between streamStart+6 and streamEnd
+     size = streamEnd - (streamStart+6) - 2; // 2 for \r\n before streamEnd
+     if (size > 0) {
+       cnt = cnt + size;
+       log_debug("capacity of pdf increase by %d", size);
+     }
+     bp += 9;
+  }
+  return cnt;
+}
+
+
+
+
+
+
+
+
+
+/*
+ * init_payload_pool initializes the arrays pertaining to 
+ * message payloads for the specified content type
+ *
+ * Specifically, it populates the following arrays
+ * static int initTypePayload[MAX_CONTENT_TYPE];
+ * static int typePayloadCount[MAX_CONTENT_TYPE];
+ * static int typePayload[MAX_CONTENT_TYPE][MAX_PAYLOADS];
+ * static int typePayloadCap[MAX_CONTENT_TYPE][MAX_PAYLOADS];
+ *
+ * Input:
+ * len - max length of payload
+ * type - ptype field value in pentry_header
+ * contentType - (e.g, HTTP_CONTENT_JAVASCRIPT for JavaScript content)
+ */
+
+
+
+
+int  init_JS_payload_pool(int len, int type, int minCapacity) {
+
+  // stat for usable payload
+  int minPayloadSize = 0, maxPayloadSize = 0; 
+  int sumPayloadSize = 0;
+  int minPayloadCap = 0, maxPayloadCap = 0;
+  int sumPayloadCap = 0;
+
+  unsigned int contentType = HTTP_CONTENT_JAVASCRIPT;
+
+  int cnt = 0;
+  int r;
+  pentry_header* p;
+  char* msgbuf;
+  int cap;
+  int mode;
+
+
+
+  if (payload_count == 0) {
+    log_debug("payload_count == 0; forgot to run load_payloads()?\n");
+    return 0;
+  }
+  
+  if (initTypePayload[contentType] != 0) return 1; // init is done already
+
+
+  for (r = 0; r < payload_count; r++) {
+    p = &payload_hdrs[r];
+    if (p->ptype != type || p->length > len) {
+      continue;
+    }
+
+    msgbuf = payloads[r];
+
+    mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_JAVASCRIPT);
+    if (mode == CONTENT_JAVASCRIPT) {
+      
+      cap = capacityJS3(msgbuf, p->length, mode);
+      if (cap <  JS_DELIMITER_SIZE) 
+	continue;
+
+      cap = (cap - JS_DELIMITER_SIZE)/2;
+
+      if (cap > minCapacity) {
+	typePayloadCap[contentType][cnt] = cap; // (cap-JS_DELIMITER_SIZE)/2;
+	// because we use 2 hex char to encode every data byte, the available
+	// capacity for encoding data is divided by 2
+	typePayload[contentType][cnt] = r;
+	cnt++;
+	
+	// update stat
+	if (cnt == 1) {
+	  minPayloadSize = p->length; maxPayloadSize = p->length;
+	  minPayloadCap = cap; maxPayloadCap = cap;
+	} 
+	else {
+	  if (minPayloadSize > p->length) minPayloadSize = p->length; 
+	  if (maxPayloadSize < p->length) maxPayloadSize = p->length; 
+	  if (minPayloadCap > cap) minPayloadCap = cap;
+	  if (maxPayloadCap < cap) {
+	    maxPayloadCap = cap;
+	  }
+	  
+	}
+	sumPayloadSize += p->length; sumPayloadCap += cap;
+      }
+    }
+  }
+
+  
+  max_JS_capacity = maxPayloadCap;
+
+
+  initTypePayload[contentType] = 1;
+  typePayloadCount[contentType] = cnt;
+  log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
+     contentType, typePayloadCount[contentType]); 
+  log_debug("minPayloadSize = %d", minPayloadSize); 
+  log_debug("maxPayloadSize = %d", maxPayloadSize); 
+  log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt); 
+  log_debug("minPayloadCap  = %d", minPayloadCap); 
+  log_debug("maxPayloadCap  = %d", maxPayloadCap); 
+  log_debug("avgPayloadCap  = %f", (float)sumPayloadCap/(float)cnt); 
+  return 1;
+}
+
+
+int  init_HTML_payload_pool(int len, int type, int minCapacity) {
+
+  // stat for usable payload
+  int minPayloadSize = 0, maxPayloadSize = 0; 
+  int sumPayloadSize = 0;
+  int minPayloadCap = 0, maxPayloadCap = 0;
+  int sumPayloadCap = 0;
+
+  unsigned int contentType = HTTP_CONTENT_HTML;
+
+  int cnt = 0;
+  int r;
+  pentry_header* p;
+  char* msgbuf;
+  int cap;
+  int mode;
+
+
+
+  if (payload_count == 0) {
+    log_debug("payload_count == 0; forgot to run load_payloads()?\n");
+    return 0;
+  }
+  
+  if (initTypePayload[contentType] != 0) return 1; // init is done already
+
+
+  for (r = 0; r < payload_count; r++) {
+    p = &payload_hdrs[r];
+    if (p->ptype != type || p->length > len) {
+      continue;
+    }
+
+    msgbuf = payloads[r];
+
+    mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_HTML);
+    if (mode == CONTENT_HTML_JAVASCRIPT) {
+      
+      cap = capacityJS3(msgbuf, p->length, mode);
+      if (cap <  JS_DELIMITER_SIZE) 
+	continue;
+
+      cap = (cap - JS_DELIMITER_SIZE)/2;
+
+      if (cap > minCapacity) {
+	typePayloadCap[contentType][cnt] = cap; // (cap-JS_DELIMITER_SIZE)/2;
+	// because we use 2 hex char to encode every data byte, the available
+	// capacity for encoding data is divided by 2
+	typePayload[contentType][cnt] = r;
+	cnt++;
+	
+	// update stat
+	if (cnt == 1) {
+	  minPayloadSize = p->length; maxPayloadSize = p->length;
+	  minPayloadCap = cap; maxPayloadCap = cap;
+	} 
+	else {
+	  if (minPayloadSize > p->length) minPayloadSize = p->length; 
+	  if (maxPayloadSize < p->length) maxPayloadSize = p->length; 
+	  if (minPayloadCap > cap) minPayloadCap = cap;
+	  if (maxPayloadCap < cap) {
+	    maxPayloadCap = cap;
+	  }
+	  
+	}
+	sumPayloadSize += p->length; sumPayloadCap += cap;
+      }
+    }
+  }
+
+  
+  max_HTML_capacity = maxPayloadCap;
+
+
+  initTypePayload[contentType] = 1;
+  typePayloadCount[contentType] = cnt;
+  log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
+     contentType, typePayloadCount[contentType]); 
+  log_debug("minPayloadSize = %d", minPayloadSize); 
+  log_debug("maxPayloadSize = %d", maxPayloadSize); 
+  log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt); 
+  log_debug("minPayloadCap  = %d", minPayloadCap); 
+  log_debug("maxPayloadCap  = %d", maxPayloadCap); 
+  log_debug("avgPayloadCap  = %f", (float)sumPayloadCap/(float)cnt); 
+  return 1;
+}
+
+
+
+
+
+
+
+
+int  init_PDF_payload_pool(int len, int type, int minCapacity) {
+
+  // stat for usable payload
+  int minPayloadSize = 0, maxPayloadSize = 0; 
+  int sumPayloadSize = 0;
+  int minPayloadCap = 0, maxPayloadCap = 0;
+  int sumPayloadCap = 0;
+
+  int cnt = 0;
+  int r;
+  pentry_header* p;
+  char* msgbuf;
+  int cap;
+  int mode;
+  unsigned int contentType = HTTP_CONTENT_PDF;
+  
+
+  if (payload_count == 0) {
+     fprintf(stderr, "payload_count == 0; forgot to run load_payloads()?\n");
+     return 0;
+  }
+  
+  if (initTypePayload[contentType] != 0) return 1; // init is done already
+
+
+  for (r = 0; r < payload_count; r++) {
+    p = &payload_hdrs[r];
+    if (p->ptype != type || p->length > len) {
+      continue;
+    }
+
+    msgbuf = payloads[r];
+
+    mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_PDF);
+    if (mode > 0) {
+      // use capacityPDF() to find out the amount of data that we
+      // can encode in the pdf doc 
+      // cap = minCapacity+1;
+      cap = capacityPDF(msgbuf, p->length);
+      log_debug("got pdf (index %d) with capacity %d", r, cap);
+      if (cap > minCapacity) {
+	log_debug("pdf (index %d) greater than mincapacity %d", cnt, minCapacity);
+	typePayloadCap[contentType][cnt] = (cap-PDF_DELIMITER_SIZE)/2;
+	typePayload[contentType][cnt] = r;
+	cnt++;
+	
+	// update stat
+	if (cnt == 1) {
+	  minPayloadSize = p->length; maxPayloadSize = p->length;
+	  minPayloadCap = cap; maxPayloadCap = cap;
+	} 
+	else {
+	  if (minPayloadSize > p->length) minPayloadSize = p->length; 
+	  if (maxPayloadSize < p->length) maxPayloadSize = p->length; 
+	  if (minPayloadCap > cap) minPayloadCap = cap;
+	  if (maxPayloadCap < cap) maxPayloadCap = cap;
+	}
+	sumPayloadSize += p->length; sumPayloadCap += cap;
+      }
+    }
+  }
+
+  max_PDF_capacity = maxPayloadCap;
+  initTypePayload[contentType] = 1;
+  typePayloadCount[contentType] = cnt;
+  log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
+     contentType, typePayloadCount[contentType]); 
+  log_debug("minPayloadSize = %d", minPayloadSize); 
+  log_debug("maxPayloadSize = %d", maxPayloadSize); 
+  log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt); 
+  log_debug("minPayloadCap  = %d", minPayloadCap); 
+  log_debug("maxPayloadCap  = %d", maxPayloadCap); 
+  log_debug("avgPayloadCap  = %f", (float)sumPayloadCap/(float)cnt); 
+  return 1;
+}
+
+
+
+
+
+int  init_SWF_payload_pool(int len, int type, int minCapacity) {
+
+  // stat for usable payload
+  int minPayloadSize = 0, maxPayloadSize = 0; 
+  int sumPayloadSize = 0;
+
+  int cnt = 0;
+  int r;
+  pentry_header* p;
+  char* msgbuf;
+  int mode;
+  unsigned int contentType = HTTP_CONTENT_SWF;
+
+
+  if (payload_count == 0) {
+     fprintf(stderr, "payload_count == 0; forgot to run load_payloads()?\n");
+     return 0;
+  }
+  
+  if (initTypePayload[contentType] != 0) return 1; // init is done already
+
+
+  for (r = 0; r < payload_count; r++) {
+    p = &payload_hdrs[r];
+    if (p->ptype != type || p->length > len) {
+      continue;
+    }
+
+    msgbuf = payloads[r];
+    // found a payload corr to the specified contentType
+
+    mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_SWF);
+    if (mode > 0) {
+      typePayload[contentType][cnt] = r;
+      cnt++;
+      // update stat
+      if (cnt == 1) {
+	minPayloadSize = p->length; 
+	maxPayloadSize = p->length;
+      } 
+      else {
+	if (minPayloadSize > p->length) 
+	  minPayloadSize = p->length; 
+	if (maxPayloadSize < p->length) 
+	  maxPayloadSize = p->length; 
+      }
+      sumPayloadSize += p->length;
+    }
+  }
+    
+  initTypePayload[contentType] = 1;
+  typePayloadCount[contentType] = cnt;
+  log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
+     contentType, typePayloadCount[contentType]); 
+  log_debug("minPayloadSize = %d", minPayloadSize); 
+  log_debug("maxPayloadSize = %d", maxPayloadSize); 
+  log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt); 
+  return 1;
+}
+
+
+
+
+
+
+
+
+
+int get_next_payload (int contentType, char** buf, int* size, int* cap) {
+  int r;
+
+  log_debug("get_next_payload: contentType = %d, initTypePayload = %d, typePayloadCount = %d",
+      contentType, initTypePayload[contentType], typePayloadCount[contentType]);
+
+
+  if (contentType <= 0 ||
+      contentType >= MAX_CONTENT_TYPE ||
+      initTypePayload[contentType] == 0 ||
+      typePayloadCount[contentType] == 0)
+    return 0;
+
+  r = rand() % typePayloadCount[contentType];
+//  int r = 1;
+//  log_debug("SERVER: *** always choose the same payload ***");
+
+  log_debug("SERVER: picked payload with index %d", r);
+  *buf = payloads[typePayload[contentType][r]];
+  *size = payload_hdrs[typePayload[contentType][r]].length;
+  *cap = typePayloadCap[contentType][r];
+  return 1;
+}
+
+
+
+
+
+
+
+
+int get_payload (int contentType, int cap, char** buf, int* size) {
+  int r;
+  unsigned int i = 0;
+  unsigned int cnt = 0;
+
+  log_debug("get_payload: contentType = %d, initTypePayload = %d, typePayloadCount = %d",
+      contentType, initTypePayload[contentType], typePayloadCount[contentType]);
+
+
+  if (contentType <= 0 ||
+      contentType >= MAX_CONTENT_TYPE ||
+      initTypePayload[contentType] == 0 ||
+      typePayloadCount[contentType] == 0)
+    return 0;
+
+
+  cnt = typePayloadCount[contentType];
+   r = rand() % cnt;
+
+  for (i=0; i < cnt; i++) {
+
+    if (typePayloadCap[contentType][(r+i) % cnt] <= cap)
+      continue;
+
+    *buf = payloads[typePayload[contentType][(r+i)%cnt]];
+    *size = payload_hdrs[typePayload[contentType][(r+i)%cnt]].length;
+    return 1;
+  }
+
+
+
+  return 0;
+
+}
+
+
+
+
+int
+find_content_length (char *hdr, int hlen) {
+  char *clStart;
+  char* clEnd;
+  char *clValStart;
+  int valLen;
+  int contentLen;
+  char buf[10];
+
+  clStart = strstr(hdr, "Content-Length: ");
+  if (clStart == NULL) {
+    log_debug("Unable to find Content-Length in the header");
+    return -1;
+  }
+
+  clEnd = strstr((char *)clStart, "\r\n");
+  if (clEnd == NULL) {
+    log_debug("Unable to find end of line for Content-Length");
+    return -1;
+  }
+
+  // clValStart = clStart+strlen("Content-Length: ");
+  clValStart = clStart+16;
+
+  valLen = clEnd-clValStart;
+  if (valLen > 9) return -1;
+  memcpy(buf, clValStart, valLen);
+  buf[valLen] = 0;
+  contentLen = atoi(buf);
+  return contentLen;
+}
+
+
+
+
+
+
+/*
+
+void testOffset2Alnum_skipJSPattern () {
+  char s1[] = "for (i=0; i<10; i++) { print i; }";
+
+  char s2[] = "***abcde*****";
+  int d, i;
+
+  printf("s1 = %s\n", s1);
+  printf("s2 = %s\n", s2);
+
+
+  d = offset2Alnum_(s1, strlen(s1));
+  printf ("offset2Alnum_ for s1 = %d\n", d);
+  d = offset2Alnum_(s2, strlen(s2));
+  printf ("offset2Alnum_ for s2 = %d\n", d);
+
+  i = skipJSPattern (s1, strlen(s1));
+  printf ("skipJSPattern for s1 = %d\n", i);
+  i = skipJSPattern (s2, strlen(s2));
+  printf ("skipJSPattern for s2 = %d\n", i);
+}
+
+
+
+
+void testOffset2Hex () {
+  int d;
+  char s3[] = "for (bc=0; bc<10; bc++) { ad=2*bc+ad; }";
+  printf("len(s3)=%d; s3 = |%s|\n", (int)strlen(s3), s3);
+
+  d = offset2Alnum_(s3, strlen(s3));
+  printf ("offset2Alnum_ for s3 = %d\n", d);
+  d = offset2Hex(s3, strlen(s3), 0);
+  printf ("offset2Hex for s3 = %d\n", d);
+}
+
+
+void testCapacityJS () {
+  int d;
+  char s4[] = "\r\n\r\n abc = abc + 1;";
+  char s6[] = "\r\n\r\n <script type=\"text/javascript\">abc = abc + 1;</script>";
+
+  printf("\nTest for CONTENT_JAVASCRIPT:\n");
+  printf("len(s4)=%d; s4 = |%s|\n", (int)strlen(s4), s4);
+
+  d = offset2Alnum_(s4, strlen(s4));
+  printf ("offset2Alnum_ for s4 = %d\n", d);
+  d = offset2Hex(s4, strlen(s4), 0);
+  printf ("offset2Hex for s4 = %d\n", d);
+
+  printf("capacityJS  (JS) returns %d\n", capacityJS(s4, strlen(s4), CONTENT_JAVASCRIPT));
+  printf("capacityJS3 (JS) returns %d\n", capacityJS3(s4, strlen(s4), CONTENT_JAVASCRIPT));
+
+  printf("\nTest for CONTENT_HTML_JAVASCRIPT:\n");
+  printf("len(s6)=%d; s6 = |%s|\n", (int)strlen(s6), s6);
+
+  d = offset2Alnum_(s6, strlen(s6));
+  printf ("offset2Alnum_ for s6 = %d\n", d);
+  d = offset2Hex(s6, strlen(s6), 0);
+  printf ("offset2Hex for s6 = %d\n", d);
+
+  printf("capacityJS  (HTML) returns %d\n", capacityJS(s6, strlen(s6), CONTENT_HTML_JAVASCRIPT));
+  printf("capacityJS3 (HTML) returns %d\n", capacityJS3(s6, strlen(s6), CONTENT_HTML_JAVASCRIPT));
+}
+*/
+
+
+/*****
+int main() {
+  char buf[HTTP_MSG_BUF_SIZE];
+  bzero(buf, sizeof(buf));
+  // test for TYPE_HTTP_REQUEST
+  // load_payloads("../../traces/client.out");
+  // int len = find_client_payload(buf, 10000, TYPE_HTTP_REQUEST);
+  // printf("%s\n", buf);
+
+  // test for TYPE_HTTP_RESPONSE
+  // load_payloads("../../traces/server-cnn-nogzip.out");
+  // load_payloads("../../traces/server-portals.out"); // ptype==1?
+
+  // testOffset2Alnum_skipJSPattern();
+  // testOffset2Hex();
+  // testCapacityJS();
+  
+  load_payloads("../../traces/server.out");
+  // int r;
+  // r = find_server_payload(&buf, sizeof(buf), TYPE_HTTP_RESPONSE, HTTP_CONTENT_JAVASCRIPT);
+  // if (r > 0) {
+  //   printf("Available payload capablity %d\n", r);
+  // }
+  // return r;
+
+  return 0;
+}
+ *****/
+
diff --git a/src/steg/pdfSteg.c b/src/steg/pdfSteg.c
deleted file mode 100644
index 81efdf4..0000000
--- a/src/steg/pdfSteg.c
+++ /dev/null
@@ -1,630 +0,0 @@
-#include "payloads.h"
-#include "pdfSteg.h"
-
-void buf_dump(unsigned char* buf, int len, FILE *out);
-
-#define STREAM_BEGIN       ">>stream"
-#define STREAM_BEGIN_SIZE  8
-#define STREAM_END         "endstream"
-#define STREAM_END_SIZE    9
-
-#define DEBUG
-
-
-/*
- * pdfSteg: A PDF-based steganography module
- *
- */
-
-
-/*
- * addDelimiter processes the input buffer (inbuf) of length inbuflen,
- * copies it to output buffer (outbuf) of size outbufsize,
- * and adds a two-char-long, end-of-data pattern at the end of outbuf
- * based on delimiter1 and delimiter2.
- *
- * The end-of-data pattern consists of delimiter1 followed by a char
- * that is not delimiter1. Thus, delimiter1 and delimiter2 must be
- * different.
- * 
- * If delimiter1 appears in the input buffer, addDelimiter puts two
- * delimiter1 char in output buffer (to enable removeDelimiter to perform
- * the back transformation)
- *
- * addDelimiter returns the length of the data written to outbuf, including
- * the end-of-data pattern, if the transformation succeeds;
- * otherwise, it returns -1
- *
- */
-int
-addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen, 
-             const char delimiter1, const char delimiter2)
-{
-  int cnt;
-  char *ibp, ic, rc;
-
-  if (delimiter1 == delimiter2) return -1;  
-
-  cnt = 0;
-  ibp = inbuf;
-  while ((ibp-inbuf)<inbuflen && cnt<(outbuflen-2)) {
-    ic = *(ibp++);
-    if (ic != delimiter1) {
-      outbuf[cnt++] = ic;
-    } else {
-      outbuf[cnt++] = delimiter1;
-      outbuf[cnt++] = delimiter1;
-    }
-  }
-
-  // error if outbuf is no large enough for storing the resulting data
-  if (cnt >= (outbuflen-2)) return -1;
-
-  // put delimiter1 and a char that is not a delimiter1
-  // as the end-of-data pattern at the end of outbuf
-  outbuf[cnt++] = delimiter1;
-  // try to get a random char (that is not delimiter1)
-  rc = (char) (rand() % 256);
-  if (rc != delimiter1) {
-    outbuf[cnt++] = rc;
-  } else { // unable to get a rand char != delimiter1, use delimiter2
-    outbuf[cnt++] = delimiter2;
-  }
-  return cnt;
-}
-
-
-/*
- * removeDelimiter performs the reverse transformation of addDelimiter.
- * 
- * returns the length of data written to outbuf, if succeed;
- * otherwise, it returns -1
- *
- * endFlag indicates whether the end-of-encoding byte pattern (i.e.,
- * delimiter1 followed by non-delimiter1) is detected
- *
- * escape indicates if a dangling delimiter1 has been
- * seen in the previous invocation of removeDelimiter
- */
-int
-removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen, 
-                const char delimiter1, int *endFlag, int *escape)
-{
-  int cnt;
-  char *ibp, ic1, ic2;
-
-  cnt = 0;
-  *endFlag = 0;
-  ibp = inbuf;
-
-  if (inbuflen <= 0) return -1;
-
-  // special case: 2-char, end-of-data pattern could be in two buffers
-  // if *escape == true, we need to see if
-  // 1) (*ibp == delimiter1) -> put delimiter1 in outbuf
-  // 2) (*ibp != delimiter1) -> end-of-data detected
-  if (*escape) {
-    ic1 = *ibp;
-    if (ic1 == delimiter1) {
-      outbuf[cnt++] = ic1; ibp++;
-    } else {
-      *endFlag = 1;
-      return 0;
-    }
-  }
-
-  *escape = 0;
-  while ((ibp-inbuf+1)<inbuflen && cnt<outbuflen) {
-    ic1 = *(ibp++);
-    if (ic1 != delimiter1) {
-      outbuf[cnt++] = ic1;
-    } else {
-      // lookahead 1 char
-      ic2 = *ibp;
-      // if the next char is delimiter1
-      if (ic2 == delimiter1) {
-        outbuf[cnt++] = delimiter1; ibp++;
-      } else { // end-of-data pattern detected
-        *endFlag = 1;
-        return cnt;
-      }
-    }
-  }
-
-  if (ibp-inbuf == inbuflen) return cnt;
-
-  // handling the last char in inbuf, if needed
-  ic1 = *ibp;
-  if (ic1 != delimiter1) {
-    outbuf[cnt++] = ic1;
-  } else {
-    // look at the next stream obj to handle the special cases
-    *escape = 1;
-  }
-
-  return cnt;
-}
-
-
-
-/*
- * pdfWrap embeds data of length dlen inside the stream objects of the PDF
- * document (length plen) that appears in the body of a HTTP msg, and
- * stores the result in the output buffer of size outsize
- *
- * pdfWrap returns the length of the pdf document with the data embedded
- * inside, if succeed; otherwise, it returns -1 to indicate an error
- *  
- */ 
-int 
-pdfWrap (char *data, unsigned int dlen,
-         char *pdfTemplate, unsigned int plen,
-         char *outbuf, unsigned int outbufsize)
-{
-  char data2[dlen*2+2];
-  char *tp, *dp, *op, *streamStart, *streamEnd, *plimit;
-  int data2len, cnt, size, size2;
-
-  // assumption: pdfWrap is length-preserving
-  if (outbufsize < plen) return -1;
-
-  data2len = addDelimiter(data, dlen, data2, HTTP_MSG_BUF_SIZE, PDF_DELIMITER, PDF_DELIMITER2);
-  if (data2len < 1) return -1;
-
-
-  op = outbuf;       // current pointer for output buffer 
-  tp = pdfTemplate;  // current pointer for http msg template
-  dp = data2;        // current pointer for data2
-  cnt = 0;           // number of data char encoded
-  plimit = pdfTemplate+plen;
-
-  while (tp < plimit) {
-    // find the next stream obj
-    streamStart = strInBinary(STREAM_BEGIN, STREAM_BEGIN_SIZE, tp, plimit-tp);
-    if (streamStart == NULL) {
-      log_warn("Cannot find stream in pdf");
-      return -1;
-    }
- 
-    // copy everything between tp and "stream" (inclusive) to outbuf
-    size = streamStart - tp + STREAM_BEGIN_SIZE;
-    memcpy(op, tp, size);
-    op += size;
-    tp = streamStart + STREAM_BEGIN_SIZE;
-
-    streamEnd = strInBinary(STREAM_END, STREAM_END_SIZE, tp, plimit-tp);
-    if (streamEnd == NULL) {
-      log_warn("Cannot find endstream in pdf");
-      return -1;
-    }
-
-    // count the number of usable char between tp and streamEnd
-    size = streamEnd-tp;
-
-    // encoding data in the stream obj
-    if (size > 0) {
-        size2 = data2len - cnt;
-        if (size < size2) {
-          memcpy(op, dp, size);
-          op += size; tp += size; dp += size; 
-          memcpy(op, tp, STREAM_END_SIZE);
-          op += STREAM_END_SIZE; tp += STREAM_END_SIZE;
-          cnt += size;
-        } else { // done encoding data
-          memcpy(op, dp, size2);
-          op += size2; tp += size2; dp += size2; 
-          cnt += size2;
-          // printf("Encoded %d char in pdf. Done encoding\n", size2);
-          break;
-        }
-        log_debug("Encoded %d char in pdf", size);
-    } else { // empty stream
-      memcpy(op, tp, STREAM_END_SIZE);
-      op += STREAM_END_SIZE; tp += STREAM_END_SIZE;
-    }
-
-    if (cnt >= data2len) break; // this shouldn't happen ...
-  }
-
-  // copy the rest of pdfTemplate to outbuf
-  size = plimit-tp;
-  log_debug("copying the rest of pdfTemplate to outbuf (size %d)", size); 
-  memcpy(op, tp, size);
-  op += size;
-  return (op-outbuf);
-}
-
-
-
-
-/*
- * pdfUnwrap is the inverse operation of pdfWrap
- */
-int 
-pdfUnwrap (char *data, unsigned int dlen,
-           char *outbuf, unsigned int outbufsize)
-{
-  char *dp, *op, *streamStart, *streamEnd, *dlimit, *olimit;
-  int cnt, size, size2, endFlag;
-  int escape = 0;
-
-  dp = data;   // current pointer for data
-  op = outbuf; // current pointer for outbuf
-  cnt = 0;     // number of char decoded
-  dlimit = data+dlen;
-  olimit = outbuf+outbufsize;
-
-  while (dp < dlimit) {
-    // find the next stream obj
-    streamStart = strInBinary(STREAM_BEGIN, STREAM_BEGIN_SIZE, dp, dlimit-dp);
-    if (streamStart == NULL) {
-      log_warn("Cannot find stream in pdf");
-      return -1;
-    }
-
-    dp = streamStart + STREAM_BEGIN_SIZE;
-    streamEnd = strInBinary(STREAM_END, STREAM_END_SIZE, dp, dlimit-dp);
-    if (streamEnd == NULL) {
-      log_warn("Cannot find endstream in pdf");
-      return -1;
-    }
-
-    // count the number of usable char between tp and streamEnd
-    size = streamEnd-dp;
-
-    if (size > 0) { 
-      size2 = removeDelimiter(dp, size, op, olimit-op, PDF_DELIMITER, &endFlag, &escape);
-      if (size2 < 0) {
-        return -1;
-      }
-      cnt += size2;
-      if (endFlag) { // Done decoding
-        break;
-      } else { // Continue decoding
-        op += size2;
-        dp = streamEnd + STREAM_END_SIZE;
-      }
-    } else { // empty stream obj
-      dp = streamEnd + STREAM_END_SIZE;
-    }
-  }
-
-  return cnt;
-}
-
-
-
-
-
-int x_http2_server_PDF_transmit (steg_t* s, struct evbuffer *source, conn_t *conn) {
-
-  struct evbuffer *dest = conn_get_outbound(conn);
-  size_t sbuflen = evbuffer_get_length(source);
-  unsigned int mpdf;
-  char *pdfTemplate = NULL, *hend;
-  int pdfTemplateSize = 0;
-  // char data1[HTTP_MSG_BUF_SIZE];
-  char data1[(int) sbuflen];
-  char outbuf[HTTP_MSG_BUF_SIZE];
-  int cnt, hLen, outbuflen, i;
-
-  char newHdr[MAX_RESP_HDR_SIZE];
-  int newHdrLen = 0;
-
-  struct evbuffer_iovec *iv;
-  int nv;
-
-  // for debugging pdfWrap and pdfUnwrap
-  // char data2[(int) sbuflen];
-  // int data2len;
-
-  log_debug("Entering SERVER PDF transmit with sbuflen %d", (int)sbuflen);
-
-  nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0);
-  iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
-
-  if (evbuffer_peek(source, sbuflen, NULL, iv, nv) != nv) {
-    free(iv);
-    return -1;
-  }
-
-  cnt = 0;
-  for (i = 0; i < nv; i++) {
-    const unsigned char *p = iv[i].iov_base;
-    const unsigned char *limit = p + iv[i].iov_len;
-    while (p < limit && cnt < (int)sbuflen) {
-      data1[cnt++] = *p++;
-    }
-  }
-
-  free(iv);
-
-  log_debug("SERVER sbuflen = %d; cnt = %d", (int)sbuflen, cnt);
-
-  mpdf = get_max_PDF_capacity();
-
-  if (mpdf <= 0) {
-    log_warn("SERVER ERROR: No pdfTemplate found\n");
-    return -1;
-  }
-
-  if (sbuflen > (size_t) mpdf) {
-    log_warn("SERVER ERROR: pdfTemplate cannot accommodate data %d %dn",
-                (int) sbuflen, (int) mpdf);
-    return -1;
-  }
-
-  if (get_payload(HTTP_CONTENT_PDF, sbuflen, &pdfTemplate, &pdfTemplateSize) == 1) {
-    log_debug("SERVER found the next HTTP response template with size %d", pdfTemplateSize);
-  } else {
-    log_warn("SERVER couldn't find the next HTTP response template");
-    return -1;
-  }
-
-  hend = strstr(pdfTemplate, "\r\n\r\n");
-  if (hend == NULL) {
-    log_warn("SERVER unable to find end of header in the HTTP template");
-    return -1;
-  }
-
-  hLen = hend+4-pdfTemplate;
-  
-  log_debug("SERVER calling pdfWrap for data1 with length %d", cnt);
-  outbuflen = pdfWrap(data1, cnt, hend+4, pdfTemplateSize-hLen, outbuf, HTTP_MSG_BUF_SIZE);
-  if (outbuflen < 0) {
-    log_warn("SERVER pdfWrap fails");
-    return -1;
-  }
-  log_debug("SERVER pdfSteg sends resp with hdr len %d body len %d", hLen, outbuflen);
-
-
-  // debugging
-  // buf_dump((unsigned char *)data1, cnt, stderr);
-
-  // data2len = pdfUnwrap(outbuf, outbuflen, data2, sbuflen);
-  // if ((int)sbuflen == data2len) {
-  //   log_warn("sbuflen == data2len == %d", (int)sbuflen);
-  //   if (memcmp(data1, data2, sbuflen) == 0) {
-  //     log_warn("data1 and data2 match");
-  //   } else {
-  //     log_warn("data1 and data2 DO NOT match!! Dumping data1 ...");
-  //     buf_dump((unsigned char *)data1, cnt, stderr);
-  //     log_warn("data1 and data2 DO NOT match!! Dumping data2...");
-  //     buf_dump((unsigned char *)data2, data2len, stderr);
-  //   }
-  // } else {
-  //   log_warn("*** sbuflen = %d, data2len = %d *** Dumping data1 ...", (int)sbuflen, data2len);
-  //   buf_dump((unsigned char *)data1, cnt, stderr);
-  //   log_warn("*** sbuflen = %d, data2len = %d *** Dumping data2 ...", (int)sbuflen, data2len);
-  //   buf_dump((unsigned char *)data2, data2len, stderr);
-  // }
-
-
-  newHdrLen = gen_response_header((char*) "application/pdf", 0, outbuflen, newHdr, sizeof(newHdr));
-  if (newHdrLen < 0) {
-    log_warn("SERVER ERROR: gen_response_header fails for pdfSteg");
-    return -1;
-  }
-
-  if (evbuffer_add(dest, newHdr, newHdrLen)) {
-    log_warn("SERVER ERROR: evbuffer_add() fails for newHdr");
-    return -1;
-  }
-  // if (evbuffer_add(dest, pdfTemplate, hLen)) {
-  //   log_warn("SERVER ERROR: evbuffer_add() fails for pdfTemplate");
-  //   return -1;
-  // }
-
-  if (evbuffer_add(dest, outbuf, outbuflen)) {
-    log_warn("SERVER ERROR: evbuffer_add() fails for outbuf");
-    return -1;
-  }
-
-  evbuffer_drain(source, sbuflen);
-
-  conn_close_after_transmit(conn);
-  //  downcast_steg(s)->have_transmitted = 1;
-  return 0;
-}
-
-
-
-int
-x_http2_handle_client_PDF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
-  struct evbuffer_ptr s2;
-  unsigned int response_len = 0, hdrLen;
-  char outbuf[HTTP_MSG_BUF_SIZE];
-  int content_len = 0, outbuflen;
-  char *httpHdr, *httpBody;
-
-  log_debug("Entering CLIENT PDF receive");
-
-  s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
-  if (s2.pos == -1) {
-    log_warn("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
-    //    evbuffer_dump(source, stderr);
-    return RECV_INCOMPLETE;
-  }
-
-  log_debug("CLIENT received response header with len %d", (int)s2.pos);
-
-  response_len = 0;
-  hdrLen = s2.pos + strlen("\r\n\r\n");
-  response_len += hdrLen;
-
-  httpHdr = (char *) evbuffer_pullup(source, s2.pos);
-  if (httpHdr == NULL) {
-    log_warn("CLIENT unable to pullup the complete HTTP header");
-    return RECV_BAD;
-  }
-
-  content_len = find_content_length(httpHdr, hdrLen);
-  if (content_len < 0) {
-    log_warn("CLIENT unable to find content length");
-    return RECV_BAD;
-  }
-  log_debug("CLIENT received Content-Length = %d\n", content_len);
-
-  response_len += content_len;
-
-  if (response_len > evbuffer_get_length(source))
-    return RECV_INCOMPLETE;
-
-  httpHdr = (char *) evbuffer_pullup(source, response_len);
-
-  if (httpHdr == NULL) {
-    log_warn("CLIENT unable to pullup the complete HTTP body");
-    return RECV_BAD;
-  }
-
-
-  httpBody = httpHdr + hdrLen;
-
-
-  outbuflen = pdfUnwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
-  if (outbuflen < 0) {
-    log_warn("CLIENT ERROR: pdfUnwrap fails\n");
-    return RECV_BAD;
-  }
-
-  log_debug("CLIENT unwrapped data of length %d:", outbuflen);
-
-
-  if (evbuffer_add(dest, outbuf, outbuflen)) {
-    log_warn("CLIENT ERROR: evbuffer_add to dest fails\n");
-    return RECV_BAD;
-  }
-
-  // log_debug("Drained source for %d char\n", response_len);
-  if (evbuffer_drain(source, response_len) == -1) {
-    log_warn("CLIENT ERROR: failed to drain source\n");
-    return RECV_BAD;
-  }
-
-  //  downcast_steg(s)->have_received = 1;
-  conn_expect_close(conn);
-  return RECV_GOOD;
-}
-
-
-
-
-/*****
-int main() {
-  char data1[] = "this is a test?? yes!";
-  char data2[100];
-  char data3[100];
-  int dlen1, dlen2, dlen3, end;
-  char last = ' ';
-  printf("hello world\n");
- 
-  dlen2 = addDelimiter(data1, strlen(data1), data2, 100, '?', '.');
-  printf("dlen2 = %d\n", dlen2);
-  dlen3 = removeDelimiter(data2, dlen2, data3, 100, '?', &end, &last);
-  printf("endflag = %d", end);
-  printf("dlen3 = %d\n", dlen3);
-  if (memcmp(data1, data3, dlen3) == 0) {
-    data1[dlen3] = 0;
-    printf("removeDelimiter(addDelimiter(x)) == x for |%s|\n", data1);
-  } else {
-    printf("removeDelimiter(addDelimiter(x)) != x for |%s|\n", data1);
-  }
-  return 1;
-}
- *****/
-
-/*****
-int main() {
-  char data1[] = "12345";
-  char data2[] = "123456789012";
-  char data3[] = "12345678901";
-  char data4[] = "1234567890?";
-  char pdf1[] = "[PDFHDR][STUFFS1]>>streamABCDEFGHIJYYendstream[STUFFS2]>>streamABCDEFGHIJYYendstream[STUFF3][PDFTRAILER]";
-  char out[200];
-  char orig[200];
-  int r1, r2;
-
-  printf("********************\n");
-  printf("pdfwrap for %s\n", data1);
-  printf("strlen(pdf1) = %d\n", (int)strlen(pdf1));
-  r1 = pdfWrap(data1, strlen(data1), pdf1, strlen(pdf1), out, (int)sizeof(out));
-  if (r1 > 0) {
-    printf("pdfWrap returns %d\n", r1);
-    out[r1] = 0;
-    printf("out[] contains |%s|\n", out);
-  } else {
-    printf("pdfWrap returns %d\n", r1);
-  }
-
-  r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
-  if (r2 > 0) {
-    printf("pdfUnwrap returns %d\n", r2);
-    orig[r2] = 0;
-    printf("orig[] contains |%s|\n", orig);
-  } else {
-    printf("pdfUnwrap returns %d\n", r2);
-  }
-
-  printf("********************\n");
-  printf("pdfwrap for %s\n", data2);
-  r1 = pdfWrap(data2, strlen(data2), pdf1, strlen(pdf1), out, (int)sizeof(out));
-  if (r1 > 0) {
-    printf("pdfWrap returns %d\n", r1);
-    out[r1] = 0;
-    printf("out[] contains |%s|\n", out);
-  } else {
-    printf("pdfWrap returns %d\n", r1);
-  }
-
-  r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
-  if (r2 > 0) {
-    printf("pdfUnwrap returns %d\n", r2);
-    orig[r2] = 0;
-    printf("orig[] contains |%s|\n", orig);
-  } else {
-    printf("pdfUnwrap returns %d\n", r2);
-  }
-
-  printf("********************\n");
-  printf("pdfwrap for %s\n", data3);
-  r1 = pdfWrap(data3, strlen(data3), pdf1, strlen(pdf1), out, (int)sizeof(out));
-  if (r1 > 0) {
-    printf("pdfWrap returns %d\n", r1);
-    out[r1] = 0;
-    printf("out[] contains |%s|\n", out);
-  } else {
-    printf("pdfWrap returns %d\n", r1);
-  }
-
-  r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
-  if (r2 > 0) {
-    printf("pdfUnwrap returns %d\n", r2);
-    orig[r2] = 0;
-    printf("orig[] contains |%s|\n", orig);
-  } else {
-    printf("pdfUnwrap returns %d\n", r2);
-  }
-
-  printf("********************\n");
-  printf("pdfwrap for %s\n", data4);
-  r1 = pdfWrap(data4, strlen(data4), pdf1, strlen(pdf1), out, (int)sizeof(out));
-  if (r1 > 0) {
-    printf("pdfWrap returns %d\n", r1);
-    out[r1] = 0;
-    printf("out[] contains |%s|\n", out);
-  } else {
-    printf("pdfWrap returns %d\n", r1);
-  }
-
-  r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
-  if (r2 > 0) {
-    printf("pdfUnwrap returns %d\n", r2);
-    orig[r2] = 0;
-    printf("orig[] contains |%s|\n", orig);
-  } else {
-    printf("pdfUnwrap returns %d\n", r2);
-  }
-
-  return 0;
-}
- *****/
diff --git a/src/steg/pdfSteg.cc b/src/steg/pdfSteg.cc
new file mode 100644
index 0000000..81efdf4
--- /dev/null
+++ b/src/steg/pdfSteg.cc
@@ -0,0 +1,630 @@
+#include "payloads.h"
+#include "pdfSteg.h"
+
+void buf_dump(unsigned char* buf, int len, FILE *out);
+
+#define STREAM_BEGIN       ">>stream"
+#define STREAM_BEGIN_SIZE  8
+#define STREAM_END         "endstream"
+#define STREAM_END_SIZE    9
+
+#define DEBUG
+
+
+/*
+ * pdfSteg: A PDF-based steganography module
+ *
+ */
+
+
+/*
+ * addDelimiter processes the input buffer (inbuf) of length inbuflen,
+ * copies it to output buffer (outbuf) of size outbufsize,
+ * and adds a two-char-long, end-of-data pattern at the end of outbuf
+ * based on delimiter1 and delimiter2.
+ *
+ * The end-of-data pattern consists of delimiter1 followed by a char
+ * that is not delimiter1. Thus, delimiter1 and delimiter2 must be
+ * different.
+ * 
+ * If delimiter1 appears in the input buffer, addDelimiter puts two
+ * delimiter1 char in output buffer (to enable removeDelimiter to perform
+ * the back transformation)
+ *
+ * addDelimiter returns the length of the data written to outbuf, including
+ * the end-of-data pattern, if the transformation succeeds;
+ * otherwise, it returns -1
+ *
+ */
+int
+addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen, 
+             const char delimiter1, const char delimiter2)
+{
+  int cnt;
+  char *ibp, ic, rc;
+
+  if (delimiter1 == delimiter2) return -1;  
+
+  cnt = 0;
+  ibp = inbuf;
+  while ((ibp-inbuf)<inbuflen && cnt<(outbuflen-2)) {
+    ic = *(ibp++);
+    if (ic != delimiter1) {
+      outbuf[cnt++] = ic;
+    } else {
+      outbuf[cnt++] = delimiter1;
+      outbuf[cnt++] = delimiter1;
+    }
+  }
+
+  // error if outbuf is no large enough for storing the resulting data
+  if (cnt >= (outbuflen-2)) return -1;
+
+  // put delimiter1 and a char that is not a delimiter1
+  // as the end-of-data pattern at the end of outbuf
+  outbuf[cnt++] = delimiter1;
+  // try to get a random char (that is not delimiter1)
+  rc = (char) (rand() % 256);
+  if (rc != delimiter1) {
+    outbuf[cnt++] = rc;
+  } else { // unable to get a rand char != delimiter1, use delimiter2
+    outbuf[cnt++] = delimiter2;
+  }
+  return cnt;
+}
+
+
+/*
+ * removeDelimiter performs the reverse transformation of addDelimiter.
+ * 
+ * returns the length of data written to outbuf, if succeed;
+ * otherwise, it returns -1
+ *
+ * endFlag indicates whether the end-of-encoding byte pattern (i.e.,
+ * delimiter1 followed by non-delimiter1) is detected
+ *
+ * escape indicates if a dangling delimiter1 has been
+ * seen in the previous invocation of removeDelimiter
+ */
+int
+removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen, 
+                const char delimiter1, int *endFlag, int *escape)
+{
+  int cnt;
+  char *ibp, ic1, ic2;
+
+  cnt = 0;
+  *endFlag = 0;
+  ibp = inbuf;
+
+  if (inbuflen <= 0) return -1;
+
+  // special case: 2-char, end-of-data pattern could be in two buffers
+  // if *escape == true, we need to see if
+  // 1) (*ibp == delimiter1) -> put delimiter1 in outbuf
+  // 2) (*ibp != delimiter1) -> end-of-data detected
+  if (*escape) {
+    ic1 = *ibp;
+    if (ic1 == delimiter1) {
+      outbuf[cnt++] = ic1; ibp++;
+    } else {
+      *endFlag = 1;
+      return 0;
+    }
+  }
+
+  *escape = 0;
+  while ((ibp-inbuf+1)<inbuflen && cnt<outbuflen) {
+    ic1 = *(ibp++);
+    if (ic1 != delimiter1) {
+      outbuf[cnt++] = ic1;
+    } else {
+      // lookahead 1 char
+      ic2 = *ibp;
+      // if the next char is delimiter1
+      if (ic2 == delimiter1) {
+        outbuf[cnt++] = delimiter1; ibp++;
+      } else { // end-of-data pattern detected
+        *endFlag = 1;
+        return cnt;
+      }
+    }
+  }
+
+  if (ibp-inbuf == inbuflen) return cnt;
+
+  // handling the last char in inbuf, if needed
+  ic1 = *ibp;
+  if (ic1 != delimiter1) {
+    outbuf[cnt++] = ic1;
+  } else {
+    // look at the next stream obj to handle the special cases
+    *escape = 1;
+  }
+
+  return cnt;
+}
+
+
+
+/*
+ * pdfWrap embeds data of length dlen inside the stream objects of the PDF
+ * document (length plen) that appears in the body of a HTTP msg, and
+ * stores the result in the output buffer of size outsize
+ *
+ * pdfWrap returns the length of the pdf document with the data embedded
+ * inside, if succeed; otherwise, it returns -1 to indicate an error
+ *  
+ */ 
+int 
+pdfWrap (char *data, unsigned int dlen,
+         char *pdfTemplate, unsigned int plen,
+         char *outbuf, unsigned int outbufsize)
+{
+  char data2[dlen*2+2];
+  char *tp, *dp, *op, *streamStart, *streamEnd, *plimit;
+  int data2len, cnt, size, size2;
+
+  // assumption: pdfWrap is length-preserving
+  if (outbufsize < plen) return -1;
+
+  data2len = addDelimiter(data, dlen, data2, HTTP_MSG_BUF_SIZE, PDF_DELIMITER, PDF_DELIMITER2);
+  if (data2len < 1) return -1;
+
+
+  op = outbuf;       // current pointer for output buffer 
+  tp = pdfTemplate;  // current pointer for http msg template
+  dp = data2;        // current pointer for data2
+  cnt = 0;           // number of data char encoded
+  plimit = pdfTemplate+plen;
+
+  while (tp < plimit) {
+    // find the next stream obj
+    streamStart = strInBinary(STREAM_BEGIN, STREAM_BEGIN_SIZE, tp, plimit-tp);
+    if (streamStart == NULL) {
+      log_warn("Cannot find stream in pdf");
+      return -1;
+    }
+ 
+    // copy everything between tp and "stream" (inclusive) to outbuf
+    size = streamStart - tp + STREAM_BEGIN_SIZE;
+    memcpy(op, tp, size);
+    op += size;
+    tp = streamStart + STREAM_BEGIN_SIZE;
+
+    streamEnd = strInBinary(STREAM_END, STREAM_END_SIZE, tp, plimit-tp);
+    if (streamEnd == NULL) {
+      log_warn("Cannot find endstream in pdf");
+      return -1;
+    }
+
+    // count the number of usable char between tp and streamEnd
+    size = streamEnd-tp;
+
+    // encoding data in the stream obj
+    if (size > 0) {
+        size2 = data2len - cnt;
+        if (size < size2) {
+          memcpy(op, dp, size);
+          op += size; tp += size; dp += size; 
+          memcpy(op, tp, STREAM_END_SIZE);
+          op += STREAM_END_SIZE; tp += STREAM_END_SIZE;
+          cnt += size;
+        } else { // done encoding data
+          memcpy(op, dp, size2);
+          op += size2; tp += size2; dp += size2; 
+          cnt += size2;
+          // printf("Encoded %d char in pdf. Done encoding\n", size2);
+          break;
+        }
+        log_debug("Encoded %d char in pdf", size);
+    } else { // empty stream
+      memcpy(op, tp, STREAM_END_SIZE);
+      op += STREAM_END_SIZE; tp += STREAM_END_SIZE;
+    }
+
+    if (cnt >= data2len) break; // this shouldn't happen ...
+  }
+
+  // copy the rest of pdfTemplate to outbuf
+  size = plimit-tp;
+  log_debug("copying the rest of pdfTemplate to outbuf (size %d)", size); 
+  memcpy(op, tp, size);
+  op += size;
+  return (op-outbuf);
+}
+
+
+
+
+/*
+ * pdfUnwrap is the inverse operation of pdfWrap
+ */
+int 
+pdfUnwrap (char *data, unsigned int dlen,
+           char *outbuf, unsigned int outbufsize)
+{
+  char *dp, *op, *streamStart, *streamEnd, *dlimit, *olimit;
+  int cnt, size, size2, endFlag;
+  int escape = 0;
+
+  dp = data;   // current pointer for data
+  op = outbuf; // current pointer for outbuf
+  cnt = 0;     // number of char decoded
+  dlimit = data+dlen;
+  olimit = outbuf+outbufsize;
+
+  while (dp < dlimit) {
+    // find the next stream obj
+    streamStart = strInBinary(STREAM_BEGIN, STREAM_BEGIN_SIZE, dp, dlimit-dp);
+    if (streamStart == NULL) {
+      log_warn("Cannot find stream in pdf");
+      return -1;
+    }
+
+    dp = streamStart + STREAM_BEGIN_SIZE;
+    streamEnd = strInBinary(STREAM_END, STREAM_END_SIZE, dp, dlimit-dp);
+    if (streamEnd == NULL) {
+      log_warn("Cannot find endstream in pdf");
+      return -1;
+    }
+
+    // count the number of usable char between tp and streamEnd
+    size = streamEnd-dp;
+
+    if (size > 0) { 
+      size2 = removeDelimiter(dp, size, op, olimit-op, PDF_DELIMITER, &endFlag, &escape);
+      if (size2 < 0) {
+        return -1;
+      }
+      cnt += size2;
+      if (endFlag) { // Done decoding
+        break;
+      } else { // Continue decoding
+        op += size2;
+        dp = streamEnd + STREAM_END_SIZE;
+      }
+    } else { // empty stream obj
+      dp = streamEnd + STREAM_END_SIZE;
+    }
+  }
+
+  return cnt;
+}
+
+
+
+
+
+int x_http2_server_PDF_transmit (steg_t* s, struct evbuffer *source, conn_t *conn) {
+
+  struct evbuffer *dest = conn_get_outbound(conn);
+  size_t sbuflen = evbuffer_get_length(source);
+  unsigned int mpdf;
+  char *pdfTemplate = NULL, *hend;
+  int pdfTemplateSize = 0;
+  // char data1[HTTP_MSG_BUF_SIZE];
+  char data1[(int) sbuflen];
+  char outbuf[HTTP_MSG_BUF_SIZE];
+  int cnt, hLen, outbuflen, i;
+
+  char newHdr[MAX_RESP_HDR_SIZE];
+  int newHdrLen = 0;
+
+  struct evbuffer_iovec *iv;
+  int nv;
+
+  // for debugging pdfWrap and pdfUnwrap
+  // char data2[(int) sbuflen];
+  // int data2len;
+
+  log_debug("Entering SERVER PDF transmit with sbuflen %d", (int)sbuflen);
+
+  nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0);
+  iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
+
+  if (evbuffer_peek(source, sbuflen, NULL, iv, nv) != nv) {
+    free(iv);
+    return -1;
+  }
+
+  cnt = 0;
+  for (i = 0; i < nv; i++) {
+    const unsigned char *p = iv[i].iov_base;
+    const unsigned char *limit = p + iv[i].iov_len;
+    while (p < limit && cnt < (int)sbuflen) {
+      data1[cnt++] = *p++;
+    }
+  }
+
+  free(iv);
+
+  log_debug("SERVER sbuflen = %d; cnt = %d", (int)sbuflen, cnt);
+
+  mpdf = get_max_PDF_capacity();
+
+  if (mpdf <= 0) {
+    log_warn("SERVER ERROR: No pdfTemplate found\n");
+    return -1;
+  }
+
+  if (sbuflen > (size_t) mpdf) {
+    log_warn("SERVER ERROR: pdfTemplate cannot accommodate data %d %dn",
+                (int) sbuflen, (int) mpdf);
+    return -1;
+  }
+
+  if (get_payload(HTTP_CONTENT_PDF, sbuflen, &pdfTemplate, &pdfTemplateSize) == 1) {
+    log_debug("SERVER found the next HTTP response template with size %d", pdfTemplateSize);
+  } else {
+    log_warn("SERVER couldn't find the next HTTP response template");
+    return -1;
+  }
+
+  hend = strstr(pdfTemplate, "\r\n\r\n");
+  if (hend == NULL) {
+    log_warn("SERVER unable to find end of header in the HTTP template");
+    return -1;
+  }
+
+  hLen = hend+4-pdfTemplate;
+  
+  log_debug("SERVER calling pdfWrap for data1 with length %d", cnt);
+  outbuflen = pdfWrap(data1, cnt, hend+4, pdfTemplateSize-hLen, outbuf, HTTP_MSG_BUF_SIZE);
+  if (outbuflen < 0) {
+    log_warn("SERVER pdfWrap fails");
+    return -1;
+  }
+  log_debug("SERVER pdfSteg sends resp with hdr len %d body len %d", hLen, outbuflen);
+
+
+  // debugging
+  // buf_dump((unsigned char *)data1, cnt, stderr);
+
+  // data2len = pdfUnwrap(outbuf, outbuflen, data2, sbuflen);
+  // if ((int)sbuflen == data2len) {
+  //   log_warn("sbuflen == data2len == %d", (int)sbuflen);
+  //   if (memcmp(data1, data2, sbuflen) == 0) {
+  //     log_warn("data1 and data2 match");
+  //   } else {
+  //     log_warn("data1 and data2 DO NOT match!! Dumping data1 ...");
+  //     buf_dump((unsigned char *)data1, cnt, stderr);
+  //     log_warn("data1 and data2 DO NOT match!! Dumping data2...");
+  //     buf_dump((unsigned char *)data2, data2len, stderr);
+  //   }
+  // } else {
+  //   log_warn("*** sbuflen = %d, data2len = %d *** Dumping data1 ...", (int)sbuflen, data2len);
+  //   buf_dump((unsigned char *)data1, cnt, stderr);
+  //   log_warn("*** sbuflen = %d, data2len = %d *** Dumping data2 ...", (int)sbuflen, data2len);
+  //   buf_dump((unsigned char *)data2, data2len, stderr);
+  // }
+
+
+  newHdrLen = gen_response_header((char*) "application/pdf", 0, outbuflen, newHdr, sizeof(newHdr));
+  if (newHdrLen < 0) {
+    log_warn("SERVER ERROR: gen_response_header fails for pdfSteg");
+    return -1;
+  }
+
+  if (evbuffer_add(dest, newHdr, newHdrLen)) {
+    log_warn("SERVER ERROR: evbuffer_add() fails for newHdr");
+    return -1;
+  }
+  // if (evbuffer_add(dest, pdfTemplate, hLen)) {
+  //   log_warn("SERVER ERROR: evbuffer_add() fails for pdfTemplate");
+  //   return -1;
+  // }
+
+  if (evbuffer_add(dest, outbuf, outbuflen)) {
+    log_warn("SERVER ERROR: evbuffer_add() fails for outbuf");
+    return -1;
+  }
+
+  evbuffer_drain(source, sbuflen);
+
+  conn_close_after_transmit(conn);
+  //  downcast_steg(s)->have_transmitted = 1;
+  return 0;
+}
+
+
+
+int
+x_http2_handle_client_PDF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
+  struct evbuffer_ptr s2;
+  unsigned int response_len = 0, hdrLen;
+  char outbuf[HTTP_MSG_BUF_SIZE];
+  int content_len = 0, outbuflen;
+  char *httpHdr, *httpBody;
+
+  log_debug("Entering CLIENT PDF receive");
+
+  s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
+  if (s2.pos == -1) {
+    log_warn("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
+    //    evbuffer_dump(source, stderr);
+    return RECV_INCOMPLETE;
+  }
+
+  log_debug("CLIENT received response header with len %d", (int)s2.pos);
+
+  response_len = 0;
+  hdrLen = s2.pos + strlen("\r\n\r\n");
+  response_len += hdrLen;
+
+  httpHdr = (char *) evbuffer_pullup(source, s2.pos);
+  if (httpHdr == NULL) {
+    log_warn("CLIENT unable to pullup the complete HTTP header");
+    return RECV_BAD;
+  }
+
+  content_len = find_content_length(httpHdr, hdrLen);
+  if (content_len < 0) {
+    log_warn("CLIENT unable to find content length");
+    return RECV_BAD;
+  }
+  log_debug("CLIENT received Content-Length = %d\n", content_len);
+
+  response_len += content_len;
+
+  if (response_len > evbuffer_get_length(source))
+    return RECV_INCOMPLETE;
+
+  httpHdr = (char *) evbuffer_pullup(source, response_len);
+
+  if (httpHdr == NULL) {
+    log_warn("CLIENT unable to pullup the complete HTTP body");
+    return RECV_BAD;
+  }
+
+
+  httpBody = httpHdr + hdrLen;
+
+
+  outbuflen = pdfUnwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
+  if (outbuflen < 0) {
+    log_warn("CLIENT ERROR: pdfUnwrap fails\n");
+    return RECV_BAD;
+  }
+
+  log_debug("CLIENT unwrapped data of length %d:", outbuflen);
+
+
+  if (evbuffer_add(dest, outbuf, outbuflen)) {
+    log_warn("CLIENT ERROR: evbuffer_add to dest fails\n");
+    return RECV_BAD;
+  }
+
+  // log_debug("Drained source for %d char\n", response_len);
+  if (evbuffer_drain(source, response_len) == -1) {
+    log_warn("CLIENT ERROR: failed to drain source\n");
+    return RECV_BAD;
+  }
+
+  //  downcast_steg(s)->have_received = 1;
+  conn_expect_close(conn);
+  return RECV_GOOD;
+}
+
+
+
+
+/*****
+int main() {
+  char data1[] = "this is a test?? yes!";
+  char data2[100];
+  char data3[100];
+  int dlen1, dlen2, dlen3, end;
+  char last = ' ';
+  printf("hello world\n");
+ 
+  dlen2 = addDelimiter(data1, strlen(data1), data2, 100, '?', '.');
+  printf("dlen2 = %d\n", dlen2);
+  dlen3 = removeDelimiter(data2, dlen2, data3, 100, '?', &end, &last);
+  printf("endflag = %d", end);
+  printf("dlen3 = %d\n", dlen3);
+  if (memcmp(data1, data3, dlen3) == 0) {
+    data1[dlen3] = 0;
+    printf("removeDelimiter(addDelimiter(x)) == x for |%s|\n", data1);
+  } else {
+    printf("removeDelimiter(addDelimiter(x)) != x for |%s|\n", data1);
+  }
+  return 1;
+}
+ *****/
+
+/*****
+int main() {
+  char data1[] = "12345";
+  char data2[] = "123456789012";
+  char data3[] = "12345678901";
+  char data4[] = "1234567890?";
+  char pdf1[] = "[PDFHDR][STUFFS1]>>streamABCDEFGHIJYYendstream[STUFFS2]>>streamABCDEFGHIJYYendstream[STUFF3][PDFTRAILER]";
+  char out[200];
+  char orig[200];
+  int r1, r2;
+
+  printf("********************\n");
+  printf("pdfwrap for %s\n", data1);
+  printf("strlen(pdf1) = %d\n", (int)strlen(pdf1));
+  r1 = pdfWrap(data1, strlen(data1), pdf1, strlen(pdf1), out, (int)sizeof(out));
+  if (r1 > 0) {
+    printf("pdfWrap returns %d\n", r1);
+    out[r1] = 0;
+    printf("out[] contains |%s|\n", out);
+  } else {
+    printf("pdfWrap returns %d\n", r1);
+  }
+
+  r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
+  if (r2 > 0) {
+    printf("pdfUnwrap returns %d\n", r2);
+    orig[r2] = 0;
+    printf("orig[] contains |%s|\n", orig);
+  } else {
+    printf("pdfUnwrap returns %d\n", r2);
+  }
+
+  printf("********************\n");
+  printf("pdfwrap for %s\n", data2);
+  r1 = pdfWrap(data2, strlen(data2), pdf1, strlen(pdf1), out, (int)sizeof(out));
+  if (r1 > 0) {
+    printf("pdfWrap returns %d\n", r1);
+    out[r1] = 0;
+    printf("out[] contains |%s|\n", out);
+  } else {
+    printf("pdfWrap returns %d\n", r1);
+  }
+
+  r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
+  if (r2 > 0) {
+    printf("pdfUnwrap returns %d\n", r2);
+    orig[r2] = 0;
+    printf("orig[] contains |%s|\n", orig);
+  } else {
+    printf("pdfUnwrap returns %d\n", r2);
+  }
+
+  printf("********************\n");
+  printf("pdfwrap for %s\n", data3);
+  r1 = pdfWrap(data3, strlen(data3), pdf1, strlen(pdf1), out, (int)sizeof(out));
+  if (r1 > 0) {
+    printf("pdfWrap returns %d\n", r1);
+    out[r1] = 0;
+    printf("out[] contains |%s|\n", out);
+  } else {
+    printf("pdfWrap returns %d\n", r1);
+  }
+
+  r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
+  if (r2 > 0) {
+    printf("pdfUnwrap returns %d\n", r2);
+    orig[r2] = 0;
+    printf("orig[] contains |%s|\n", orig);
+  } else {
+    printf("pdfUnwrap returns %d\n", r2);
+  }
+
+  printf("********************\n");
+  printf("pdfwrap for %s\n", data4);
+  r1 = pdfWrap(data4, strlen(data4), pdf1, strlen(pdf1), out, (int)sizeof(out));
+  if (r1 > 0) {
+    printf("pdfWrap returns %d\n", r1);
+    out[r1] = 0;
+    printf("out[] contains |%s|\n", out);
+  } else {
+    printf("pdfWrap returns %d\n", r1);
+  }
+
+  r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
+  if (r2 > 0) {
+    printf("pdfUnwrap returns %d\n", r2);
+    orig[r2] = 0;
+    printf("orig[] contains |%s|\n", orig);
+  } else {
+    printf("pdfUnwrap returns %d\n", r2);
+  }
+
+  return 0;
+}
+ *****/
diff --git a/src/steg/swfSteg.c b/src/steg/swfSteg.c
deleted file mode 100644
index ad3d5c8..0000000
--- a/src/steg/swfSteg.c
+++ /dev/null
@@ -1,282 +0,0 @@
-#include "swfSteg.h"
-
-
-static const char http_response_1[] =
-  "HTTP/1.1 200 OK\r\n"
-  "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n"
-  "Cache-Control: no-store\r\n"
-  "Connection: close\r\n"
-  "Content-Type: application/x-shockwave-flash\r\n"
-  "Content-Length: ";
-
-
-
-
-
-
-
-
-
-
-
-unsigned int 
-swf_wrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
-
-  char* swf;
-  int in_swf_len;
-
-  char* tmp_buf;
-  int out_swf_len;
-
-  char* resp;
-  int resp_len;
-
-  char hdr[512];
-  unsigned int hdr_len;
-
-  char* tmp_buf2;
-  
-
-
-  if (!get_payload(HTTP_CONTENT_SWF, -1, &resp, &resp_len)) {
-    log_warn("swfsteg: no suitable payload found\n");
-    return -1;
-  }
-
-  swf = strstr(resp, "\r\n\r\n") + 4;
-  in_swf_len = resp_len - (swf - resp);
-
-
-
-  
-  if (out_sz - in_len < (SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 8 + 512)) {
-    fprintf(stderr, "swfsteg: outbuf too small %d \n", out_sz - in_len);
-
-    log_warn("swfsteg: outbuf too small\n");
-    return -1;
-  }
-
-
-  tmp_buf = malloc(in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN);
-
-  if (tmp_buf == NULL) {
-    log_warn("swfsteg: malloc failed\n");
-    return -1;
-  }
-
-
-  tmp_buf2 = malloc(in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN + 512);
-
-  if (tmp_buf2 == NULL) {
-    free(tmp_buf);
-    log_warn("swfsteg: malloc failed\n");
-    return -1;
-  }
-
-
-  memcpy(tmp_buf, swf+8, SWF_SAVE_HEADER_LEN);
-  memcpy(tmp_buf+SWF_SAVE_HEADER_LEN, inbuf, in_len);
-  memcpy(tmp_buf+SWF_SAVE_HEADER_LEN+in_len, swf + in_swf_len - SWF_SAVE_FOOTER_LEN, SWF_SAVE_FOOTER_LEN);
-  out_swf_len = def(tmp_buf, SWF_SAVE_HEADER_LEN + in_len + SWF_SAVE_FOOTER_LEN, tmp_buf2+8, 
-		    in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN + 512-8, 
-		    Z_DEFAULT_COMPRESSION);
-
-  //  sprintf(hdr, "%s%d\r\n\r\n", http_response_1, out_swf_len + 8);
-
-
-
-  //  fprintf(stderr, "out_swf_len = %d\n", out_swf_len);
-
-
-  hdr_len =   gen_response_header((char*) "application/x-shockwave-flash", 0, out_swf_len + 8, hdr, sizeof(hdr));
-
-  //  fprintf(stderr, "hdr = %s\n", hdr);
-				       
-  memcpy(tmp_buf2, swf, 4);
-  ((int*) (tmp_buf2))[1] = out_swf_len;
-  
-  memcpy(outbuf, hdr, hdr_len);
-  memcpy(outbuf+hdr_len, tmp_buf2, out_swf_len + 8);
-
-  free(tmp_buf);
-  free(tmp_buf2);
-  return out_swf_len + 8 + hdr_len;
-}
-
-
-
-
-unsigned int 
-swf_unwrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
-  char* tmp_buf;
-  int inf_len;
-
-  tmp_buf = malloc(in_len * 8);
-
-  inf_len = inf(inbuf + 8, in_len - 8, tmp_buf, in_len * 8); 
-
-  //  fprintf(stderr, "in_swf_len = %d\n", in_len -8 );
-
-
-  if (inf_len < 0 || out_sz < inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN) {
-    fprintf(stderr, "inf_len = %d\n", inf_len);
-    free(tmp_buf);
-    //    buf_dump((unsigned char*) (inbuf+8), in_len -8, stderr);
-    
-
-
-    return -1;
-  }
-
-  memcpy(outbuf, tmp_buf + SWF_SAVE_HEADER_LEN, inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN);
-  return inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN;
-}
-
-
-
-
-
-int 
-x_http2_server_SWF_transmit (steg_t* s, struct evbuffer *source, conn_t *conn) {
-
-  struct evbuffer *dest = conn_get_outbound(conn);
-  size_t sbuflen = evbuffer_get_length(source);
-  char* inbuf;
-  char* outbuf;
-  int outlen;
-
-
-
-  inbuf = malloc(sbuflen);
-
-  if (inbuf == NULL) {
-    log_warn("malloc inbuf failed\n");
-    return -1;
-  }
-
-  
-  if (evbuffer_remove(source, inbuf, sbuflen) == -1) {
-    log_debug("evbuffer_remove failed in x_http2_server_SWF_transmit");
-    return -1;
-  }
-
-  outbuf = malloc(4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
-
-  if (outbuf == NULL) {
-    free(inbuf);
-    log_warn("malloc outbuf failed\n");
-    return -1;
-  }
-  
-  //  fprintf(stderr, "server wrapping swf len %d\n", (int) sbuflen);
-  outlen = swf_wrap(inbuf, sbuflen, outbuf, 4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
-
-  if (outlen < 0) {
-    log_warn("swf_wrap failed\n");
-    //    fprintf(stderr, "swf_wrap failed\n");
-    free(inbuf);
-    free(outbuf);
-    return -1;
-  }
-
-  
-  if (evbuffer_add(dest, outbuf, outlen)) {
-    log_debug("SERVER ERROR: x_http2_server_transmit: evbuffer_add() fails for jsTemplate");
-    free(inbuf);
-    free(outbuf);
-    return -1;
-  }
-
-    
-  // conn_cease_transmission(conn);
-  conn_close_after_transmit(conn);
-
-
-  free(inbuf);
-  free(outbuf);
-  return 0;
-}
-
-
-
-
-int
-x_http2_handle_client_SWF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
-  struct evbuffer_ptr s2;
-  unsigned int response_len = 0, hdrLen;
-  char outbuf[HTTP_MSG_BUF_SIZE];
-  int content_len = 0, outbuflen;
-  char *httpHdr, *httpBody;
-
-
-
-  s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
-  if (s2.pos == -1) {
-    log_warn("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
-    fprintf(stderr, "client did not find end of HTTP header\n");
-
-    //    evbuffer_dump(source, stderr);
-    return RECV_INCOMPLETE;
-  }
-
-  log_debug("CLIENT received response header with len %d", (int)s2.pos);
-
-  response_len = 0;
-  hdrLen = s2.pos + strlen("\r\n\r\n");
-  response_len += hdrLen;
-
-  httpHdr = (char *) evbuffer_pullup(source, s2.pos);
-  if (httpHdr == NULL) {
-    log_warn("CLIENT unable to pullup the complete HTTP header");
-    return RECV_BAD;
-  }
-
-  content_len = find_content_length(httpHdr, hdrLen);
-
-
-
-  if (content_len < 0) {
-    log_warn("CLIENT unable to find content length");
-    return RECV_BAD;
-  }
-  log_debug("CLIENT received Content-Length = %d\n", content_len);
-
-
-
-  response_len += content_len;
-
-  if (response_len > evbuffer_get_length(source))
-    return RECV_INCOMPLETE;
-
-
-
-  httpHdr = (char *) evbuffer_pullup(source, response_len);
-  httpBody = httpHdr + hdrLen;
-
-
-  outbuflen = swf_unwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
-
-  if (outbuflen < 0) {
-    fprintf(stderr, "swf_unwrap failed\n");
-    log_debug("CLIENT ERROR: swf_unwrap failed\n");
-    return RECV_BAD;
-  }
-
-  //  fprintf(stderr, "CLIENT unwrapped data of length %d:", outbuflen);
-  // buf_dump(outbuf, outbuflen, stderr);
-
-  if (evbuffer_add(dest, outbuf, outbuflen)) {
-    log_debug("CLIENT ERROR: evbuffer_add to dest fails\n");
-    return RECV_BAD;
-  }
-
-  // log_debug("Drained source for %d char\n", response_len);
-  if (evbuffer_drain(source, response_len) == -1) {
-    log_debug("CLIENT ERROR: failed to drain source\n");
-    return RECV_BAD;
-  }
-
-  //  downcast_steg(s)->have_received = 1;
-  conn_expect_close(conn);
-  return RECV_GOOD;
-}
diff --git a/src/steg/swfSteg.c.old b/src/steg/swfSteg.c.old
deleted file mode 100644
index 833ea9f..0000000
--- a/src/steg/swfSteg.c.old
+++ /dev/null
@@ -1,264 +0,0 @@
-#include "swfSteg.h"
-
-
-static const char http_response_1[] =
-  "HTTP/1.1 200 OK\r\n"
-  "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n"
-  "Cache-Control: no-store\r\n"
-  "Connection: close\r\n"
-  "Content-Type: application/x-shockwave-flash\r\n"
-  "Content-Length: ";
-
-
-
-
-
-
-
-
-
-
-
-unsigned int 
-swf_wrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
-
-  char* swf;
-  int in_swf_len;
-
-  char* tmp_buf;
-  int out_swf_len;
-
-  char* resp;
-  int resp_len;
-
-  char hdr[512];
-  unsigned int hdr_len;
-
-  char* tmp_buf2;
-  
-
-
-  if (!get_payload(HTTP_CONTENT_SWF, -1, &resp, &resp_len)) {
-    log_warn("swfsteg: no suitable payload found\n");
-    return -1;
-  }
-
-  swf = strstr(resp, "\r\n\r\n") + 4;
-  in_swf_len = resp_len - (swf - resp);
-
-
-
-  
-  if (out_sz - in_len < (SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 8 + 512)) {
-    fprintf(stderr, "swfsteg: outbuf too small %d \n", out_sz - in_len);
-
-    log_warn("swfsteg: outbuf too small\n");
-    return -1;
-  }
-
-
-  tmp_buf = malloc(in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN);
-
-  if (tmp_buf == NULL) {
-    log_warn("swfsteg: malloc failed\n");
-    return -1;
-  }
-
-
-  tmp_buf2 = malloc(in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN + 512);
-
-  if (tmp_buf2 == NULL) {
-    free(tmp_buf);
-    log_warn("swfsteg: malloc failed\n");
-    return -1;
-  }
-
-
-  memcpy(tmp_buf, swf+8, SWF_SAVE_HEADER_LEN);
-  memcpy(tmp_buf+SWF_SAVE_HEADER_LEN, inbuf, in_len);
-  memcpy(tmp_buf+SWF_SAVE_HEADER_LEN+in_len, swf + in_swf_len - SWF_SAVE_FOOTER_LEN, SWF_SAVE_FOOTER_LEN);
-  out_swf_len = def(tmp_buf, SWF_SAVE_HEADER_LEN + in_len + SWF_SAVE_FOOTER_LEN, tmp_buf2+8, 
-		    in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN + 512-8, 
-		    Z_DEFAULT_COMPRESSION);
-
-  //  sprintf(hdr, "%s%d\r\n\r\n", http_response_1, out_swf_len + 8);
-
-
-  hdr_len =   gen_response_header((char*) "application/x-shockwave-flash", 0, out_swf_len + 8, hdr, sizeof(hdr));
-
-  //  fprintf(stderr, "hdr = %s\n", hdr);
-				       
-  memcpy(tmp_buf2, swf, 4);
-  ((int*) (tmp_buf2))[1] = out_swf_len;
-  
-  memcpy(outbuf, hdr, hdr_len);
-  memcpy(outbuf+hdr_len, tmp_buf2, out_swf_len + 8);
-
-  free(tmp_buf);
-  free(tmp_buf2);
-  return out_swf_len + 8 + hdr_len;
-}
-
-
-
-unsigned int 
-swf_unwrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
-  char* tmp_buf;
-  int inf_len;
-
-  tmp_buf = malloc(in_len * 5);
-  inf_len = inf(inbuf + 8, in_len - 8, tmp_buf, in_len * 5); 
-
-  if (inf_len < 0 || out_sz < inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN) {
-    fprintf(stderr, "swf_unwrap failed \n");
-    free(tmp_buf);
-    return -1;
-  }
-
-  memcpy(outbuf, tmp_buf + SWF_SAVE_HEADER_LEN, inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN);
-  return inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN;
-}
-
-
-
-
-
-int 
-x_http2_server_SWF_transmit (steg_t* s, struct evbuffer *source, conn_t *conn) {
-
-  struct evbuffer *dest = conn_get_outbound(conn);
-  size_t sbuflen = evbuffer_get_length(source);
-  char* inbuf;
-  char* outbuf;
-  int outlen;
-
-
-
-  inbuf = malloc(sbuflen);
-
-  if (inbuf == NULL) {
-    log_warn("malloc inbuf failed\n");
-    return -1;
-  }
-
-  
-  if (evbuffer_remove(source, inbuf, sbuflen) == -1) {
-    log_debug("evbuffer_remove failed in x_http2_server_SWF_transmit");
-    return -1;
-  }
-
-  outbuf = malloc(4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
-
-  if (outbuf == NULL) {
-    free(inbuf);
-    log_warn("malloc outbuf failed\n");
-    return -1;
-  }
-  
-  //  fprintf(stderr, "server wrapping swf len %d\n", (int) sbuflen);
-  outlen = swf_wrap(inbuf, sbuflen, outbuf, 4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
-
-  if (outlen < 0) {
-    log_warn("swf_wrap failed\n");
-    fprintf(stderr, "swf_wrap failed\n");
-    free(inbuf);
-    free(outbuf);
-    return -1;
-  }
-
-  
-  if (evbuffer_add(dest, outbuf, outlen)) {
-    log_debug("SERVER ERROR: x_http2_server_transmit: evbuffer_add() fails for jsTemplate");
-    free(inbuf);
-    free(outbuf);
-    return -1;
-  }
-
-    
-  // conn_cease_transmission(conn);
-  conn_close_after_transmit(conn);
-
-
-  free(inbuf);
-  free(outbuf);
-  return 0;
-}
-
-
-
-
-int
-x_http2_handle_client_SWF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
-  struct evbuffer_ptr s2;
-  unsigned int response_len = 0, hdrLen;
-  char outbuf[HTTP_MSG_BUF_SIZE];
-  int content_len = 0, outbuflen;
-  char *httpHdr, *httpBody;
-
-
-
-  s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
-  if (s2.pos == -1) {
-    log_warn("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
-    fprintf(stderr, "client did not find end of HTTP header\n");
-
-    //    evbuffer_dump(source, stderr);
-    return RECV_INCOMPLETE;
-  }
-
-  log_debug("CLIENT received response header with len %d", (int)s2.pos);
-
-  response_len = 0;
-  hdrLen = s2.pos + strlen("\r\n\r\n");
-  response_len += hdrLen;
-
-  httpHdr = (char *) evbuffer_pullup(source, s2.pos);
-  if (httpHdr == NULL) {
-    log_warn("CLIENT unable to pullup the complete HTTP header");
-    return RECV_BAD;
-  }
-
-  content_len = find_content_length(httpHdr, hdrLen);
-
-
-
-  if (content_len < 0) {
-    log_warn("CLIENT unable to find content length");
-    return RECV_BAD;
-  }
-  log_debug("CLIENT received Content-Length = %d\n", content_len);
-
-
-
-  response_len += content_len;
-
-  if (response_len > evbuffer_get_length(source))
-    return RECV_INCOMPLETE;
-
-  httpBody = httpHdr + hdrLen;
-  outbuflen = swf_unwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
-
-  if (outbuflen < 0) {
-    fprintf(stderr, "swf_unwrap failed\n");
-    log_debug("CLIENT ERROR: swf_unwrap failed\n");
-    return RECV_BAD;
-  }
-
-  //  fprintf(stderr, "CLIENT unwrapped data of length %d:", outbuflen);
-  // buf_dump(outbuf, outbuflen, stderr);
-
-  if (evbuffer_add(dest, outbuf, outbuflen)) {
-    log_debug("CLIENT ERROR: evbuffer_add to dest fails\n");
-    return RECV_BAD;
-  }
-
-  // log_debug("Drained source for %d char\n", response_len);
-  if (evbuffer_drain(source, response_len) == -1) {
-    log_debug("CLIENT ERROR: failed to drain source\n");
-    return RECV_BAD;
-  }
-
-  //  downcast_steg(s)->have_received = 1;
-  conn_expect_close(conn);
-  return RECV_GOOD;
-}
diff --git a/src/steg/swfSteg.cc b/src/steg/swfSteg.cc
new file mode 100644
index 0000000..ad3d5c8
--- /dev/null
+++ b/src/steg/swfSteg.cc
@@ -0,0 +1,282 @@
+#include "swfSteg.h"
+
+
+static const char http_response_1[] =
+  "HTTP/1.1 200 OK\r\n"
+  "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n"
+  "Cache-Control: no-store\r\n"
+  "Connection: close\r\n"
+  "Content-Type: application/x-shockwave-flash\r\n"
+  "Content-Length: ";
+
+
+
+
+
+
+
+
+
+
+
+unsigned int 
+swf_wrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
+
+  char* swf;
+  int in_swf_len;
+
+  char* tmp_buf;
+  int out_swf_len;
+
+  char* resp;
+  int resp_len;
+
+  char hdr[512];
+  unsigned int hdr_len;
+
+  char* tmp_buf2;
+  
+
+
+  if (!get_payload(HTTP_CONTENT_SWF, -1, &resp, &resp_len)) {
+    log_warn("swfsteg: no suitable payload found\n");
+    return -1;
+  }
+
+  swf = strstr(resp, "\r\n\r\n") + 4;
+  in_swf_len = resp_len - (swf - resp);
+
+
+
+  
+  if (out_sz - in_len < (SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 8 + 512)) {
+    fprintf(stderr, "swfsteg: outbuf too small %d \n", out_sz - in_len);
+
+    log_warn("swfsteg: outbuf too small\n");
+    return -1;
+  }
+
+
+  tmp_buf = malloc(in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN);
+
+  if (tmp_buf == NULL) {
+    log_warn("swfsteg: malloc failed\n");
+    return -1;
+  }
+
+
+  tmp_buf2 = malloc(in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN + 512);
+
+  if (tmp_buf2 == NULL) {
+    free(tmp_buf);
+    log_warn("swfsteg: malloc failed\n");
+    return -1;
+  }
+
+
+  memcpy(tmp_buf, swf+8, SWF_SAVE_HEADER_LEN);
+  memcpy(tmp_buf+SWF_SAVE_HEADER_LEN, inbuf, in_len);
+  memcpy(tmp_buf+SWF_SAVE_HEADER_LEN+in_len, swf + in_swf_len - SWF_SAVE_FOOTER_LEN, SWF_SAVE_FOOTER_LEN);
+  out_swf_len = def(tmp_buf, SWF_SAVE_HEADER_LEN + in_len + SWF_SAVE_FOOTER_LEN, tmp_buf2+8, 
+		    in_len + SWF_SAVE_HEADER_LEN + SWF_SAVE_FOOTER_LEN + 512-8, 
+		    Z_DEFAULT_COMPRESSION);
+
+  //  sprintf(hdr, "%s%d\r\n\r\n", http_response_1, out_swf_len + 8);
+
+
+
+  //  fprintf(stderr, "out_swf_len = %d\n", out_swf_len);
+
+
+  hdr_len =   gen_response_header((char*) "application/x-shockwave-flash", 0, out_swf_len + 8, hdr, sizeof(hdr));
+
+  //  fprintf(stderr, "hdr = %s\n", hdr);
+				       
+  memcpy(tmp_buf2, swf, 4);
+  ((int*) (tmp_buf2))[1] = out_swf_len;
+  
+  memcpy(outbuf, hdr, hdr_len);
+  memcpy(outbuf+hdr_len, tmp_buf2, out_swf_len + 8);
+
+  free(tmp_buf);
+  free(tmp_buf2);
+  return out_swf_len + 8 + hdr_len;
+}
+
+
+
+
+unsigned int 
+swf_unwrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
+  char* tmp_buf;
+  int inf_len;
+
+  tmp_buf = malloc(in_len * 8);
+
+  inf_len = inf(inbuf + 8, in_len - 8, tmp_buf, in_len * 8); 
+
+  //  fprintf(stderr, "in_swf_len = %d\n", in_len -8 );
+
+
+  if (inf_len < 0 || out_sz < inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN) {
+    fprintf(stderr, "inf_len = %d\n", inf_len);
+    free(tmp_buf);
+    //    buf_dump((unsigned char*) (inbuf+8), in_len -8, stderr);
+    
+
+
+    return -1;
+  }
+
+  memcpy(outbuf, tmp_buf + SWF_SAVE_HEADER_LEN, inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN);
+  return inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN;
+}
+
+
+
+
+
+int 
+x_http2_server_SWF_transmit (steg_t* s, struct evbuffer *source, conn_t *conn) {
+
+  struct evbuffer *dest = conn_get_outbound(conn);
+  size_t sbuflen = evbuffer_get_length(source);
+  char* inbuf;
+  char* outbuf;
+  int outlen;
+
+
+
+  inbuf = malloc(sbuflen);
+
+  if (inbuf == NULL) {
+    log_warn("malloc inbuf failed\n");
+    return -1;
+  }
+
+  
+  if (evbuffer_remove(source, inbuf, sbuflen) == -1) {
+    log_debug("evbuffer_remove failed in x_http2_server_SWF_transmit");
+    return -1;
+  }
+
+  outbuf = malloc(4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
+
+  if (outbuf == NULL) {
+    free(inbuf);
+    log_warn("malloc outbuf failed\n");
+    return -1;
+  }
+  
+  //  fprintf(stderr, "server wrapping swf len %d\n", (int) sbuflen);
+  outlen = swf_wrap(inbuf, sbuflen, outbuf, 4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
+
+  if (outlen < 0) {
+    log_warn("swf_wrap failed\n");
+    //    fprintf(stderr, "swf_wrap failed\n");
+    free(inbuf);
+    free(outbuf);
+    return -1;
+  }
+
+  
+  if (evbuffer_add(dest, outbuf, outlen)) {
+    log_debug("SERVER ERROR: x_http2_server_transmit: evbuffer_add() fails for jsTemplate");
+    free(inbuf);
+    free(outbuf);
+    return -1;
+  }
+
+    
+  // conn_cease_transmission(conn);
+  conn_close_after_transmit(conn);
+
+
+  free(inbuf);
+  free(outbuf);
+  return 0;
+}
+
+
+
+
+int
+x_http2_handle_client_SWF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
+  struct evbuffer_ptr s2;
+  unsigned int response_len = 0, hdrLen;
+  char outbuf[HTTP_MSG_BUF_SIZE];
+  int content_len = 0, outbuflen;
+  char *httpHdr, *httpBody;
+
+
+
+  s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
+  if (s2.pos == -1) {
+    log_warn("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
+    fprintf(stderr, "client did not find end of HTTP header\n");
+
+    //    evbuffer_dump(source, stderr);
+    return RECV_INCOMPLETE;
+  }
+
+  log_debug("CLIENT received response header with len %d", (int)s2.pos);
+
+  response_len = 0;
+  hdrLen = s2.pos + strlen("\r\n\r\n");
+  response_len += hdrLen;
+
+  httpHdr = (char *) evbuffer_pullup(source, s2.pos);
+  if (httpHdr == NULL) {
+    log_warn("CLIENT unable to pullup the complete HTTP header");
+    return RECV_BAD;
+  }
+
+  content_len = find_content_length(httpHdr, hdrLen);
+
+
+
+  if (content_len < 0) {
+    log_warn("CLIENT unable to find content length");
+    return RECV_BAD;
+  }
+  log_debug("CLIENT received Content-Length = %d\n", content_len);
+
+
+
+  response_len += content_len;
+
+  if (response_len > evbuffer_get_length(source))
+    return RECV_INCOMPLETE;
+
+
+
+  httpHdr = (char *) evbuffer_pullup(source, response_len);
+  httpBody = httpHdr + hdrLen;
+
+
+  outbuflen = swf_unwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
+
+  if (outbuflen < 0) {
+    fprintf(stderr, "swf_unwrap failed\n");
+    log_debug("CLIENT ERROR: swf_unwrap failed\n");
+    return RECV_BAD;
+  }
+
+  //  fprintf(stderr, "CLIENT unwrapped data of length %d:", outbuflen);
+  // buf_dump(outbuf, outbuflen, stderr);
+
+  if (evbuffer_add(dest, outbuf, outbuflen)) {
+    log_debug("CLIENT ERROR: evbuffer_add to dest fails\n");
+    return RECV_BAD;
+  }
+
+  // log_debug("Drained source for %d char\n", response_len);
+  if (evbuffer_drain(source, response_len) == -1) {
+    log_debug("CLIENT ERROR: failed to drain source\n");
+    return RECV_BAD;
+  }
+
+  //  downcast_steg(s)->have_received = 1;
+  conn_expect_close(conn);
+  return RECV_GOOD;
+}
diff --git a/src/steg/x_http.c.old b/src/steg/x_http.c.old
deleted file mode 100644
index 2799078..0000000
--- a/src/steg/x_http.c.old
+++ /dev/null
@@ -1,337 +0,0 @@
-/* Copyright 2011 Zack Weinberg
-   See LICENSE for other credits and copying information
-*/
-
-#include "util.h"
-#include "connections.h"
-#include "steg.h"
-
-#include <event2/buffer.h>
-
-
-
-/* This is an example steganography module.  Don't use it to disguise real
-   traffic!  It packages client->server traffic as HTTP GET requests and
-   server->client traffic as HTTP responses, but makes no actual attempt
-   to obscure the data proper. */
-
-struct x_http_steg_t
-{
-  steg_t super;
-  /* no extra stuff is presently necessary */
-};
-
-STEG_DEFINE_MODULE(x_http,
-                   1024,  /* client-server max data rate - made up */
-                   10240, /* server-client max data rate - ditto */
-                   1,     /* max concurrent connections per IP */
-                   1);     /* max concurrent IPs */
-
-/* Canned HTTP query and response headers. */
-static const char http_query_1[] =
-  "GET /";
-static const char http_query_2[] =
-  " HTTP/1.1\r\n"
-  "Host: ";
-static const char http_query_3[] =
-  "\r\n"
-  "Connection: close\r\n\r\n";
-
-static const char http_response_1[] =
-  "HTTP/1.1 200 OK\r\n"
-  "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n"
-  "Cache-Control: no-store\r\n"
-  "Connection: close\r\n"
-  "Content-Type: application/octet-stream\r\n"
-  "Content-Length: ";
-static const char http_response_2[] =
-  "%lu\r\n"
-  "\r\n";
-
-
-steg_t *
-x_http_new(rng_t *rng, unsigned int is_clientside)
-{
-  STEG_NEW(x_http, state, rng, is_clientside);
-  /* if there were extra stuff to fill in, you would do it here */
-  return upcast_steg(state);
-}
-
-void
-x_http_del(steg_t *s)
-{
-  x_http_steg_t *state = downcast_steg(s);
-  STEG_DEL(s);
-  /* if there were extra stuff to deallocate, you would do it here */
-  free(state);
-}
-
-unsigned int
-x_http_detect(conn_t *conn)
-{
-  struct evbuffer *buf = conn_get_inbound(conn);
-  unsigned char *data;
-
-  return 0;
-
-  /* Look for the text of http_response_1. */
-  if (evbuffer_get_length(buf) >= sizeof http_response_1 - 1) {
-    data = evbuffer_pullup(buf, sizeof http_response_1 - 1);
-    if (!memcmp(data, http_response_1, sizeof http_response_1 - 1))
-      return 1;
-  }
-
-  /* The client always transmits "GET /" followed by at least four
-     characters that are either lowercase hex digits or equals
-     signs, so we need nine bytes of incoming data. */
-  if (evbuffer_get_length(buf) >= 9) {
-    data = evbuffer_pullup(buf, 9);
-    if (!memcmp(data, "GET /", 5) &&
-        (ascii_isxdigit(data[5]) || data[5] == '=') &&
-        (ascii_isxdigit(data[6]) || data[6] == '=') &&
-        (ascii_isxdigit(data[7]) || data[7] == '=') &&
-        (ascii_isxdigit(data[8]) || data[8] == '='))
-      return 1;
-  }
-
-  /* Didn't find either the client or the server pattern. */
-  return 0;
-}
-
-size_t
-x_http_transmit_room(steg_t *s, conn_t *conn)
-{
-  if (s->is_clientside)
-    /* per http://www.boutell.com/newfaq/misc/urllength.html,
-       IE<9 can handle no more than 2048 characters in the path
-       component of a URL; we're not talking to IE, but this limit
-       means longer paths look fishy; we hex-encode the path, so
-       we have to cut the number in half. */
-    return 1024;
-  else
-    /* no practical limit applies */
-    return SIZE_MAX;
-}
-
-int
-x_http_transmit(steg_t *s, struct evbuffer *source, conn_t *conn)
-{
-  struct evbuffer *dest = conn_get_outbound(conn);
-
-  if (s->is_clientside) {
-    /* On the client side, we have to embed the data in a GET query somehow;
-       the only plausible places to put it are the URL and cookies.  This
-       presently uses the URL. And it can't be binary. */
-    struct evbuffer *scratch;
-    struct evbuffer_iovec *iv;
-    int i, nv;
-
-    /* Convert all the data in 'source' to hexadecimal and write it to
-       'scratch'. Data is padded to a multiple of four characters with
-       equals signs. */
-    size_t slen = evbuffer_get_length(source);
-    size_t dlen = slen * 2;
-
-    dlen = dlen + 3 - (dlen-1)%4;
-    if (dlen == 0) dlen = 4;
-
-    scratch = evbuffer_new();
-    if (!scratch) return -1;
-    if (evbuffer_expand(scratch, dlen)) {
-      evbuffer_free(scratch);
-      return -1;
-    }
-
-    nv = evbuffer_peek(source, slen, NULL, NULL, 0);
-    iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
-    if (evbuffer_peek(source, slen, NULL, iv, nv) != nv) {
-      evbuffer_free(scratch);
-      free(iv);
-      return -1;
-    }
-
-    for (i = 0; i < nv; i++) {
-      const unsigned char *p = iv[i].iov_base;
-      const unsigned char *limit = p + iv[i].iov_len;
-      char hex[2], c;
-      while (p < limit) {
-        c = *p++;
-        hex[0] = "0123456789abcdef"[(c & 0xF0) >> 4];
-        hex[1] = "0123456789abcdef"[(c & 0x0F) >> 0];
-        evbuffer_add(scratch, hex, 2);
-      }
-    }
-    free(iv);
-    while (evbuffer_get_length(scratch) == 0 ||
-           evbuffer_get_length(scratch) % 4 != 0)
-      evbuffer_add(scratch, "=", 1);
-
-    if (evbuffer_add(dest, http_query_1, sizeof http_query_1-1) ||
-        evbuffer_add_buffer(dest, scratch) ||
-        evbuffer_add(dest, http_query_2, sizeof http_query_2-1) ||
-        evbuffer_add(dest, conn->peername, strlen(conn->peername)) ||
-        evbuffer_add(dest, http_query_3, sizeof http_query_3-1)) {
-      evbuffer_free(scratch);
-      return -1;
-    }
-
-    evbuffer_free(scratch);
-    evbuffer_drain(source, slen);
-    conn_cease_transmission(conn);
-    return 0;
-
-  } else {
-    /* On the server side, we just fake up some HTTP response headers and
-       then splat the data we were given. Binary is OK. */
-
-    if (evbuffer_add(dest, http_response_1, sizeof http_response_1-1))
-        return -1;
-    if (evbuffer_add_printf(dest, http_response_2,
-                            (unsigned long)evbuffer_get_length(source)) == -1)
-      return -1;
-    if (evbuffer_add_buffer(dest, source))
-      return -1;
-
-    conn_close_after_transmit(conn);
-    return 0;
-  }
-}
-
-// enum recv_ret
-static int
-x_http_receive(steg_t *s, conn_t *conn, struct evbuffer *dest)
-{
-  struct evbuffer *source = conn_get_inbound(conn);
-  if (s->is_clientside) {
-    /* This loop should not be necessary, but we are currently not
-       enforcing the query-response pattern, so we can get more than
-       one response per request. */
-    do {
-      /* Linearize the buffer out past the longest possible
-         Content-Length header and subsequent blank line.  2**64 fits in
-         20 characters, and then we have two CRLFs; minus one for the
-         NUL in sizeof http_response_1. Note that this does _not_
-         guarantee that that much data is available. */
-
-      unsigned char *data = evbuffer_pullup(source, sizeof http_response_1 + 23);
-      size_t hlen = evbuffer_get_length(source);
-      if (hlen > sizeof http_response_1 + 23)
-        hlen = sizeof http_response_1 + 23;
-
-      /* Validate response headers. */
-      if (hlen < sizeof http_response_1 - 1)
-        return 0; // RECV_INCOMPLETE;
-      if (memcmp(data, http_response_1, sizeof http_response_1 - 1))
-        return -1; // RECV_BAD;
-
-      /* There should be an unsigned number immediately after the text of
-         http_response_1, followed by the four characters \r\n\r\n.
-         We may not have the complete number yet. */
-      unsigned char *p = data + sizeof http_response_1 - 1;
-      unsigned char *limit = data + hlen;
-      uint64_t clen = 0;
-      while (p < limit && '0' <= *p && *p <= '9') {
-        clen = clen*10 + *p - '0';
-        p++;
-      }
-      if (p+4 > limit)
-        return 0; // RECV_INCOMPLETE;
-      if (p[0] != '\r' || p[1] != '\n' || p[2] != '\r' || p[3] != '\n')
-        return -1; // RECV_BAD;
-
-      p += 4;
-      hlen = p - data;
-      /* Now we know how much data we're expecting after the blank line. */
-      if (evbuffer_get_length(source) < hlen + clen)
-        return 0; // RECV_INCOMPLETE;
-
-      /* we are go */
-      if (evbuffer_drain(source, hlen))
-        return -1; // RECV_BAD;
-
-      if (evbuffer_remove_buffer(source, dest, clen) != clen)
-        return -1; // RECV_BAD;
-
-    } while (evbuffer_get_length(source));
-
-    conn_expect_close(conn);
-    return 0; // RECV_GOOD;
-  } else {
-    /* We need a scratch buffer here because the contract is that if
-       we hit a decode error we *don't* write anything to 'dest'. */
-    struct evbuffer *scratch;
-
-    /* This loop should not be necessary either, but is, for the same
-       reason given above */
-    do {
-      /* Search for the second and third invariant bits of the query headers
-         we expect.  We completely ignore the contents of the Host header. */
-      struct evbuffer_ptr s2 = evbuffer_search(source, http_query_2,
-                                               sizeof http_query_2 - 1,
-                                               NULL);
-      if (s2.pos == -1) {
-        log_debug("Did not find second piece of HTTP query");
-        return 0; // RECV_INCOMPLETE;
-      }
-      struct evbuffer_ptr s3 = evbuffer_search(source, http_query_3,
-                                               sizeof http_query_3 - 1,
-                                               &s2);
-      if (s3.pos == -1) {
-        log_debug("Did not find third piece of HTTP query");
-        return 0; // RECV_INCOMPLETE;
-      }
-      obfs_assert(s3.pos + sizeof http_query_3 - 1
-                  <= evbuffer_get_length(source));
-
-      unsigned char *data = evbuffer_pullup(source, s2.pos);
-      if (memcmp(data, "GET /", sizeof "GET /"-1)) {
-        log_debug("Unexpected HTTP verb: %.*s", 5, data);
-        return -1; // RECV_BAD;
-      }
-
-      unsigned char *p = data + sizeof "GET /"-1;
-      unsigned char *limit = data + s2.pos;
-
-      scratch = evbuffer_new();
-      if (!scratch) return -1; // RECV_BAD;
-      if (evbuffer_expand(scratch, (limit - p)/2)) {
-        evbuffer_free(scratch);
-        return -1; // RECV_BAD;
-      }
-
-      unsigned char c, h, secondhalf = 0;
-      while (p < limit) {
-        if (!secondhalf) c = 0;
-        if ('0' <= *p && *p <= '9') h = *p - '0';
-        else if ('a' <= *p && *p <= 'f') h = *p - 'a' + 10;
-        else if ('A' <= *p && *p <= 'F') h = *p - 'A' + 10;
-        else if (*p == '=' && !secondhalf) {
-          p++;
-          continue;
-        } else {
-          evbuffer_free(scratch);
-          log_debug("Decode error: unexpected URI character %c", *p);
-          return -1; // RECV_BAD;
-        }
-
-        c = (c << 4) + h;
-        if (secondhalf)
-          evbuffer_add(scratch, &c, 1);
-        secondhalf = !secondhalf;
-        p++;
-      }
-
-      if (evbuffer_add_buffer(dest, scratch)) {
-        evbuffer_free(scratch);
-        log_debug("Failed to transfer buffer");
-        return -1; // RECV_BAD;
-      }
-      evbuffer_drain(source, s3.pos + sizeof http_query_3 - 1);
-      evbuffer_free(scratch);
-
-    } while (evbuffer_get_length(source));
-
-    conn_transmit_soon(conn, 100);
-    return 0; // RECV_GOOD;
-  }
-}
diff --git a/src/steg/x_http.cc b/src/steg/x_http.cc
deleted file mode 100644
index e1d9780..0000000
--- a/src/steg/x_http.cc
+++ /dev/null
@@ -1,360 +0,0 @@
-/* Copyright 2011 Zack Weinberg
-   See LICENSE for other credits and copying information
-*/
-
-#include "util.h"
-#include "connections.h"
-#include "steg.h"
-#include "crypt.h"
-
-#include <event2/buffer.h>
-
-/* This is an example steganography module.  Don't use it to disguise real
-   traffic!  It packages client->server traffic as HTTP GET requests and
-   server->client traffic as HTTP responses, but makes no actual attempt
-   to obscure the data proper. */
-
-namespace {
-  struct x_http : steg_t
-  {
-    bool have_transmitted : 1;
-    bool have_received : 1;
-    STEG_DECLARE_METHODS(x_http);
-  };
-}
-
-STEG_DEFINE_MODULE(x_http,
-                   1024,  /* client-server max data rate - made up */
-                   10240, /* server-client max data rate - ditto */
-                   1,     /* max concurrent connections per IP */
-                   1);     /* max concurrent IPs */
-
-/* Canned HTTP query and response headers. */
-static const char http_query_1[] =
-  "GET /";
-static const char http_query_2[] =
-  " HTTP/1.1\r\n"
-  "Host: ";
-static const char http_query_3[] =
-  "\r\n"
-  "Connection: close\r\n\r\n";
-
-static const char http_response_1[] =
-  "HTTP/1.1 200 OK\r\n"
-  "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n"
-  "Cache-Control: no-store\r\n"
-  "Connection: close\r\n"
-  "Content-Type: application/octet-stream\r\n"
-  "Content-Length: ";
-
-
-x_http::x_http()
-  : have_transmitted(false), have_received(false)
-{}
-
-x_http::~x_http()
-{}
-
-bool
-x_http::detect(conn_t *conn)
-{
-  struct evbuffer *buf = conn_get_inbound(conn);
-  uint8_t *data;
-  return 0;
-
-  /* Look for the text of http_response_1. */
-  if (evbuffer_get_length(buf) >= sizeof http_response_1 - 1) {
-    data = evbuffer_pullup(buf, sizeof http_response_1 - 1);
-    if (!memcmp(data, http_response_1, sizeof http_response_1 - 1))
-      return true;
-  }
-
-  /* The client always transmits "GET /" followed by at least four
-     characters that are either lowercase hex digits or equals
-     signs, so we need nine bytes of incoming data. */
-  if (evbuffer_get_length(buf) >= 9) {
-    data = evbuffer_pullup(buf, 9);
-    if (!memcmp(data, "GET /", 5) &&
-        (ascii_isxdigit(data[5]) || data[5] == '=') &&
-        (ascii_isxdigit(data[6]) || data[6] == '=') &&
-        (ascii_isxdigit(data[7]) || data[7] == '=') &&
-        (ascii_isxdigit(data[8]) || data[8] == '='))
-      return true;
-  }
-
-  /* Didn't find either the client or the server pattern. */
-  return false;
-}
-
-size_t
-x_http::transmit_room(conn_t *)
-{
-  if (this->have_transmitted)
-    /* can't send any more on this connection */
-    return 0;
-
-  if (this->is_clientside)
-    /* per http://www.boutell.com/newfaq/misc/urllength.html,
-       IE<9 can handle no more than 2048 characters in the path
-       component of a URL; we're not talking to IE, but this limit
-       means longer paths look fishy; we hex-encode the path, so
-       we have to cut the number in half. */
-    return 1024;
-  else {
-    if (!this->have_received)
-      return 0;
-    /* no practical limit applies */
-    return SIZE_MAX;
-  }
-}
-
-int
-x_http::transmit(struct evbuffer *source, conn_t *conn)
-{
-  struct evbuffer *dest = conn_get_outbound(conn);
-
-  if (this->is_clientside) {
-    /* On the client side, we have to embed the data in a GET query somehow;
-       the only plausible places to put it are the URL and cookies.  This
-       presently uses the URL. And it can't be binary. */
-    struct evbuffer *scratch;
-    struct evbuffer_iovec *iv;
-    int i, nv;
-
-    /* Convert all the data in 'source' to hexadecimal and write it to
-       'scratch'. Data is padded to a multiple of four characters with
-       equals signs. */
-    size_t slen = evbuffer_get_length(source);
-    size_t dlen = slen * 2;
-
-    dlen = dlen + 3 - (dlen-1)%4;
-    if (dlen == 0) dlen = 4;
-
-    scratch = evbuffer_new();
-    if (!scratch) return -1;
-    if (evbuffer_expand(scratch, dlen)) {
-      evbuffer_free(scratch);
-      return -1;
-    }
-
-    nv = evbuffer_peek(source, slen, NULL, NULL, 0);
-    iv = (struct evbuffer_iovec *)xzalloc(sizeof(struct evbuffer_iovec) * nv);
-    if (evbuffer_peek(source, slen, NULL, iv, nv) != nv) {
-      evbuffer_free(scratch);
-      free(iv);
-      return -1;
-    }
-
-    for (i = 0; i < nv; i++) {
-      const uint8_t *p = (const uint8_t *)iv[i].iov_base;
-      const uint8_t *limit = p + iv[i].iov_len;
-      char hex[2], c;
-      while (p < limit) {
-        c = *p++;
-        hex[0] = "0123456789abcdef"[(c & 0xF0) >> 4];
-        hex[1] = "0123456789abcdef"[(c & 0x0F) >> 0];
-        evbuffer_add(scratch, hex, 2);
-      }
-    }
-    free(iv);
-    while (evbuffer_get_length(scratch) == 0 ||
-           evbuffer_get_length(scratch) % 4 != 0)
-      evbuffer_add(scratch, "=", 1);
-
-    if (evbuffer_add(dest, http_query_1, sizeof http_query_1-1) ||
-        evbuffer_add_buffer(dest, scratch) ||
-        evbuffer_add(dest, http_query_2, sizeof http_query_2-1) ||
-        evbuffer_add(dest, conn->peername, strlen(conn->peername)) ||
-        evbuffer_add(dest, http_query_3, sizeof http_query_3-1)) {
-      evbuffer_free(scratch);
-      return -1;
-    }
-
-    evbuffer_free(scratch);
-    evbuffer_drain(source, slen);
-    conn_cease_transmission(conn);
-    this->have_transmitted = true;
-    return 0;
-
-  } else {
-    /* On the server side, we just fake up some HTTP response headers
-       and then splat the data we were given. Binary is OK.  */
-    if (evbuffer_add(dest, http_response_1, sizeof http_response_1-1))
-        return -1;
-    if (evbuffer_add_printf(dest, "%lu\r\n\r\n",
-                            (unsigned long)evbuffer_get_length(source)) == -1)
-      return -1;
-    if (evbuffer_add_buffer(dest, source))
-      return -1;
-
-    conn_close_after_transmit(conn);
-    this->have_transmitted = true;
-    return 0;
-  }
-}
-
-int
-x_http::receive(conn_t *conn, struct evbuffer *dest)
-{
-  struct evbuffer *source = conn_get_inbound(conn);
-  if (this->is_clientside) {
-    /* Linearize the buffer out past the longest possible
-       Content-Length header and subsequent blank line.  2**64 fits in
-       20 characters, and then we have two CRLFs; minus one for the
-       NUL in sizeof http_response_1. Note that this does _not_
-       guarantee that that much data is available. */
-
-    size_t hlen = evbuffer_get_length(source);
-    uint8_t *data, *p, *limit;
-    uint64_t clen;
-
-    log_debug("x_http: %lu byte response stream available%s",
-              (unsigned long)hlen,
-              hlen >= sizeof http_response_1 - 1 ? "" : " (incomplete)");
-
-    if (this->have_received) {
-      log_warn("x_http: protocol error: multiple responses");
-      return -1;
-    }
-
-    if (hlen < sizeof http_response_1 - 1)
-      return 0; /* incomplete */
-
-    if (hlen > sizeof http_response_1 + 23)
-      hlen = sizeof http_response_1 + 23;
-
-    data = evbuffer_pullup(source, hlen);
-    /* Validate response headers. */
-    if (memcmp(data, http_response_1, sizeof http_response_1 - 1))
-      return -1;
-
-    /* There should be an unsigned number immediately after the text of
-       http_response_1, followed by the four characters \r\n\r\n.
-       We may not have the complete number yet. */
-    p = data + sizeof http_response_1 - 1;
-    limit = data + hlen;
-    clen = 0;
-    while (p < limit && '0' <= *p && *p <= '9') {
-      clen = clen*10 + *p - '0';
-      p++;
-    }
-    if (p+4 > limit)
-      return 0; /* incomplete */
-    if (p[0] != '\r' || p[1] != '\n' || p[2] != '\r' || p[3] != '\n')
-      return -1;
-
-    p += 4;
-    hlen = p - data;
-    /* Now we know how much data we're expecting after the blank line. */
-    if (evbuffer_get_length(source) < hlen + clen)
-      return 0; /* incomplete */
-
-    /* we are go */
-    if (evbuffer_drain(source, hlen))
-      return -1;
-
-    if ((uint64_t)evbuffer_remove_buffer(source, dest, clen) != clen)
-      return -1;
-
-    log_debug("x_http: decoded %lu byte response",
-              (unsigned long)(hlen + clen));
-
-    if (evbuffer_get_length(source) > 0) {
-      log_warn("x_http: protocol error: extra response data");
-      return -1;
-    }
-
-    this->have_received = 1;
-    conn_expect_close(conn);
-    return 0;
-  } else {
-    /* We need a scratch buffer here because the contract is that if
-       we hit a decode error we *don't* write anything to 'dest'. */
-    struct evbuffer *scratch;
-    struct evbuffer_ptr s2, s3;
-    uint8_t *data, *p, *limit;
-    uint8_t c, h, secondhalf;
-
-    log_debug("x_http: %lu byte query stream available",
-              (unsigned long)evbuffer_get_length(source));
-
-    if (this->have_received) {
-      log_warn("x_http: protocol error: multiple queries");
-      return -1;
-    }
-
-    /* Search for the second and third invariant bits of the query headers
-       we expect.  We completely ignore the contents of the Host header. */
-    s2 = evbuffer_search(source, http_query_2,
-                         sizeof http_query_2 - 1, NULL);
-    if (s2.pos == -1) {
-      log_debug("x_http: did not find second piece of HTTP query");
-      return 0;
-    }
-    s3 = evbuffer_search(source, http_query_3,
-                         sizeof http_query_3 - 1, &s2);
-    if (s3.pos == -1) {
-      log_debug("x_http: did not find third piece of HTTP query");
-      return 0;
-    }
-    log_assert(s3.pos + sizeof http_query_3 - 1
-                <= evbuffer_get_length(source));
-
-    data = evbuffer_pullup(source, s2.pos);
-    if (memcmp(data, "GET /", sizeof "GET /"-1)) {
-      log_debug("x_http: unexpected HTTP verb: %.*s", 5, data);
-      return -1;
-    }
-
-    p = data + sizeof "GET /"-1;
-    limit = data + s2.pos;
-
-    scratch = evbuffer_new();
-    if (!scratch) return -1;
-    if (evbuffer_expand(scratch, (limit - p)/2)) {
-      evbuffer_free(scratch);
-      return -1;
-    }
-
-    secondhalf = 0;
-    while (p < limit) {
-      if (!secondhalf) c = 0;
-      if ('0' <= *p && *p <= '9') h = *p - '0';
-      else if ('a' <= *p && *p <= 'f') h = *p - 'a' + 10;
-      else if ('A' <= *p && *p <= 'F') h = *p - 'A' + 10;
-      else if (*p == '=' && !secondhalf) {
-        p++;
-        continue;
-      } else {
-        evbuffer_free(scratch);
-        log_debug("x_http: decode error: unexpected URI character %c", *p);
-        return -1;
-      }
-
-      c = (c << 4) + h;
-      if (secondhalf)
-        evbuffer_add(scratch, &c, 1);
-      secondhalf = !secondhalf;
-      p++;
-    }
-
-    if (evbuffer_add_buffer(dest, scratch)) {
-      evbuffer_free(scratch);
-      log_debug("x_http: failed to transfer buffer");
-      return -1;
-    }
-    evbuffer_drain(source, s3.pos + sizeof http_query_3 - 1);
-    evbuffer_free(scratch);
-    log_debug("x_http: decoded %lu byte query",
-              (unsigned long)(s3.pos + sizeof http_query_3 - 1));
-
-    if (evbuffer_get_length(source) > 0) {
-      log_warn("x_http: protocol error: extra query data");
-      return -1;
-    }
-
-    this->have_received = 1;
-    conn_transmit_soon(conn, 2);
-    return 0;
-  }
-}
diff --git a/src/steg/x_http2.c b/src/steg/x_http2.c
deleted file mode 100644
index 7377196..0000000
--- a/src/steg/x_http2.c
+++ /dev/null
@@ -1,857 +0,0 @@
-/*  Copyright (c) 2011, SRI International
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-
-    * Neither the names of the copyright owners nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-    Contributors: Zack Weinberg, Vinod Yegneswaran
-    See LICENSE for other credits and copying information
-*/
-
-
-
-#include "util.h"
-#include "connections.h"
-#include "steg.h"
-#include "payloads.h"
-#include "cookies.h"
-#include "swfSteg.h"
-#include "pdfSteg.h"
-#include "jsSteg.h"
-
-#include <event2/buffer.h>
-#include <stdio.h>
-
-
-
-
-
-
-#define MIN_COOKIE_SIZE 24
-#define MAX_COOKIE_SIZE 1024
-
-
-int 
-x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source);
-
-int
-lookup_peer_name_from_ip(char* p_ip, char* p_name);
-
-
-static int has_peer_name = 0;
-static char peername[512];
-
-
-struct x_http2_steg_t
-{
-  steg_t super;
-  
-  int have_transmitted;
-  int have_received;
-  int type;
-};
-
-
-STEG_DEFINE_MODULE(x_http2,
-                   1024,  /* client-server max data rate - made up */
-                   10240, /* server-client max data rate - ditto */
-                   1,     /* max concurrent connections per IP */
-                   1);     /* max concurrent IPs */
-
-
-
-
-
-
-int x_http2_client_uri_transmit (steg_t *s, struct evbuffer *source, conn_t *conn);
-int x_http2_client_cookie_transmit (steg_t *s, struct evbuffer *source, conn_t *conn);
-
-void evbuffer_dump(struct evbuffer *buf, FILE *out);
-void buf_dump(unsigned char* buf, int len, FILE *out);
-int gen_uri_field(char* uri, unsigned int uri_sz, char* data, int datalen);
-
-
-void 
-evbuffer_dump(struct evbuffer *buf, FILE *out) 
-{
-  int nextent = evbuffer_peek(buf, SSIZE_MAX, 0, 0, 0);
-  struct evbuffer_iovec v[nextent];
-  int i;
-  const unsigned char *p, *limit;
-  
-  if (evbuffer_peek(buf, -1, 0, v, nextent) != nextent)
-    abort();
-  
-  for (i = 0; i < nextent; i++) {
-    p = v[i].iov_base;
-    limit = p + v[i].iov_len;
-    
-    putc('|', out);
-    while (p < limit) {
-      if (*p < 0x20 || *p >= 0x7F || *p == '\\' || *p == '|')
-	fprintf(out, "\\x%02x", *p);
-      else
-	putc(*p, out);
-      p++;
-    }
-  }
-  putc('|', out);
-}
-
-
-
-
-
-void 
-buf_dump(unsigned char* buf, int len, FILE *out) 
-{
-  int i=0;
-  putc('|', out);
-  while (i < len) {
-    if (buf[i] < 0x20 || buf[i] >= 0x7F || buf[i] == '\\' || buf[i]== '|')
-      fprintf(out, "\\x%02x", buf[i]);
-    else
-      putc(buf[i], out);
-    i++;
-  }
-  putc('|', out);
-  putc('\n', out);
-}
-
-
-
-
-
-steg_t * 
-x_http2_new(rng_t *rng, unsigned int is_clientside)
-{
-
-  STEG_NEW(x_http2, state, rng, is_clientside);
-
-  if (is_clientside)
-    load_payloads("traces/client.out");
-  else {
-    load_payloads("traces/server.out");
-    init_JS_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, JS_MIN_AVAIL_SIZE);
-    //   init_JS_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, JS_MIN_AVAIL_SIZE, HTTP_CONTENT_HTML);
-    init_HTML_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, HTML_MIN_AVAIL_SIZE);
-    init_PDF_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, PDF_MIN_AVAIL_SIZE);
-    init_SWF_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, 0);
-  }
-
-
-  /* if there were extra stuff to fill in, you would do it here */
-  return upcast_steg(state);
-}
-
-void
-x_http2_del(steg_t *s)
-{
-  x_http2_steg_t *state = downcast_steg(s);
-
-  STEG_DEL(s);
-
-  /* if there were extra stuff to deallocate, you would do it here */
-  free(state);
-}
-
-
-// x_http2_detect determines if a packet should be processed by the http2 steg module 
-unsigned int
-x_http2_detect(conn_t *conn)
-{
-  struct evbuffer *buf = conn_get_inbound(conn);
-  unsigned char *data;
-
-  //return 0;
-/*****
- Here is a list of HTTP response codes extracted from the server-portals.out trace
-
-7369 HTTP/1.1 200 OK
- 470 HTTP/1.1 302 Found
- 350 HTTP/1.1 304 Not Modified
- 212 HTTP/1.1 302 Moved Temporarily
- 184 HTTP/1.1 204 No Content
- 451 HTTP/1.0 200 OK
-  36 HTTP/1.0 204 No Content
-  21 HTTP/1.1 301 Moved Permanently
-  19 HTTP/1.1 302 Object moved
-  15 HTTP/1.1 404 Not Found
-
-   7 HTTP/1.0 304 Not Modified
-   6 HTTP/1.1 302 Redirect
-   3 HTTP/1.0 200 Ok
-   2 HTTP/1.1 303 Object Moved
-   2 HTTP/1.0 301 Moved Permanently
-   2 HTTP/1.0 302 Moved Temporarily
-   2 HTTP/1.0 400 Bad request
-   2 HTTP/1.0 403 Forbidden
-   1 HTTP/1.0 404 Not Found
-   1 HTTP/1.1 200
-   1 HTTP/1.1 302 FOUND
-   1 HTTP/1.1 304
-   1 HTTP/1.1 400 Bad Request
-   1 HTTP/1.1 403 Forbidden
-   1 HTTP/1.1 503 Service Unavailable.
- *****/
-
-  // The first part of a valid HTTP response should be of the form
-  // HTTP/1.x nnn
-
-  if (evbuffer_get_length(buf) >= 12) {
-    data = evbuffer_pullup(buf, 12);
-    
-    if (data != NULL &&
-         ((!memcmp(data, "HTTP/1.1 200", 12)) ||
-          (!memcmp(data, "HTTP/1.1 302", 12)) ||
-          (!memcmp(data, "HTTP/1.1 304", 12)) ||
-          (!memcmp(data, "HTTP/1.1 204", 12)) ||
-          (!memcmp(data, "HTTP/1.0 200", 12)) ||
-          (!memcmp(data, "HTTP/1.0 204", 12)) ||
-          (!memcmp(data, "HTTP/1.1 301", 12)) ||
-          (!memcmp(data, "HTTP/1.1 302", 12)) ||
-          (!memcmp(data, "HTTP/1.1 404", 12)))) {
-      log_debug("x_http2_detect: valid response");
-      return 1;
-    }
-  }
-
-
-
-
-
-  // SC: if we are only interested in jsSteg, we may want to
-  // consider HTTP/1.1 and HTTP/1.0 responses whose code is 200 only
-
-  // check to see if this is a valid HTTP request
-  //
-  // the following is for HTTP requests used by the http2 steg module
-  // The client always transmits "GET /" followed by at least four
-  // characters that are either lowercase hex digits or equals
-  // signs, so we need nine bytes of incoming data.
-
-
-
-  if (evbuffer_get_length(buf) >= 9) {
-    data = evbuffer_pullup(buf, 9);
-    if (data != NULL && (!memcmp(data, "GET /", 5) || !memcmp(data, "POST /", 5) || !memcmp(data, "Cookie", 6))) {
-      log_debug("x_http2_detect: valid request");
-      return 1;
-    }
-  }
- 
-  log_debug("x_http2_detect: didn't find either HTTP request or response");
-  /* Didn't find either the client or the server pattern. */
-  return 0;
-}
-
-size_t
-x_http2_transmit_room(steg_t *s, conn_t *conn)
-{
-  unsigned int mjc;
-
-  if (downcast_steg(s)->have_transmitted)
-    /* can't send any more on this connection */
-    return 0;
-  
-
-  if (s->is_clientside) {
-    /* per http://www.boutell.com/newfaq/misc/urllength.html,
-       IE<9 can handle no more than 2048 characters in the path
-       component of a URL; we're not talking to IE, but this limit
-       means longer paths look fishy; we hex-encode the path, so
-       we have to cut the number in half. */
-    return (MIN_COOKIE_SIZE + rand() % (MAX_COOKIE_SIZE - MIN_COOKIE_SIZE)) / 4;
-    // return 1024;
-  } 
-  else {
-
-    if (!downcast_steg(s)->have_received)
-      return 0;
-
-    switch(downcast_steg(s)->type) {
-
-    case HTTP_CONTENT_SWF:
-      return 1024;
-
-    case HTTP_CONTENT_JAVASCRIPT:
-      mjc = get_max_JS_capacity() / 2;
-      if (mjc > 1024) {
-	// it should be 1024 + ...., but seems like we need to be a little bit smaller (chopper bug?)
-	int rval = 512 + rand()%(mjc - 1024);  
-	//	fprintf(stderr, "returning rval %d, mjc  %d\n", rval, mjc);
-	return rval;
-      }
-      log_warn("js capacity too small\n");
-      exit(-1);
-
-    case HTTP_CONTENT_HTML:
-      mjc = get_max_HTML_capacity() / 2;
-      if (mjc > 1024) {
-	// it should be 1024 + ...., but seems like we need to be a little bit smaller (chopper bug?)
-	int rval = 512 + rand()%(mjc - 1024);  
-	//	fprintf(stderr, "returning rval %d, mjc  %d\n", rval, mjc);
-	return rval;
-      }
-      log_warn("js capacity too small\n");
-      exit(-1);
-
-    case HTTP_CONTENT_PDF:
-      // return 1024 + rand()%(get_max_PDF_capacity() - 1024)
-      return PDF_MIN_AVAIL_SIZE;
-    }
-
-    return SIZE_MAX;
-  }
-}
-
-
-
-
-
-
-int
-lookup_peer_name_from_ip(char* p_ip, char* p_name)  {
-  struct addrinfo* ailist;
-  struct addrinfo* aip;
-  struct addrinfo hint;
-  char buf[128];
-     
-  hint.ai_flags = AI_CANONNAME;
-  hint.ai_family = 0;
-  hint.ai_socktype = 0;
-  hint.ai_protocol = 0;
-  hint.ai_addrlen = 0;
-  hint.ai_canonname = NULL;
-  hint.ai_addr = NULL;
-  hint.ai_next = NULL;
-  
-  strcpy(buf, p_ip);
-  buf[strchr(buf, ':') - buf] = 0;
-
-  
-  if (getaddrinfo(buf, NULL, &hint, &ailist)) {
-    fprintf(stderr, "error: getaddrinfo() %s\n", p_ip);
-    exit(1);
-  }
- 
-  for (aip = ailist; aip != NULL; aip = aip->ai_next) {
-    char buf[512];
-    if (getnameinfo(aip->ai_addr, sizeof(struct sockaddr), buf, 512, NULL, 0, 0) == 0) {
-      sprintf(p_name, "%s", buf);
-      return 1;
-    }
-  }
-  
-  return 0;
-}
-
-
-
-
-
-
-
-
-int 
-x_http2_client_cookie_transmit (steg_t *s, struct evbuffer *source, conn_t *conn) {
-
-  /* On the client side, we have to embed the data in a GET query somehow;
-     the only plausible places to put it are the URL and cookies.  This
-     presently uses the URL. And it can't be binary. */
-  // struct evbuffer *scratch;
-  struct evbuffer_iovec *iv;
-  int i, nv;
-  struct evbuffer *dest = conn_get_outbound(conn);
-  size_t sbuflen = evbuffer_get_length(source);
-  char buf[10000];
-  unsigned char data[(int) sbuflen*2];
-  //  unsigned char outbuf[MAX_COOKIE_SIZE];
-
-  unsigned char outbuf[(int) sbuflen*8];
-  int datalen;
-
-
-  //  size_t sofar = 0;
-  size_t cookie_len;
-  
-
-  /* Convert all the data in 'source' to hexadecimal and write it to
-     'scratch'. Data is padded to a multiple of four characters with
-     equals signs. */
-
-
-  unsigned int len = 0;
-  unsigned int cnt = 0;
-
-
-
-  datalen = 0;    
-  cookie_len = 4 * sbuflen + rand() % 4;
-  
-
-  nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0);
-  iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
-
-  if (evbuffer_peek(source, sbuflen, NULL, iv, nv) != nv) {
-    free(iv);
-    return -1;
-  }
-
-  // retry up to 10 times
-  while (!len) {
-    len = find_client_payload(buf, sizeof(buf), TYPE_HTTP_REQUEST);
-    if (cnt++ == 10) return -1;
-  }
-
-
-  if (has_peer_name == 0 && lookup_peer_name_from_ip((char*) conn->peername, peername))
-    has_peer_name = 1;
-
-  // if (find_uri_type(buf) != HTTP_CONTENT_SWF) {
-  //   fprintf(stderr, "%s\n", buf);
-  //   exit(-1);
-  // }
-    
-
-  
-  cnt = 0;
-  
-  for (i = 0; i < nv; i++) {
-    const unsigned char *p = iv[i].iov_base;
-    const unsigned char *limit = p + iv[i].iov_len;
-    char c;
-    while (p < limit && cnt < sbuflen) {
-      c = *p++;
-      data[datalen] = "0123456789abcdef"[(c & 0xF0) >> 4];
-      data[datalen+1] = "0123456789abcdef"[(c & 0x0F) >> 0];
-      datalen += 2;
-      cnt++;
-    }
-  }
-  
-  free(iv);
-
-  if (cookie_len < 4) cookie_len = 4;
-
-  datalen = gen_cookie_field(outbuf, cookie_len, data, datalen);
-  log_debug("CLIENT: sending cookie of length = %d %d\n", datalen, (int) cookie_len);
-  //  fprintf(stderr, "CLIENT: sending cookie of length = %d %d\n", datalen, (int) cookie_len);
-
-  if (datalen < 0) {
-    log_debug("cookie generation failed\n");
-    return -1;
-  }
-
-
-  if (evbuffer_add(dest, buf, strstr(buf, "\r\n") - buf + 2)  ||  // add uri field
-      evbuffer_add(dest, "Host: ", 6) ||
-      evbuffer_add(dest, peername, strlen(peername)) ||
-      evbuffer_add(dest, strstr(buf, "\r\n"), len - (unsigned int) (strstr(buf, "\r\n") - buf))  ||  // add everything but first line
-      evbuffer_add(dest, "Cookie: ", 8) ||
-      evbuffer_add(dest, outbuf, cookie_len) ||
-      evbuffer_add(dest, "\r\n\r\n", 4)) {
-      log_debug("error ***********************");
-      return -1;
-    }
- 
-  // debug
-  // log_warn("CLIENT HTTP request header:");
-  // buf_dump((unsigned char*)buf, len, stderr);
- 
-  //  sofar += datalen/2;
-  evbuffer_drain(source, datalen/2);
-  
-  log_debug("CLIENT TRANSMITTED payload %d\n", (int) sbuflen);
-  
-  conn_cease_transmission(conn);
-
-  downcast_steg(s)->type = find_uri_type(buf, sizeof(buf));
-  downcast_steg(s)->have_transmitted = 1;
-  return 0;
-}
-
-
-
-
-int gen_uri_field(char* uri, unsigned int uri_sz, char* data, int datalen) {
-  unsigned int so_far = 0;
-  uri[0] = 0;
-
-  strcat(uri, "GET /");
-  so_far = 5;
-
-  while (datalen > 0) {
-    unsigned int r = rand() % 4;
-
-    if (r == 1) {
-      r = rand() % 46;
-      if (r < 20) 
-	uri[so_far++] = 'g' + r;      
-      else 
-	uri[so_far++] = 'A' + r - 20;
-    }
-    else {
-      uri[so_far++] = data[0];
-      data++;
-      datalen--;
-    }
-
-
-
-    r = rand() % 8;
-
-    if (r == 0 && datalen > 0)
-      uri[so_far++] = '/';
-
-    if (r == 2 && datalen > 0)
-      uri[so_far++] = '_';
-
-
-    if (so_far > uri_sz - 6) {
-      fprintf(stderr, "too small\n");
-      return 0;
-    }
-  }
-
-  switch(rand()%4){
-  case 1:
-    memcpy(uri+so_far, ".htm ", 6);
-    break;
-  case 2:
-    memcpy(uri+so_far, ".html ", 7);
-    break;
-  case 3:
-    memcpy(uri+so_far, ".js ", 5);
-    break;
-  case 0:
-    memcpy(uri+so_far, ".swf ", 6);
-    break;
-
-  }
-
-  return strlen(uri);
-
-}
-
-
-
-
-
-int 
-x_http2_client_uri_transmit (steg_t *s, struct evbuffer *source, conn_t *conn) {
-
-
-  struct evbuffer *dest = conn_get_outbound(conn);
-
-  
-  struct evbuffer_iovec *iv;
-  int i, nv;
-  
-  /* Convert all the data in 'source' to hexadecimal and write it to
-     'scratch'. Data is padded to a multiple of four characters with
-     equals signs. */
-  size_t slen = evbuffer_get_length(source);
-  size_t datalen = 0;
-  int cnt = 0;
-  char data[2*slen];
-  
-  char outbuf[1024];
-  int len =0;
-  char buf[10000];
-  
-  
-  if (has_peer_name == 0 && lookup_peer_name_from_ip((char*) conn->peername, peername))
-    has_peer_name = 1;
-  
-  
-
-  nv = evbuffer_peek(source, slen, NULL, NULL, 0);
-  iv = xzalloc(sizeof(struct evbuffer_iovec) * nv);
-  if (evbuffer_peek(source, slen, NULL, iv, nv) != nv) {
-    free(iv);
-    return -1;
-  }
-  
-  for (i = 0; i < nv; i++) {
-    const unsigned char *p = iv[i].iov_base;
-    const unsigned char *limit = p + iv[i].iov_len;
-    char c;
-    while (p < limit) {
-      c = *p++;
-      data[datalen++] = "0123456789abcdef"[(c & 0xF0) >> 4];
-      data[datalen++] = "0123456789abcdef"[(c & 0x0F) >> 0];
-      }
-  }
-  free(iv);
-  
-
-
-  do {
-    datalen = gen_uri_field(outbuf, sizeof(outbuf), data, datalen);
-  } while (datalen == 0);
-  
-
-
-
-  // retry up to 10 times
-  while (!len) {
-    len = find_client_payload(buf, sizeof(buf), TYPE_HTTP_REQUEST);
-    if (cnt++ == 10) return -1;
-  }
-  
-  
-  //  fprintf(stderr, "outbuf = %s\n", outbuf);
-
-  if (evbuffer_add(dest, outbuf, datalen)  ||  // add uri field
-      evbuffer_add(dest, "HTTP/1.1\r\nHost: ", 19) ||
-      evbuffer_add(dest, peername, strlen(peername)) ||
-      evbuffer_add(dest, strstr(buf, "\r\n"), len - (unsigned int) (strstr(buf, "\r\n") - buf))  ||  // add everything but first line
-      evbuffer_add(dest, "\r\n", 2)) {
-      log_debug("error ***********************");
-      return -1;
-  }
-
-
-
-  evbuffer_drain(source, slen);
-  conn_cease_transmission(conn);
-  downcast_steg(s)->type = find_uri_type(outbuf, sizeof(outbuf));
-  downcast_steg(s)->have_transmitted = 1;
-  return 0;
- 
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-int
-x_http2_transmit(steg_t *s, struct evbuffer *source, conn_t *conn)
-{
-  //  struct evbuffer *dest = conn_get_outbound(conn);
-
-  //  fprintf(stderr, "in x_http2_ transmit %d\n", downcast_steg(s)->type);
-    
-
-
-  if (s->is_clientside) {
-        /* On the client side, we have to embed the data in a GET query somehow;
-       the only plausible places to put it are the URL and cookies.  This
-       presently uses the URL. And it can't be binary. */
-
-    if (evbuffer_get_length(source) < 72)
-      return x_http2_client_uri_transmit(s, source, conn); //@@
-    return x_http2_client_cookie_transmit(s, source, conn); //@@
-  } 
-  else {
-    int rval = -1;
-    switch(downcast_steg(s)->type) {
-      
-    case HTTP_CONTENT_SWF: 
-      rval = x_http2_server_SWF_transmit(s, source, conn);
-      break;
-
-    case HTTP_CONTENT_JAVASCRIPT:
-      rval = x_http2_server_JS_transmit(s, source, conn, HTTP_CONTENT_JAVASCRIPT);
-      break;
-
-    case HTTP_CONTENT_HTML:
-      rval = x_http2_server_JS_transmit(s, source, conn, HTTP_CONTENT_HTML);
-      break;
-
-    case HTTP_CONTENT_PDF:
-      rval = x_http2_server_PDF_transmit(s, source, conn);
-      break;
-    }
-
-    if (rval == 0) downcast_steg(s)->have_transmitted = 1;
-    return rval;
-  }
-}
-
-
-
-
-
-
-int 
-x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
-
-  int cnt = 0;
-  unsigned char* data;
-  int type;
-
-  do {
-    struct evbuffer_ptr s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
-    unsigned char *p;
-    unsigned char c, h, secondhalf;
-    char outbuf[MAX_COOKIE_SIZE];
-    int sofar = 0;
-    int cookie_mode = 0;
-
-
-    if (s2.pos == -1) {
-      log_debug("Did not find end of request %d", (int) evbuffer_get_length(source));
-      //      evbuffer_dump(source, stderr);
-      return RECV_INCOMPLETE;
-    }
-
-    log_debug("SERVER received request header of length %d", (int)s2.pos);
-
-    data = evbuffer_pullup(source, s2.pos+4);
-
-    if (data == NULL) {
-      log_debug("SERVER evbuffer_pullup fails");
-      return RECV_BAD;
-    }
-
-
-    data[s2.pos+3] = 0;
-
-    type = find_uri_type((char *)data, s2.pos+4);
-
-    if (strstr((char*) data, "Cookie") != NULL) {
-      p = (unsigned char*) strstr((char*) data, "Cookie:") + sizeof "Cookie: "-1;
-      cookie_mode = 1;
-    }
-    else
-      p = data + sizeof "GET /" -1;
-
-
-    secondhalf = 0;
-    c = 0;
-   
-
-    while (strncmp((char*) p, "\r\n", 2) != 0 && (cookie_mode != 0 || p[0] != '.')) {
-      if (!secondhalf) 
-	c = 0;
-      if ('0' <= *p && *p <= '9') 
-	h = *p - '0';
-      else if ('a' <= *p && *p <= 'f') 
-	h = *p - 'a' + 10;
-      else {
-	p++;
-	continue;
-      }
-
-      c = (c << 4) + h;
-      if (secondhalf) {
-	outbuf[sofar++] = c;
-	cnt++;
-      }
-      secondhalf = !secondhalf;
-      p++;
-    }
-
-    outbuf[sofar] = 0;
-
-    if (secondhalf) {
-      fprintf(stderr, "incorrect cookie or uri recovery \n");
-      exit(-1);
-    }
-
-
-
-    if (evbuffer_add(dest, outbuf, sofar)) {
-      log_debug("Failed to transfer buffer");
-      return RECV_BAD;
-    } 
-    evbuffer_drain(source, s2.pos + sizeof("\r\n\r\n") - 1);
-  } while (evbuffer_get_length(source));
-  
-
-  downcast_steg(s)->have_received = 1;
-  downcast_steg(s)->type = type;
-  //  fprintf(stderr, "SERVER RECEIVED payload %d %d\n", cnt, type);
-    
-  conn_transmit_soon(conn, 100);
-  return RECV_GOOD;
-}
-
-
-
-
-
-
-
-
-
-
-
-static int
-x_http2_receive(steg_t *s, conn_t *conn, struct evbuffer *dest)
-{
-  struct evbuffer *source = conn_get_inbound(conn);
-  // unsigned int type;
-  int rval = RECV_BAD;
-
-
-  if (s->is_clientside) {
-
-    //    fprintf(stderr, "client type = %d\n", downcast_steg(s)->type);
-
-    switch(downcast_steg(s)->type) {
-      
-    case HTTP_CONTENT_SWF: 
-      rval = x_http2_handle_client_SWF_receive(s, conn, dest, source);
-      break;
-
-    case HTTP_CONTENT_JAVASCRIPT:
-    case HTTP_CONTENT_HTML:
-      rval = x_http2_handle_client_JS_receive(s, conn, dest, source);
-      break;
-
-    case HTTP_CONTENT_PDF:
-      rval = x_http2_handle_client_PDF_receive(s, conn, dest, source);
-      break;
-    }
-
-    if (rval == RECV_GOOD) downcast_steg(s)->have_received = 1;
-    return rval;
-
-  } else {
-    return x_http2_server_receive(s, conn, dest, source);
-  }
-
-   
-}
diff --git a/src/steg/zpack.c b/src/steg/zpack.c
deleted file mode 100644
index 63aa412..0000000
--- a/src/steg/zpack.c
+++ /dev/null
@@ -1,408 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-#include <stdlib.h>
-#include "zlib.h"
-#include "zpack.h"
-
-
-#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
-#  include <fcntl.h>
-#  include <io.h>
-#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
-#else
-#  define SET_BINARY_MODE(file)
-#endif
-
-#define CHUNK 16384
-
-/* Compress from file source to file dest until EOF on source.
-   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
-   allocated for processing, Z_STREAM_ERROR if an invalid compression
-   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
-   version of the library linked do not match, or Z_ERRNO if there is
-   an error reading or writing the files. */
-
-
-int def(char *source, int slen, char *dest, int dlen, int level)
-{
-  int ret, flush;
-  unsigned have;
-  z_stream strm;
-  unsigned char in[CHUNK];
-  unsigned char out[CHUNK];
-  int dlen_orig = dlen;
-
-  /* allocate deflate state */
-  strm.zalloc = Z_NULL;
-  strm.zfree = Z_NULL;
-  strm.opaque = Z_NULL;
-  ret = deflateInit(&strm, level);
-  if (ret != Z_OK)
-    return ret;
-
-  /* compress until end of file */
-  do {
-
-    if (slen > CHUNK)
-      strm.avail_in = CHUNK;
-    else
-      strm.avail_in = slen;
-
-    memcpy (in, source, strm.avail_in);
-    slen = slen - strm.avail_in;
-    source = source + strm.avail_in;
-
-    flush = (slen == 0) ? Z_FINISH : Z_NO_FLUSH;
-    strm.next_in = in;
-
-    /* run deflate() on input until output buffer not full, finish
-       compression if all of source has been read in */
-    do {
-      strm.avail_out = CHUNK;
-      strm.next_out = out;
-      ret = deflate(&strm, flush);    /* no bad return value */
-      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
-      have = CHUNK - strm.avail_out;
-
-      if ((unsigned int) dlen < have) {
-	fprintf(stderr, "dest buf too small!\n");
-	return Z_ERRNO;
-      }
-
-      memcpy(dest, out, have);
-      dest += have;
-      dlen = dlen - have;
-    } while (strm.avail_out == 0);
-    assert(strm.avail_in == 0);     /* all input will be used */
-
-    /* done when last data in file processed */
-  } while (flush != Z_FINISH);
-  assert(ret == Z_STREAM_END);        /* stream will be complete */
-
-  /* clean up and return */
-  (void)deflateEnd(&strm);
-
-  printf("hello here...\n");
-  return (dlen_orig - dlen);
-  //  return Z_OK;
-}
-
-/* Decompress from file source to file dest until stream ends or EOF.
-   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
-   allocated for processing, Z_DATA_ERROR if the deflate data is
-   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
-   the version of the library linked do not match, or Z_ERRNO if there
-   is an error reading or writing the files. */
-
-
-
-
-int inf(char *source, int slen, char *dest, int dlen)
-{
-  int ret;
-  unsigned have;
-  z_stream strm;
-  unsigned char in[CHUNK];
-  unsigned char out[CHUNK];
-  int dlen_orig = dlen;
-
-
-  /* allocate inflate state */
-  strm.zalloc = Z_NULL;
-  strm.zfree = Z_NULL;
-  strm.opaque = Z_NULL;
-  strm.avail_in = 0;
-  strm.next_in = Z_NULL;
-  ret = inflateInit(&strm);
-  if (ret != Z_OK)
-    return ret;
-
-  /* decompress until deflate stream ends or end of file */
-  do {
-
-    if (slen == 0)
-      break;
-	
-    if (slen > CHUNK)
-      strm.avail_in = CHUNK;
-    else
-      strm.avail_in = slen;
-
-    memcpy(in, source, strm.avail_in);
-    slen = slen - strm.avail_in;
-    source = source + strm.avail_in;
-
-
-      
-    strm.next_in = in;
-
-    /* run inflate() on input until output buffer not full */
-    do {
-      strm.avail_out = CHUNK;
-      strm.next_out = out;
-      ret = inflate(&strm, Z_NO_FLUSH);
-      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
-      switch (ret) {
-      case Z_NEED_DICT:
-	ret = Z_DATA_ERROR;     /* and fall through */
-      case Z_DATA_ERROR:
-      case Z_MEM_ERROR:
-	(void)inflateEnd(&strm);
-	return ret;
-      }
-      have = CHUNK - strm.avail_out;
-
-
-      if ((unsigned int) dlen < have) {
-	fprintf(stderr, "dest buf too small!\n");
-	return Z_ERRNO;
-      }
-
-      memcpy(dest, out, have);
-      dest += have;
-      dlen = dlen - have;
-
-    } while (strm.avail_out == 0);
-
-    /* done when inflate() says it's done */
-  } while (ret != Z_STREAM_END);
-
-  /* clean up and return */
-  (void)inflateEnd(&strm);
-
-  if (ret == Z_STREAM_END)
-    return dlen_orig - dlen;
-  return Z_DATA_ERROR;
-}
-
-/* report a zlib or i/o error */
-void zerr(int ret)
-
-{
-  fputs("zpipe: ", stderr);
-  switch (ret) {
-  case Z_ERRNO:
-    if (ferror(stdin))
-      fputs("error reading stdin\n", stderr);
-    if (ferror(stdout))
-      fputs("error writing stdout\n", stderr);
-    break;
-  case Z_STREAM_ERROR:
-    fputs("invalid compression level\n", stderr);
-    break;
-  case Z_DATA_ERROR:
-    fputs("invalid or incomplete deflate data\n", stderr);
-    break;
-  case Z_MEM_ERROR:
-    fputs("out of memory\n", stderr);
-    break;
-  case Z_VERSION_ERROR:
-    fputs("zlib version mismatch!\n", stderr);
-  }
-}
-
-
-
-
-
-
-
-
-/* assumes that we know there is exactly 10 bytes of gzip header */
-
-int gzInflate(char *source, int slen, char *dest, int dlen)
-{
-  int ret;
-  unsigned have;
-  z_stream strm;
-  unsigned char in[CHUNK];
-  unsigned char out[CHUNK];
-  int dlen_orig = dlen;
-
-
-  /* allocate inflate state */
-  strm.zalloc = Z_NULL;
-  strm.zfree = Z_NULL;
-  strm.opaque = Z_NULL;
-  strm.avail_in = 0;
-  strm.next_in = Z_NULL;
-
-
-  ret = inflateInit2(&strm, -MAX_WBITS);
-  if (ret != Z_OK)
-    return ret;
-
-  source = source + 10;
-  slen -= 10;
-
-  /* decompress until deflate stream ends or end of file */
-  do {
-
-    if (slen == 0)
-      break;
-	
-    if (slen > CHUNK)
-      strm.avail_in = CHUNK;
-    else
-      strm.avail_in = slen;
-
-    memcpy(in, source, strm.avail_in);
-    slen = slen - strm.avail_in;
-    source = source + strm.avail_in;
-
-
-      
-    strm.next_in = in;
-
-    /* run inflate() on input until output buffer not full */
-    do {
-      strm.avail_out = CHUNK;
-      strm.next_out = out;
-      ret = inflate(&strm, Z_NO_FLUSH);
-      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
-      switch (ret) {
-      case Z_NEED_DICT:
-	ret = Z_DATA_ERROR;     /* and fall through */
-      case Z_DATA_ERROR:
-      case Z_MEM_ERROR:
-	(void)inflateEnd(&strm);
-	return ret;
-      }
-      have = CHUNK - strm.avail_out;
-
-      if ((unsigned int) dlen < have) {
-	fprintf(stderr, "dest buf too small!\n");
-	return Z_ERRNO;
-      }
-
-      memcpy(dest, out, have);
-      dest += have;
-      dlen = dlen - have;
-
-    } while (strm.avail_out == 0);
-
-    /* done when inflate() says it's done */
-  } while (ret != Z_STREAM_END);
-
-  /* clean up and return */
-  (void)inflateEnd(&strm);
-
-  if (ret == Z_STREAM_END)
-    return dlen_orig - dlen;
-  return Z_DATA_ERROR;
-}
-
-
-
-
-
-
-
-int gzDeflate(char* start, off_t insz, char *buf, off_t outsz, time_t mtime) {
-  unsigned char *c;
-  unsigned long crc;
-  z_stream z;
-
-  z.zalloc = Z_NULL;
-  z.zfree = Z_NULL;
-  z.opaque = Z_NULL;
-
-  if (Z_OK != deflateInit2(&z,
-			   Z_DEFAULT_COMPRESSION,
-			   Z_DEFLATED,
-			   -MAX_WBITS,  /* supress zlib-header */
-			   8,
-			   Z_DEFAULT_STRATEGY)) {
-    return -1;
-  }
-
-  z.next_in = (unsigned char *)start;
-  z.avail_in = insz;
-  z.total_in = 0;
-
-
-  /* write gzip header */
-
-  c = (unsigned char *) buf;
-  c[0] = 0x1f;
-  c[1] = 0x8b;
-  c[2] = Z_DEFLATED;
-  c[3] = 0; /* options */
-  c[4] = (mtime >>  0) & 0xff;
-  c[5] = (mtime >>  8) & 0xff;
-  c[6] = (mtime >> 16) & 0xff;
-  c[7] = (mtime >> 24) & 0xff;
-  c[8] = 0x00; /* extra flags */
-  c[9] = 0x03; /* UNIX */
-
-  z.next_out = c + 10;
-  z.avail_out = outsz - 10 - 8;
-  z.total_out = 0;
-
-  if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
-    deflateEnd(&z);
-    return -1;
-  }
-
-
-  crc = generate_crc32c(start, insz);
-
-  c = (unsigned char *)buf + 10 + z.total_out; 
-
-  c[0] = (crc >>  0) & 0xff;
-  c[1] = (crc >>  8) & 0xff;
-  c[2] = (crc >> 16) & 0xff;
-  c[3] = (crc >> 24) & 0xff;
-  c[4] = (z.total_in >>  0) & 0xff;
-  c[5] = (z.total_in >>  8) & 0xff;
-  c[6] = (z.total_in >> 16) & 0xff;
-  c[7] = (z.total_in >> 24) & 0xff;
-
-
-
-  if (Z_OK != deflateEnd(&z)) {
-    return -1;
-  }
-
-  return 10 + z.total_out + 8;
-
-}
-
-
-
-
-
-/* compress or decompress from stdin to stdout */
-/* int main(int argc, char **argv) */
-/* { */
-/*   int ret; */
-/*   char buf1[32] = "abcasdfadfadfadf23fasdfa23sdfsdf"; */
-/*   char buf2[100]; */
-/*   char buf3[100]; */
-/*   int i; */
-
-/*   bzero(buf2, sizeof(buf2)); */
-/*   bzero(buf3, sizeof(buf3)); */
-  
-
-/*   //  ret = def(buf1, 3, buf2, 100,  Z_DEFAULT_COMPRESSION); */
-/*   ret = gzDeflate(buf1, sizeof(buf1), buf2, sizeof(buf2), time(NULL)); */
-/*   if (ret <= 0) */
-/*     zerr(ret); */
-
-/*   /\*  for (i=0; i < ret; i++) */
-/*     putc(buf2[i], stdout); */
-/*   *\/ */
-
-
-/*   //  printf("len = %d\n", ret); */
-
-/*   ret = gzInflate(buf2, ret, buf3, 100); */
-/*   if (ret <= 0) */
-/*     zerr(ret); */
-/*   printf("hello %s\n", buf3); */
-
-
-/* } */
diff --git a/src/steg/zpack.cc b/src/steg/zpack.cc
new file mode 100644
index 0000000..63aa412
--- /dev/null
+++ b/src/steg/zpack.cc
@@ -0,0 +1,408 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include <stdlib.h>
+#include "zlib.h"
+#include "zpack.h"
+
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+#  include <fcntl.h>
+#  include <io.h>
+#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#  define SET_BINARY_MODE(file)
+#endif
+
+#define CHUNK 16384
+
+/* Compress from file source to file dest until EOF on source.
+   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_STREAM_ERROR if an invalid compression
+   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+   version of the library linked do not match, or Z_ERRNO if there is
+   an error reading or writing the files. */
+
+
+int def(char *source, int slen, char *dest, int dlen, int level)
+{
+  int ret, flush;
+  unsigned have;
+  z_stream strm;
+  unsigned char in[CHUNK];
+  unsigned char out[CHUNK];
+  int dlen_orig = dlen;
+
+  /* allocate deflate state */
+  strm.zalloc = Z_NULL;
+  strm.zfree = Z_NULL;
+  strm.opaque = Z_NULL;
+  ret = deflateInit(&strm, level);
+  if (ret != Z_OK)
+    return ret;
+
+  /* compress until end of file */
+  do {
+
+    if (slen > CHUNK)
+      strm.avail_in = CHUNK;
+    else
+      strm.avail_in = slen;
+
+    memcpy (in, source, strm.avail_in);
+    slen = slen - strm.avail_in;
+    source = source + strm.avail_in;
+
+    flush = (slen == 0) ? Z_FINISH : Z_NO_FLUSH;
+    strm.next_in = in;
+
+    /* run deflate() on input until output buffer not full, finish
+       compression if all of source has been read in */
+    do {
+      strm.avail_out = CHUNK;
+      strm.next_out = out;
+      ret = deflate(&strm, flush);    /* no bad return value */
+      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+      have = CHUNK - strm.avail_out;
+
+      if ((unsigned int) dlen < have) {
+	fprintf(stderr, "dest buf too small!\n");
+	return Z_ERRNO;
+      }
+
+      memcpy(dest, out, have);
+      dest += have;
+      dlen = dlen - have;
+    } while (strm.avail_out == 0);
+    assert(strm.avail_in == 0);     /* all input will be used */
+
+    /* done when last data in file processed */
+  } while (flush != Z_FINISH);
+  assert(ret == Z_STREAM_END);        /* stream will be complete */
+
+  /* clean up and return */
+  (void)deflateEnd(&strm);
+
+  printf("hello here...\n");
+  return (dlen_orig - dlen);
+  //  return Z_OK;
+}
+
+/* Decompress from file source to file dest until stream ends or EOF.
+   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_DATA_ERROR if the deflate data is
+   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+   the version of the library linked do not match, or Z_ERRNO if there
+   is an error reading or writing the files. */
+
+
+
+
+int inf(char *source, int slen, char *dest, int dlen)
+{
+  int ret;
+  unsigned have;
+  z_stream strm;
+  unsigned char in[CHUNK];
+  unsigned char out[CHUNK];
+  int dlen_orig = dlen;
+
+
+  /* allocate inflate state */
+  strm.zalloc = Z_NULL;
+  strm.zfree = Z_NULL;
+  strm.opaque = Z_NULL;
+  strm.avail_in = 0;
+  strm.next_in = Z_NULL;
+  ret = inflateInit(&strm);
+  if (ret != Z_OK)
+    return ret;
+
+  /* decompress until deflate stream ends or end of file */
+  do {
+
+    if (slen == 0)
+      break;
+	
+    if (slen > CHUNK)
+      strm.avail_in = CHUNK;
+    else
+      strm.avail_in = slen;
+
+    memcpy(in, source, strm.avail_in);
+    slen = slen - strm.avail_in;
+    source = source + strm.avail_in;
+
+
+      
+    strm.next_in = in;
+
+    /* run inflate() on input until output buffer not full */
+    do {
+      strm.avail_out = CHUNK;
+      strm.next_out = out;
+      ret = inflate(&strm, Z_NO_FLUSH);
+      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+      switch (ret) {
+      case Z_NEED_DICT:
+	ret = Z_DATA_ERROR;     /* and fall through */
+      case Z_DATA_ERROR:
+      case Z_MEM_ERROR:
+	(void)inflateEnd(&strm);
+	return ret;
+      }
+      have = CHUNK - strm.avail_out;
+
+
+      if ((unsigned int) dlen < have) {
+	fprintf(stderr, "dest buf too small!\n");
+	return Z_ERRNO;
+      }
+
+      memcpy(dest, out, have);
+      dest += have;
+      dlen = dlen - have;
+
+    } while (strm.avail_out == 0);
+
+    /* done when inflate() says it's done */
+  } while (ret != Z_STREAM_END);
+
+  /* clean up and return */
+  (void)inflateEnd(&strm);
+
+  if (ret == Z_STREAM_END)
+    return dlen_orig - dlen;
+  return Z_DATA_ERROR;
+}
+
+/* report a zlib or i/o error */
+void zerr(int ret)
+
+{
+  fputs("zpipe: ", stderr);
+  switch (ret) {
+  case Z_ERRNO:
+    if (ferror(stdin))
+      fputs("error reading stdin\n", stderr);
+    if (ferror(stdout))
+      fputs("error writing stdout\n", stderr);
+    break;
+  case Z_STREAM_ERROR:
+    fputs("invalid compression level\n", stderr);
+    break;
+  case Z_DATA_ERROR:
+    fputs("invalid or incomplete deflate data\n", stderr);
+    break;
+  case Z_MEM_ERROR:
+    fputs("out of memory\n", stderr);
+    break;
+  case Z_VERSION_ERROR:
+    fputs("zlib version mismatch!\n", stderr);
+  }
+}
+
+
+
+
+
+
+
+
+/* assumes that we know there is exactly 10 bytes of gzip header */
+
+int gzInflate(char *source, int slen, char *dest, int dlen)
+{
+  int ret;
+  unsigned have;
+  z_stream strm;
+  unsigned char in[CHUNK];
+  unsigned char out[CHUNK];
+  int dlen_orig = dlen;
+
+
+  /* allocate inflate state */
+  strm.zalloc = Z_NULL;
+  strm.zfree = Z_NULL;
+  strm.opaque = Z_NULL;
+  strm.avail_in = 0;
+  strm.next_in = Z_NULL;
+
+
+  ret = inflateInit2(&strm, -MAX_WBITS);
+  if (ret != Z_OK)
+    return ret;
+
+  source = source + 10;
+  slen -= 10;
+
+  /* decompress until deflate stream ends or end of file */
+  do {
+
+    if (slen == 0)
+      break;
+	
+    if (slen > CHUNK)
+      strm.avail_in = CHUNK;
+    else
+      strm.avail_in = slen;
+
+    memcpy(in, source, strm.avail_in);
+    slen = slen - strm.avail_in;
+    source = source + strm.avail_in;
+
+
+      
+    strm.next_in = in;
+
+    /* run inflate() on input until output buffer not full */
+    do {
+      strm.avail_out = CHUNK;
+      strm.next_out = out;
+      ret = inflate(&strm, Z_NO_FLUSH);
+      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+      switch (ret) {
+      case Z_NEED_DICT:
+	ret = Z_DATA_ERROR;     /* and fall through */
+      case Z_DATA_ERROR:
+      case Z_MEM_ERROR:
+	(void)inflateEnd(&strm);
+	return ret;
+      }
+      have = CHUNK - strm.avail_out;
+
+      if ((unsigned int) dlen < have) {
+	fprintf(stderr, "dest buf too small!\n");
+	return Z_ERRNO;
+      }
+
+      memcpy(dest, out, have);
+      dest += have;
+      dlen = dlen - have;
+
+    } while (strm.avail_out == 0);
+
+    /* done when inflate() says it's done */
+  } while (ret != Z_STREAM_END);
+
+  /* clean up and return */
+  (void)inflateEnd(&strm);
+
+  if (ret == Z_STREAM_END)
+    return dlen_orig - dlen;
+  return Z_DATA_ERROR;
+}
+
+
+
+
+
+
+
+int gzDeflate(char* start, off_t insz, char *buf, off_t outsz, time_t mtime) {
+  unsigned char *c;
+  unsigned long crc;
+  z_stream z;
+
+  z.zalloc = Z_NULL;
+  z.zfree = Z_NULL;
+  z.opaque = Z_NULL;
+
+  if (Z_OK != deflateInit2(&z,
+			   Z_DEFAULT_COMPRESSION,
+			   Z_DEFLATED,
+			   -MAX_WBITS,  /* supress zlib-header */
+			   8,
+			   Z_DEFAULT_STRATEGY)) {
+    return -1;
+  }
+
+  z.next_in = (unsigned char *)start;
+  z.avail_in = insz;
+  z.total_in = 0;
+
+
+  /* write gzip header */
+
+  c = (unsigned char *) buf;
+  c[0] = 0x1f;
+  c[1] = 0x8b;
+  c[2] = Z_DEFLATED;
+  c[3] = 0; /* options */
+  c[4] = (mtime >>  0) & 0xff;
+  c[5] = (mtime >>  8) & 0xff;
+  c[6] = (mtime >> 16) & 0xff;
+  c[7] = (mtime >> 24) & 0xff;
+  c[8] = 0x00; /* extra flags */
+  c[9] = 0x03; /* UNIX */
+
+  z.next_out = c + 10;
+  z.avail_out = outsz - 10 - 8;
+  z.total_out = 0;
+
+  if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
+    deflateEnd(&z);
+    return -1;
+  }
+
+
+  crc = generate_crc32c(start, insz);
+
+  c = (unsigned char *)buf + 10 + z.total_out; 
+
+  c[0] = (crc >>  0) & 0xff;
+  c[1] = (crc >>  8) & 0xff;
+  c[2] = (crc >> 16) & 0xff;
+  c[3] = (crc >> 24) & 0xff;
+  c[4] = (z.total_in >>  0) & 0xff;
+  c[5] = (z.total_in >>  8) & 0xff;
+  c[6] = (z.total_in >> 16) & 0xff;
+  c[7] = (z.total_in >> 24) & 0xff;
+
+
+
+  if (Z_OK != deflateEnd(&z)) {
+    return -1;
+  }
+
+  return 10 + z.total_out + 8;
+
+}
+
+
+
+
+
+/* compress or decompress from stdin to stdout */
+/* int main(int argc, char **argv) */
+/* { */
+/*   int ret; */
+/*   char buf1[32] = "abcasdfadfadfadf23fasdfa23sdfsdf"; */
+/*   char buf2[100]; */
+/*   char buf3[100]; */
+/*   int i; */
+
+/*   bzero(buf2, sizeof(buf2)); */
+/*   bzero(buf3, sizeof(buf3)); */
+  
+
+/*   //  ret = def(buf1, 3, buf2, 100,  Z_DEFAULT_COMPRESSION); */
+/*   ret = gzDeflate(buf1, sizeof(buf1), buf2, sizeof(buf2), time(NULL)); */
+/*   if (ret <= 0) */
+/*     zerr(ret); */
+
+/*   /\*  for (i=0; i < ret; i++) */
+/*     putc(buf2[i], stdout); */
+/*   *\/ */
+
+
+/*   //  printf("len = %d\n", ret); */
+
+/*   ret = gzInflate(buf2, ret, buf3, 100); */
+/*   if (ret <= 0) */
+/*     zerr(ret); */
+/*   printf("hello %s\n", buf3); */
+
+
+/* } */





More information about the tor-commits mailing list