Index: net/base/force_tls_state.cc |
=================================================================== |
--- net/base/force_tls_state.cc (revision 17278) |
+++ net/base/force_tls_state.cc (working copy) |
@@ -5,6 +5,8 @@ |
#include "net/base/force_tls_state.h" |
#include "base/logging.h" |
+#include "base/string_tokenizer.h" |
+#include "base/string_util.h" |
#include "googleurl/src/gurl.h" |
#include "net/base/registry_controlled_domain.h" |
@@ -31,4 +33,101 @@ |
return enabled_hosts_.find(host) != enabled_hosts_.end(); |
} |
+// "X-Force-TLS" ":" "max-age" "=" delta-seconds *1INCLUDESUBDOMAINS |
wtc
2009/06/01 17:59:19
OK, so you have the header's definition here. Wou
abarth-chromium
2009/06/02 02:24:05
Ok...... The only reason this method is public is
|
+// INCLUDESUBDOMAINS = [ " includeSubDomains" ] |
+bool ForceTLSState::ParseHeader(const std::string& value, |
+ int* max_age, |
+ bool* include_subdomains) { |
+ DCHECK(max_age); |
+ DCHECK(include_subdomains); |
+ |
+ int max_age_candidate; |
+ |
+ enum ParserState { |
+ START, |
+ AFTER_MAX_AGE_LABEL, |
+ AFTER_MAX_AGE_EQUALS, |
+ AFTER_MAX_AGE, |
+ AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER, |
+ AFTER_INCLUDE_SUBDOMAINS, |
+ } state = START; |
+ |
+ StringTokenizer tokenizer(value, " ="); |
+ tokenizer.set_options(StringTokenizer::RETURN_DELIMS); |
+ while (tokenizer.GetNext()) { |
+ DCHECK(!tokenizer.token_is_delim() || tokenizer.token().length() == 1); |
+ DCHECK(tokenizer.token_is_delim() || *tokenizer.token_begin() != ' '); |
+ switch (state) { |
+ case START: |
+ if (*tokenizer.token_begin() == ' ') |
+ continue; |
+ if (!LowerCaseEqualsASCII(tokenizer.token(), "max-age")) |
+ return false; |
+ state = AFTER_MAX_AGE_LABEL; |
+ break; |
+ |
+ case AFTER_MAX_AGE_LABEL: |
+ if (*tokenizer.token_begin() == ' ') |
+ continue; |
+ if (*tokenizer.token_begin() != '=') |
+ return false; |
+ DCHECK(tokenizer.token().length() == 1); |
+ state = AFTER_MAX_AGE_EQUALS; |
+ break; |
+ |
+ case AFTER_MAX_AGE_EQUALS: |
+ if (*tokenizer.token_begin() == ' ') |
+ continue; |
+ if (!StringToInt(tokenizer.token(), &max_age_candidate)) |
+ return false; |
+ if (max_age_candidate < 0) |
+ return false; |
+ state = AFTER_MAX_AGE; |
+ break; |
+ |
+ case AFTER_MAX_AGE: |
+ if (*tokenizer.token_begin() != ' ') |
+ return false; |
+ state = AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER; |
+ break; |
+ |
+ case AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER: |
+ if (*tokenizer.token_begin() == ' ') |
+ continue; |
+ if (!LowerCaseEqualsASCII(tokenizer.token(), "includesubdomains")) |
+ return false; |
+ state = AFTER_INCLUDE_SUBDOMAINS; |
+ break; |
+ |
+ case AFTER_INCLUDE_SUBDOMAINS: |
+ if (*tokenizer.token_begin() != ' ') |
+ return false; |
+ break; |
+ |
+ default: |
+ NOTREACHED(); |
+ } |
+ } |
+ |
+ // We've consumed all the input. Let's see what state we ended up in. |
+ switch (state) { |
+ case START: |
+ case AFTER_MAX_AGE_LABEL: |
+ case AFTER_MAX_AGE_EQUALS: |
+ return false; |
+ case AFTER_MAX_AGE: |
+ case AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER: |
+ *max_age = max_age_candidate; |
+ *include_subdomains = false; |
+ return true; |
+ case AFTER_INCLUDE_SUBDOMAINS: |
+ *max_age = max_age_candidate; |
+ *include_subdomains = true; |
+ return true; |
+ default: |
+ NOTREACHED(); |
+ return false; |
+ } |
+} |
+ |
} // namespace |