Exemple #1
0
int
vsf_access_check_file_visible(const struct mystr* p_filename_str)
{
  static struct mystr s_access_str;

  if (!tunable_hide_file)
  {
    return 1;
  }
  if (str_isempty(&s_access_str))
  {
    str_alloc_text(&s_access_str, tunable_hide_file);
  }
  if (vsf_filename_passes_filter(p_filename_str, &s_access_str))
  {
    return 0;
  }
  else
  {
    struct str_locate_result loc_res =
      str_locate_str(p_filename_str, &s_access_str);
    if (loc_res.found)
    {
      return 0;
    }
  }
  return 1;
}
Exemple #2
0
int
vsf_filename_passes_filter(const struct mystr* p_filename_str,
                           const struct mystr* p_filter_str,
                           unsigned int* iters)
{
    /* A simple routine to match a filename against a pattern.
     * This routine is used instead of e.g. fnmatch(3), because we should be
     * reluctant to trust the latter. fnmatch(3) involves _lots_ of string
     * parsing and handling. There is broad potential for any given fnmatch(3)
     * implementation to be buggy.
     *
     * Currently supported pattern(s):
     * - any number of wildcards, "*" or "?"
     * - {,} syntax (not nested)
     *
     * Note that pattern matching is only supported within the last path
     * component. For example, searching for /a/b/? will work, but searching
     * for /a/?/c will not.
     */
    struct mystr filter_remain_str = INIT_MYSTR;
    struct mystr name_remain_str = INIT_MYSTR;
    struct mystr temp_str = INIT_MYSTR;
    struct mystr brace_list_str = INIT_MYSTR;
    struct mystr new_filter_str = INIT_MYSTR;
    int ret = 0;
    char last_token = 0;
    int must_match_at_current_pos = 1;
    str_copy(&filter_remain_str, p_filter_str);
    str_copy(&name_remain_str, p_filename_str);

    while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX)
    {
        static struct mystr s_match_needed_str;
        /* Locate next special token */
        struct str_locate_result locate_result =
            str_locate_chars(&filter_remain_str, "*?{");
        (*iters)++;
        /* Isolate text leading up to token (if any) - needs to be matched */
        if (locate_result.found)
        {
            unsigned int indexx = locate_result.index;
            str_left(&filter_remain_str, &s_match_needed_str, indexx);
            str_mid_to_end(&filter_remain_str, &temp_str, indexx + 1);
            str_copy(&filter_remain_str, &temp_str);
            last_token = locate_result.char_found;
        }
        else
        {
            /* No more tokens. Must match remaining filter string exactly. */
            str_copy(&s_match_needed_str, &filter_remain_str);
            str_empty(&filter_remain_str);
            last_token = 0;
        }
        if (!str_isempty(&s_match_needed_str))
        {
            /* Need to match something.. could be a match which has to start at
             * current position, or we could allow it to start anywhere
             */
            unsigned int indexx;
            locate_result = str_locate_str(&name_remain_str, &s_match_needed_str);
            if (!locate_result.found)
            {
                /* Fail */
                goto out;
            }
            indexx = locate_result.index;
            if (must_match_at_current_pos && indexx > 0)
            {
                goto out;
            }
            /* Chop matched string out of remainder */
            str_mid_to_end(&name_remain_str, &temp_str,
                           indexx + str_getlen(&s_match_needed_str));
            str_copy(&name_remain_str, &temp_str);
        }
        if (last_token == '?')
        {
            if (str_isempty(&name_remain_str))
            {
                goto out;
            }
            str_right(&name_remain_str, &temp_str, str_getlen(&name_remain_str) - 1);
            str_copy(&name_remain_str, &temp_str);
            must_match_at_current_pos = 1;
        }
        else if (last_token == '{')
        {
            struct str_locate_result end_brace =
                str_locate_char(&filter_remain_str, '}');
            must_match_at_current_pos = 1;
            if (end_brace.found)
            {
                str_split_char(&filter_remain_str, &temp_str, '}');
                str_copy(&brace_list_str, &filter_remain_str);
                str_copy(&filter_remain_str, &temp_str);
                str_split_char(&brace_list_str, &temp_str, ',');
                while (!str_isempty(&brace_list_str))
                {
                    str_copy(&new_filter_str, &brace_list_str);
                    str_append_str(&new_filter_str, &filter_remain_str);
                    if (vsf_filename_passes_filter(&name_remain_str, &new_filter_str,
                                                   iters))
                    {
                        ret = 1;
                        goto out;
                    }
                    str_copy(&brace_list_str, &temp_str);
                    str_split_char(&brace_list_str, &temp_str, ',');
                }
                goto out;
            }
            else if (str_isempty(&name_remain_str) ||
                     str_get_char_at(&name_remain_str, 0) != '{')
            {
                goto out;
            }
            else
            {
                str_right(&name_remain_str, &temp_str,
                          str_getlen(&name_remain_str) - 1);
                str_copy(&name_remain_str, &temp_str);
            }
        }
        else
        {
            must_match_at_current_pos = 0;
        }
    }
    /* Any incoming string left means no match unless we ended on the correct
     * type of wildcard.
     */
    if (str_getlen(&name_remain_str) > 0 && last_token != '*')
    {
        goto out;
    }
    /* OK, a match */
    ret = 1;
    if (*iters == VSFTP_MATCHITERS_MAX) {
        ret = 0;
    }
out:
    str_free(&filter_remain_str);
    str_free(&name_remain_str);
    str_free(&temp_str);
    str_free(&brace_list_str);
    str_free(&new_filter_str);
    return ret;
}