Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Private Member Functions | Private Attributes
nsHttpResponseHead Class Reference

#include <nsHttpResponseHead.h>

Collaboration diagram for nsHttpResponseHead:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsHttpResponseHead ()
 ~nsHttpResponseHead ()
nsHttpHeaderArrayHeaders ()
nsHttpVersion Version ()
PRUint16 Status ()
const nsAFlatCStringStatusText ()
PRInt64 ContentLength ()
const nsAFlatCStringContentType ()
const nsAFlatCStringContentCharset ()
PRBool NoStore ()
PRBool NoCache ()
PRInt64 TotalEntitySize ()
 Full length of the entity.
const char * PeekHeader (nsHttpAtom h)
nsresult SetHeader (nsHttpAtom h, const nsACString &v, PRBool m=PR_FALSE)
nsresult GetHeader (nsHttpAtom h, nsACString &v)
void ClearHeader (nsHttpAtom h)
void ClearHeaders ()
void SetContentType (const nsACString &s)
void SetContentCharset (const nsACString &s)
void SetContentLength (PRInt64)
void Flatten (nsACString &, PRBool pruneTransients)
nsresult Parse (char *block)
void ParseStatusLine (char *line)
void ParseHeaderLine (char *line)
nsresult ComputeFreshnessLifetime (PRUint32 *)
nsresult ComputeCurrentAge (PRUint32 now, PRUint32 requestTime, PRUint32 *result)
PRBool MustValidate ()
PRBool MustValidateIfExpired ()
PRBool IsResumable ()
PRBool ExpiresInPast ()
nsresult UpdateHeaders (nsHttpHeaderArray &headers)
void Reset ()
nsresult ParseDateHeader (nsHttpAtom header, PRUint32 *result)
nsresult GetAgeValue (PRUint32 *result)
nsresult GetMaxAgeValue (PRUint32 *result)
nsresult GetDateValue (PRUint32 *result)
nsresult GetExpiresValue (PRUint32 *result)
nsresult GetLastModifiedValue (PRUint32 *result)

Private Member Functions

void ParseVersion (const char *)
void ParseCacheControl (const char *)
void ParsePragma (const char *)

Private Attributes

nsHttpHeaderArray mHeaders
nsHttpVersion mVersion
PRUint16 mStatus
nsCString mStatusText
PRInt64 mContentLength
nsCString mContentType
nsCString mContentCharset
PRPackedBool mCacheControlNoStore
PRPackedBool mCacheControlNoCache
PRPackedBool mPragmaNoCache

Detailed Description

Definition at line 51 of file nsHttpResponseHead.h.


Constructor & Destructor Documentation

Definition at line 60 of file nsHttpResponseHead.h.

    {
        Reset();
    }

Here is the call graph for this function:


Member Function Documentation

Definition at line 84 of file nsHttpResponseHead.h.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 85 of file nsHttpResponseHead.h.

{ mHeaders.Clear(); }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 241 of file nsHttpResponseHead.cpp.

