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       mNoCache(false),
21       mNoStore(false) {
22   SkipWhites();
23   if (!CheckEOF()) {
24     Directive();
25   }
26 }
27 
Directive()28 void CacheControlParser::Directive() {
29   if (CheckWord("no-cache")) {
30     mNoCache = true;
31     IgnoreDirective();  // ignore any optionally added values
32   } else if (CheckWord("no-store")) {
33     mNoStore = true;
34   } else if (CheckWord("max-age")) {
35     mMaxAgeSet = SecondsValue(&mMaxAge);
36   } else if (CheckWord("max-stale")) {
37     mMaxStaleSet = SecondsValue(&mMaxStale, PR_UINT32_MAX);
38   } else if (CheckWord("min-fresh")) {
39     mMinFreshSet = SecondsValue(&mMinFresh);
40   } else {
41     IgnoreDirective();
42   }
43 
44   SkipWhites();
45   if (CheckEOF()) {
46     return;
47   }
48   if (CheckChar(',')) {
49     SkipWhites();
50     Directive();
51     return;
52   }
53 
54   NS_WARNING("Unexpected input in Cache-control header value");
55 }
56 
SecondsValue(uint32_t * seconds,uint32_t defaultVal)57 bool CacheControlParser::SecondsValue(uint32_t *seconds, uint32_t defaultVal) {
58   SkipWhites();
59   if (!CheckChar('=')) {
60     *seconds = defaultVal;
61     return !!defaultVal;
62   }
63 
64   SkipWhites();
65   if (!ReadInteger(seconds)) {
66     NS_WARNING("Unexpected value in Cache-control header value");
67     return false;
68   }
69 
70   return true;
71 }
72 
IgnoreDirective()73 void CacheControlParser::IgnoreDirective() {
74   Token t;
75   while (Next(t)) {
76     if (t.Equals(Token::Char(',')) || t.Equals(Token::EndOfFile())) {
77       Rollback();
78       break;
79     }
80     if (t.Equals(Token::Char('"'))) {
81       SkipUntil(Token::Char('"'));
82       if (!CheckChar('"')) {
83         NS_WARNING(
84             "Missing quoted string expansion in Cache-control header value");
85         break;
86       }
87     }
88   }
89 }
90 
MaxAge(uint32_t * seconds)91 bool CacheControlParser::MaxAge(uint32_t *seconds) {
92   *seconds = mMaxAge;
93   return mMaxAgeSet;
94 }
95 
MaxStale(uint32_t * seconds)96 bool CacheControlParser::MaxStale(uint32_t *seconds) {
97   *seconds = mMaxStale;
98   return mMaxStaleSet;
99 }
100 
MinFresh(uint32_t * seconds)101 bool CacheControlParser::MinFresh(uint32_t *seconds) {
102   *seconds = mMinFresh;
103   return mMinFreshSet;
104 }
105 
NoCache()106 bool CacheControlParser::NoCache() { return mNoCache; }
107 
NoStore()108 bool CacheControlParser::NoStore() { return mNoStore; }
109 
110 }  // namespace net
111 }  // namespace mozilla
112