? mozilla/netwerk/protocol/http/extensions
? mozilla/netwerk/protocol/http/src/nsHttpExtInstance.cpp
? mozilla/netwerk/protocol/http/src/nsHttpExtInstance.h
? mozilla/netwerk/protocol/http/src/nsHttpExtension.cpp
? mozilla/netwerk/protocol/http/src/nsHttpExtension.h
Index: mozilla/netwerk/protocol/http/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/Makefile.in,v
retrieving revision 1.8.130.1
diff -u -r1.8.130.1 Makefile.in
--- mozilla/netwerk/protocol/http/Makefile.in	10 Apr 2002 03:15:07 -0000	1.8.130.1
+++ mozilla/netwerk/protocol/http/Makefile.in	20 Jul 2002 20:02:31 -0000
@@ -28,7 +28,7 @@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS		= public src
+DIRS		= public src extensions
 
 include $(topsrcdir)/config/rules.mk
 
Index: mozilla/netwerk/protocol/http/src/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/Makefile.in,v
retrieving revision 1.55.16.3
diff -u -r1.55.16.3 Makefile.in
--- mozilla/netwerk/protocol/http/src/Makefile.in	1 May 2002 01:20:13 -0000	1.55.16.3
+++ mozilla/netwerk/protocol/http/src/Makefile.in	20 Jul 2002 20:02:32 -0000
@@ -42,6 +42,8 @@
 
 CPPSRCS		= \
 		nsHttp.cpp \
+		nsHttpExtension.cpp \
+		nsHttpExtInstance.cpp \
 		nsHttpHandler.cpp \
 		nsHttpHeaderArray.cpp \
 		nsHttpConnection.cpp \
Index: mozilla/netwerk/protocol/http/src/nsHttpAtomList.h
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/nsHttpAtomList.h,v
retrieving revision 1.3.36.1
diff -u -r1.3.36.1 nsHttpAtomList.h
--- mozilla/netwerk/protocol/http/src/nsHttpAtomList.h	10 Apr 2002 03:15:10 -0000	1.3.36.1
+++ mozilla/netwerk/protocol/http/src/nsHttpAtomList.h	20 Jul 2002 20:02:32 -0000
@@ -60,6 +60,8 @@
 HTTP_ATOM(Authentication,            "Authentication")
 HTTP_ATOM(Authorization,             "Authorization")
 HTTP_ATOM(Cache_Control,             "Cache-Control")
+HTTP_ATOM(C_Man,                     "C-Man")
+HTTP_ATOM(C_Opt,                     "C-Opt")
 HTTP_ATOM(Connection,                "Connection")
 HTTP_ATOM(Content_Base,              "Content-Base")
 HTTP_ATOM(Content_Encoding,          "Content-Encoding")
@@ -89,9 +91,11 @@
 HTTP_ATOM(Last_Modified,             "Last-Modified")
 HTTP_ATOM(Link,                      "Link")
 HTTP_ATOM(Location,                  "Location")
+HTTP_ATOM(Man,                       "Man")
 HTTP_ATOM(Max_Forwards,              "Max-Forwards")
 HTTP_ATOM(Message_Id,                "Message-Id")
 HTTP_ATOM(Mime,                      "Mime")
+HTTP_ATOM(Opt,                       "Opt")
 HTTP_ATOM(Pragma,                    "Pragma")
 HTTP_ATOM(Vary,                      "Vary")
 HTTP_ATOM(Proxy_Authenticate,        "Proxy-Authenticate")
Index: mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp,v
retrieving revision 1.108.2.8
diff -u -r1.108.2.8 nsHttpChannel.cpp
--- mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp	9 May 2002 06:43:49 -0000	1.108.2.8
+++ mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp	20 Jul 2002 20:02:32 -0000
@@ -47,6 +47,8 @@
 #include "plstr.h"
 #include "prprf.h"
 #include "nsEscape.h"
+#include "../extensions/nsMetaPackExt.h"
+
 
 static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID);
 
