Ejemplo n.º 1
0
static int
http_handle_host_header(http_t *ctx, const char *name, char *value)
{
  char *ep;

  RUNTIME_ASSERT(ctx);
  RUNTIME_ASSERT(name);
  RUNTIME_ASSERT(value);
 
  if ('\0' != value[0]) {
    ep = http_parse_host(value);
    if (!ep) {
      goto bad_host;
    }
  } else {
    ep = value;
  }

  if (':' != *ep) {
    ctx->port = 0;
  } else {
    ep++;
    if (!parse_port_number(ep, &ctx->port, &ep)) {
      http_set_status(ctx, 400, "Bad Request (Bad Port)");
      return -1;
    }
  }

  ep = skip_spaces(ep);
  if ('\0' != *ep) {
    goto bad_host;
  }

  http_set_host(ctx, value);

  return 0;

bad_host:
  
  http_set_status(ctx, 400, "Bad Request (Bad Host)");
  return -1;
}
Ejemplo n.º 2
0
int
http_parser_parse_uri(const char *buf, size_t buflen, int is_connect,
                      struct http_parser_uri *u)
{
  enum state s;
  const char *p;
  enum http_parser_uri_fields uf, old_uf;
  int found_at = 0;

  u->port = u->field_set = 0;
  s = is_connect ? s_req_server_start : s_req_spaces_before_url;
  old_uf = URI_FLD_MAX;

  for (p = buf; p < buf + buflen; p++) {
    s = parse_url_char(s, *p);

    /* Figure out the next field that we're operating on */
    switch (s) {
      case s_dead:
        return 1;

      /* Skip delimeters */
      case s_req_schema_slash:
      case s_req_schema_slash_slash:
      case s_req_server_start:
      case s_req_query_string_start:
      case s_req_fragment_start:
        continue;

      case s_req_schema:
        uf = URI_FLD_SCHEMA;
        break;

      case s_req_server_with_at:
        found_at = 1;

      /* FALLTROUGH */
      case s_req_server:
        uf = URI_FLD_HOST;
        break;

      case s_req_path:
        uf = URI_FLD_PATH;
        break;

      case s_req_query_string:
        uf = URI_FLD_QUERY;
        break;

      case s_req_fragment:
        uf = URI_FLD_FRAGMENT;
        break;

      default:
        assert(!"Unexpected state");
        return 1;
    }

    /* Nothing's changed; soldier on */
    if (uf == old_uf) {
      u->field_data[uf].len++;
      continue;
    }

    u->field_data[uf].off = p - buf;
    u->field_data[uf].len = 1;

    u->field_set |= (1 << uf);
    old_uf = uf;
  }

  /* host must be present if there is a schema */
  /* parsing http:///toto will fail */
  if ((u->field_set & (1 << URI_FLD_SCHEMA)) &&
      (u->field_set & (1 << URI_FLD_HOST)) == 0) {
    return 1;
  }

  if (u->field_set & (1 << URI_FLD_HOST)) {
    if (http_parse_host(buf, u, found_at) != 0) {
      return 1;
    }
  }

  /* CONNECT requests can only contain "hostname:port" */
  if (is_connect && u->field_set != ((1 << URI_FLD_HOST)|(1 << URI_FLD_PORT))) {
    return 1;
  }

  if (u->field_set & (1 << URI_FLD_PORT)) {
    /* Don't bother with endp; we've already validated the string */
    unsigned long v = strtoul(buf + u->field_data[URI_FLD_PORT].off, NULL, 10);

    /* Ports have a max value of 2^16 */
    if (v > 0xffff) {
      return 1;
    }

    u->port = (uint16_t) v;
  }

  return 0;
}