* add contexttype, so the subst can precheck the context pointer for us, and bad...
[citadel.git] / webcit / webcit.c
index 27edb1a3d3aeef1d12fdfb511c7182cb5930f50d..ed2eefc54bb4670794e31eb0a197948d4b8f32d8 100644 (file)
@@ -88,64 +88,74 @@ long unescape_input(char *buf)
 void free_url(void *U)
 {
        urlcontent *u = (urlcontent*) U;
-       free(u->url_data);
+       FreeStrBuf(&u->url_data);
        free(u);
 }
 
 /*
  * Extract variables from the URL.
  */
-void addurls(char *url, long ulen)
+void addurls(StrBuf *url)
 {
-       char *aptr, *bptr, *eptr;
-       char *up;
-       char *buf;
+       const char *aptr, *bptr, *eptr, *up;
+///    char *buf;
        int len, keylen;
        urlcontent *u;
        struct wcsession *WCC = WC;
 
        if (WCC->urlstrings == NULL)
                WCC->urlstrings = NewHash(1, NULL);
-       buf = (char*) malloc (ulen + 1);
-       memcpy(buf, url, ulen);
-       buf[ulen] = '\0';
-       eptr = buf + ulen;
-       up = buf;
+//     buf = (char*) malloc (ulen + 1);
+//     memcpy(buf, url, ulen);
+///    buf[ulen] = '\0';
+       eptr = ChrPtr(url) + StrLength(url);
+       up = ChrPtr(url);
        while ((up < eptr) && (!IsEmptyStr(up))) {
                aptr = up;
                while ((aptr < eptr) && (*aptr != '\0') && (*aptr != '='))
                        aptr++;
-               if (*aptr != '=')
+               if (*aptr != '=') {
+                       ///free(buf);
                        return;
-               *aptr = '\0';
+               }
+               ///*aptr = '\0';
                aptr++;
                bptr = aptr;
                while ((bptr < eptr) && (*bptr != '\0')
                      && (*bptr != '&') && (*bptr != '?') && (*bptr != ' ')) {
                        bptr++;
                }
-               *bptr = '\0';
-               u = (urlcontent *) malloc(sizeof(urlcontent));
+               //*bptr = '\0';
+               keylen = aptr - up - 1; /* -1 -> '=' */
+               if(keylen > sizeof(u->url_key)) {
+                       lprintf(1, "URLkey to long! [%s]", up);
+                       continue;
+               }
 
-               keylen = safestrncpy(u->url_key, up, sizeof u->url_key);
-               if (keylen < 0){
+               u = (urlcontent *) malloc(sizeof(urlcontent));
+               memcpy(u->url_key, up, keylen);
+               u->url_key[keylen] = '\0';
+               if (keylen < 0) {
                        lprintf(1, "URLkey to long! [%s]", up);
+                       free(u);
                        continue;
                }
 
                Put(WCC->urlstrings, u->url_key, keylen, u, free_url);
                len = bptr - aptr;
-               u->url_data = malloc(len + 2);
-               safestrncpy(u->url_data, aptr, len + 2);
-               u->url_data_size = unescape_input(u->url_data);
-               u->url_data[u->url_data_size] = '\0';
+               u->url_data = NewStrBufPlain(aptr, len);
+               StrBufUnescape(u->url_data, 1);
+            
                up = bptr;
                ++up;
 #ifdef DEBUG_URLSTRINGS
-               lprintf(9, "%s = [%ld]  %s\n", u->url_key, u->url_data_size, u->url_data); 
+               lprintf(9, "%s = [%ld]  %s\n", 
+                       u->url_key, 
+                       StrLength(u->url_data), 
+                       ChrPtr(u->url_data)); 
 #endif
        }
-       free(buf);
+       //free(buf);
 }
 
 /*
@@ -166,13 +176,13 @@ void dump_vars(void)
        urlcontent *u;
        void *U;
        long HKLen;
-       char *HKey;
+       const char *HKey;
        HashPos *Cursor;
        
        Cursor = GetNewHashPos ();
        while (GetNextHashPos(WCC->urlstrings, Cursor, &HKLen, &HKey, &U)) {
                u = (urlcontent*) U;
-               wprintf("%38s = %s\n", u->url_key, u->url_data);
+               wprintf("%38s = %s\n", u->url_key, ChrPtr(u->url_data));
        }
 }
 
@@ -180,14 +190,14 @@ void dump_vars(void)
  * Return the value of a variable supplied to the current web page (from the url or a form)
  */
 
-const char *XBstr(char *key, size_t keylen, size_t *len)
+const char *XBstr(const char *key, size_t keylen, size_t *len)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, keylen, &U)) {
-               *len = ((urlcontent *)U)->url_data_size;
-               return ((urlcontent *)U)->url_data;
+               *len = StrLength(((urlcontent *)U)->url_data);
+               return ChrPtr(((urlcontent *)U)->url_data);
        }
        else {
                *len = 0;
@@ -195,14 +205,14 @@ const char *XBstr(char *key, size_t keylen, size_t *len)
        }
 }
 
-const char *XBSTR(char *key, size_t *len)
+const char *XBSTR(const char *key, size_t *len)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) &&
            GetHash(WC->urlstrings, key, strlen (key), &U)){
-               *len = ((urlcontent *)U)->url_data_size;
-               return ((urlcontent *)U)->url_data;
+               *len = StrLength(((urlcontent *)U)->url_data);
+               return ChrPtr(((urlcontent *)U)->url_data);
        }
        else {
                *len = 0;
@@ -211,113 +221,135 @@ const char *XBSTR(char *key, size_t *len)
 }
 
 
-const char *BSTR(char *key)
+const char *BSTR(const char *key)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) &&
            GetHash(WC->urlstrings, key, strlen (key), &U))
-               return ((urlcontent *)U)->url_data;
+               return ChrPtr(((urlcontent *)U)->url_data);
        else    
                return ("");
 }
 
-const char *Bstr(char *key, size_t keylen)
+const char *Bstr(const char *key, size_t keylen)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, keylen, &U))
-               return ((urlcontent *)U)->url_data;
+               return ChrPtr(((urlcontent *)U)->url_data);
        else    
                return ("");
 }
 