@@ -80,7 +82,7 @@
     , mUploadStreamHasHeaders(PR_FALSE)
 {
     LOG(("Creating nsHttpChannel @%x\n", this));
-
+    // earliest place to nsMetaPackExt::sMakeInst(this);
     NS_INIT_ISUPPORTS();
 
     // grab a reference to the handler to ensure that it doesn't go away.
Index: mozilla/netwerk/protocol/http/src/nsHttpHeaderArray.h
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/nsHttpHeaderArray.h,v
retrieving revision 1.7.2.1
diff -u -r1.7.2.1 nsHttpHeaderArray.h
--- mozilla/netwerk/protocol/http/src/nsHttpHeaderArray.h	10 Apr 2002 03:15:11 -0000	1.7.2.1
+++ mozilla/netwerk/protocol/http/src/nsHttpHeaderArray.h	20 Jul 2002 20:02:32 -0000
@@ -55,7 +55,7 @@
 
     void Clear();
 
-private:
+protected:
     struct nsEntry
     {
         nsEntry(nsHttpAtom h, const nsACString &v)
@@ -68,7 +68,7 @@
     PRInt32 LookupEntry(nsHttpAtom header, nsEntry **);
     PRBool  CanAppendToHeader(nsHttpAtom header);
 
-private:
+protected:
     nsAutoVoidArray mHeaders;
 };
 
Index: mozilla/netwerk/protocol/http/src/nsHttpRequestHead.cpp
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/nsHttpRequestHead.cpp,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 nsHttpRequestHead.cpp
--- mozilla/netwerk/protocol/http/src/nsHttpRequestHead.cpp	10 Apr 2002 03:15:12 -0000	1.4.2.1
+++ mozilla/netwerk/protocol/http/src/nsHttpRequestHead.cpp	20 Jul 2002 20:02:32 -0000
@@ -22,14 +22,28 @@
  */
 
 #include "nsHttpRequestHead.h"
+#include "nsHttpExtInstance.h"
+#include "nsHashtable.h"
 
 //-----------------------------------------------------------------------------
 // nsHttpRequestHead
 //-----------------------------------------------------------------------------
 
 void
+nsHttpRequestHead::AddHttpExtInstance(nsHashKey *decl, nsHttpExtInstance *inst)
+{
+    char * space = new char[3];
+    sprintf(space, "%02d", mNsInt);
+    inst->SetDeclNS(space);
+    ++mNsInt;
+    mHttpExtInstances.Put(decl, inst);
+}
+
+void
 nsHttpRequestHead::Flatten(nsACString &buf, PRBool pruneProxyHeaders)
 {
+    setHttpExtHeaders();
+
     // note: the first append is intentional.
  
     buf.Append(mMethod.get());
@@ -52,3 +66,62 @@
 
     mHeaders.Flatten(buf, pruneProxyHeaders);
 }
+
+void
+nsHttpRequestHead::clearHttpExtInstances()
+{
+#if 0
+    delete mHttpExtInstancesIn;
+#endif
+#if 0
+    PRInt32 i, count = mHttpExtInstances.Count();
+    for (i=0; i<count; ++i)
+        delete (nsHttpExtInstance *) mHttpExtInstances[i];
+    mHttpExtInstances.Clear();
+#endif
+}
+
+typedef struct {
+    nsHttpRequestHead *requestHead;
+    nsresult rv;
+} setHttpExtHeadersContext;
+
+static PRBool
+setHttpExtHeadersEnumFunc(nsHashKey *aKey, void *aData, void* aClosure)
+{
+    const nsHttpAtom names[2][2] = {{nsHttp::Opt, nsHttp::Man}, {nsHttp::C_Opt, nsHttp::C_Man}};
+
+    nsHttpExtInstance *inst = (nsHttpExtInstance *) aData;
+    setHttpExtHeadersContext *ctx = (setHttpExtHeadersContext *) aClosure;
+
+    ctx->rv = inst->SetHttpExtHeaders(ctx->requestHead);
+    if (NS_FAILED(ctx->rv)) {
+        LOG(("setHttpExtHeaders: inst->SetHttpExtHeaders(requestHead) returned [rv=%x]\n", ctx->rv));
+        return PR_FALSE;
+    }
+
+    nsHttpAtom name = names[inst->GetConnection()][inst->GetMandatory()];
+    char * declStr = inst->GetDeclStr();
+    ctx->requestHead->SetHeader(name, nsDependentCString(declStr));
+    return PR_TRUE;
+}
+
+nsresult
+nsHttpRequestHead::setHttpExtHeaders()
+{
+    setHttpExtHeadersContext ctx = {this, NS_OK};
+
+    LOG(("nsHttpTransaction::SetupRequest [this=%x]\n", this));
+
+    mHttpExtInstances.Enumerate(&setHttpExtHeadersEnumFunc, &ctx);
+    return NS_OK;
+}
+
+#if 0
+void f (const char* declName)
+{
+    nsCStringKey key(declName);
+    nsHttpExtInstance *entry = (nsHttpExtInstance *) mHttpExtInstancesOut->Get(&key);
+}
+#endif
+
Index: mozilla/netwerk/protocol/http/src/nsHttpRequestHead.h
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/nsHttpRequestHead.h,v
retrieving revision 1.7.2.2
diff -u -r1.7.2.2 nsHttpRequestHead.h
--- mozilla/netwerk/protocol/http/src/nsHttpRequestHead.h	16 May 2002 23:57:13 -0000	1.7.2.2
+++ mozilla/netwerk/protocol/http/src/nsHttpRequestHead.h	20 Jul 2002 20:02:32 -0000
@@ -28,17 +28,20 @@
 #include "nsHttp.h"
 #include "nsString.h"
 #include "nsCRT.h"
+#include "nsHashtable.h"
 
 //-----------------------------------------------------------------------------
 // nsHttpRequestHead represents the request line and headers from an HTTP
 // request.
 //-----------------------------------------------------------------------------
 
+class nsHttpExtInstance;
+
 class nsHttpRequestHead
 {
 public:
-    nsHttpRequestHead() : mMethod(nsHttp::Get), mVersion(NS_HTTP_VERSION_1_1) {}
-   ~nsHttpRequestHead() {}
+    nsHttpRequestHead() : mMethod(nsHttp::Get), mVersion(NS_HTTP_VERSION_1_1) {mNsInt = 0;}
+   ~nsHttpRequestHead() { clearHttpExtInstances(); }
 
     void SetMethod(nsHttpAtom method) { mMethod = method; }
     void SetVersion(nsHttpVersion version) { mVersion = version; }
@@ -55,12 +58,18 @@
     void ClearHeaders()                                   { mHeaders.Clear(); }
 
     void Flatten(nsACString &, PRBool pruneProxyHeaders = PR_FALSE);
+    void AddHttpExtInstance(nsHashKey *decl, nsHttpExtInstance *inst);
+    nsresult setHttpExtHeaders();
 
 private:
     nsHttpHeaderArray mHeaders;
     nsHttpAtom        mMethod;
     nsHttpVersion     mVersion;
     nsCString         mRequestURI;
+    void              clearHttpExtInstances();
+
+    nsHashtable       mHttpExtInstances;
+    int               mNsInt;
 };
 
 #endif // nsHttpRequestHead_h__
Index: mozilla/netwerk/protocol/http/src/nsHttpResponseHead.cpp
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.cpp,v
retrieving revision 1.28.2.3
diff -u -r1.28.2.3 nsHttpResponseHead.cpp
--- mozilla/netwerk/protocol/http/src/nsHttpResponseHead.cpp	16 May 2002 23:57:14 -0000	1.28.2.3
+++ mozilla/netwerk/protocol/http/src/nsHttpResponseHead.cpp	20 Jul 2002 20:02:32 -0000
@@ -28,6 +28,7 @@
 #include "prprf.h"
 #include "prtime.h"
 #include "nsCRT.h"
+#include "nsHttpExtInstance.h"
 
 //-----------------------------------------------------------------------------
 // nsHttpResponseHead <public>
@@ -197,6 +198,17 @@
         ParseCacheControl(val);
     else if (hdr == nsHttp::Pragma)
         ParsePragma(val);
+	else if (hdr == nsHttp::C_Man)
+        ParseHTTPExtDecl(val, PR_TRUE, PR_TRUE);
+	else if (hdr == nsHttp::C_Opt)
+        ParseHTTPExtDecl(val, PR_FALSE, PR_TRUE);
+	else if (hdr == nsHttp::Man)
+        ParseHTTPExtDecl(val, PR_TRUE, PR_FALSE);
+    else if (hdr == nsHttp::Opt)
+        ParseHTTPExtDecl(val, PR_FALSE, PR_FALSE);
+    else if (line[0] >= '0' && line[0] <= '9' && 
+             line[1] >= '0' && line[1] <= '9' && line[2] == '-')
+        StoreHTTPExtHeader(line, val);
 }
 
 // From section 13.2.3 of RFC2616, we compute the current age of a cached
