// Copyright 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "net/instaweb/rewriter/public/rewrite_query.h"

#include <algorithm>  // for std::binary_search
#include <map>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/rewriter/public/image_rewrite_filter.h"
#include "net/instaweb/rewriter/public/request_properties.h"
#include "net/instaweb/rewriter/public/resource_namer.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_driver_factory.h"
#include "net/instaweb/rewriter/public/rewrite_filter.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_multi_map.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/http/google_url.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/query_params.h"
#include "pagespeed/kernel/http/response_headers.h"

namespace net_instaweb {

namespace {

// We use + and = inside the resource-options URL segment because they will not
// be quoted by UrlEscaper, unlike "," and ":".
const char kResourceFilterSeparator[] = "+";
const char kResourceOptionValueSeparator[] = "=";

const char kProxyOptionSeparator[] = ",";
const char kProxyOptionValueSeparator = '=';
const char kProxyOptionVersion[] = "v";
const char kProxyOptionMode[] = "m";
const char kProxyOptionImageQualityPreference[] = "iqp";
const char kProxyOptionValidVersionValue[] = "1";

StringPiece SanitizeValueAsQP(StringPiece untrusted_value,
                              GoogleUrl* storage) {
  // This is ever so slightly hacky: we dummy up an URL with a QP where the
  // value of the QP is the untrusted value, then we discard everything
  // prior to the possibly-modified value in the resulting GoogleUrl.
  const char kUrlBase[] = "http://www.example.com/?x=";
  storage->Reset(StrCat(kUrlBase, untrusted_value));
  StringPiece sanitized_value = storage->Spec();
  return StringPiece(sanitized_value.data() + STATIC_STRLEN(kUrlBase),
                     sanitized_value.size() - STATIC_STRLEN(kUrlBase));
}

}  // namespace

const char RewriteQuery::kModPagespeed[] = "ModPagespeed";
const char RewriteQuery::kPageSpeed[] = "PageSpeed";

const char RewriteQuery::kModPagespeedFilters[] = "ModPagespeedFilters";
const char RewriteQuery::kPageSpeedFilters[] = "PageSpeedFilters";

const char RewriteQuery::kNoscriptValue[] = "noscript";

template <class HeaderT>
RewriteQuery::Status RewriteQuery::ScanHeader(
    bool allow_options,
    const GoogleString& request_option_override,
    const RequestContextPtr& request_context,
    HeaderT* headers,
    RequestProperties* request_properties,
    RewriteOptions* options,
    MessageHandler* handler) {
  Status status = kNoneFound;

  if (headers == NULL) {
    return status;
  }

  // Check to see if the override token exists.
  if (!allow_options && !request_option_override.empty()) {
    GoogleString mod_pagespeed_override =
        StrCat(kModPagespeed, RewriteOptions::kRequestOptionOverride);
    GoogleString page_speed_override =
        StrCat(kPageSpeed, RewriteOptions::kRequestOptionOverride);
    for (int i = 0, n = headers->NumAttributes(); i < n; ++i) {
      const StringPiece name(headers->Name(i));
      const GoogleString& value = headers->Value(i);
      if (name == mod_pagespeed_override || name == page_speed_override) {
        allow_options = (value == request_option_override);
        break;
      }
    }
  }

  // Tracks the headers that need to be removed.
  // It doesn't matter what type of headers we use, so we use RequestHeaders.
  RequestHeaders headers_to_remove;

  for (int i = 0, n = headers->NumAttributes(); i < n; ++i) {
    const StringPiece name(headers->Name(i));
    const GoogleString& value = headers->Value(i);
    switch (ScanNameValue(name, value, allow_options, request_context,
                          request_properties, options, handler)) {
      case kNoneFound:
        break;
      case kSuccess:
        if (name.starts_with(kModPagespeed) || name.starts_with(kPageSpeed)) {
          headers_to_remove.Add(name, value);
        }
        status = kSuccess;
        break;
      case kInvalid:
        return kInvalid;
    }
  }

  // TODO(bolian): jmarantz suggested below change.  we should make a
  // StringSetInsensitive and put all the names we want to remove including
  // XPSAClientOptions and then call RemoveAllFromSet.
  // That will be more efficient.
  for (int i = 0, n = headers_to_remove.NumAttributes(); i < n; ++i) {
    headers->Remove(headers_to_remove.Name(i), headers_to_remove.Value(i));
  }
  // kXPsaClientOptions is meant for proxy only. Remove it in any case.
  headers->RemoveAll(HttpAttributes::kXPsaClientOptions);

  return status;
}

RewriteQuery::RewriteQuery() {
}

RewriteQuery::~RewriteQuery() {
}

// Scan for option-sets in cookies, query params, request and response headers.
// We only allow a limited number of options to be set. In particular, some
// options are risky to set this way, such as image inline threshold, which
// exposes a DOS vulnerability and a risk of poisoning our internal cache, and
// domain adjustments, which can introduce a security vulnerability.
RewriteQuery::Status RewriteQuery::Scan(
    bool allow_related_options,
    bool allow_options_to_be_specified_by_cookies,
    const GoogleString& request_option_override,
    const RequestContextPtr& request_context,
    RewriteDriverFactory* factory,
    ServerContext* server_context,
    GoogleUrl* request_url,
    RequestHeaders* request_headers,
    ResponseHeaders* response_headers,
    MessageHandler* handler) {
  Status status = kNoneFound;
  query_params_.Clear();
  pagespeed_query_params_.Clear();
  pagespeed_option_cookies_.Clear();
  options_.reset(NULL);

  // To support serving resources from servers that don't share the
  // same settings as the ones generating HTML, we can put whitelisted
  // option-settings into the query-params by ID.  But we expose this
  // setting (a) only for .pagespeed. resources, not HTML, and (b)
  // only when allow_related_options is true.
  ResourceNamer namer;

  bool return_after_parsing = false;
  if (allow_related_options &&
      namer.DecodeIgnoreHashAndSignature(request_url->LeafSansQuery()) &&
      namer.has_options()) {
    const RewriteFilter* rewrite_filter =
        server_context->FindFilterForDecoding(namer.id());
    if (rewrite_filter != NULL) {
      options_.reset(factory->NewRewriteOptionsForQuery());
      status = ParseResourceOption(namer.options(), options_.get(),
                                   rewrite_filter);
      if (status != kSuccess) {
        options_.reset(NULL);

        // We want query_params() to be populated after calling
        // RewriteQuery::Scan, even if any URL-embedded configuration
        // parameters are invalid.  So we delay our early exit until
        // after the query_params_.Parse call below.
        return_after_parsing = true;
      }
    }
  }

  // Extract all cookies iff we can use them to set options.
  RequestHeaders::CookieMultimap no_cookies;
  const RequestHeaders::CookieMultimap& all_cookies(
      (allow_options_to_be_specified_by_cookies && request_headers != NULL)
      ? request_headers->GetAllCookies()
      : no_cookies);

  // For XmlHttpRequests, disable filters that can't run in Ajax.
  //
  // For example, for filters that insert scripts, there will be two
  // copies of the same scripts in the html dom -- one from main html
  // page and another from html content fetched from ajax --- which
  // will generally confuse the heck out of it. The code for this is a
  // little special since unlike a PageSpeedFoo= header we should not
  // take it as an invitation to turn stuff on.
  //
  // Another commmon case is filters that require a <head> element -- we
  // don't want to add a <head> in the ajax response, so we can't run
  // any filters that might depend on that.
  //
  // TODO(sriharis): Set a flag in RewriteOptions indicating that we are
  // working with Ajax and thus should not assume the base URL is correct.
  // Note that there is no guarantee that the header will be set on an ajax
  // request and so the option will not be set for all ajax requests.
  //
  // TODO(jmarantz): Ajax status should probably be in RequestProperties
  // rather than RewriteOptions so we don't have to create a new driver
  // on an ajax request, but can instead reference properties.  However
  // that change may be fairly significant.
  if (request_headers != NULL && request_headers->IsXmlHttpRequest()) {
    if (options_.get() == NULL) {
      options_.reset(factory->NewRewriteOptionsForQuery());
    }
    options_->DisableFiltersThatCantRunInAjax();
    status = kSuccess;
  }

  // See if anything looks even remotely like one of our options before doing
  // any more work.  Note that when options are correctly embedded in the URL,
  // we will have a success-status here.  But we still allow a hand-added
  // query-param to override the embedded options.
  query_params_.ParseFromUrl(*request_url);
  if (return_after_parsing ||
      !MayHaveCustomOptions(query_params_, request_headers, response_headers,
                            all_cookies)) {
    return status;
  }

  if (options_.get() == NULL) {
    options_.reset(factory->NewRewriteOptionsForQuery());
  }

  scoped_ptr<RequestProperties> request_properties;
  if (request_headers != NULL) {
    request_properties.reset(server_context->NewRequestProperties());
    request_properties->SetUserAgent(
        request_headers->Lookup1(HttpAttributes::kUserAgent));
  }

  // Check to see if options should be parsed.
  // If the config disallows parsing, and the proper token is not provided,
  // do not use the options passed in the url.
  bool allow_options = true;
  if (!request_option_override.empty()) {
    allow_options = false;
    GoogleString override_token;
    GoogleString mod_pagespeed_override =
        StrCat(kModPagespeed, RewriteOptions::kRequestOptionOverride);
    GoogleString page_speed_override =
        StrCat(kPageSpeed, RewriteOptions::kRequestOptionOverride);
    if (query_params_.Lookup1Unescaped(mod_pagespeed_override,
                                       &override_token) ||
        query_params_.Lookup1Unescaped(page_speed_override, &override_token)) {
      allow_options = (override_token == request_option_override);
    }
  }

  // Scan for options set as cookies. They can be overridden by QPs or headers.
  // An explanation of the life cycle of a PageSpeed option cookie:
  // * Initially the value is passed in as a GoogleUrl query parameter.
  // * GoogleUrl does minimal escaping, mainly removing whitespace and
  //   percent-encoding control characters.
  // * That is parsed by QueryParams (above), which does no further escaping.
  // * Since cookie values have restrictions on the characters allowed in the
  //   value (e.g. no ';'s), we GoogleUrl::Escape the value, which does
  //   significant percent-escaping (nearly everything except alphanumeric).
  //   This is done in ResponseHeaders::SetPageSpeedQueryParamsAsCookies().
  // [So now we're here, where we use the cookie values set by the above steps]
  // * We unescape the cookie value to reverse the previous step.
  //   Note that GoogleUrl::UnescapeQueryParam(GoogleUrl::EscapeQueryParam(x))
  //   is the identify function, so we expect the value to be GoogleUrl
  //   minimally escaped.
  // TODO(sligocki): GoogleUrl::UnescapeIgnorePlus(GoogleUrl::EscapeQueryParam)
  //                 is not the identity function. Is this a problem?
  // * We sanitize the unescaped cookie value by dummying up a GoogleUrl with
  //   the value as a query parameter value, hence re-minimally escaping it.
  // * We then escape this sanitized value since that's the process that we
  //   went through above: if this escaped value equals the cookie value then
  //   the cookie value seems authentic -and- the unescaped value must also be
  //   sanitized, meaning it's safe to pass to our value parsing logic. If the
  //   escaped value does -not- equal the cookie value, it means the cookie has
  //   characters that we cannot have put there, and we assume that someone has
  //   manually set it in an attempt to circumvent our precautions, so we
  //   ignore the cookie completely.
  RequestHeaders::CookieMultimapConstIter it, end;
  for (it = all_cookies.begin(), end = all_cookies.end(); it != end; ++it) {
    StringPiece cookie_name = it->first;
    if (MightBeCustomOption(cookie_name)) {
      GoogleUrl gurl;
      StringPiece cookie_value = it->second.first;
      GoogleString unescaped = GoogleUrl::UnescapeIgnorePlus(cookie_value);
      StringPiece sanitized = SanitizeValueAsQP(unescaped, &gurl);
      GoogleString escaped = GoogleUrl::EscapeQueryParam(sanitized);
      if (unescaped == sanitized && escaped == cookie_value) {
        RequestContextPtr null_request_context;
        if (ScanNameValue(cookie_name, unescaped, allow_options,
                          null_request_context, request_properties.get(),
                          options_.get(), handler) == kSuccess) {
          pagespeed_option_cookies_.AddEscaped(cookie_name, unescaped);
          status = kSuccess;
        }
      } else {
        // PageSpeed cookies with an invalid value will not be cleared. This
        // is unfortunate but OK since they'll never apply (due to the invalid
        // value) and will eventually expire anyway.
        handler->Message(kInfo, "PageSpeed Cookie value seems mangled: "
                         "name='%s', value='%s', escaped value='%s'",
                         cookie_name.as_string().c_str(),
                         cookie_value.as_string().c_str(),
                         escaped.c_str());
      }
    }
  }

  pagespeed_query_params_.Clear();
  QueryParams temp_query_params;
  for (int i = 0; i < query_params_.size(); ++i) {
    GoogleString unescaped_value;
    if (query_params_.UnescapedValue(i, &unescaped_value)) {
      // The Unescaper changes "+" to " ", which is not what we want, and
      // is not what happens for response headers and request headers, so
      // let's fix it now.
      GlobalReplaceSubstring(" " , "+", &unescaped_value);
      switch (ScanNameValue(
          query_params_.name(i), unescaped_value, allow_options,
          request_context, request_properties.get(), options_.get(), handler)) {
        case kNoneFound:
          // If this is not a PageSpeed-related query-parameter, then save it
          // in its escaped form.
          temp_query_params.AddEscaped(query_params_.name(i),
                                       *query_params_.EscapedValue(i));
          break;
        case kSuccess:
          // If it is a PageSpeed-related query parameter, also save it so we
          // can add it back if we receive a redirection response to our fetch.
          pagespeed_query_params_.AddEscaped(query_params_.name(i),
                                             *query_params_.EscapedValue(i));
          status = kSuccess;
          break;
        case kInvalid:
          status = kInvalid;
          options_.reset(NULL);
          return status;
      }
    } else {
      temp_query_params.AddEscaped(query_params_.name(i), StringPiece());
    }
  }
  if (status == kSuccess) {
    // Remove the ModPagespeed* or PageSpeed* for url.
    GoogleString temp_params = temp_query_params.empty() ? "" :
        StrCat("?", temp_query_params.ToEscapedString());
    request_url->Reset(StrCat(request_url->AllExceptQuery(), temp_params,
                              request_url->AllAfterQuery()));
  }

  switch (ScanHeader<RequestHeaders>(
      allow_options, request_option_override, request_context, request_headers,
      request_properties.get(), options_.get(), handler)) {
    case kNoneFound:
      break;
    case kSuccess:
      status = kSuccess;
      break;
    case kInvalid:
      status = kInvalid;
      options_.reset(NULL);
      return status;
  }

  switch (ScanHeader<ResponseHeaders>(
      allow_options, request_option_override, request_context, response_headers,
      request_properties.get(), options_.get(), handler)) {
    case kNoneFound:
      break;
    case kSuccess:
      status = kSuccess;
      break;
    case kInvalid:
      status = kInvalid;
      options_.reset(NULL);
      return status;
  }

  // Set a default rewrite level in case the mod_pagespeed server has no
  // rewriting options configured.
  // Note that if any filters are explicitly set with
  // PageSpeedFilters=..., then the call to
  // DisableAllFiltersNotExplicitlyEnabled() below will make the 'level'
  // irrelevant.
  switch (status) {
    case kSuccess:
      options_->SetDefaultRewriteLevel(RewriteOptions::kCoreFilters);
      break;
    case kNoneFound:
      options_.reset(NULL);
      break;
    case kInvalid:
      LOG(DFATAL) << "Invalid responses always use early exit";
      options_.reset(NULL);
      break;
  }
  return status;
}

bool RewriteQuery::MightBeCustomOption(StringPiece name) {
  // TODO(jmarantz): switch to case-insenstive comparisons for these prefixes.
  return name.starts_with(kModPagespeed) || name.starts_with(kPageSpeed) ||
      StringCaseEqual(name, HttpAttributes::kXPsaClientOptions);
}

template <class HeaderT>
bool RewriteQuery::HeadersMayHaveCustomOptions(const QueryParams& params,
                                               const HeaderT* headers) {
  if (headers != NULL) {
    for (int i = 0, n = headers->NumAttributes(); i < n; ++i) {
      if (MightBeCustomOption(headers->Name(i))) {
        return true;
      }
    }
  }
  return false;
}

bool RewriteQuery::CookiesMayHaveCustomOptions(
    const RequestHeaders::CookieMultimap& cookies) {
  RequestHeaders::CookieMultimapConstIter it = cookies.begin();
  RequestHeaders::CookieMultimapConstIter end = cookies.end();
  for (; it != end; ++it) {
    if (MightBeCustomOption(it->first)) {
      return true;
    }
  }
  return false;
}

bool RewriteQuery::MayHaveCustomOptions(
    const QueryParams& params, const RequestHeaders* req_headers,
    const ResponseHeaders* resp_headers,
    const RequestHeaders::CookieMultimap& cookies) {
  for (int i = 0, n = params.size(); i < n; ++i) {
    if (MightBeCustomOption(params.name(i))) {
      return true;
    }
  }
  if (HeadersMayHaveCustomOptions(params, req_headers)) {
    return true;
  }
  if (HeadersMayHaveCustomOptions(params, resp_headers)) {
    return true;
  }
  if (CookiesMayHaveCustomOptions(cookies)) {
    return true;
  }
  if (req_headers != NULL &&
      (req_headers->Has(HttpAttributes::kXPsaClientOptions) ||
       req_headers->HasValue(HttpAttributes::kCacheControl, "no-transform"))) {
    return true;
  }
  if ((resp_headers != NULL) && resp_headers->HasValue(
          HttpAttributes::kCacheControl, "no-transform")) {
    return true;
  }
  return false;
}

RewriteQuery::Status RewriteQuery::ScanNameValue(
    const StringPiece& name, const StringPiece& value, bool allow_options,
    const RequestContextPtr& request_context,
    RequestProperties* request_properties, RewriteOptions* options,
    MessageHandler* handler) {
  Status status = kNoneFound;

  // See https://github.com/pagespeed/mod_pagespeed/issues/627
  // Evidently bots and other clients may not properly resolve the quoted
  // URLs we send into noscript links, so remove any excess quoting we
  // see around the value.
  StringPiece trimmed_value(value);
  TrimUrlQuotes(&trimmed_value);
  if (name == kModPagespeed || name == kPageSpeed) {
    RewriteOptions::EnabledEnum enabled;
    if (RewriteOptions::ParseFromString(trimmed_value, &enabled)) {
      options->set_enabled(enabled);
      status = kSuccess;
    } else if (trimmed_value.starts_with(kNoscriptValue)) {
      // We use starts_with("noscript") to help resolve Issue 874.
      // Disable filters that depend on custom script execution.
      options->DisableFiltersRequiringScriptExecution();
      options->EnableFilter(RewriteOptions::kHandleNoscriptRedirect);
      status = kSuccess;
    } else {
      // TODO(sligocki): Return 404s instead of logging server errors here
      // and below.
      handler->Message(kWarning, "Invalid value for %s: %s "
                       "(should be on, off, unplugged, or noscript)",
                       name.as_string().c_str(),
                       trimmed_value.as_string().c_str());
      status = kInvalid;
    }
  } else if (!allow_options) {
    status = kNoneFound;
  } else if (name == kModPagespeedFilters || name == kPageSpeedFilters) {
    // When using PageSpeedFilters query param, only the specified filters
    // should be enabled.
    if (options->AdjustFiltersByCommaSeparatedList(trimmed_value, handler)) {
      status = kSuccess;
    } else {
      status = kInvalid;
    }
  } else if (StringCaseEqual(name, HttpAttributes::kXPsaClientOptions)) {
    if (UpdateRewriteOptionsWithClientOptions(
        trimmed_value, request_properties, options)) {
      status = kSuccess;
    }
    // We don't want to return kInvalid, which causes 405 (kMethodNotAllowed)
    // returned to client.
  } else if (StringCaseEqual(name, HttpAttributes::kCacheControl)) {
    StringPieceVector pairs;
    SplitStringPieceToVector(trimmed_value, ",", &pairs,
                             true /* omit_empty_strings */);
    for (int i = 0, n = pairs.size(); i < n; ++i) {
      TrimWhitespace(&pairs[i]);
      if (pairs[i] == "no-transform") {
        // TODO(jmarantz): A .pagespeed resource should return un-optimized
        // content with "Cache-Control: no-transform".
        options->set_enabled(RewriteOptions::kEnabledStandby);
        status = kSuccess;
        break;
      }
    }
  } else if (name.starts_with(kModPagespeed) || name.starts_with(kPageSpeed)) {
    // Remove the initial ModPagespeed or PageSpeed.
    StringPiece name_suffix = name;
    stringpiece_ssize_type prefix_len;
    if (name.starts_with(kModPagespeed)) {
      prefix_len = sizeof(kModPagespeed)-1;
    } else {
      prefix_len = sizeof(kPageSpeed)-1;
    }
    name_suffix.remove_prefix(prefix_len);
    switch (options->SetOptionFromQuery(name_suffix, trimmed_value)) {
      case RewriteOptions::kOptionOk:
        status = kSuccess;
        break;
      case RewriteOptions::kOptionNameUnknown:
        if (request_context.get() != NULL &&
            StringCaseEqual(name_suffix,
                            RewriteOptions::kStickyQueryParameters)) {
          request_context->set_sticky_query_parameters_token(trimmed_value);
          status = kSuccess;
        } else {
          status = kNoneFound;
        }
        break;
      case RewriteOptions::kOptionValueInvalid:
        status = kInvalid;
        break;
    }
  }
  return status;
}

// In some environments it is desirable to bind a URL to the options
// that affect it.  One example of where this would be needed is if
// images are served by a separate cluster that doesn't share the same
// configuration as the mod_pagespeed instances that rewrote the HTML.
// In this case, we must encode the relevant options as query-params
// to be appended to the URL.  These should be decodable by Scan()
// above, though they don't need to be in the same verbose format that
// we document for debugging and experimentation.  They can use the
// more concise abbreviations of 2-4 letters for each option.
GoogleString RewriteQuery::GenerateResourceOption(
    StringPiece filter_id, RewriteDriver* driver) {
  const RewriteFilter* filter = driver->FindFilter(filter_id);
  // TODO(sligocki): We do not seem to be detecting Apache crashes in the
  // system_test. We should detect and fail when these crashes occur.
  CHECK(filter != NULL)
      << "Filter ID " << filter_id << " is not registered in RewriteDriver. "
      << "You must register it with a call to RegisterRewriteFilter() in "
      << "RewriteDriver::SetServerContext().";
  StringPiece prefix("");
  GoogleString value;
  const RewriteOptions* options = driver->options();

  // All the filters & options will be encoded into the value of a
  // single query param with name kAddQueryFromOptionName ("PsolOpt").
  // The value will have the comma-separated filters IDs, and option IDs,
  // which are all given a 2-4 letter codes.  The only difference between
  // options & filters syntactically is that options have values preceded
  // by a colon:
  //   filter1,filter2,filter3,option1:value1,option2:value2

  // Add any relevant enabled filters.
  int num_filters;
  const RewriteOptions::Filter* filters = filter->RelatedFilters(&num_filters);
  for (int i = 0; i < num_filters; ++i) {
    RewriteOptions::Filter filter_enum = filters[i];
    if (options->Enabled(filter_enum)) {
      StrAppend(&value, prefix, RewriteOptions::FilterId(filter_enum));
      prefix = kResourceFilterSeparator;
    }
  }

  // Add any non-default options.
  GoogleString option_value;
  const StringPieceVector* opts = filter->RelatedOptions();
  for (int i = 0, n = (opts == NULL ? 0 : opts->size()); i < n; ++i) {
    StringPiece option = (*opts)[i];
    const char* id;
    bool was_set = false;
    if (options->OptionValue(option, &id, &was_set, &option_value) && was_set) {
      StrAppend(&value, prefix, id, kResourceOptionValueSeparator,
                option_value);
      prefix = kResourceFilterSeparator;
    }
  }
  return value;
}

RewriteQuery::Status RewriteQuery::ParseResourceOption(
    StringPiece value, RewriteOptions* options, const RewriteFilter* filter) {
  Status status = kNoneFound;
  StringPieceVector filters_and_options;
  SplitStringPieceToVector(value, kResourceFilterSeparator,
                           &filters_and_options, true);

  // We will want to validate any filters & options we are trying to set
  // with this mechanism against the whitelist of whatever the filter thinks is
  // needed.  But do this lazily.
  int num_filters;
  const RewriteOptions::Filter* filters = filter->RelatedFilters(&num_filters);
  const StringPieceVector* opts = filter->RelatedOptions();

  for (int i = 0, n = filters_and_options.size(); i < n; ++i) {
    StringPieceVector name_value;
    SplitStringPieceToVector(filters_and_options[i],
                             kResourceOptionValueSeparator, &name_value, true);
    switch (name_value.size()) {
      case 1: {
        RewriteOptions::Filter filter_enum =
            RewriteOptions::LookupFilterById(name_value[0]);
        if ((filter_enum == RewriteOptions::kEndOfFilters) ||
            !std::binary_search(filters, filters + num_filters, filter_enum)) {
          status = kInvalid;
        } else {
          options->EnableFilter(filter_enum);
          status = kSuccess;
        }
        break;
      }
      case 2: {
        StringPiece option_name =
            RewriteOptions::LookupOptionNameById(name_value[0]);
        if (!option_name.empty() &&
            opts != NULL &&
            std::binary_search(opts->begin(), opts->end(), option_name) &&
            options->SetOptionFromName(option_name, name_value[1])
            == RewriteOptions::kOptionOk) {
          status = kSuccess;
        } else {
          status = kInvalid;
        }
        break;
      }
      default:
        status = kInvalid;
    }
  }
  options->SetRewriteLevel(RewriteOptions::kPassThrough);
  options->DisableAllFiltersNotExplicitlyEnabled();
  return status;
}

bool RewriteQuery::ParseProxyMode(
    const GoogleString* mode_name, ProxyMode* mode) {
  int mode_value = 0;
  if (mode_name != NULL &&
      !mode_name->empty() &&
      StringToInt(*mode_name, &mode_value) &&
      mode_value >= kProxyModeDefault &&
      mode_value <= kProxyModeNoTransform) {
    *mode = static_cast<ProxyMode>(mode_value);
    return true;
  }
  return false;
}

bool RewriteQuery::ParseImageQualityPreference(
    const GoogleString* preference_value,
    DeviceProperties::ImageQualityPreference* preference) {
  int value = 0;
  if (preference_value != NULL &&
      !preference_value->empty() &&
      StringToInt(*preference_value, &value) &&
      value >= DeviceProperties::kImageQualityDefault &&
      value <= DeviceProperties::kImageQualityHigh) {
    *preference = static_cast<DeviceProperties::ImageQualityPreference>(value);
    return true;
  }
  return false;
}

bool RewriteQuery::ParseClientOptions(
    const StringPiece& client_options, ProxyMode* proxy_mode,
    DeviceProperties::ImageQualityPreference* image_quality_preference) {
  StringMultiMapSensitive options;
  options.AddFromNameValuePairs(
      client_options, kProxyOptionSeparator, kProxyOptionValueSeparator,
      true);

  const GoogleString* version_value = options.Lookup1(kProxyOptionVersion);
  // We only support version value of kProxyOptionValidVersionValue for now.
  // New supported version might be added later.
  if (version_value != NULL &&
      *version_value == kProxyOptionValidVersionValue) {
    *proxy_mode = kProxyModeDefault;
    *image_quality_preference = DeviceProperties::kImageQualityDefault;
    ParseProxyMode(options.Lookup1(kProxyOptionMode), proxy_mode);

    if (*proxy_mode == kProxyModeDefault) {
      ParseImageQualityPreference(
          options.Lookup1(kProxyOptionImageQualityPreference),
          image_quality_preference);
    }
    return true;
  }
  return false;
}

bool RewriteQuery::UpdateRewriteOptionsWithClientOptions(
    StringPiece client_options, RequestProperties* request_properties,
    RewriteOptions* options) {
  ProxyMode proxy_mode = kProxyModeDefault;
  DeviceProperties::ImageQualityPreference quality_preference =
      DeviceProperties::kImageQualityDefault;
  if (!ParseClientOptions(client_options, &proxy_mode, &quality_preference)) {
    return false;
  }

  if (proxy_mode == kProxyModeNoTransform) {
    options->DisableAllFilters();
    return true;
  } else if (proxy_mode == kProxyModeNoImageTransform) {
    ImageRewriteFilter::DisableRelatedFilters(options);
    return true;
  } else if (proxy_mode == kProxyModeDefault) {
    return false;
  }
  DCHECK(false);
  return false;
}

}  // namespace net_instaweb
