1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "CacheControlParser.h"
8 
9 namespace mozilla {
10 namespace net {
11 
CacheControlParser(nsACString const & aHeader)12 CacheControlParser::CacheControlParser(nsACString const& aHeader)
13     : Tokenizer(aHeader, nullptr, "-_"),
14       mMaxAgeSet(false),
15       mMaxAge(0),
16       mMaxStaleSet(false),
17       mMaxStale(0),
18       mMinFreshSet(false),
19       mMinFresh(0),
20       mStaleWhileRevalidateSet(false),
21       mStaleWhileRevalidate(0),
22       mNoCache(false),
23       mNoStore(false),
24       mPublic(false),
25       mPrivate(false),
26       mImmutable(false) {
27   SkipWhites();
28   if (!CheckEOF()) {
29     Directive();
30   }
31 }
32 
Directive()33 void CacheControlParser::Directive() {
34   if (CheckWord("no-cache")) {
35     mNoCache = true;
36     IgnoreDirective();  // ignore any optionally added values
37   } else if (CheckWord("no-store")) {
38     mNoStore = true;
39   } else if (CheckWord("max-age")) {
40     mMaxAgeSet = SecondsValue(&mMaxAge);
41   } else if (CheckWord("max-stale")) {
42     mMaxStaleSet = SecondsValue(&mMaxStale, PR_UINT32_MAX);
43   } else if (CheckWord("min-fresh")) {
44     mMinFreshSet = SecondsValue(&mMinFresh);
45   } else if (CheckWord("stale-while-revalidate")) {
46     mStaleWhileRevalidateSet = SecondsValue(&mStaleWhileRevalidate);
47   } else if (CheckWord("public")) {
48     mPublic = true;
49   } else if (CheckWord("private")) {
50     mPrivate = true;
51   } else if (CheckWord("immutable")) {
52     mImmutable = true;
53   } else {
54     IgnoreDirective();
55   }
56 
57   SkipWhites();
58   if (CheckEOF()) {
59     return;
60   }
61   if (CheckChar(',')) {
62     SkipWhites();
63     Directive();
64     return;
65   }
66 
67   NS_WARNING("Unexpected input in Cache-control header value");
68 }
69 
SecondsValue(uint32_t * seconds,uint32_t defaultVal)70 bool CacheControlParser::SecondsValue(uint32_t* seconds, uint32_t defaultVal) {
71   SkipWhites();
72   if (!CheckChar('=')) {
73     *seconds = defaultVal;
74     return !!defaultVal;
75   }
76 
77   SkipWhites();
78   if (!ReadInteger(seconds)) {
79     NS_WARNING("Unexpected value in Cache-control header value");
80     return false;
81   }
82 
83   return true;
84 }
85 
IgnoreDirective()86 void CacheControlParser::IgnoreDirective() {
87   Token t;
88   while (Next(t)) {
89     if (t.Equals(Token::Char(',')) || t.Equals(Token::EndOfFile())) {
90       Rollback();
91       break;
92     }
93     if (t.Equals(Token::Char('"'))) {
94       SkipUntil(Token::Char('"'));
95       if (!CheckChar('"')) {
96         NS_WARNING(
97             "Missing quoted string expansion in Cache-control header value");
98         break;
99       }
100     }
101   }
102 }
103 
MaxAge(uint32_t * seconds)104 bool CacheControlParser::MaxAge(uint32_t* seconds) {
105   *seconds = mMaxAge;
106   return mMaxAgeSet;
107 }
108 
MaxStale(uint32_t * seconds)109 bool CacheControlParser::MaxStale(uint32_t* seconds) {
110   *seconds = mMaxStale;
111   return mMaxStaleSet;
112 }
113 
MinFresh(uint32_t * seconds)114 bool CacheControlParser::MinFresh(uint32_t* seconds) {
115   *seconds = mMinFresh;
116   return mMinFreshSet;
117 }
118 
StaleWhileRevalidate(uint32_t * seconds)119 bool CacheControlParser::StaleWhileRevalidate(uint32_t* seconds) {
120   *seconds = mStaleWhileRevalidate;
121   return mStaleWhileRevalidateSet;
122 }
123 
NoCache()124 bool CacheControlParser::NoCache() { return mNoCache; }
125 
NoStore()126 bool CacheControlParser::NoStore() { return mNoStore; }
127 
Public()128 bool CacheControlParser::Public() { return mPublic; }
129 
Private()130 bool CacheControlParser::Private() { return mPrivate; }
131 
Immutable()132 bool CacheControlParser::Immutable() { return mImmutable; }
133 
134 }  // namespace net
135 }  // namespace mozilla
136