Example #1
0
static w_query_expr *suffix_parser(w_query *query, json_t *term)
{
  const char *ignore, *suffix;
  char *arg;
  w_string_t *str;
  int i, l;

  if (json_unpack(term, "[s,s]", &ignore, &suffix) != 0) {
    query->errmsg = strdup("must use [\"suffix\", \"suffixstring\"]");
    return NULL;
  }

  arg = strdup(suffix);
  if (!arg) {
    query->errmsg = strdup("out of memory");
    return NULL;
  }

  l = strlen_uint32(arg);
  for (i = 0; i < l; i++) {
    arg[i] = (char)tolower((uint8_t)arg[i]);
  }

  str = w_string_new_typed(arg, W_STRING_BYTE);
  free(arg);
  if (!str) {
    query->errmsg = strdup("out of memory");
    return NULL;
  }

  return w_query_expr_new(eval_suffix, dispose_suffix, str);
}
Example #2
0
static w_query_expr *match_parser(w_query *query,
    json_t *term, bool caseless)
{
  const char *ignore, *pattern, *scope = "basename";
  const char *which = caseless ? "imatch" : "match";
  struct match_data *data;

  if (json_unpack(term, "[s,s,s]", &ignore, &pattern, &scope) != 0 &&
      json_unpack(term, "[s,s]", &ignore, &pattern) != 0) {
    asprintf(&query->errmsg,
        "Expected [\"%s\", \"pattern\", \"scope\"?]",
        which);
    return NULL;
  }

  if (strcmp(scope, "basename") && strcmp(scope, "wholename")) {
    asprintf(&query->errmsg,
        "Invalid scope '%s' for %s expression",
        scope, which);
    return NULL;
  }

  data = malloc(sizeof(*data));
  data->pattern = strdup(pattern);
  data->caseless = caseless;
  data->wholename = !strcmp(scope, "wholename");

  return w_query_expr_new(eval_match, dispose_match, data);
}
Example #3
0
static w_query_expr *pcre_parser(w_query *query,
    json_t *term, bool caseless)
{
  const char *ignore, *pattern, *scope = "basename";
  const char *which = caseless ? "ipcre" : "pcre";
  struct match_pcre *data;
  pcre *re;
  const char *errptr = NULL;
  int erroff = 0;
  int errcode = 0;

  if (json_unpack(term, "[s,s,s]", &ignore, &pattern, &scope) != 0 &&
      json_unpack(term, "[s,s]", &ignore, &pattern) != 0) {
    asprintf(&query->errmsg,
        "Expected [\"%s\", \"pattern\", \"scope\"?]",
        which);
    return NULL;
  }

  if (strcmp(scope, "basename") && strcmp(scope, "wholename")) {
    asprintf(&query->errmsg,
        "Invalid scope '%s' for %s expression",
        scope, which);
    return NULL;
  }

  re = pcre_compile2(pattern, caseless ? PCRE_CASELESS : 0,
        &errcode, &errptr, &erroff, NULL);
  if (!re) {
    asprintf(&query->errmsg,
      "invalid %s: code %d %s at offset %d in %s",
      which, errcode, errptr, erroff, pattern);
    return NULL;
  }

  data = malloc(sizeof(*data));
  data->re = re;
  data->extra = pcre_study(re, 0, &errptr);
  data->wholename = !strcmp(scope, "wholename");

  return w_query_expr_new(eval_pcre, dispose_pcre, data);
}
Example #4
0
static w_query_expr *not_parser(w_query *query, json_t *term)
{
    json_t *other;
    w_query_expr *other_expr;

    /* rigidly require ["not", expr] */
    if (!json_is_array(term) || json_array_size(term) != 2) {
        query->errmsg = strdup("must use [\"not\", expr]");
        return NULL;
    }

    other = json_array_get(term, 1);
    other_expr = w_query_expr_parse(query, other);
    if (!other_expr) {
        // other expr sets errmsg
        return NULL;
    }

    return w_query_expr_new(eval_not, dispose_expr, other_expr);
}
Example #5
0
static w_query_expr *size_parser(w_query *query, json_t *term) {
  struct w_query_int_compare *comp;

  if (!json_is_array(term)) {
    ignore_result(asprintf(&query->errmsg, "Expected array for 'size' term"));
    return NULL;
  }

  comp = calloc(1, sizeof(*comp));
  if (!comp) {
    ignore_result(asprintf(&query->errmsg, "out of memory"));
    return NULL;
  }

  if (!parse_int_compare(term, comp, &query->errmsg)) {
    free(comp);
    return NULL;
  }

  return w_query_expr_new(eval_size, free, comp);
}
Example #6
0
static w_query_expr *type_parser(w_query *query, json_t *term)
{
  const char *ignore, *typestr, *found;
  intptr_t arg;

  if (json_unpack(term, "[s,s]", &ignore, &typestr) != 0) {
    query->errmsg = strdup("must use [\"type\", \"typestr\"]");
    return NULL;
  }

  found = strpbrk(typestr, "bcdfplsD");
  if (!found || strlen(typestr) > 1) {
    ignore_result(asprintf(&query->errmsg, "invalid type string '%s'",
        typestr));
    return NULL;
  }

  arg = *found;

  return w_query_expr_new(eval_type, dispose_type, (void*)arg);
}
Example #7
0
static w_query_expr *parse_list(w_query *query, json_t *term, bool allof)
{
    struct w_expr_list *list;
    size_t i;

    /* don't allow "allof" on its own */
    if (!json_is_array(term) || json_array_size(term) < 2) {
        query->errmsg = strdup("must use [\"allof\", expr...]");
        return NULL;
    }

    list = calloc(1, sizeof(*list));
    if (!list) {
        query->errmsg = strdup("out of memory");
        return NULL;
    }

    list->allof = allof;
    list->num = json_array_size(term) - 1;
    list->exprs = calloc(list->num, sizeof(list->exprs[0]));

    for (i = 0; i < list->num; i++) {
        w_query_expr *parsed;
        json_t *exp = json_array_get(term, i + 1);

        parsed = w_query_expr_parse(query, exp);
        if (!parsed) {
            // other expression parser sets errmsg
            dispose_list(list);
            return NULL;
        }

        list->exprs[i] = parsed;
    }

    return w_query_expr_new(eval_list, dispose_list, list);
}
Example #8
0
// ["dirname", "foo"] -> ["dirname", "foo", ["depth", "ge", 0]]
static w_query_expr *dirname_parser_inner(w_query *query, json_t *term,
        bool caseless)
{
    const char *which = caseless ? "idirname" : "dirname";
    struct dirname_data *data;
    json_t *name;
    struct w_query_int_compare depth_comp;

    if (!json_is_array(term)) {
        ignore_result(asprintf(&query->errmsg, "Expected array for '%s' term",
                               which));
        return NULL;
    }

    if (json_array_size(term) < 2) {
        ignore_result(asprintf(&query->errmsg,
                               "Invalid number of arguments for '%s' term",
                               which));
        return NULL;
    }

    if (json_array_size(term) > 3) {
        ignore_result(asprintf(&query->errmsg,
                               "Invalid number of arguments for '%s' term",
                               which));
        return NULL;
    }

    name = json_array_get(term, 1);
    if (!json_is_string(name)) {
        ignore_result(asprintf(&query->errmsg,
                               "Argument 2 to '%s' must be a string", which));
        return NULL;
    }

    if (json_array_size(term) == 3) {
        json_t *depth;

        depth = json_array_get(term, 2);
        if (!json_is_array(depth)) {
            ignore_result(asprintf(&query->errmsg,
                                   "Invalid number of arguments for '%s' term",
                                   which));
            return NULL;
        }

        if (!parse_int_compare(depth, &depth_comp, &query->errmsg)) {
            return NULL;
        }

        if (strcmp("depth", json_string_value(json_array_get(depth, 0)))) {
            ignore_result(asprintf(&query->errmsg,
                                   "Third parameter to '%s' should be a relational depth term",
                                   which));
            return NULL;
        }
    } else {
        depth_comp.operand = 0;
        depth_comp.op = W_QUERY_ICMP_GE;
    }

    data = calloc(1, sizeof(*data));
    if (!data) {
        ignore_result(asprintf(&query->errmsg, "out of memory"));
        return NULL;
    }
    data->dirname = w_string_new(json_string_value(name));
    data->startswith =
        caseless ?  w_string_startswith_caseless : w_string_startswith;
    data->depth = depth_comp;

    return w_query_expr_new(eval_dirname, dispose_dirname, data);
}
Example #9
0
static w_query_expr *false_parser(w_query *query, json_t *term)
{
    unused_parameter(term);
    unused_parameter(query);
    return w_query_expr_new(eval_bool, NULL, 0);
}
Example #10
0
static w_query_expr *true_parser(w_query *query, json_t *term)
{
    unused_parameter(term);
    unused_parameter(query);
    return w_query_expr_new(eval_bool, NULL, (void*)1);
}
Example #11
0
w_query_expr *w_expr_since_parser(w_query *query, json_t *term)
{
  json_t *jval;

  struct w_clockspec *spec;
  struct since_term *sterm;
  int selected_field = SINCE_OCLOCK;
  const char *fieldname = "oclock";

  if (!json_is_array(term)) {
    query->errmsg = strdup("\"since\" term must be an array");
    return NULL;
  }

  if (json_array_size(term) < 2 || json_array_size(term) > 3) {
    query->errmsg = strdup("\"since\" term has invalid number of parameters");
    return NULL;
  }

  jval = json_array_get(term, 1);
  spec = w_clockspec_parse(jval);
  if (!spec) {
    query->errmsg = strdup("invalid clockspec for \"since\" term");
    return NULL;
  }
  if (spec->tag == w_cs_named_cursor) {
    query->errmsg = strdup("named cursors are not allowed in \"since\" terms");
    goto fail;
  }

  jval = json_array_get(term, 2);
  if (jval) {
    int i;
    bool valid = false;

    fieldname = json_string_value(jval);
    if (!fieldname) {
      query->errmsg = strdup("field name for \"since\" term must be a string");
      goto fail;
    }

    for (i = 0; allowed_fields[i].label; i++) {
      if (!strcmp(allowed_fields[i].label, fieldname)) {
        selected_field = allowed_fields[i].value;
        valid = true;
        break;
      }
    }

    if (!valid) {
      ignore_result(asprintf(&query->errmsg,
          "invalid field name \"%s\" for \"since\" term",
          fieldname));
      goto fail;
    }
  }

  switch (selected_field) {
    case SINCE_CTIME:
    case SINCE_MTIME:
      if (spec->tag != w_cs_timestamp) {
        ignore_result(asprintf(&query->errmsg,
            "field \"%s\" requires a timestamp value "
            "for comparison in \"since\" term",
            fieldname));
        goto fail;
      }
      break;
    case SINCE_OCLOCK:
    case SINCE_CCLOCK:
      /* we'll work with clocks or timestamps */
      break;
  }

  sterm = calloc(1, sizeof(*sterm));
  if (!sterm) {
    query->errmsg = strdup("out of memory");
    goto fail;
  }

  sterm->spec = spec;
  sterm->field = selected_field;

  return w_query_expr_new(eval_since, dispose_since, sterm);

fail:
  w_clockspec_free(spec);
  return NULL;
}
Example #12
0
static w_query_expr *name_parser(w_query *query,
    json_t *term, bool caseless)
{
  const char *pattern = NULL, *scope = "basename";
  const char *which = caseless ? "iname" : "name";
  struct name_data *data;
  json_t *name;
  w_ht_t *map = NULL;

  if (!json_is_array(term)) {
    ignore_result(asprintf(&query->errmsg, "Expected array for '%s' term",
        which));
    return NULL;
  }

  if (json_array_size(term) > 3) {
    ignore_result(asprintf(&query->errmsg,
        "Invalid number of arguments for '%s' term",
        which));
    return NULL;
  }

  if (json_array_size(term) == 3) {
    json_t *jscope;

    jscope = json_array_get(term, 2);
    if (!json_is_string(jscope)) {
      ignore_result(asprintf(&query->errmsg,
          "Argument 3 to '%s' must be a string",
          which));
      return NULL;
    }

    scope = json_string_value(jscope);

    if (strcmp(scope, "basename") && strcmp(scope, "wholename")) {
      ignore_result(asprintf(&query->errmsg,
          "Invalid scope '%s' for %s expression",
          scope, which));
      return NULL;
    }
  }

  name = json_array_get(term, 1);

  if (json_is_array(name)) {
    uint32_t i;

    for (i = 0; i < json_array_size(name); i++) {
      if (!json_is_string(json_array_get(name, i))) {
        ignore_result(asprintf(&query->errmsg,
          "Argument 2 to '%s' must be either a string or an array of string",
          which));
        return NULL;
      }
    }

    map = w_ht_new(json_array_size(name), &w_ht_string_funcs);
    for (i = 0; i < json_array_size(name); i++) {
      w_string_t *element;
      const char *ele;

      ele = json_string_value(json_array_get(name, i));
      if (caseless) {
        element = w_string_new_lower(ele);
      } else {
        element = w_string_new(ele);
      }

      w_ht_set(map, w_ht_ptr_val(element), 1);
      w_string_delref(element);
    }

  } else if (json_is_string(name)) {
    pattern = json_string_value(name);
  } else {
    ignore_result(asprintf(&query->errmsg,
        "Argument 2 to '%s' must be either a string or an array of string",
        which));
    return NULL;
  }


  data = calloc(1, sizeof(*data));
  if (pattern) {
    data->name = w_string_new(pattern);
  }
  data->map = map;
  data->caseless = caseless;
  data->wholename = !strcmp(scope, "wholename");

  return w_query_expr_new(eval_name, dispose_name, data);
}