-long LBstr(char *key, size_t keylen)
+const StrBuf *SBSTR(const char *key)
+{
+       void *U;
+
+       if ((WC->urlstrings != NULL) &&
+           GetHash(WC->urlstrings, key, strlen (key), &U))
+               return ((urlcontent *)U)->url_data;
+       else    
+               return NULL;
+}
+
+const StrBuf *SBstr(const char *key, size_t keylen)
+{
+       void *U;
+
+       if ((WC->urlstrings != NULL) && 
+           GetHash(WC->urlstrings, key, keylen, &U))
+               return ((urlcontent *)U)->url_data;
+       else    
+               return NULL;
+}
+
+long LBstr(const char *key, size_t keylen)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, keylen, &U))
-               return atol(((urlcontent *)U)->url_data);
+               return StrTol(((urlcontent *)U)->url_data);
        else    
                return (0);
 }
 
-long LBSTR(char *key)
+long LBSTR(const char *key)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, strlen(key), &U))
-               return atol(((urlcontent *)U)->url_data);
+               return StrTol(((urlcontent *)U)->url_data);
        else    
                return (0);
 }
 
-int IBstr(char *key, size_t keylen)
+int IBstr(const char *key, size_t keylen)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, keylen, &U))
-               return atoi(((urlcontent *)U)->url_data);
+               return StrTol(((urlcontent *)U)->url_data);
        else    
                return (0);
 }
 
-int IBSTR(char *key)
+int IBSTR(const char *key)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, strlen(key), &U))
-               return atoi(((urlcontent *)U)->url_data);
+               return StrToi(((urlcontent *)U)->url_data);
        else    
                return (0);
 }
 
-int HaveBstr(char *key, size_t keylen)
+int HaveBstr(const char *key, size_t keylen)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, keylen, &U))
-               return ((urlcontent *)U)->url_data_size != 0;
+               return (StrLength(((urlcontent *)U)->url_data) != 0);
        else    
                return (0);
 }
 
-int HAVEBSTR(char *key)
+int HAVEBSTR(const char *key)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, strlen(key), &U))
-               return ((urlcontent *)U)->url_data_size != 0;
+               return (StrLength(((urlcontent *)U)->url_data) != 0);
        else    
                return (0);
 }
 
 
-int YesBstr(char *key, size_t keylen)
+int YesBstr(const char *key, size_t keylen)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, keylen, &U))
-               return strcmp( ((urlcontent *)U)->url_data, "yes") == 0;
+               return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0;
        else    
                return (0);
 }
 
-int YESBSTR(char *key)
+int YESBSTR(const char *key)
 {
        void *U;
 
        if ((WC->urlstrings != NULL) && 
            GetHash(WC->urlstrings, key, strlen(key), &U))
-               return strcmp( ((urlcontent *)U)->url_data, "yes") == 0;
+               return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0;
        else    
                return (0);
 }
@@ -370,7 +402,7 @@ void wDumpContent(int print_standard_html_footer)
 {
        if (print_standard_html_footer) {
                wprintf("</div>\n");    /* end of "text" div */
-               do_template("trailing");
+               do_template("trailing", NULL);
        }
 
        /* If we've been saving it all up for one big output burst,
@@ -380,89 +412,89 @@ void wDumpContent(int print_standard_html_footer)
 }
 
 
 /*
  * Copy a string, escaping characters which have meaning in HTML.  
  *
- * target              target buffer
- * strbuf              source buffer
- * nbsp                        If nonzero, spaces are converted to non-breaking spaces.
- * nolinebreaks                if set, linebreaks are removed from the string.
+ * target              target buffer
+ * strbuf              source buffer
+ * nbsp                        If nonzero, spaces are converted to non-breaking spaces.
+ * nolinebreaks                if set, linebreaks are removed from the string.
  */
 long stresc(char *target, long tSize, char *strbuf, int nbsp, int nolinebreaks)
 {
-       char *aptr, *bptr, *eptr;
-
-       *target = '\0';
-       aptr = strbuf;
-       bptr = target;
-       eptr = target + tSize - 6; // our biggest unit to put in... 
-
-       while ((bptr < eptr) && !IsEmptyStr(aptr) ){
-               if (*aptr == '<') {
-                       memcpy(bptr, "&lt;", 4);
-                       bptr += 4;
-               }
-               else if (*aptr == '>') {
-                       memcpy(bptr, "&gt;", 4);
-                       bptr += 4;
-               }
-               else if (*aptr == '&') {
-                       memcpy(bptr, "&amp;", 5);
-                       bptr += 5;
-               }
-               else if (*aptr == '\"') {
-                       memcpy(bptr, "&quot;", 6);
-                       bptr += 6;
-               }
-               else if (*aptr == '\'') {
-                       memcpy(bptr, "&#39;", 5);
-                       bptr += 5;
-               }
-               else if (*aptr == LB) {
-                       *bptr = '<';
-                       bptr ++;
-               }
-               else if (*aptr == RB) {
-                       *bptr = '>';
-                       bptr ++;
-               }
-               else if (*aptr == QU) {
-                       *bptr ='"';
-                       bptr ++;
-               }
-               else if ((*aptr == 32) && (nbsp == 1)) {
-                       memcpy(bptr, "&nbsp;", 6);
-                       bptr += 6;
-               }
-               else if ((*aptr == '\n') && (nolinebreaks)) {
-                       *bptr='\0';     /* nothing */
-               }
-               else if ((*aptr == '\r') && (nolinebreaks)) {
-                       *bptr='\0';     /* nothing */
-               }
-               else{
-                       *bptr = *aptr;
-                       bptr++;
-               }
-               aptr ++;
-       }
-       *bptr = '\0';
-       if ((bptr = eptr - 1 ) && !IsEmptyStr(aptr) )
-               return -1;
-       return (bptr - target);
+        char *aptr, *bptr, *eptr;
+        *target = '\0';
+        aptr = strbuf;
+        bptr = target;
+        eptr = target + tSize - 6; // our biggest unit to put in... 
+        while ((bptr < eptr) && !IsEmptyStr(aptr) ){
+                if (*aptr == '<') {
+                        memcpy(bptr, "&lt;", 4);
+                        bptr += 4;
+                }
+                else if (*aptr == '>') {
+                        memcpy(bptr, "&gt;", 4);
+                        bptr += 4;
+                }
+                else if (*aptr == '&') {
+                        memcpy(bptr, "&amp;", 5);
+                        bptr += 5;
+                }
+                else if (*aptr == '\"') {
+                        memcpy(bptr, "&quot;", 6);
+                        bptr += 6;
+                }
+                else if (*aptr == '\'') {
+                        memcpy(bptr, "&#39;", 5);
+                        bptr += 5;
+                }
+                else if (*aptr == LB) {
+                        *bptr = '<';
+                        bptr ++;
+                }
+                else if (*aptr == RB) {
+                        *bptr = '>';
+                        bptr ++;
+                }
+                else if (*aptr == QU) {
+                        *bptr ='"';
+                        bptr ++;
+                }
+                else if ((*aptr == 32) && (nbsp == 1)) {
+                        memcpy(bptr, "&nbsp;", 6);
+                        bptr += 6;
+                }
+                else if ((*aptr == '\n') && (nolinebreaks)) {
+                        *bptr='\0';     /* nothing */
+                }
+                else if ((*aptr == '\r') && (nolinebreaks)) {
+                        *bptr='\0';     /* nothing */
+                }
+                else{
+                        *bptr = *aptr;
+                        bptr++;
+                }
+                aptr ++;
+        }
+        *bptr = '\0';
+        if ((bptr = eptr - 1 ) && !IsEmptyStr(aptr) )
+                return -1;
+        return (bptr - target);
 }
 
+
 void escputs1(char *strbuf, int nbsp, int nolinebreaks)
 {
-       char *buf;
-       long Siz;
+       StrEscAppend(WC->WBuf, NULL, strbuf, nbsp, nolinebreaks);
+}
 
-       if (strbuf == NULL) return;
-       Siz = (3 * strlen(strbuf)) + SIZ ;
-       buf = malloc(Siz);
-       stresc(buf, Siz, strbuf, nbsp, nolinebreaks);
-       wprintf("%s", buf);
-       free(buf);
+void StrEscputs1(const StrBuf *strbuf, int nbsp, int nolinebreaks)
+{
+       StrEscAppend(WC->WBuf, strbuf, NULL, nbsp, nolinebreaks);
 }
 
 /* 
@@ -474,15 +506,37 @@ void escputs(char *strbuf)
 }
 
 
+/* 
+ * static wrapper for ecsputs1
+ */
+void StrEscPuts(const StrBuf *strbuf)
+{
+       StrEscputs1(strbuf, 0, 0);
+}
+
+
 /*
  * urlescape buffer and print it to the client
  */
-void urlescputs(char *strbuf)
+void urlescputs(const char *strbuf)
 {
-       char outbuf[SIZ];
-       
-       urlesc(outbuf, SIZ, strbuf);
-       wprintf("%s", outbuf);
+       StrBufUrlescAppend(WC->WBuf, NULL, strbuf);
+}
+
+/*
+ * urlescape buffer and print it to the client
+ */
+void UrlescPutStrBuf(const StrBuf *strbuf)
+{
+       StrBufUrlescAppend(WC->WBuf, strbuf, NULL);
+}
+
+/**
+ * urlescape buffer and print it as header 
+ */
+void hurlescputs(const char *strbuf) 
+{
+       StrBufUrlescAppend(WC->HBuf, NULL, strbuf);
 }
 
 
@@ -555,81 +609,27 @@ void jsescputs(char *strbuf)
        wprintf("%s", outbuf);
 }
 
-/*
- * Copy a string, escaping characters for message text hold
- */
-void msgesc(char *target, size_t tlen, char *strbuf)
-{
-       int len;
-       char *tend;
-       char *send;
-       char *tptr;
-       char *sptr;
-
-       target[0]='\0';
-       len = strlen (strbuf);
-       send = strbuf + len;
-       tend = target + tlen;
-       sptr = strbuf;
-       tptr = target;
-
-       while (!IsEmptyStr(sptr) && 
-              (sptr < send) &&
-              (tptr < tend)) {
-              
-               if (*sptr == '\n')
-                       *tptr = ' ';
-               else if (*sptr == '\r')
-                       *tptr = ' ';
-               else if (*sptr == '\'') {
-                       if (tend - tptr < 8)
-                               return;
-                       *(tptr++) = '&';
-                       *(tptr++) = '#';
-                       *(tptr++) = '3';
-                       *(tptr++) = '9';
-                       *tptr = ';';
-               } else {
-                       *tptr = *sptr;
-               }
-               tptr++; sptr++;
-       }
-       *tptr = '\0';
-}
-
 /*
  * print a string to the client after cleaning it with msgesc() and stresc()
  */
 void msgescputs1( char *strbuf)
 {
-       char *outbuf;
-       char *outbuf2;
-       int buflen;
+       StrBuf *OutBuf;
 
-       if (strbuf == NULL) return;
-       buflen = 3 * strlen(strbuf) + SIZ;
-       outbuf = malloc( buflen);
-       outbuf2 = malloc( buflen);
-       msgesc(outbuf, buflen, strbuf);
-       stresc(outbuf2, buflen, outbuf, 0, 0);
-       wprintf("%s", outbuf2);
-       free(outbuf);
-       free(outbuf2);
+       if ((strbuf == NULL) || IsEmptyStr(strbuf))
+               return;
+       OutBuf = NewStrBuf();
+       StrMsgEscAppend(OutBuf, NULL, strbuf);
+       StrEscAppend(WC->WBuf, OutBuf, NULL, 0, 0);
+       FreeStrBuf(&OutBuf);
 }
 
 /*
  * print a string to the client after cleaning it with msgesc()
  */
 void msgescputs(char *strbuf) {
-       char *outbuf;
-       size_t len;
-
-       if (strbuf == NULL) return;
-       len =  (3 * strlen(strbuf)) + SIZ;
-       outbuf = malloc(len);
-       msgesc(outbuf, len, strbuf);
-       wprintf("%s", outbuf);
-       free(outbuf);
+       if ((strbuf != NULL) && !IsEmptyStr(strbuf))
+               StrMsgEscAppend(WC->WBuf, NULL, strbuf);
 }
 
 
@@ -704,12 +704,12 @@ void output_headers(      int do_httpheaders,     /* 1 = output HTTP headers
                           "<link href=\"static.local/webcit.css\" rel=\"stylesheet\" type=\"text/css\">"
                        );
                }
-               do_template("head");
+               do_template("head", NULL);
        }
 
        /* ICONBAR */
        if (do_htmlhead) {
-
+               begin_burst();
 
                /* check for ImportantMessages (these display in a div overlaying the main screen) */
                if (!IsEmptyStr(WC->ImportantMessage)) {
@@ -764,9 +764,13 @@ void http_redirect(const char *whichpage) {
 /*
  * Output a piece of content to the web browser using conformant HTTP and MIME semantics
  */
-void http_transmit_thing(StrBuf *thing, const char *content_type,
+void http_transmit_thing(const char *content_type,
                         int is_static) {
 
+       lprintf(9, "http_transmit_thing(%s)%s\n",
+               content_type,
+               (is_static ? " (static)" : "")
+       );
        output_headers(0, 0, 0, 0, 0, is_static);
 
        hprintf("Content-type: %s\r\n"
@@ -775,9 +779,7 @@ void http_transmit_thing(StrBuf *thing, const char *content_type,
                content_type,
                PACKAGE_STRING);
 
-       WC->WBuf = thing;
        end_burst();
-       WC->WBuf = NULL;
 }
 
 /*
@@ -794,7 +796,7 @@ void print_menu_box(char* Title, char *Class, int nLines, ...)
        long i;
        
        svput("BOXTITLE", WCS_STRING, Title);
-       do_template("beginbox");
+       do_template("beginbox", NULL);
        
        wprintf("<ul class=\"%s\">", Class);
        
@@ -811,7 +813,7 @@ void print_menu_box(char* Title, char *Class, int nLines, ...)
        
        wprintf("</ul>");
        
-       do_template("endbox");
+       do_template("endbox", NULL);
 }
 
 
@@ -824,7 +826,6 @@ void output_static(char *what)
        struct stat statbuf;
        off_t bytes;
        off_t count = 0;
-       StrBuf *Buf;
        const char *content_type;
        int len;
        const char *Err;
@@ -851,17 +852,10 @@ void output_static(char *what)
 
                count = 0;
                bytes = statbuf.st_size;
-               Buf = NewStrBufPlain(NULL, bytes + 2);
-               if (Buf == NULL) {
-                       lprintf(9, "output_static('%s')  -- MALLOC FAILED (%s) --\n", what, strerror(errno));
-                       hprintf("HTTP/1.1 500 internal server error\r\n");
-                       hprintf("Content-Type: text/plain\r\n");
-                       end_burst();
-                       return;
-               }
-///            StrBufAppendBuf(Buf, WC->WBuf, 0);
-               if (StrBufReadBLOB(Buf, &fd, 1, bytes, &Err) < 0)
+
+               if (StrBufReadBLOB(WC->WBuf, &fd, 1, bytes, &Err) < 0)
                {
+                       if (fd > 0) close(fd);
                        lprintf(9, "output_static('%s')  -- FREAD FAILED (%s) --\n", what, strerror(errno));
                                hprintf("HTTP/1.1 500 internal server error \r\n");
                                hprintf("Content-Type: text/plain\r\n");
@@ -872,8 +866,7 @@ void output_static(char *what)
 
                close(fd);
                lprintf(9, "output_static('%s')  %s\n", what, content_type);
-               http_transmit_thing(Buf, content_type, 1);
-               FreeStrBuf(&Buf);
+               http_transmit_thing(content_type, 1);
        }
        if (yesbstr("force_close_session")) {
                end_webcit_session();
@@ -886,33 +879,29 @@ void output_static(char *what)
  */
 void output_image()
 {
+       struct wcsession *WCC = WC;
        char buf[SIZ];
-       char *xferbuf = NULL;
        off_t bytes;
        const char *MimeType;
-       StrBuf *Buf;
-
+       
        serv_printf("OIMG %s|%s", bstr("name"), bstr("parm"));
        serv_getln(buf, sizeof buf);
        if (buf[0] == '2') {
                bytes = extract_long(&buf[4], 0);
-               xferbuf = malloc(bytes + 2);
 
                /** Read it from the server */
                
-               Buf = read_server_binary(bytes);
-               serv_puts("CLOS");
-               serv_getln(buf, sizeof buf);
-
-               MimeType = GuessMimeType (ChrPtr(Buf), StrLength(Buf));
-               /** Write it to the browser */
-               if (!IsEmptyStr(MimeType))
-               {
-                       http_transmit_thing(Buf, 
-                                           MimeType, 
-                                           0);
-                       FreeStrBuf(&Buf);
-                       return;
+               if (read_server_binary(WCC->WBuf, bytes) > 0) {
+                       serv_puts("CLOS");
+                       serv_getln(buf, sizeof buf);
+               
+                       MimeType = GuessMimeType (ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
+                       /** Write it to the browser */
+                       if (!IsEmptyStr(MimeType))
+                       {
+                               http_transmit_thing(MimeType, 0);
+                               return;
+                       }
                }
                /* hm... unknown mimetype? fallback to blank gif */
        } 
@@ -935,35 +924,32 @@ void display_vcard_photo_img(void)
        long msgnum = 0L;
        char *vcard;
        struct vCard *v;
-       char *xferbuf;
        char *photosrc;
-       int decoded;
        const char *contentType;
-       StrBuf *Buf;
+       struct wcsession *WCC = WC;
 
-       msgnum = StrTol(WC->UrlFragment1);
+       msgnum = StrTol(WCC->UrlFragment1);
        
        vcard = load_mimepart(msgnum,"1");
        v = vcard_load(vcard);
        
        photosrc = vcard_get_prop(v, "PHOTO", 1,0,0);
-       xferbuf = malloc(strlen(photosrc));
-       if (xferbuf == NULL) {
-               lprintf(5, "xferbuf malloc failed\n");
+       FlushStrBuf(WCC->WBuf);
+       StrBufAppendBufPlain(WCC->WBuf, photosrc, -1, 0);
+       if (StrBufDecodeBase64(WCC->WBuf) <= 0) {
+               FlushStrBuf(WCC->WBuf);
+               
+               hprintf("HTTP/1.1 500 %s\n","Unable to get photo");
+               output_headers(0, 0, 0, 0, 0, 0);
+               hprintf("Content-Type: text/plain\r\n");
+               wprintf(_("Could Not decode vcard photo\n"));
+               end_burst();
                return;
        }
-       memset(xferbuf, 1, SIZ);
-       decoded = CtdlDecodeBase64(
-               xferbuf,
-               photosrc,
-               strlen(photosrc));
-       contentType = GuessMimeType(xferbuf, decoded);
-       Buf = _NewConstStrBuf(xferbuf, decoded);
-       http_transmit_thing(Buf, contentType, 0);
+       contentType = GuessMimeType(ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
+       http_transmit_thing(contentType, 0);
        free(v);
        free(photosrc);
-       free(xferbuf);
-       FreeStrBuf(&Buf);
 }
 
 /*
@@ -979,14 +965,11 @@ void mimepart(const char *msgnum, const char *partnum, int force_download)
        char buf[256];
        off_t bytes;
        char content_type[256];
-       char *content = NULL;
        
        serv_printf("OPNA %s|%s", msgnum, partnum);
        serv_getln(buf, sizeof buf);
        if (buf[0] == '2') {
-               StrBuf *Buf;
                bytes = extract_long(&buf[4], 0);
-               content = malloc(bytes + 2);
                if (force_download) {
                        strcpy(content_type, "application/octet-stream");
                }
@@ -995,11 +978,10 @@ void mimepart(const char *msgnum, const char *partnum, int force_download)
                }
                output_headers(0, 0, 0, 0, 0, 0);
 
-               Buf = read_server_binary(bytes);
+               read_server_binary(WC->WBuf, bytes);
                serv_puts("CLOS");
                serv_getln(buf, sizeof buf);
-               http_transmit_thing(Buf, content_type, 0);
-               FreeStrBuf(&Buf);
+               http_transmit_thing(content_type, 0);
        } else {
                hprintf("HTTP/1.1 404 %s\n", &buf[4]);
                output_headers(0, 0, 0, 0, 0, 0);
@@ -1007,7 +989,6 @@ void mimepart(const char *msgnum, const char *partnum, int force_download)
                wprintf(_("An error occurred while retrieving this part: %s\n"), &buf[4]);
                end_burst();
        }
-
 }
 
 
@@ -1036,7 +1017,6 @@ char *load_mimepart(long msgnum, char *partnum)
        else {
                return(NULL);
        }
-
 }
 
 
@@ -1076,7 +1056,11 @@ void blank_page(void) {
  * A template has been requested
  */
 void url_do_template(void) {
-       do_template(bstr("template"));
+       const StrBuf *Tmpl = sbstr("template");
+       begin_burst();
+       output_headers(1, 0, 0, 0, 1, 0);
+       DoTemplate(ChrPtr(Tmpl), StrLength(Tmpl), NULL, NULL, 0);
+       end_burst();
 }
 
 
@@ -1084,7 +1068,7 @@ void url_do_template(void) {
 /*
  * Offer to make any page the user's "start page."
  */
-void offer_start_page(void) {
+void offer_start_page(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) {
        wprintf("<a href=\"change_start_page?startpage=");
        urlescputs(WC->this_page);
        wprintf("\">");
@@ -1116,7 +1100,7 @@ void change_start_page(void) {
        set_preference("startpage", NewStrBufPlain(bstr("startpage"), -1), 1);
 
        output_headers(1, 1, 0, 0, 0, 0);
-       do_template("newstartpage");
+       do_template("newstartpage", NULL);
        wDumpContent(1);
 }
 
@@ -1181,13 +1165,14 @@ void upload_handler(char *name, char *filename, char *partnum, char *disp,
                u = (urlcontent *) malloc(sizeof(urlcontent));
                
                safestrncpy(u->url_key, name, sizeof(u->url_key));
-               u->url_data = malloc(length + 1);
-               u->url_data_size = length;
-               memcpy(u->url_data, content, length);
-               u->url_data[length] = 0;
+               u->url_data = NewStrBufPlain(content, length);
+               
                Put(WC->urlstrings, u->url_key, strlen(u->url_key), u, free_url);
 #ifdef DEBUG_URLSTRINGS
-               lprintf(9, "Key: <%s> len: [%ld] Data: <%s>\n", u->url_key, u->url_data_size, u->url_data);
+               lprintf(9, "Key: <%s> len: [%ld] Data: <%s>\n", 
+                       u->url_key, 
+                       StrLength(u->url_data), 
+                       ChrPtr(u->url_data));
 #endif
        }
 
@@ -1213,14 +1198,14 @@ void upload_handler(char *name, char *filename, char *partnum, char *disp,
  * Convenience functions to wrap around asynchronous ajax responses
  */
 void begin_ajax_response(void) {
+       struct wcsession *WCC = WC;
+
+       FlushStrBuf(WCC->HBuf);
         output_headers(0, 0, 0, 0, 0, 0);
 
         hprintf("Content-type: text/html; charset=UTF-8\r\n"
                 "Server: %s\r\n"
                 "Connection: close\r\n"
-                "Pragma: no-cache\r\n"
-                "Cache-Control: no-cache\r\n"
-               "Expires: -1\r\n"
                ,
                 PACKAGE_STRING);
         begin_burst();
@@ -1230,7 +1215,6 @@ void begin_ajax_response(void) {
  * print ajax response footer 
  */
 void end_ajax_response(void) {
-        ///hprintf("\r\n");///// todo: is this right?
         wDumpContent(0);
 }
 
@@ -1299,11 +1283,11 @@ void seconds_since_last_gexp(void)
 {
        char buf[256];
 
-       begin_ajax_response();
        if ( (time(NULL) - WC->last_pager_check) < 30) {
                wprintf("NO\n");
        }
        else {
+               memset(buf, 5, 0);
                serv_puts("NOOP");
                serv_getln(buf, sizeof buf);
                if (buf[3] == '*') {
@@ -1313,43 +1297,46 @@ void seconds_since_last_gexp(void)
                        wprintf("NO");
                }
        }
-       end_ajax_response();
 }
 
 /**
  * \brief Detects a 'mobile' user agent 
  */
 int is_mobile_ua(char *user_agent) {
-       if (strstr(user_agent,"iPhone OS") != NULL) {
-               return 1;
-       } else if (strstr(user_agent,"Windows CE") != NULL) {
-               return 1;
-       } else if (strstr(user_agent,"SymbianOS") != NULL) {
-               return 1;
-       }
-       return 0;
+      if (strstr(user_agent,"iPhone OS") != NULL) {
+       return 1;
+      } else if (strstr(user_agent,"Windows CE") != NULL) {
+       return 1;
+      } else if (strstr(user_agent,"SymbianOS") != NULL) {
+       return 1;
+      } else if (strstr(user_agent, "Opera Mobi") != NULL) {
+       return 1;
+      } else if (strstr(user_agent, "Firefox/2.0.0 Opera 9.51 Beta") != NULL) {
+                // For some reason a new install of Opera 9.51beta decided to spoof.
+         return 1;
+         }
+      return 0;
 }
 
 
 /*
  * Entry point for WebCit transaction
  */
-void session_loop(struct httprequest *req)
+void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method, StrBuf *ReadBuf)
 {
-       char cmd[1024];
+       const char *pch, *pchs, *pche;
+       void *vLine;
        char action[1024];
        char arg[8][128];
        size_t sizes[10];
        char *index[10];
        char buf[SIZ];
-       char request_method[128];
-       char pathname[1024];
-       int a, b, nBackDots, nEmpty;
+       int a, nBackDots, nEmpty;
        int ContentLength = 0;
-       char ContentType[512];
-       char *content = NULL;
-       char *content_end = NULL;
-       struct httprequest *hptr;
+       StrBuf *ContentType = NULL;
+       StrBuf *UrlLine = NULL;
+       StrBuf *content = NULL;
+       const char *content_end = NULL;
        char browser_host[256];
        char user_agent[256];
        int body_start = 0;
@@ -1366,7 +1353,6 @@ void session_loop(struct httprequest *req)
        char c_httpauth_string[SIZ];
        char c_httpauth_user[SIZ];
        char c_httpauth_pass[SIZ];
-       char cookie[SIZ];
        struct wcsession *WCC;
        
        safestrncpy(c_username, "", sizeof c_username);
@@ -1378,21 +1364,18 @@ void session_loop(struct httprequest *req)
        strcpy(browser_host, "");
 
        WCC= WC;
+       if (WCC->WBuf == NULL)
+               WC->WBuf = NewStrBufPlain(NULL, 32768);
+       FlushStrBuf(WCC->WBuf);
+
        if (WCC->HBuf == NULL)
                WCC->HBuf = NewStrBuf();
        FlushStrBuf(WCC->HBuf);
+
        WCC->upload_length = 0;
        WCC->upload = NULL;
        WCC->is_mobile = 0;
 
-       hptr = req;
-       if (hptr == NULL) return;
-
-       safestrncpy(cmd, hptr->line, sizeof cmd);
-       hptr = hptr->next;
-       extract_token(request_method, cmd, 0, ' ', sizeof request_method);
-       extract_token(pathname, cmd, 1, ' ', sizeof pathname);
-
        /** Figure out the action */
        index[0] = action;
        sizes[0] = sizeof action;
@@ -1406,7 +1389,7 @@ void session_loop(struct httprequest *req)
        nEmpty = 0;
        for ( a = 0; a < 9; ++a)
        {
-               extract_token(index[a], pathname, a + 1, '/', sizes[a]);
+               extract_token(index[a], ChrPtr(ReqLine), a + 1, '/', sizes[a]);
                if (strstr(index[a], "?")) *strstr(index[a], "?") = 0;
                if (strstr(index[a], "&")) *strstr(index[a], "&") = 0;
                if (strstr(index[a], " ")) *strstr(index[a], " ") = 0;
@@ -1416,98 +1399,109 @@ void session_loop(struct httprequest *req)
                        nEmpty++;
        }
 
-       while (hptr != NULL) {
-               safestrncpy(buf, hptr->line, sizeof buf);
-               /* lprintf(9, "HTTP HEADER: %s\n", buf); */
-               hptr = hptr->next;
 
-               if (!strncasecmp(buf, "Cookie: webcit=", 15)) {
-                       safestrncpy(cookie, &buf[15], sizeof cookie);
-                       cookie_to_stuff(cookie, NULL,
-                                       c_username, sizeof c_username,
-                                       c_password, sizeof c_password,
-                                       c_roomname, sizeof c_roomname);
-               }
-               else if (!strncasecmp(buf, "Authorization: Basic ", 21)) {
-                       CtdlDecodeBase64(c_httpauth_string, &buf[21], strlen(&buf[21]));
-                       extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user);
-                       extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass);
-               }
-               else if (!strncasecmp(buf, "Content-length: ", 16)) {
-                       ContentLength = atoi(&buf[16]);
-               }
-               else if (!strncasecmp(buf, "Content-type: ", 14)) {
-                       safestrncpy(ContentType, &buf[14], sizeof ContentType);
-               }
-               else if (!strncasecmp(buf, "User-agent: ", 12)) {
-                       safestrncpy(user_agent, &buf[12], sizeof user_agent);
-                       if (is_mobile_ua(&buf[12])) {
-                               WCC->is_mobile = 1;
-                       }
-               }
-               else if (!strncasecmp(buf, "X-Forwarded-Host: ", 18)) {
-                       if (follow_xff) {
-                               safestrncpy(WCC->http_host, &buf[18], sizeof WCC->http_host);
-                       }
+       if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && 
+           (vLine != NULL)){
+               cookie_to_stuff((StrBuf *)vLine, NULL,
+                               c_username, sizeof c_username,
+                               c_password, sizeof c_password,
+                               c_roomname, sizeof c_roomname);
+       }
+       if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) &&
+           (vLine!=NULL)) {
+               CtdlDecodeBase64(c_httpauth_string, ChrPtr((StrBuf*)vLine), StrLength((StrBuf*)vLine));
+               extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user);
+               extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass);
+       }
+       if (GetHash(HTTPHeaders, HKEY("CONTENT-LENGTH"), &vLine) &&
+           (vLine!=NULL)) {
+               ContentLength = StrToi((StrBuf*)vLine);
+       }
+       if (GetHash(HTTPHeaders, HKEY("CONTENT-TYPE"), &vLine) &&
+           (vLine!=NULL)) {
+               ContentType = (StrBuf*)vLine;
+       }
+       if (GetHash(HTTPHeaders, HKEY("USER-AGENT"), &vLine) &&
+           (vLine!=NULL)) {
+               safestrncpy(user_agent, ChrPtr((StrBuf*)vLine), sizeof user_agent);
+#ifdef TECH_PREVIEW
+               if ((WCC->is_mobile < 0) && is_mobile_ua(&buf[12])) {                   
+                       WCC->is_mobile = 1;
                }
-               else if (!strncasecmp(buf, "Host: ", 6)) {
-                       if (IsEmptyStr(WCC->http_host)) {
-                               safestrncpy(WCC->http_host, &buf[6], sizeof WCC->http_host);
-                       }
+               else {
+                       WCC->is_mobile = 0;
                }
-               else if (!strncasecmp(buf, "X-Forwarded-For: ", 17)) {
-                       safestrncpy(browser_host, &buf[17], sizeof browser_host);
-                       while (num_tokens(browser_host, ',') > 1) {
-                               remove_token(browser_host, 0, ',');
-                       }
-                       striplt(browser_host);
+#endif
+       }
+       if ((follow_xff) &&
+           GetHash(HTTPHeaders, HKEY("X-FORWARDED-HOST"), &vLine) &&
+           (vLine != NULL)) {
+               safestrncpy(WCC->http_host, &buf[18], sizeof WCC->http_host);
+       }
+       if (IsEmptyStr(WCC->http_host) && 
+           GetHash(HTTPHeaders, HKEY("HOST"), &vLine) &&
+           (vLine!=NULL)) {
+               safestrncpy(WCC->http_host, 
+                           ChrPtr((StrBuf*)vLine), 
+                           sizeof WCC->http_host);
+               
+       }
+       if (GetHash(HTTPHeaders, HKEY("X-FORWARDED-FOR"), &vLine) &&
+           (vLine!=NULL)) {
+               safestrncpy(browser_host, 
+                           ChrPtr((StrBuf*) vLine), 
+                           sizeof browser_host);
+               while (num_tokens(browser_host, ',') > 1) {
+                       remove_token(browser_host, 0, ',');
                }
+               striplt(browser_host);
        }
 
        if (ContentLength > 0) {
-               int BuffSize;
-
-               BuffSize = ContentLength + SIZ;
-               content = malloc(BuffSize);
-               memset(content, 0, BuffSize);
-               snprintf(content,  BuffSize, "Content-type: %s\n"
-                               "Content-length: %d\n\n",
-                               ContentType, ContentLength);
-               body_start = strlen(content);
+               content = NewStrBuf();
+               StrBufPrintf(content, "Content-type: %s\n"
+                        "Content-length: %d\n\n",
+                        ChrPtr(ContentType), ContentLength);
+/*
+               hprintf("Content-type: %s\n"
+                       "Content-length: %d\n\n",
+                       ContentType, ContentLength);
+*/
+               body_start = StrLength(content);
 
                /** Read the entire input data at once. */
-               client_read(WCC->http_sock, &content[body_start], ContentLength);
-
-               if (!strncasecmp(ContentType, "application/x-www-form-urlencoded", 33)) {
-                       addurls(&content[body_start], ContentLength);
-               } else if (!strncasecmp(ContentType, "multipart", 9)) {
-                       content_end = content + ContentLength + body_start;
-                       mime_parser(content, content_end, *upload_handler, NULL, NULL, NULL, 0);
+               client_read(&WCC->http_sock, content, ReadBuf, ContentLength);
+
+               if (!strncasecmp(ChrPtr(ContentType), "application/x-www-form-urlencoded", 33)) {
+                       StrBufCutLeft(content, body_start);
+                       addurls(content);
+               } else if (!strncasecmp(ChrPtr(ContentType), "multipart", 9)) {
+                       content_end = ChrPtr(content) + ContentLength + body_start;
+                       mime_parser(ChrPtr(content), content_end, *upload_handler, NULL, NULL, NULL, 0);
                }
        } else {
                content = NULL;
        }
 
        /* make a note of where we are in case the user wants to save it */
-       safestrncpy(WCC->this_page, cmd, sizeof(WCC->this_page));
+       safestrncpy(WCC->this_page, ChrPtr(ReqLine), sizeof(WCC->this_page));
        remove_token(WCC->this_page, 2, ' ');
        remove_token(WCC->this_page, 0, ' ');
 
        /* If there are variables in the URL, we must grab them now */
-       len = strlen(cmd);
-       for (a = 0; a < len; ++a) {
-               if ((cmd[a] == '?') || (cmd[a] == '&')) {
-                       for (b = a; b < len; ++b) {
-                               if (isspace(cmd[b])){
-                                       cmd[b] = 0;
-                                       len = b - 1;
-                               }
-                       }
-                       addurls(&cmd[a + 1], len - a);
-                       cmd[a] = 0;
-                       len = a - 1;
+       UrlLine = NewStrBufDup(ReqLine);
+       len = StrLength(UrlLine);
+       pch = pchs = ChrPtr(UrlLine);
+       pche = pchs + len;
+       while (pch < pche) {
+               if ((*pch == '?') || (*pch == '&')) {
+                       StrBufCutLeft(UrlLine, pch - pchs + 1);
+                       addurls(UrlLine);
+                       break;
                }
+               pch ++;
        }
+       FreeStrBuf(&UrlLine);
 
        /* If it's a "force 404" situation then display the error and bail. */
        if (!strcmp(action, "404")) {
@@ -1520,7 +1514,7 @@ void session_loop(struct httprequest *req)
 
        /* Static content can be sent without connecting to Citadel. */
        is_static = 0;
-       for (a=0; a<ndirs; ++a) {
+       for (a=0; a<ndirs && ! is_static; ++a) {
                if (!strcasecmp(action, (char*)static_content_dirs[a])) { /* map web to disk location */
                        is_static = 1;
                        n_static = a;
@@ -1619,7 +1613,7 @@ void session_loop(struct httprequest *req)
                        }
                }
        }
-
+////////todo: restore language in this case
        /*
         * Functions which can be performed without logging in
         */
@@ -1628,7 +1622,7 @@ void session_loop(struct httprequest *req)
                goto SKIP_ALL_THIS_CRAP;
        }
        if (!strcasecmp(action, "freebusy")) {
-               do_freebusy(cmd);
+               do_freebusy(ChrPtr(ReqLine));
                goto SKIP_ALL_THIS_CRAP;
        }
 
@@ -1670,8 +1664,10 @@ void session_loop(struct httprequest *req)
         * our session's authentication.
         */
        if (!strncasecmp(action, "groupdav", 8)) {
-               groupdav_main(req, ContentType, /* do GroupDAV methods */
-                       ContentLength, content+body_start);
+               groupdav_main(HTTPHeaders, 
+                             ReqLine, request_method,
+                             ContentType, /* do GroupDAV methods */
+                             ContentLength, content, body_start);
                if (!WCC->logged_in) {
                        WCC->killthis = 1;      /* If not logged in, don't */
                }                               /* keep the session active */
@@ -1683,9 +1679,10 @@ void session_loop(struct httprequest *req)
         * Automatically send requests with any method other than GET or
         * POST to the GroupDAV code as well.
         */
-       if ((strcasecmp(request_method, "GET")) && (strcasecmp(request_method, "POST"))) {
-               groupdav_main(req, ContentType, /** do GroupDAV methods */
-                       ContentLength, content+body_start);
+       if ((strcasecmp(ChrPtr(request_method), "GET")) && (strcasecmp(ChrPtr(request_method), "POST"))) {
+               groupdav_main(HTTPHeaders, ReqLine, 
+                             request_method, ContentType, /** do GroupDAV methods */
+                             ContentLength, content, body_start);
                if (!WCC->logged_in) {
                        WCC->killthis = 1;      /** If not logged in, don't */
                }                               /** keep the session active */
@@ -1705,7 +1702,12 @@ void session_loop(struct httprequest *req)
                        serv_printf("PASS %s", c_password);
                        serv_getln(buf, sizeof buf);
                        if (buf[0] == '2') {
+                               StrBuf *Lang;
                                become_logged_in(c_username, c_password, buf);
+                               if (get_preference("language", &Lang)) {
+                                       set_selected_language(ChrPtr(Lang));
+                                       go_selected_language();         /* set locale */
+                               }
                        }
                }
        }
@@ -1763,7 +1765,7 @@ void session_loop(struct httprequest *req)
 SKIP_ALL_THIS_CRAP:
        fflush(stdout);
        if (content != NULL) {
-               free(content);
+               FreeStrBuf(&content);
                content = NULL;
        }
        free_urls();
@@ -1791,9 +1793,9 @@ void diagnostics(void)
        output_headers(1, 1, 1, 0, 0, 0);
        wprintf("Session: %d<hr />\n", WC->wc_session);
        wprintf("Command: <br /><PRE>\n");
-       escputs(WC->UrlFragment1);
+       StrEscPuts(WC->UrlFragment1);
        wprintf("<br />\n");
-       escputs(WC->UrlFragment2);
+       StrEscPuts(WC->UrlFragment2);
        wprintf("</PRE><hr />\n");
        wprintf("Variables: <br /><PRE>\n");
        dump_vars();
@@ -1813,6 +1815,44 @@ void download_mimepart(void) {
                 1);
 }
 
+
+int ConditionalImportantMesage(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       struct wcsession *WCC = WC;
+       if (WCC != NULL)
+               return (!IsEmptyStr(WCC->ImportantMessage));
+       else
+               return 0;
+}
+
+void tmplput_importantmessage(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       struct wcsession *WCC = WC;
+       
+       if (WCC != NULL) {
+               StrEscAppend(Target, NULL, WCC->ImportantMessage, 0, 0);
+                       WCC->ImportantMessage[0] = '\0';
+       }
+}
+
+int ConditionalBstr(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       if(Tokens->nParameters == 1)
+               return HaveBstr(Tokens->Params[0]->Start, 
+                               Tokens->Params[0]->len);
+       else
+               return strcmp(Bstr(Tokens->Params[0]->Start, 
+                                  Tokens->Params[0]->len),
+                             Tokens->Params[1]->Start) == 0;
+}
+
+void tmplput_bstr(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       StrBufAppendBuf(Target, 
+                       SBstr(Tokens->Params[0]->Start, 
+                             Tokens->Params[0]->len), 0);
+}
+
 void 
 InitModule_WEBCIT
 (void)
@@ -1827,4 +1867,10 @@ InitModule_WEBCIT
        WebcitAddUrlHandler(HKEY("mimepart"), view_mimepart, NEED_URL);
        WebcitAddUrlHandler(HKEY("mimepart_download"), download_mimepart, NEED_URL);
        WebcitAddUrlHandler(HKEY("diagnostics"), diagnostics, NEED_URL);
+
+       RegisterConditional(HKEY("COND:IMPMSG"), 0, ConditionalImportantMesage, CTX_NONE);
+       RegisterConditional(HKEY("COND:BSTR"), 1, ConditionalBstr, CTX_NONE);
+       RegisterNamespace("BSTR", 1, 2, tmplput_bstr, CTX_NONE);
+       RegisterNamespace("IMPORTANTMESSAGE", 0, 0, tmplput_importantmessage, CTX_NONE);
+       RegisterNamespace("OFFERSTARTPAGE", 0, 0, offer_start_page, CTX_NONE);
 }