Branch: Tag:

2018-03-27

2018-03-27 14:50:59 by Henrik Grubbström (Grubba) <grubba@grubba.org>

RequestID: Fixed parsing of if-header.

The parser should now be RFC 4918-compliant.

1846:    //! the first is one of the strings @expr{"not"@}, @expr{"etag"@},    //! or @expr{"key"@}, and the second is the value.    //! -  //! The resource @expr{0@} (zero) represents the default resource. +  //! There is an implicit @b{OR@} between sub-conditions +  //! (cf @rfc{4918:10.4.6@}), and an implicit @b{AND@} +  //! between the elements in a sub-condition. +  //! +  //! The default resource is mapped to @[not_query]. +  //! +  //! As @rfc{4918:10.4.1@} states that the mere fact that a state +  //! token appears in an If header means that it has been submitted, +  //! we as a convenience add all non-negated lock tokens to the +  //! @expr{0@} resource. +  //! +  //! @seealso +  //! @rfc{4918:10.4.2@}    mapping(string:array(array(array(string)))) get_if_data()    {    if (if_data) {
1874:    return 0;    }    -  mapping(string:array(array(array(string)))) res = ([ 0: ({}) ]); +  mapping(string:array(array(array(string)))) res = ([ +  0:({}), +  ]);    -  +  array(string) keys = ({});    string tmp_resource; -  string resource; +  string resource = not_query;    foreach(decoded_if, array(string|int|array(array(string))) symbol) {    switch (symbol[0]) {    case "special":
1889:    // Normalize.    // FIXME: Check that the protocol and server parts refer    // to this server. +  // NB: Above invalid according to rfc 4918 8.3. +  // +  // NB: RFC 4918 8.3 adds support for path-absolute resources. +  // NB: The resource reference may have a query section. +  //    // FIXME: Support for servers mounted on subpaths.    catch { resource = Standards.URI(resource)->path; }; -  if (!sizeof(resource) || (resource[-1] != '/')) resource += "/"; +  catch { resource = Protocols.HTTP.percent_decode(resource); }; +  catch { resource = utf8_to_string(resource); }; +  resource = Unicode.normalize(resource, "NFC"); +  if (!sizeof(resource)) resource = "/";    if (!res[resource])    res[resource] = ({});    break;
1928:    IF_HDR_MSG("No tmp_key.\n");    return 0;    } +  if (!sizeof(expr) || (expr[-1][0] != "not")) { +  keys += ({ tmp_key }); +  }    expr += ({ ({ "key", tmp_key }) });    tmp_key = 0;    break;
1955:    }    if (lower_case(sub_expr[i][1]) == "not") {    // Not +  if (sizeof(expr) && (expr[-1][0] == "not")) { +  IF_HDR_MSG("Double negation."); +  report_debug("Syntax error in if-header: %O\n", raw_header); +  return 0; +  }    expr += ({ ({ "not", 0 }) });    break;    }
1975:    return 0;    }    } +  if (sizeof(keys)) { +  res[0] = ({ +  map(keys, lambda(string key) { +  return ({ "key", key }); +  }), +  }); +  }    if (tmp_resource) {    IF_HDR_MSG("Active tmp_resource: %O\n", tmp_resource);    report_debug("Syntax error in if-header: %O\n", raw_header);