{
    PRUint32 dateValue;
    PRUint32 ageValue;

    *result = 0;

    if (NS_FAILED(GetDateValue(&dateValue))) {
        LOG(("nsHttpResponseHead::ComputeCurrentAge [this=%x] "
             "Date response header not set!\n", this));
        // Assume we have a fast connection and that our clock
        // is in sync with the server.
        dateValue = now;
    }

    // Compute apparent age
    if (now > dateValue)
        *result = now - dateValue;

    // Compute corrected received age
    if (NS_SUCCEEDED(GetAgeValue(&ageValue)))
        *result = PR_MAX(*result, ageValue);

    NS_ASSERTION(now >= requestTime, "bogus request time");

    // Compute current age
    *result += (now - requestTime);
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 285 of file nsHttpResponseHead.cpp.

{
    *result = 0;

    // Try HTTP/1.1 style max-age directive...
    if (NS_SUCCEEDED(GetMaxAgeValue(result)))
        return NS_OK;

    *result = 0;

    PRUint32 date = 0, date2 = 0;
    if (NS_FAILED(GetDateValue(&date)))
        date = NowInSeconds(); // synthesize a date header if none exists

    // Try HTTP/1.0 style expires header...
    if (NS_SUCCEEDED(GetExpiresValue(&date2))) {
        if (date2 > date)
            *result = date2 - date;
        // the Expires header can specify a date in the past.
        return NS_OK;
    }
    
    // Fallback on heuristic using last modified header...
    if (NS_SUCCEEDED(GetLastModifiedValue(&date2))) {
        LOG(("using last-modified to determine freshness-lifetime\n"));
        LOG(("last-modified = %u, date = %u\n", date2, date));
        if (date2 <= date) {
            // this only makes sense if last-modified is actually in the past
            *result = (date - date2) / 10;
            return NS_OK;
        }
    }

    // These responses can be cached indefinitely.
    if ((mStatus == 300) || (mStatus == 301)) {
        *result = PRUint32(-1);
        return NS_OK;
    }

    LOG(("nsHttpResponseHead::ComputeFreshnessLifetime [this = %x] "
         "Insufficient information to compute a non-zero freshness "
         "lifetime!\n", this));

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 71 of file nsHttpResponseHead.h.

{ return mContentCharset; }

Here is the caller graph for this function:

Definition at line 69 of file nsHttpResponseHead.h.

{ return mContentLength; }

Here is the caller graph for this function:

Definition at line 70 of file nsHttpResponseHead.h.

{ return mContentType; }

Here is the caller graph for this function:

Definition at line 416 of file nsHttpResponseHead.cpp.

{
    PRUint32 expiresVal, dateVal;
    return NS_SUCCEEDED(GetExpiresValue(&expiresVal)) &&
           NS_SUCCEEDED(GetDateValue(&dateVal)) &&
           expiresVal < dateVal;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsHttpResponseHead::Flatten ( nsACString &  buf,
PRBool  pruneTransients 
)

Definition at line 82 of file nsHttpResponseHead.cpp.

{
    if (mVersion == NS_HTTP_VERSION_0_9)
        return;

    buf.AppendLiteral("HTTP/");
    if (mVersion == NS_HTTP_VERSION_1_1)
        buf.AppendLiteral("1.1 ");
    else
        buf.AppendLiteral("1.0 ");

    buf.Append(nsPrintfCString("%u", PRUintn(mStatus)) +
               NS_LITERAL_CSTRING(" ") +
               mStatusText +
               NS_LITERAL_CSTRING("\r\n"));

    if (!pruneTransients) {
        mHeaders.Flatten(buf, PR_FALSE);
        return;
    }

    // otherwise, we need to iterate over the headers and only flatten
    // those that are appropriate.
    PRUint32 i, count = mHeaders.Count();
    for (i=0; i<count; ++i) {
        nsHttpAtom header;
        const char *value = mHeaders.PeekHeaderAt(i, header);

        if (!value || header == nsHttp::Connection
                   || header == nsHttp::Proxy_Connection
                   || header == nsHttp::Keep_Alive
                   || header == nsHttp::WWW_Authenticate
                   || header == nsHttp::Proxy_Authenticate
                   || header == nsHttp::Trailer
                   || header == nsHttp::Transfer_Encoding
                   || header == nsHttp::Upgrade
                   // XXX this will cause problems when we start honoring
                   // Cache-Control: no-cache="set-cookie", what to do?
                   || header == nsHttp::Set_Cookie)
            continue;

        // otherwise, write out the "header: value\r\n" line
        buf.Append(nsDependentCString(header.get()) +
                   NS_LITERAL_CSTRING(": ") +
                   nsDependentCString(value) +
                   NS_LITERAL_CSTRING("\r\n"));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 509 of file nsHttpResponseHead.cpp.

{
    const char *val = PeekHeader(nsHttp::Age);
    if (!val)
        return NS_ERROR_NOT_AVAILABLE;

    *result = (PRUint32) atoi(val);
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 129 of file nsHttpResponseHead.h.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 537 of file nsHttpResponseHead.cpp.

{
    const char *val = PeekHeader(nsHttp::Expires);
    if (!val)
        return NS_ERROR_NOT_AVAILABLE;

    PRTime time;
    PRStatus st = PR_ParseTimeString(val, PR_TRUE, &time);
    if (st != PR_SUCCESS) {
        // parsing failed... RFC 2616 section 14.21 says we should treat this
        // as an expiration time in the past.
        *result = 0;
        return NS_OK;
    }

    if (LL_CMP(time, <, LL_Zero()))
        *result = 0;
    else
        *result = PRTimeToSeconds(time); 
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsHttpResponseHead::GetHeader ( nsHttpAtom  h,
nsACString &  v 
) [inline]

Definition at line 83 of file nsHttpResponseHead.h.

{ return mHeaders.GetHeader(h, v); }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 131 of file nsHttpResponseHead.h.

{ return ParseDateHeader(nsHttp::Last_Modified, result); }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 522 of file nsHttpResponseHead.cpp.

{
    const char *val = PeekHeader(nsHttp::Cache_Control);
    if (!val)
        return NS_ERROR_NOT_AVAILABLE;

    const char *p = PL_strcasestr(val, "max-age=");
    if (!p)
        return NS_ERROR_NOT_AVAILABLE;

    *result = (PRUint32) atoi(p + 8);
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 65 of file nsHttpResponseHead.h.

{ return mHeaders; }

Here is the caller graph for this function:

Definition at line 405 of file nsHttpResponseHead.cpp.

{
    // even though some HTTP/1.0 servers may support byte range requests, we're not
    // going to bother with them, since those servers wouldn't understand If-Range.
    return mVersion >= NS_HTTP_VERSION_1_1 &&
           PeekHeader(nsHttp::Content_Length) && 
          (PeekHeader(nsHttp::ETag) || PeekHeader(nsHttp::Last_Modified)) &&
           PL_strcasestr(PeekHeader(nsHttp::Accept_Ranges), "bytes");
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 332 of file nsHttpResponseHead.cpp.

{
    LOG(("nsHttpResponseHead::MustValidate ??\n"));

    // Some response codes are cacheable, but the rest are not.  This switch
    // should stay in sync with the list in nsHttpChannel::ProcessResponse
    switch (mStatus) {
        // Success codes
    case 200:
    case 203:
    case 206:
        // Cacheable redirects
    case 300:
    case 301:
    case 302:
    case 304:
    case 307:
        break;
        // Uncacheable redirects
    case 303:
    case 305:
        // Other known errors
    case 401:
    case 407:
    case 412:
    case 416:
    default:  // revalidate unknown error pages
        LOG(("Must validate since response is an uncacheable error page\n"));
        return PR_TRUE;
    }
    
    // The no-cache response header indicates that we must validate this
    // cached response before reusing.
    if (NoCache()) {
        LOG(("Must validate since response contains 'no-cache' header\n"));
        return PR_TRUE;
    }

    // Likewise, if the response is no-store, then we must validate this
    // cached response before reusing.  NOTE: it may seem odd that a no-store
    // response may be cached, but indeed all responses are cached in order
    // to support File->SaveAs, View->PageSource, and other browser features.
    if (NoStore()) {
        LOG(("Must validate since response contains 'no-store' header\n"));
        return PR_TRUE;
    }

    // Compare the Expires header to the Date header.  If the server sent an
    // Expires header with a timestamp in the past, then we must validate this
    // cached response before reusing.
    if (ExpiresInPast()) {
        LOG(("Must validate since Expires < Date\n"));
        return PR_TRUE;
    }

    LOG(("no mandatory validation requirement\n"));
    return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 392 of file nsHttpResponseHead.cpp.

{
    // according to RFC2616, section 14.9.4:
    //
    //  When the must-revalidate directive is present in a response received by a   
    //  cache, that cache MUST NOT use the entry after it becomes stale to respond to 
    //  a subsequent request without first revalidating it with the origin server.
    //
    const char *val = PeekHeader(nsHttp::Cache_Control);
    return val && PL_strcasestr(val, "must-revalidate");
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 73 of file nsHttpResponseHead.h.

Here is the caller graph for this function:

Definition at line 72 of file nsHttpResponseHead.h.

Here is the caller graph for this function:

Definition at line 132 of file nsHttpResponseHead.cpp.

{

    LOG(("nsHttpResponseHead::Parse [this=%x]\n", this));

    // this command works on a buffer as prepared by Flatten, as such it is
    // not very forgiving ;-)

    char *p = PL_strstr(block, "\r\n");
    if (!p)
        return NS_ERROR_UNEXPECTED;

    *p = 0;
    ParseStatusLine(block);

    do {
        block = p + 2;

              if (*block == 0)
                     break;

        p = PL_strstr(block, "\r\n");
        if (!p)
            return NS_ERROR_UNEXPECTED;

        *p = 0;
        ParseHeaderLine(block);

    } while (1);

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 629 of file nsHttpResponseHead.cpp.

{
    if (!(val && *val)) {
        // clear flags
        mCacheControlNoCache = PR_FALSE;
        mCacheControlNoStore = PR_FALSE;
        return;
    }

    const char *s = val;

    // search header value for occurance(s) of "no-cache" but ignore
    // occurance(s) of "no-cache=blah"
    while ((s = PL_strcasestr(s, "no-cache")) != nsnull) {
        s += (sizeof("no-cache") - 1);
        if (*s != '=')
            mCacheControlNoCache = PR_TRUE;
    }

    // search header value for occurance of "no-store" 
    if (PL_strcasestr(val, "no-store"))
        mCacheControlNoStore = PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 493 of file nsHttpResponseHead.cpp.

{
    const char *val = PeekHeader(header);
    if (!val)
        return NS_ERROR_NOT_AVAILABLE;

    PRTime time;
    PRStatus st = PR_ParseTimeString(val, PR_TRUE, &time);
    if (st != PR_SUCCESS)
        return NS_ERROR_NOT_AVAILABLE;

    *result = PRTimeToSeconds(time); 
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 201 of file nsHttpResponseHead.cpp.

{
    nsHttpAtom hdr = {0};
    char *val;

    mHeaders.ParseHeaderLine(line, &hdr, &val);
    // leading and trailing LWS has been removed from |val|

    // handle some special case headers...
    if (hdr == nsHttp::Content_Length) {
        PRInt64 len;
        // permit only a single value here.
        if (nsHttp::ParseInt64(val, &len))
            mContentLength = len;
        else
            LOG(("invalid content-length!\n"));
    }
    else if (hdr == nsHttp::Content_Type) {
        LOG(("ParseContentType [type=%s]\n", val));
        PRBool dummy;
        net_ParseContentType(nsDependentCString(val),
                             mContentType, mContentCharset, &dummy);
    }
    else if (hdr == nsHttp::Cache_Control)
        ParseCacheControl(val);
    else if (hdr == nsHttp::Pragma)
        ParsePragma(val);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsHttpResponseHead::ParsePragma ( const char *  val) [private]

Definition at line 654 of file nsHttpResponseHead.cpp.

{
    LOG(("nsHttpResponseHead::ParsePragma [val=%s]\n", val));

    if (!(val && *val)) {
        // clear no-cache flag
        mPragmaNoCache = PR_FALSE;
        return;
    }

    // Although 'Pragma: no-cache' is not a standard HTTP response header (it's
    // a request header), caching is inhibited when this header is present so
    // as to match existing Navigator behavior.
    if (PL_strcasestr(val, "no-cache"))
        mPragmaNoCache = PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 166 of file nsHttpResponseHead.cpp.

{
    //
    // Parse Status-Line:: HTTP-Version SP Status-Code SP Reason-Phrase CRLF
    //
 
    // HTTP-Version
    ParseVersion(line);
    
    if ((mVersion == NS_HTTP_VERSION_0_9) || !(line = PL_strchr(line, ' '))) {
        mStatus = 200;
        mStatusText.AssignLiteral("OK");
    }
    else {
        // Status-Code
        mStatus = (PRUint16) atoi(++line);
        if (mStatus == 0) {
            LOG(("mal-formed response status; assuming status = 200\n"));
            mStatus = 200;
        }

        // Reason-Phrase is whatever is remaining of the line
        if (!(line = PL_strchr(line, ' '))) {
            LOG(("mal-formed response status line; assuming statusText = 'OK'\n"));
            mStatusText.AssignLiteral("OK");
        }
        else
            mStatusText = ++line;
    }

    LOG(("Have status line [version=%u status=%u statusText=%s]\n",
        PRUintn(mVersion), PRUintn(mStatus), mStatusText.get()));
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsHttpResponseHead::ParseVersion ( const char *  str) [private]

Definition at line 586 of file nsHttpResponseHead.cpp.

{
    // Parse HTTP-Version:: "HTTP" "/" 1*DIGIT "." 1*DIGIT

    LOG(("nsHttpResponseHead::ParseVersion [version=%s]\n", str));

    // make sure we have HTTP at the beginning
    if (PL_strncasecmp(str, "HTTP", 4) != 0) {
        LOG(("looks like a HTTP/0.9 response\n"));
        mVersion = NS_HTTP_VERSION_0_9;
        return;
    }
    str += 4;

    if (*str != '/') {
        LOG(("server did not send a version number; assuming HTTP/1.0\n"));
        // NCSA/1.5.2 has a bug in which it fails to send a version number
        // if the request version is HTTP/1.1, so we fall back on HTTP/1.0
        mVersion = NS_HTTP_VERSION_1_0;
        return;
    }

    char *p = PL_strchr(str, '.');
    if (p == nsnull) {
        LOG(("mal-formed server version; assuming HTTP/1.0\n"));
        mVersion = NS_HTTP_VERSION_1_0;
        return;
    }

    ++p; // let b point to the minor version

    int major = atoi(str + 1);
    int minor = atoi(p);

    if ((major > 1) || ((major == 1) && (minor >= 1)))
        // at least HTTP/1.1
        mVersion = NS_HTTP_VERSION_1_1;
    else
        // treat anything else as version 1.0
        mVersion = NS_HTTP_VERSION_1_0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 81 of file nsHttpResponseHead.h.

{ return mHeaders.PeekHeader(h); }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 475 of file nsHttpResponseHead.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

void nsHttpResponseHead::SetContentCharset ( const nsACString &  s) [inline]

Definition at line 88 of file nsHttpResponseHead.h.

Here is the caller graph for this function:

Definition at line 72 of file nsHttpResponseHead.cpp.

{
    mContentLength = len;
    if (!LL_GE_ZERO(len)) // < 0
        mHeaders.ClearHeader(nsHttp::Content_Length);
    else
        mHeaders.SetHeader(nsHttp::Content_Length, nsPrintfCString(20, "%lld", len));
}

Here is the call graph for this function:

void nsHttpResponseHead::SetContentType ( const nsACString &  s) [inline]

Definition at line 87 of file nsHttpResponseHead.h.

{ mContentType = s; }

Here is the caller graph for this function:

Definition at line 54 of file nsHttpResponseHead.cpp.

{
    nsresult rv = mHeaders.SetHeader(hdr, val, merge);
    if (NS_FAILED(rv)) return rv;

    // respond to changes in these headers.  we need to reparse the entire
    // header since the change may have merged in additional values.
    if (hdr == nsHttp::Cache_Control)
        ParseCacheControl(mHeaders.PeekHeader(hdr));
    else if (hdr == nsHttp::Pragma)
        ParsePragma(mHeaders.PeekHeader(hdr));

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 67 of file nsHttpResponseHead.h.

{ return mStatus; }

Here is the caller graph for this function:

Definition at line 68 of file nsHttpResponseHead.h.

{ return mStatusText; }

Full length of the entity.

For byte-range requests, this may be larger than ContentLength(), which will only represent the requested part of the entity.

Definition at line 560 of file nsHttpResponseHead.cpp.

{
    const char* contentRange = PeekHeader(nsHttp::Content_Range);
    if (!contentRange)
        return ContentLength();

    // Total length is after a slash
    const char* slash = strrchr(contentRange, '/');
    if (!slash)
        return -1; // No idea what the length is

    slash++;
    if (*slash == '*') // Server doesn't know the length
        return -1;

    PRInt64 size;
    if (!nsHttp::ParseInt64(slash, &size))
        size = LL_MAXUINT;
    return size;
}

Here is the call graph for this function:

Definition at line 425 of file nsHttpResponseHead.cpp.

{
    LOG(("nsHttpResponseHead::UpdateHeaders [this=%x]\n", this));

    PRUint32 i, count = headers.Count();
    for (i=0; i<count; ++i) {
        nsHttpAtom header;
        const char *val = headers.PeekHeaderAt(i, header);

        if (!val) {
            NS_NOTREACHED("null header value");
            continue;
        }

        // Ignore any hop-by-hop headers...
        if (header == nsHttp::Connection          ||
            header == nsHttp::Proxy_Connection    ||
            header == nsHttp::Keep_Alive          ||
            header == nsHttp::Proxy_Authenticate  ||
            header == nsHttp::Proxy_Authorization || // not a response header!
            header == nsHttp::TE                  ||
            header == nsHttp::Trailer             ||
            header == nsHttp::Transfer_Encoding   ||
            header == nsHttp::Upgrade             ||
        // Ignore any non-modifiable headers...
            header == nsHttp::Content_Location    ||
            header == nsHttp::Content_MD5         ||
            header == nsHttp::ETag                ||
        // Assume Cache-Control: "no-transform"
            header == nsHttp::Content_Encoding    ||
            header == nsHttp::Content_Range       ||
            header == nsHttp::Content_Type        ||
        // Ignore wacky headers too...
            // this one is for MS servers that send "Content-Length: 0"
            // on 304 responses
            header == nsHttp::Content_Length) {
            LOG(("ignoring response header [%s: %s]\n", header.get(), val));
        }
        else {
            LOG(("new response header [%s: %s]\n", header.get(), val));

            // overwrite the current header value with the new value...
            SetHeader(header, nsDependentCString(val));
        }
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 66 of file nsHttpResponseHead.h.

{ return mVersion; }

Here is the caller graph for this function:


Member Data Documentation

Definition at line 147 of file nsHttpResponseHead.h.

Definition at line 146 of file nsHttpResponseHead.h.

Definition at line 145 of file nsHttpResponseHead.h.

Definition at line 143 of file nsHttpResponseHead.h.

Definition at line 144 of file nsHttpResponseHead.h.

Definition at line 139 of file nsHttpResponseHead.h.

Definition at line 148 of file nsHttpResponseHead.h.

Definition at line 141 of file nsHttpResponseHead.h.

Definition at line 142 of file nsHttpResponseHead.h.

Definition at line 140 of file nsHttpResponseHead.h.


The documentation for this class was generated from the following files: