static const char *start_if_define_extended(cmd_parms * cmd, void *dummy,
                                            const char *arg)
{
    const char *endp;
    char *expr;
    int define;
    int not = 0;

    endp = ap_strrchr_c(arg, '>');
    if (endp == NULL) {
        return (const char *) apr_pstrcat(cmd->pool, cmd->cmd->name,
                                          "> directive missing closing '>'",
                                          NULL);
    }

    expr = apr_pstrndup(cmd->temp_pool, arg, endp - arg);
    if (expr[0] == '!') {
        not = 1;
        expr++;
    }

    define = is_define(cmd, expr);
    if ((!not && define) || (not && !define)) {
        ap_directive_t *parent = NULL;
        ap_directive_t *current = NULL;
        const char *retval;

        retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
                                      &current, &parent, "<IfDefineExtended");
        *(ap_directive_t **) dummy = current;
        return retval;
    }
    else {
        *(ap_directive_t **) dummy = NULL;
        return ap_soak_end_container(cmd, "<IfDefineExtended");
    }
}
Пример #2
0
/*
 * Implements the <IfVersion> container
 */
static const char *start_ifversion(cmd_parms *cmd, void *mconfig,
                                   const char *arg1, const char *arg2,
                                   const char *arg3)
{
    const char *endp;
    int reverse = 0, done = 0, match = 0, compare;
    const char *p, *error;
    char c;

    /* supplying one argument is possible, we assume an equality check then */
    if (!arg2) {
        arg2 = arg1;
        arg1 = "=";
    }

    /* surrounding quotes without operator */
    if (!arg3 && *arg2 == '>' && !arg2[1]) {
        arg3 = ">";
        arg2 = arg1;
        arg1 = "=";
    }

    /* the third argument makes version surrounding quotes plus operator
     * possible.
     */
    endp = arg2 + strlen(arg2);
    if (   endp == arg2
        || (!(arg3 && *arg3 == '>' && !arg3[1]) && *--endp != '>')) {
        return apr_pstrcat(cmd->pool, cmd->cmd->name,
                           "> directive missing closing '>'", NULL);
    }

    p = arg1;
    if (*p == '!') {
        reverse = 1;
        if (p[1]) {
            ++p;
        }
    }

    c = *p++;
    if (!*p || (*p == '=' && !p[1] && c != '~')) {
        if (!httpd_version.major) {
            ap_get_server_revision(&httpd_version);
        }

        done = 1;
        switch (c) {
        case '=':
            /* normal comparison */
            if (*arg2 != '/') {
                compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
                                                         endp-arg2),
                                          &error);
                if (error) {
                    return error;
                }

                match = !compare;
                break;
            }

            /* regexp otherwise */
            if (endp == ++arg2 || *--endp != '/') {
                return "Missing delimiting / of regular expression.";
            }

        case '~':
            /* regular expression */
            match = match_version(cmd->pool, apr_pstrmemdup(cmd->pool, arg2,
                                                            endp-arg2),
                                  &error);
            if (error) {
                return error;
            }
            break;

        case '<':
            compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
                                                     endp-arg2),
                                      &error);
            if (error) {
                return error;
            }

            match = ((-1 == compare) || (*p && !compare));
            break;

        case '>':
            compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
                                                     endp-arg2),
                                      &error);
            if (error) {
                return error;
            }

            match = ((1 == compare) || (*p && !compare));
            break;

        default:
            done = 0;
            break;
        }
    }

    if (!done) {
        return apr_pstrcat(cmd->pool, "unrecognized operator '", arg1, "'",
                           NULL);
    }

    if ((!reverse && match) || (reverse && !match)) {
        ap_directive_t *parent = NULL;
        ap_directive_t *current = NULL;
        const char *retval;

        retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
                                      &current, &parent, "<IfVersion");
        *(ap_directive_t **)mconfig = current;
        return retval;
    }

    *(ap_directive_t **)mconfig = NULL;
    return ap_soak_end_container(cmd, "<IfVersion");
}