@@ -673,3 +685,285 @@
     if (*val && PL_strcasestr(val, "no-cache"))
         mPragmaNoCache = PR_TRUE;
 }
+
+// Deal with the issue that ByNS and ByDecl both want to reap the same objects.
+#if 0
+void
+nsHttpResponseHead::clearHttpExtInstances()
+{
+#if 0
+    delete mHttpExtByNs;
+    delete mHttpExtByDecl;
+#endif
+#if 0
+    PRInt32 i, count = mHttpExtByNs.Count();
+    for (i=0; i<count; ++i)
+        delete (nsHttpExtInstance *) mHttpExtByNs[i];
+    mHttpExtByNs.Clear();
+#endif
+}
+#endif
+
+// This code is duplicated in ParseContentType above.  If you change it
+// here, change it there, too!
+
+/* ParseHTTPExtHeaders - parse comma-delimited piece of HTTP extension header.
+ * Grammer taken from RFC 2774[1]:
+ *
+ *   mandatory       = "Man" ":" 1#ext-decl
+ *   optional        = "Opt" ":" 1#ext-decl
+ *   c-mandatory     = "C-Man" ":" 1#ext-decl
+ *   c-optional      = "C-Opt" ":" 1#ext-decl
+ *
+ *   ext-decl        = <"> ( absoluteURI | field-name ) <"> [ namespace ] [ decl-extensions ]
+ *
+ *   namespace       = ";" "ns" "=" header-prefix
+ *   header-prefix   = 2*DIGIT
+ *
+ *   decl-extensions = *( decl-ext )
+ *   decl-ext        = ";" token [ "=" ( token | quoted-string ) ]
+ *
+ * [1] ftp://ftp.isi.edu/in-notes/rfc2774.txt
+ *
+ *   token           = 1*<any CHAR except CTLs or tspecials>
+ *   CHAR            = <any US-ASCII character (octets 0 - 127)>
+ *   CTL             = <any US-ASCII control character
+ *                     (octets 0 - 31) and DEL (127)>
+ *   tspecials       = "(" | ")" | "<" | ">" | "@"
+ *                   | "," | ";" | ":" | "\" | <">
+ *                   | "/" | "[" | "]" | "?" | "="
+ *                   | "{" | "}" | SP | HT 
+ *   SP              = <US-ASCII SP, space (32)>
+ *   HT              = <US-ASCII HT, horizontal-tab (9)>
+ * [2] ftp://ftp.isi.edu/in-notes/rfc2068.txt
+ *       ergo token is: 
+ *   token           = <33, 35-39, 42-43, 45-46, 48-57, 65-90, 94-122, 124, 126>
+ *                     (!   #  '   *  +   -  .   0  9   A  Z   ^  z    |    ~  )
+ */
+
+nsresult
+nsHttpResponseHead::ParseHTTPExtDecl(char *decl, PRBool mandatory, PRBool connection)
+{
+    LOG(("nsHttpResponseHead::ParseHTTPExtHeaders [decl=%s]\n", decl));
+
+    printf("HTTPEXT: nsHttpResponseHead::ParseHTTPExtDecl(%s, %d, %d)\n", decl, mandatory, connection);
+
+    char * start = decl;
+    // skip whitespace
+    while (*decl == ' ' || *decl == '\t') ++decl;
+
+    while (*decl) {
+        // declName is quoted uri or header name
+        if (*decl != '"')
+            return declError(start, decl, "missing leading '\"'");
+        ++decl;
+        char * declName = decl;
+        while (*decl && *decl != '"') ++decl;
+        if (*decl != '"')
+            return declError(start, decl, "missing trailing '\"'");
+
+        // save declName
+        {
+            PRUint32 len = decl - declName;
+            char *tmp = new char[len + 1];
+            PL_strncpy(tmp, declName, len);
+            tmp[len] = 0;
+            declName = tmp;
+        }
+        ++decl;
+
+        // ns and parms separated by ';'
+        nsHttpExtInstance *inst = nsnull;
+        while (*decl == ';') {
+            ++decl;
+            while (*decl == ' ' || *decl == '\t') ++decl;
+            if (!*decl)
+                return declError(start, decl, "missing parm");
+            char *parm = decl;
+#ifdef HTTP_EXT_FUSSY_PARSER
+            while (*decl && (*decl==33 || 
+                             *decl=>35 && *decl<=39 || 
+                             *decl==42 || *decl==43 ||
+                             *decl==45 || *decl==46 ||
+                             *decl=>48 && *decl<=57 ||
+                             *decl=>65 && *decl<=90 ||
+                             *decl=>94 && *decl<=122 ||
+                             *decl==124 ||
+                             *decl==126)) ++decl;
+#else
+            while (*decl && *decl != '=' && *decl != ' ') ++decl;
+#endif
+            if (*decl != '=')
+                return declError(start, decl, "malformed parm token");
+            // if inst is unset (first ';'), we are parsing a ns, otherwise a token or quoted string
+            if (inst == nsnull) {
+                // parse an ns
+                if (decl - parm != 2 || parm[0] != 'n' || parm[1] != 's' || 
+                    !(decl[1] >= '0' && decl[1] <= '9') || 
+                    !(decl[2] >= '0' && decl[2] <= '9'))
+                    return declError(start, decl, "malformed namespace");
+                char *ns = new char[3];
+                ns[0] = decl[1];
+                ns[1] = decl[2];
+                ns[2] = 0;
+                decl+=3;
+
+                // HTTPExtInstances are indexed by decl name and namespace.
+                nsCStringKey nsKey(ns);
+                nsCStringKey declNameKey(declName);
+
+                // Can't deal with multiple invocations of the same extension.
+                if ((inst = (nsHttpExtInstance *)mHttpExtByNS.Get(&declNameKey)) != nsnull)
+                    return declError(start, decl, "can't handle multiple decls of the same extension");
+
+                // There may be a partial ext-decl created if a prefixed-header
+                // was encountered before the ext-decl.
+                nsresult ret;
+                if ((inst = (nsHttpExtInstance *)mHttpExtByNS.Get(&nsKey)) == nsnull) {
+                    // No ext-decl for this ns - create one
+                    inst = new nsHttpExtInstance(ns);
+                    if ((ret = inst->SetDeclName(declName)) != NS_OK)
+                        return declError(declName, nsnull, "No extension found");
+                    printf("HTTPEXT: nsHttpResponseHead::ParseHTTPExtDecl created inst %p (%s)\n", inst, declName);
+                    mHttpExtByNS.Put(&nsKey, inst);
+                } else  {
+                    // Update a partial decl.
+                    if ((ret = inst->SetDeclName(declName)) != NS_OK)
+                        return declError(declName, nsnull, "No extension found");
+                    printf("HTTPEXT: nsHttpResponseHead::ParseHTTPExtDecl SetDeclName inst %p (%s)\n", inst, declName);
+                }
+                mHttpExtByDecl.Put(&declNameKey, inst);
+            } else {
+                // parse a token or quoted string
+                PRUint32 len = decl-parm;
+                char *declExtName = new char[len+1];
+                PL_strncpy(declExtName, parm, len);
+                declExtName[len] = 0;
+
+                if (!*++decl)
+                    return declError(start, decl, "no parm value");
+                char *declExtValue = decl;
+                if (*decl == '"') {
+                    ++declExtValue;
+                    ++decl;
+                    while (*decl && *decl != '"') decl++;
+                    if (!*decl)
+                        return declError(start, decl, "parm value unterminated");
+                    // save declName
+                    {
+                        PRUint32 len = decl - declExtValue;
+                        char *tmp = new char[len + 1];
+                        PL_strncpy(tmp, declExtValue, len);
+                        tmp[len] = 0;
+                        declExtValue = tmp;
+                    }
+                    ++decl;
+                } else {
+                    while (*decl && *decl != ',' && *decl != ';' && 
+                           *decl != ' ' && *decl != '\t') decl++;
+                    // save declName
+                    {
+                        PRUint32 len = decl - declExtValue;
+                        char *tmp = new char[len + 1];
+                        PL_strncpy(tmp, declExtValue, len);
+                        tmp[len] = 0;
+                        declExtValue = tmp;
+                    }
+                }
+                inst->AddDeclExtension(declExtName, declExtValue);
+                while (*decl == ' ' || *decl == '\t') ++decl;
+            }
+        }
+        if (inst == nsnull)
+            return declError(start, decl, "no namespace");
+    }
+
+    return NS_OK;
+}
+
+nsresult
+nsHttpResponseHead::declError(const char * const start, const char * const end, const char * const message)
+{
+    printf("HTTPEXT: nsHttpResponseHead::declError(%s, %s, %s)\n", start, end, message);
+    return NS_ERROR_ILLEGAL_VALUE;
+}
+
+// This should be called only when it is confirmed that the header name is 
+// a well-formed HTTP Extensions header (ie, nn-name: value).
+nsresult
+nsHttpResponseHead::StoreHTTPExtHeader(char *name, char *value)
+{
+    char ns[3];
+    ns[0] = name[0];
+    ns[1] = name[1];
+    ns[2] = 0;
+    name += 3;
+
+    nsCStringKey nsKey(ns);
+    nsHttpExtInstance *inst;
+    if ((inst = (nsHttpExtInstance *)mHttpExtByNS.Get(&nsKey)) == nsnull) {
+        inst = new nsHttpExtInstance(ns);
+        printf("HTTPEXT: nsHttpResponseHead::StoreHTTPExtHeader created inst %p (%s)\n", inst, ns);
+        mHttpExtByNS.Put(&nsKey, inst);
+    }
+
+    nsCStringKey nsHeader(name);
+    inst->SetHeader(name, value);
+    printf("HTTPEXT: nsHttpResponseHead::StoreHTTPExtHeader updated inst %p (%s)\n", inst, ns);
+    return NS_OK;
+}
+
+typedef struct {
+    nsHttpResponseHead *responseHead;
+    nsresult rv;
+} dispatchHttpExtensionsContext;
+
+PRBool
+nsHttpResponseHead::dispatchHttpExtensionsEnumFunc(nsHashKey *aKey, void *aData, void* aClosure)
+{
+    nsHttpExtInstance *inst = (nsHttpExtInstance *) aData;
+    dispatchHttpExtensionsContext *ctx = (dispatchHttpExtensionsContext *) aClosure;
+
+    ctx->rv = inst->Dispatch();
+    if (NS_FAILED(ctx->rv)) {
+        LOG(("dispatchHttpExtensions: inst->Dispatch(responseHead) returned [rv=%x]\n", ctx->rv));
+        return PR_FALSE;
+    }
+    return PR_TRUE;
+}
+
+nsresult
+nsHttpResponseHead::DispatchHttpExtensions()
+{
+    dispatchHttpExtensionsContext ctx = {this, NS_OK};
+
+    LOG(("nsHttpTransaction::SetupRequest [this=%x]\n", this));
+
+#if 0
+    nsresult ret;
+    char *value;
+    if ((ret = mHeaders->GetHeader(nsHttp::C_Man, &value)) == NS_OK)
+        ParseHttpExtHeaders(value, PR_TRUE, PR_TRUE);
+    else if (ret != NS_ERROR_NOT_AVAILABLE)
+        return ret;
+
+    if ((ret = mHeaders->GetHeader(nsHttp::C_Opt, &value)) == NS_OK)
+        ParseHttpExtHeaders(value, PR_FALSE, PR_TRUE);
+    else if (ret != NS_ERROR_NOT_AVAILABLE)
+        return ret;
+
+    if ((ret = mHeaders->GetHeader(nsHttp::Man, &value)) == NS_OK)
+        ParseHttpExtHeaders(value, PR_TRUE, PR_FALSE);
+    else if (ret != NS_ERROR_NOT_AVAILABLE)
+        return ret;
+
+    if ((ret = mHeaders->GetHeader(nsHttp::Opt, &value)) == NS_OK)
+        ParseHttpExtHeaders(value, PR_FALSE, PR_FALSE);
+    else if (ret != NS_ERROR_NOT_AVAILABLE)
+        return ret;
+#endif // 0
+
+    mHttpExtByNS.Enumerate(&dispatchHttpExtensionsEnumFunc, &ctx);
+    return NS_OK;
+}
+
Index: mozilla/netwerk/protocol/http/src/nsHttpResponseHead.h
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.h,v
retrieving revision 1.19.2.2
diff -u -r1.19.2.2 nsHttpResponseHead.h
--- mozilla/netwerk/protocol/http/src/nsHttpResponseHead.h	9 May 2002 00:01:12 -0000	1.19.2.2
+++ mozilla/netwerk/protocol/http/src/nsHttpResponseHead.h	20 Jul 2002 20:02:32 -0000
@@ -27,6 +27,7 @@
 #include "nsHttpHeaderArray.h"
 #include "nsHttp.h"
 #include "nsString.h"
+#include "nsHashtable.h"
 
 //-----------------------------------------------------------------------------
 // nsHttpResponseHead represents the status line and headers from an HTTP
@@ -107,12 +108,17 @@
     nsresult GetDateValue(PRUint32 *result)         { return ParseDateHeader(nsHttp::Date, result); }
     nsresult GetExpiresValue(PRUint32 *result);
     nsresult GetLastModifiedValue(PRUint32 *result) { return ParseDateHeader(nsHttp::Last_Modified, result); }
+    nsresult DispatchHttpExtensions();
 
 private:
     void     ParseVersion(const char *);
     void     ParseContentType(char *);
     void     ParseCacheControl(const char *);
     void     ParsePragma(const char *);
+    nsresult ParseHTTPExtDecl(char *decl, PRBool mandatory, PRBool connection);
+    nsresult StoreHTTPExtHeader(char *name, char *value);
+    nsresult declError(const char * const start, const char * const end, const char * const message);
+    static PRBool dispatchHttpExtensionsEnumFunc(nsHashKey *aKey, void *aData, void* aClosure);
 
 private:
     nsHttpHeaderArray mHeaders;
@@ -125,6 +131,8 @@
     PRPackedBool      mCacheControlNoStore;
     PRPackedBool      mCacheControlNoCache;
     PRPackedBool      mPragmaNoCache;
+    nsHashtable       mHttpExtByDecl;
+    nsHashtable       mHttpExtByNS;
 };
 
 #endif // nsHttpResponseHead_h__
Index: mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp
===================================================================
RCS file: /cvsroot/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp,v
retrieving revision 1.49.2.3
diff -u -r1.49.2.3 nsHttpTransaction.cpp
--- mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp	30 Apr 2002 01:11:12 -0000	1.49.2.3
+++ mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp	20 Jul 2002 20:02:33 -0000
@@ -33,6 +33,8 @@
 #include "nsISocketTransportService.h"
 #include "pratom.h"
 #include "plevent.h"
+#include "../extensions/nsMetaPackExt.h"
+
 
 //-----------------------------------------------------------------------------
 // helpers
@@ -485,6 +487,7 @@
             return NS_OK;
         ParseLineSegment(buf, len);
     }
+    mResponseHead->DispatchHttpExtensions();
     return NS_OK;
 }
 
