コード例 #1
0
static apr_status_t parse_status_line(response_context_t *ctx,
                                      serf_bucket_alloc_t *allocator)
{
    int res;
    char *reason; /* ### stupid APR interface makes this non-const */

    /* ctx->linebuf.line should be of form: HTTP/1.1 200 OK */
    res = apr_date_checkmask(ctx->linebuf.line, "HTTP/#.# ###*");
    if (!res) {
        /* Not an HTTP response?  Well, at least we won't understand it. */
        return SERF_ERROR_BAD_HTTP_RESPONSE;
    }

    ctx->sl.version = SERF_HTTP_VERSION(ctx->linebuf.line[5] - '0',
                                        ctx->linebuf.line[7] - '0');
    ctx->sl.code = apr_strtoi64(ctx->linebuf.line + 8, &reason, 10);

    /* Skip leading spaces for the reason string. */
    if (apr_isspace(*reason)) {
        reason++;
    }

    /* Copy the reason value out of the line buffer. */
    ctx->sl.reason = serf_bstrmemdup(allocator, reason,
                                     ctx->linebuf.used
                                     - (reason - ctx->linebuf.line));

    return APR_SUCCESS;
}
コード例 #2
0
ファイル: mod_dav_rainx.c プロジェクト: korween/oio-sds
static const char *
dav_rainx_cmd_gridconfig_sock_timeout(cmd_parms *cmd, void *config, const char *arg1)
{
	dav_rainx_server_conf *conf;
	apr_int64_t socket_timeout;
	char *endstr;
	(void) config;

	DAV_XDEBUG_POOL(cmd->pool, 0, "%s()", __FUNCTION__);

	conf = ap_get_module_config(cmd->server->module_config, &dav_rainx_module);

	socket_timeout = apr_strtoi64(arg1, &endstr, 10);
	if (errno == 0 && *endstr == '\0')
	{
		conf->socket_timeout = socket_timeout;
	}
	else
	{
		DAV_ERROR_POOL(cmd->pool, 0, "Invalid socket timeout, default value will be used");
	}

	DAV_DEBUG_POOL(cmd->pool, 0,
			"Socket timeout for rawx request is %" APR_TIME_T_FMT " microseconds",
			conf->socket_timeout);
	
	return NULL;
}
コード例 #3
0
ファイル: string.c プロジェクト: 15375514460/TortoiseGit
svn_error_t *
svn_cstring_strtoi64(apr_int64_t *n, const char *str,
                     apr_int64_t minval, apr_int64_t maxval,
                     int base)
{
  apr_int64_t val;
  char *endptr;

  /* We assume errno is thread-safe. */
  errno = 0; /* APR-0.9 doesn't always set errno */

  val = apr_strtoi64(str, &endptr, base);
  if (errno == EINVAL || endptr == str || str[0] == '\0' || *endptr != '\0')
    return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
                             _("Could not convert '%s' into a number"),
                             str);
  if ((errno == ERANGE && (val == APR_INT64_MIN || val == APR_INT64_MAX)) ||
      val < minval || val > maxval)
    /* ### Mark this for translation when gettext doesn't choke on macros. */
    return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
                             "Number '%s' is out of range "
                             "'[%" APR_INT64_T_FMT ", %" APR_INT64_T_FMT "]'",
                             str, minval, maxval);
  *n = val;
  return SVN_NO_ERROR;
}
コード例 #4
0
ファイル: config.c プロジェクト: 2asoft/freebsd
svn_error_t*
svn_config_get_server_setting_int(svn_config_t *cfg,
                                  const char *server_group,
                                  const char *option_name,
                                  apr_int64_t default_value,
                                  apr_int64_t *result_value,
                                  apr_pool_t *pool)
{
  const char* tmp_value;
  char *end_pos;

  tmp_value = svn_config_get_server_setting(cfg, server_group,
                                            option_name, NULL);
  if (tmp_value == NULL)
    *result_value = default_value;
  else
    {
      /* read tmp_value as an int now */
      *result_value = apr_strtoi64(tmp_value, &end_pos, 0);

      if (*end_pos != 0)
        {
          return svn_error_createf
            (SVN_ERR_BAD_CONFIG_VALUE, NULL,
             _("Config error: invalid integer value '%s'"),
             tmp_value);
        }
    }

  return SVN_NO_ERROR;
}
コード例 #5
0
h2_response *h2_response_create(int stream_id,
                                const char *http_status,
                                apr_array_header_t *hlines,
                                apr_pool_t *pool)
{
    apr_table_t *header;
    h2_response *response = apr_pcalloc(pool, sizeof(h2_response));
    int i;
    if (response == NULL) {
        return NULL;
    }
    
    response->stream_id = stream_id;
    response->status = http_status;
    response->content_length = -1;
    
    if (hlines) {
        header = apr_table_make(pool, hlines->nelts);        
        for (i = 0; i < hlines->nelts; ++i) {
            char *hline = ((char **)hlines->elts)[i];
            char *sep = ap_strchr(hline, ':');
            if (!sep) {
                ap_log_perror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, pool,
                              APLOGNO(02955) "h2_response(%d): invalid header[%d] '%s'",
                              response->stream_id, i, (char*)hline);
                /* not valid format, abort */
                return NULL;
            }
            (*sep++) = '\0';
            while (*sep == ' ' || *sep == '\t') {
                ++sep;
            }
            if (ignore_header(hline)) {
                /* never forward, ch. 8.1.2.2 */
            }
            else {
                apr_table_merge(header, hline, sep);
                if (*sep && H2_HD_MATCH_LIT_CS("content-length", hline)) {
                    char *end;
                    response->content_length = apr_strtoi64(sep, &end, 10);
                    if (sep == end) {
                        ap_log_perror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, 
                                      pool, APLOGNO(02956) 
                                      "h2_response(%d): content-length"
                                      " value not parsed: %s", 
                                      response->stream_id, sep);
                        response->content_length = -1;
                    }
                }
            }
        }
    }
    else {
        header = apr_table_make(pool, 0);        
    }

    response->rheader = header;
    return response;
}
コード例 #6
0
ファイル: testpipe.c プロジェクト: AbrahamJewowich/FreeSWITCH
static void test_pipe_writefull(abts_case *tc, void *data)
{
    int iterations = 1000;
    int i;
    int bytes_per_iteration = 8000;
    char *buf = (char *)malloc(bytes_per_iteration);
    char responsebuf[128];
    apr_size_t nbytes;
    int bytes_processed;
    apr_proc_t proc = {0};
    apr_procattr_t *procattr;
    const char *args[2];
    apr_status_t rv;
    apr_exit_why_e why;
    
    rv = apr_procattr_create(&procattr, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK,
                             APR_CHILD_BLOCK);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    rv = apr_procattr_error_check_set(procattr, 1);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    args[0] = "readchild" EXTENSION;
    args[1] = NULL;
    rv = apr_proc_create(&proc, "./readchild" EXTENSION, args, NULL, procattr, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    rv = apr_file_pipe_timeout_set(proc.in, apr_time_from_sec(10));
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    rv = apr_file_pipe_timeout_set(proc.out, apr_time_from_sec(10));
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    i = iterations;
    do {
        rv = apr_file_write_full(proc.in, buf, bytes_per_iteration, NULL);
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    } while (--i);

    free(buf);

    rv = apr_file_close(proc.in);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    
    nbytes = sizeof(responsebuf);
    rv = apr_file_read(proc.out, responsebuf, &nbytes);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    bytes_processed = (int)apr_strtoi64(responsebuf, NULL, 10);
    ABTS_INT_EQUAL(tc, iterations * bytes_per_iteration, bytes_processed);

    ABTS_ASSERT(tc, "wait for child process",
             apr_proc_wait(&proc, NULL, &why, APR_WAIT) == APR_CHILD_DONE);
    
    ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT);
}
コード例 #7
0
ファイル: mod_dims_ops.c プロジェクト: jzastrow/mod_dims
apr_status_t
dims_quality_operation (dims_request_rec *d, char *args, char **err) {
    int quality = apr_strtoi64(args, NULL, 0);
    int existing_quality = MagickGetImageCompressionQuality(d->wand);

    if(existing_quality == 0 || quality < existing_quality) {
        MAGICK_CHECK(MagickSetImageCompressionQuality(d->wand, quality), d);
    }
    return DIMS_SUCCESS;
}
コード例 #8
0
ファイル: testpipe.c プロジェクト: kheradmand/Break
static void test_pipe_writefull(CuTest *tc)
{
    int iterations = 1000;
    int i;
    int bytes_per_iteration = 8000;
    char *buf = (char *)malloc(bytes_per_iteration);
    char responsebuf[128];
    apr_size_t nbytes;
    int bytes_processed;
    apr_proc_t proc = {0};
    apr_procattr_t *procattr;
    const char *args[2];
    apr_status_t rv;
    
    rv = apr_procattr_create(&procattr, p);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK,
                             APR_CHILD_BLOCK);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_procattr_error_check_set(procattr, 1);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    args[0] = "readchild" EXTENSION;
    args[1] = NULL;
    rv = apr_proc_create(&proc, "./readchild" EXTENSION, args, NULL, procattr, p);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_file_pipe_timeout_set(proc.in, apr_time_from_sec(10));
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_file_pipe_timeout_set(proc.out, apr_time_from_sec(10));
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    i = iterations;
    do {
        rv = apr_file_write_full(proc.in, buf, bytes_per_iteration, NULL);
        CuAssertIntEquals(tc, APR_SUCCESS, rv);
    } while (--i);

    free(buf);

    rv = apr_file_close(proc.in);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
    
    nbytes = sizeof(responsebuf);
    rv = apr_file_read(proc.out, responsebuf, &nbytes);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
    bytes_processed = (int)apr_strtoi64(responsebuf, NULL, 10);
    CuAssertIntEquals(tc, iterations * bytes_per_iteration, bytes_processed);
}
コード例 #9
0
ファイル: mod_porter.c プロジェクト: pkmiec/modporter
static const char* porter_set_file_permission(cmd_parms *cmd, void *dir, const char *argument)
{
  porter_server_conf *config = (porter_server_conf *)ap_get_module_config(cmd->server->module_config, &porter_module);

  const char *error = ap_check_cmd_context(cmd, NOT_IN_LIMIT);

  if (error != NULL) {
    return error;
  }

  config->permission = apr_strtoi64(argument, NULL, 16);
  return NULL;
}
コード例 #10
0
ファイル: property.c プロジェクト: 2asoft/freebsd
/* Return the HTTP status code contained in STATUS_LINE, or 0 if
   there's a problem parsing it. */
static apr_int64_t parse_status_code(const char *status_line)
{
  /* STATUS_LINE should be of form: "HTTP/1.1 200 OK" */
  if (status_line[0] == 'H' &&
      status_line[1] == 'T' &&
      status_line[2] == 'T' &&
      status_line[3] == 'P' &&
      status_line[4] == '/' &&
      (status_line[5] >= '0' && status_line[5] <= '9') &&
      status_line[6] == '.' &&
      (status_line[7] >= '0' && status_line[7] <= '9') &&
      status_line[8] == ' ')
    {
      char *reason;

      return apr_strtoi64(status_line + 8, &reason, 10);
    }
  return 0;
}
コード例 #11
0
ファイル: old-and-busted.c プロジェクト: Ranga123/test1
/* Read an escaped byte on the form 'xHH' from [*BUF, END), placing
   the byte in *RESULT.  Advance *BUF to point after the escape
   sequence. */
static svn_error_t *
read_escaped(char *result, char **buf, const char *end)
{
    apr_uint64_t val;
    char digits[3];

    if (end - *buf < 3 || **buf != 'x' || ! svn_ctype_isxdigit((*buf)[1])
            || ! svn_ctype_isxdigit((*buf)[2]))
        return svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
                                _("Invalid escape sequence"));
    (*buf)++;
    digits[0] = *((*buf)++);
    digits[1] = *((*buf)++);
    digits[2] = 0;
    if ((val = apr_strtoi64(digits, NULL, 16)) == 0)
        return svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
                                _("Invalid escaped character"));
    *result = (char) val;
    return SVN_NO_ERROR;
}
コード例 #12
0
ファイル: h2_response.c プロジェクト: Sp1l/mod_h2
static h2_response *h2_response_create_int(int stream_id,
                                           int rst_error,
                                           int http_status,
                                           apr_table_t *headers,
                                           apr_table_t *notes,
                                           apr_pool_t *pool)
{
    h2_response *response;
    const char *s;

    if (!headers) {
        return NULL;
    }
    
    response = apr_pcalloc(pool, sizeof(h2_response));
    if (response == NULL) {
        return NULL;
    }
    
    response->stream_id      = stream_id;
    response->rst_error      = rst_error;
    response->http_status    = http_status? http_status : 500;
    response->content_length = -1;
    response->headers        = headers;
    response->sos_filter     = get_sos_filter(notes);
    
    s = apr_table_get(headers, "Content-Length");
    if (s) {
        char *end;
        
        response->content_length = apr_strtoi64(s, &end, 10);
        if (s == end) {
            ap_log_perror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, 
                          pool, APLOGNO(02956) 
                          "h2_response: content-length"
                          " value not parsed: %s", s);
            response->content_length = -1;
        }
    }
    return response;
}
コード例 #13
0
ファイル: at.c プロジェクト: LuaDist/apreq
static int* at_list(apr_pool_t *pool, const char *spec, int *list)
{
    apr_array_header_t arr;
    int prev, current = 0;

    arr.pool = pool;
    arr.elt_size = sizeof *list;
    arr.nelts = 0;
    arr.nalloc = AT_NELTS;
    arr.elts = (char *)list;

    do {
        while (*spec && !apr_isdigit(*spec))
            ++spec;

        prev = current;
        current = (int)apr_strtoi64(spec, (char **)(void *)&spec, 10);
        *(int *)apr_array_push(&arr) = current;

    } while (prev >= current);

    return (int *)arr.elts;
}
コード例 #14
0
ファイル: serf_get.c プロジェクト: KyleSanderson/serf
int main(int argc, const char **argv)
{
    apr_status_t status;
    apr_pool_t *pool;
    serf_bucket_alloc_t *bkt_alloc;
    serf_context_t *context;
    serf_connection_t **connections;
    app_baton_t app_ctx;
    handler_baton_t handler_ctx;
    serf_bucket_t *req_hdrs = NULL;
    apr_uri_t url;
    const char *proxy = NULL;
    const char *raw_url, *method, *req_body_path = NULL;
    int count, inflight, conn_count;
    int i;
    int print_headers, debug;
    const char *username = NULL;
    const char *password = "";
    const char *pem_path = NULL, *pem_pwd = NULL;
    apr_getopt_t *opt;
    int opt_c;
    const char *opt_arg;

    apr_initialize();
    atexit(apr_terminate);

    apr_pool_create(&pool, NULL);
    /* serf_initialize(); */
    bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);

    /* Default to one round of fetching with no limit to max inflight reqs. */
    count = 1;
    inflight = 0;
    conn_count = 1;
    /* Default to GET. */
    method = "GET";
    /* Do not print headers by default. */
    print_headers = 0;
    /* Do not debug by default. */
    debug = 0;

    
    apr_getopt_init(&opt, pool, argc, argv);
    while ((status = apr_getopt_long(opt, options, &opt_c, &opt_arg)) ==
           APR_SUCCESS) {

        switch (opt_c) {
        case 'U':
            username = opt_arg;
            break;
        case 'P':
            password = opt_arg;
            break;
        case 'd':
            debug = 1;
            break;
        case 'f':
            req_body_path = opt_arg;
            break;
        case 'h':
            print_usage(pool);
            exit(0);
            break;
        case 'H':
            print_headers = 1;
            break;
        case 'm':
            method = opt_arg;
            break;
        case 'n':
            errno = 0;
            count = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of times to fetch URL (%d)\n",
                       errno);
                return errno;
            }
            break;
        case 'c':
            errno = 0;
            conn_count = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of concurrent connections to use (%d)\n",
                       errno);
                return errno;
            }

            if (conn_count <= 0) {
                printf("Invalid number of concurrent connections to use (%d)\n",
                       conn_count);
                return 1;
            }
            break;
        case 'x':
            errno = 0;
            inflight = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of requests to have outstanding (%d)\n",
                       errno);
                return errno;
            }
            break;
        case 'p':
            proxy = opt_arg;
            break;
        case 'r':
            {
                char *sep;
                char *hdr_val;

                if (req_hdrs == NULL) {
                    /* first request header, allocate bucket */
                    req_hdrs = serf_bucket_headers_create(bkt_alloc);
                }
                sep = strchr(opt_arg, ':');
                if ((sep == NULL) || (sep == opt_arg) || (strlen(sep) <= 1)) {
                    printf("Invalid request header string (%s)\n", opt_arg);
                    return EINVAL;
                }
                hdr_val = sep + 1;
                while (*hdr_val == ' ') {
                    hdr_val++;
                }
                serf_bucket_headers_setx(req_hdrs, opt_arg, (sep - opt_arg), 1,
                                         hdr_val, strlen(hdr_val), 1);
            }
            break;
        case CERTFILE:
            pem_path = opt_arg;
            break;
        case CERTPWD:
            pem_pwd = opt_arg;
            break;
        case 'v':
            puts("Serf version: " SERF_VERSION_STRING);
            exit(0);
        default:
            break;
        }
    }

    if (opt->ind != opt->argc - 1) {
        print_usage(pool);
        exit(-1);
    }

    raw_url = argv[opt->ind];

    apr_uri_parse(pool, raw_url, &url);
    if (!url.port) {
        url.port = apr_uri_port_of_scheme(url.scheme);
    }
    if (!url.path) {
        url.path = "/";
    }

    if (strcasecmp(url.scheme, "https") == 0) {
        app_ctx.using_ssl = 1;
    }
    else {
        app_ctx.using_ssl = 0;
    }

    if (strcasecmp(method, "HEAD") == 0) {
        app_ctx.head_request = 1;
    }
    else {
        app_ctx.head_request = 0;
    }

    app_ctx.hostinfo = url.hostinfo;
    app_ctx.pem_path = pem_path;
    app_ctx.pem_pwd = pem_pwd;

    context = serf_context_create(pool);
    app_ctx.serf_ctx = context;

    if (proxy)
    {
        apr_sockaddr_t *proxy_address = NULL;
        apr_port_t proxy_port;
        char *proxy_host;
        char *proxy_scope;

        status = apr_parse_addr_port(&proxy_host, &proxy_scope, &proxy_port, proxy, pool);
        if (status)
        {
            printf("Cannot parse proxy hostname/port: %d\n", status);
            apr_pool_destroy(pool);
            exit(1);
        }

        if (!proxy_host)
        {
            printf("Proxy hostname must be specified\n");
            apr_pool_destroy(pool);
            exit(1);
        }

        if (!proxy_port)
        {
            printf("Proxy port must be specified\n");
            apr_pool_destroy(pool);
            exit(1);
        }

        status = apr_sockaddr_info_get(&proxy_address, proxy_host, APR_UNSPEC,
                                       proxy_port, 0, pool);

        if (status)
        {
            printf("Cannot resolve proxy address '%s': %d\n", proxy_host, status);
            apr_pool_destroy(pool);
            exit(1);
        }

        serf_config_proxy(context, proxy_address);
    }

    if (username)
    {
        serf_config_authn_types(context, SERF_AUTHN_ALL);
    }
    else
    {
        serf_config_authn_types(context, SERF_AUTHN_NTLM | SERF_AUTHN_NEGOTIATE);
    }

    serf_config_credentials_callback(context, credentials_callback);

    /* Setup debug logging */
    if (debug)
    {
        serf_log_output_t *output;
        apr_status_t status;

        status = serf_logging_create_stream_output(&output,
                                                   context,
                                                   SERF_LOG_DEBUG,
                                                   SERF_LOGCOMP_ALL_MSG,
                                                   SERF_LOG_DEFAULT_LAYOUT,
                                                   stderr,
                                                   pool);

        if (!status)
            serf_logging_add_output(context, output);
    }

    /* ### Connection or Context should have an allocator? */
    app_ctx.bkt_alloc = bkt_alloc;

    connections = apr_pcalloc(pool, conn_count * sizeof(serf_connection_t*));
    for (i = 0; i < conn_count; i++)
    {
        conn_baton_t *conn_ctx = apr_pcalloc(pool, sizeof(*conn_ctx));
        conn_ctx->app = &app_ctx;
        conn_ctx->ssl_ctx = NULL;

        status = serf_connection_create2(&connections[i], context, url,
                                         conn_setup, conn_ctx,
                                         closed_connection, conn_ctx,
                                         pool);
        if (status) {
            printf("Error creating connection: %d\n", status);
            apr_pool_destroy(pool);
            exit(1);
        }

        serf_connection_set_max_outstanding_requests(connections[i], inflight);
    }

    handler_ctx.completed_requests = 0;
    handler_ctx.print_headers = print_headers;

#if APR_VERSION_AT_LEAST(1, 3, 0)
    apr_file_open_flags_stdout(&handler_ctx.output_file, APR_BUFFERED, pool);
#else
    apr_file_open_stdout(&handler_ctx.output_file, pool);
#endif

    handler_ctx.host = url.hostinfo;
    handler_ctx.method = method;
    handler_ctx.path = apr_pstrcat(pool,
                                   url.path,
                                   url.query ? "?" : "",
                                   url.query ? url.query : "",
                                   NULL);
    handler_ctx.username = username;
    handler_ctx.password = password;
    handler_ctx.auth_attempts = 0;

    handler_ctx.req_body_path = req_body_path;

    handler_ctx.acceptor = accept_response;
    handler_ctx.acceptor_baton = &app_ctx;
    handler_ctx.handler = handle_response;
    handler_ctx.req_hdrs = req_hdrs;

    for (i = 0; i < count; i++) {
        /* We don't need the returned request here. */
        serf_connection_request_create(connections[i % conn_count],
                                       setup_request, &handler_ctx);
    }

    while (1) {
        status = serf_context_run(context, SERF_DURATION_FOREVER, pool);
        if (APR_STATUS_IS_TIMEUP(status))
            continue;
        if (status) {
            char buf[200];
            const char *err_string;
            err_string = serf_error_string(status);
            if (!err_string) {
                err_string = apr_strerror(status, buf, sizeof(buf));
            }

            printf("Error running context: (%d) %s\n", status, err_string);
            apr_pool_destroy(pool);
            exit(1);
        }
        if (apr_atomic_read32(&handler_ctx.completed_requests) >= count) {
            break;
        }
        /* Debugging purposes only! */
        serf_debug__closed_conn(app_ctx.bkt_alloc);
    }

    apr_file_close(handler_ctx.output_file);

    for (i = 0; i < conn_count; i++)
    {
        serf_connection_close(connections[i]);
    }

    apr_pool_destroy(pool);
    return 0;
}
コード例 #15
0
/* Perform one iteration of the state machine.
 *
 * Will return when one the following conditions occurred:
 *  1) a state change
 *  2) an error
 *  3) the stream is not ready or at EOF
 *  4) APR_SUCCESS, meaning the machine can be run again immediately
 */
static apr_status_t run_machine(serf_bucket_t *bkt, response_context_t *ctx)
{
    apr_status_t status = APR_SUCCESS; /* initialize to avoid gcc warnings */

    switch (ctx->state) {
    case STATE_STATUS_LINE:
        /* RFC 2616 says that CRLF is the only line ending, but we can easily
         * accept any kind of line ending.
         */
        status = fetch_line(ctx, SERF_NEWLINE_ANY);
        if (SERF_BUCKET_READ_ERROR(status))
            return status;

        if (ctx->linebuf.state == SERF_LINEBUF_READY) {
            /* The Status-Line is in the line buffer. Process it. */
            status = parse_status_line(ctx, bkt->allocator);
            if (status)
                return status;

            /* Good times ahead: we're switching protocols! */
            if (ctx->sl.code == 101) {
                ctx->body =
                    serf_bucket_barrier_create(ctx->stream, bkt->allocator);
                ctx->state = STATE_DONE;
                break;
            }

            /* Okay... move on to reading the headers. */
            ctx->state = STATE_HEADERS;
        }
        else {
            /* The connection closed before we could get the next
             * response.  Treat the request as lost so that our upper
             * end knows the server never tried to give us a response.
             */
            if (APR_STATUS_IS_EOF(status)) {
                return SERF_ERROR_REQUEST_LOST;
            }
        }
        break;
    case STATE_HEADERS:
        status = fetch_headers(bkt, ctx);
        if (SERF_BUCKET_READ_ERROR(status))
            return status;

        /* If an empty line was read, then we hit the end of the headers.
         * Move on to the body.
         */
        if (ctx->linebuf.state == SERF_LINEBUF_READY && !ctx->linebuf.used) {
            const void *v;

            /* Advance the state. */
            ctx->state = STATE_BODY;

            ctx->body =
                serf_bucket_barrier_create(ctx->stream, bkt->allocator);

            /*
             * Instaweb/mod_pagespeed change: This section is
             * re-ordered from the original code from serf to Follow
             * HTTP spec by checking "Transfer-Encoding: chunked",
             * before "Content-Length".
             */

            /* Are we C-L, chunked, or conn close? */
            v = serf_bucket_headers_get(ctx->headers, "Transfer-Encoding");

            /* Need to handle multiple transfer-encoding. */
            if (v && strcasecmp("chunked", v) == 0) {
                ctx->chunked = 1;
                ctx->body = serf_bucket_dechunk_create(ctx->body,
                                                       bkt->allocator);
            }
            else {
                v = serf_bucket_headers_get(ctx->headers, "Content-Length");
                if (v) {
                    apr_uint64_t length;
                    length = apr_strtoi64(v, NULL, 10);
                    if (errno == ERANGE) {
                        return APR_FROM_OS_ERROR(ERANGE);
                    }
                    ctx->body = serf_bucket_limit_create(ctx->body, length,
                                                         bkt->allocator);
                }
                else if ((ctx->sl.code == 204 || ctx->sl.code == 304)) {
                    ctx->state = STATE_DONE;
                }
            }

            /*
             * Instaweb would prefer to receive gzipped output if that's what
             * was asked for.
             *
             * v = serf_bucket_headers_get(ctx->headers, "Content-Encoding");
             * if (v) {
             *   * Need to handle multiple content-encoding. *
             *  if (v && strcasecmp("gzip", v) == 0) {
             *      ctx->body =
             *          serf_bucket_deflate_create(ctx->body, bkt->allocator,
             *                                     SERF_DEFLATE_GZIP);
             *  }
             *  else if (v && strcasecmp("deflate", v) == 0) {
             *      ctx->body =
             *          serf_bucket_deflate_create(ctx->body, bkt->allocator,
             *                                     SERF_DEFLATE_DEFLATE);
             *  }
             * }
             */

            /* If we're a HEAD request, we don't receive a body. */
            if (ctx->head_req) {
                ctx->state = STATE_DONE;
            }
        }
        break;
    case STATE_BODY:
        /* Don't do anything. */
        break;
    case STATE_TRAILERS:
        status = fetch_headers(bkt, ctx);
        if (SERF_BUCKET_READ_ERROR(status))
            return status;

        /* If an empty line was read, then we're done. */
        if (ctx->linebuf.state == SERF_LINEBUF_READY && !ctx->linebuf.used) {
            ctx->state = STATE_DONE;
            return APR_EOF;
        }
        break;
    case STATE_DONE:
        return APR_EOF;
    default:
        /* Not reachable */
        return APR_EGENERAL;
    }

    return status;
}
コード例 #16
0
ファイル: svnserve.c プロジェクト: 2asoft/freebsd
/*
 * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
 * either return an error to be displayed, or set *EXIT_CODE to non-zero and
 * return SVN_NO_ERROR.
 */
static svn_error_t *
sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
{
  enum run_mode run_mode = run_mode_unspecified;
  svn_boolean_t foreground = FALSE;
  apr_socket_t *sock;
  apr_sockaddr_t *sa;
  svn_error_t *err;
  apr_getopt_t *os;
  int opt;
  serve_params_t params;
  const char *arg;
  apr_status_t status;
#ifndef WIN32
  apr_proc_t proc;
#endif
  svn_boolean_t is_multi_threaded;
  enum connection_handling_mode handling_mode = CONNECTION_DEFAULT;
  svn_boolean_t cache_fulltexts = TRUE;
  svn_boolean_t cache_txdeltas = TRUE;
  svn_boolean_t cache_revprops = FALSE;
  svn_boolean_t use_block_read = FALSE;
  apr_uint16_t port = SVN_RA_SVN_PORT;
  const char *host = NULL;
  int family = APR_INET;
  apr_int32_t sockaddr_info_flags = 0;
#if APR_HAVE_IPV6
  svn_boolean_t prefer_v6 = FALSE;
#endif
  svn_boolean_t quiet = FALSE;
  svn_boolean_t is_version = FALSE;
  int mode_opt_count = 0;
  int handling_opt_count = 0;
  const char *config_filename = NULL;
  const char *pid_filename = NULL;
  const char *log_filename = NULL;
  svn_node_kind_t kind;
  apr_size_t min_thread_count = THREADPOOL_MIN_SIZE;
  apr_size_t max_thread_count = THREADPOOL_MAX_SIZE;
#ifdef SVN_HAVE_SASL
  SVN_ERR(cyrus_init(pool));
#endif

  /* Check library versions */
  SVN_ERR(check_lib_versions());

  /* Initialize the FS library. */
  SVN_ERR(svn_fs_initialize(pool));

  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));

  params.root = "/";
  params.tunnel = FALSE;
  params.tunnel_user = NULL;
  params.read_only = FALSE;
  params.base = NULL;
  params.cfg = NULL;
  params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
  params.logger = NULL;
  params.config_pool = NULL;
  params.authz_pool = NULL;
  params.fs_config = NULL;
  params.vhost = FALSE;
  params.username_case = CASE_ASIS;
  params.memory_cache_size = (apr_uint64_t)-1;
  params.zero_copy_limit = 0;
  params.error_check_interval = 4096;

  while (1)
    {
      status = apr_getopt_long(os, svnserve__options, &opt, &arg);
      if (APR_STATUS_IS_EOF(status))
        break;
      if (status != APR_SUCCESS)
        {
          usage(argv[0], pool);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }
      switch (opt)
        {
        case '6':
#if APR_HAVE_IPV6
          prefer_v6 = TRUE;
#endif
          /* ### Maybe error here if we don't have IPV6 support? */
          break;

        case 'h':
          help(pool);
          return SVN_NO_ERROR;

        case 'q':
          quiet = TRUE;
          break;

        case SVNSERVE_OPT_VERSION:
          is_version = TRUE;
          break;

        case 'd':
          if (run_mode != run_mode_daemon)
            {
              run_mode = run_mode_daemon;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_FOREGROUND:
          foreground = TRUE;
          break;

        case SVNSERVE_OPT_SINGLE_CONN:
          handling_mode = connection_mode_single;
          handling_opt_count++;
          break;

        case 'i':
          if (run_mode != run_mode_inetd)
            {
              run_mode = run_mode_inetd;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_LISTEN_PORT:
          {
            apr_uint64_t val;

            err = svn_cstring_strtoui64(&val, arg, 0, APR_UINT16_MAX, 10);
            if (err)
              return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
                                       _("Invalid port '%s'"), arg);
            port = (apr_uint16_t)val;
          }
          break;

        case SVNSERVE_OPT_LISTEN_HOST:
          host = arg;
          break;

        case 't':
          if (run_mode != run_mode_tunnel)
            {
              run_mode = run_mode_tunnel;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_TUNNEL_USER:
          params.tunnel_user = arg;
          break;

        case 'X':
          if (run_mode != run_mode_listen_once)
            {
              run_mode = run_mode_listen_once;
              mode_opt_count++;
            }
          break;

        case 'r':
          SVN_ERR(svn_utf_cstring_to_utf8(&params.root, arg, pool));

          SVN_ERR(svn_io_check_resolved_path(params.root, &kind, pool));
          if (kind != svn_node_dir)
            {
              return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                       _("Root path '%s' does not exist "
                         "or is not a directory"), params.root);
            }

          params.root = svn_dirent_internal_style(params.root, pool);
          SVN_ERR(svn_dirent_get_absolute(&params.root, params.root, pool));
          break;

        case 'R':
          params.read_only = TRUE;
          break;

        case 'T':
          handling_mode = connection_mode_thread;
          handling_opt_count++;
          break;

        case 'c':
          params.compression_level = atoi(arg);
          if (params.compression_level < SVN_DELTA_COMPRESSION_LEVEL_NONE)
            params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_NONE;
          if (params.compression_level > SVN_DELTA_COMPRESSION_LEVEL_MAX)
            params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_MAX;
          break;

        case 'M':
          params.memory_cache_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_CACHE_TXDELTAS:
          cache_txdeltas = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_FULLTEXTS:
          cache_fulltexts = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_REVPROPS:
          cache_revprops = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_BLOCK_READ:
          use_block_read = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CLIENT_SPEED:
          {
            apr_size_t bandwidth = (apr_size_t)apr_strtoi64(arg, NULL, 0);

            /* for slower clients, don't try anything fancy */
            if (bandwidth >= 1000)
              {
                /* block other clients for at most 1 ms (at full bandwidth).
                   Note that the send buffer is 16kB anyways. */
                params.zero_copy_limit = bandwidth * 120;

                /* check for aborted connections at the same rate */
                params.error_check_interval = bandwidth * 120;
              }
          }
          break;

        case SVNSERVE_OPT_MIN_THREADS:
          min_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_MAX_THREADS:
          max_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
          break;

#ifdef WIN32
        case SVNSERVE_OPT_SERVICE:
          if (run_mode != run_mode_service)
            {
              run_mode = run_mode_service;
              mode_opt_count++;
            }
          break;
#endif

        case SVNSERVE_OPT_CONFIG_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&config_filename, arg, pool));
          config_filename = svn_dirent_internal_style(config_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&config_filename, config_filename,
                                          pool));
          break;

        case SVNSERVE_OPT_PID_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&pid_filename, arg, pool));
          pid_filename = svn_dirent_internal_style(pid_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&pid_filename, pid_filename, pool));
          break;

         case SVNSERVE_OPT_VIRTUAL_HOST:
           params.vhost = TRUE;
           break;

         case SVNSERVE_OPT_LOG_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&log_filename, arg, pool));
          log_filename = svn_dirent_internal_style(log_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&log_filename, log_filename, pool));
          break;

        }
    }

  if (is_version)
    {
      SVN_ERR(version(quiet, pool));
      return SVN_NO_ERROR;
    }

  if (os->ind != argc)
    {
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  if (mode_opt_count != 1)
    {
      svn_error_clear(svn_cmdline_fputs(
#ifdef WIN32
                      _("You must specify exactly one of -d, -i, -t, "
                        "--service or -X.\n"),
#else
                      _("You must specify exactly one of -d, -i, -t or -X.\n"),
#endif
                       stderr, pool));
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  if (handling_opt_count > 1)
    {
      svn_error_clear(svn_cmdline_fputs(
                      _("You may only specify one of -T or --single-thread\n"),
                      stderr, pool));
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  /* construct object pools */
  is_multi_threaded = handling_mode == connection_mode_thread;
  params.fs_config = apr_hash_make(pool);
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
                cache_txdeltas ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                cache_fulltexts ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
                cache_revprops ? "2" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ,
                use_block_read ? "1" :"0");

  SVN_ERR(svn_repos__config_pool_create(&params.config_pool,
                                        is_multi_threaded,
                                        pool));
  SVN_ERR(svn_repos__authz_pool_create(&params.authz_pool,
                                       params.config_pool,
                                       is_multi_threaded,
                                       pool));

  /* If a configuration file is specified, load it and any referenced
   * password and authorization files. */
  if (config_filename)
    {
      params.base = svn_dirent_dirname(config_filename, pool);

      SVN_ERR(svn_repos__config_pool_get(&params.cfg, NULL,
                                         params.config_pool,
                                         config_filename,
                                         TRUE, /* must_exist */
                                         FALSE, /* names_case_sensitive */
                                         NULL,
                                         pool));
    }

  if (log_filename)
    SVN_ERR(logger__create(&params.logger, log_filename, pool));
  else if (run_mode == run_mode_listen_once)
    SVN_ERR(logger__create_for_stderr(&params.logger, pool));

  if (params.tunnel_user && run_mode != run_mode_tunnel)
    {
      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
               _("Option --tunnel-user is only valid in tunnel mode"));
    }

  if (run_mode == run_mode_inetd || run_mode == run_mode_tunnel)
    {
      apr_pool_t *connection_pool;
      svn_ra_svn_conn_t *conn;
      svn_stream_t *stdin_stream;
      svn_stream_t *stdout_stream;

      params.tunnel = (run_mode == run_mode_tunnel);
      apr_pool_cleanup_register(pool, pool, apr_pool_cleanup_null,
                                redirect_stdout);

      SVN_ERR(svn_stream_for_stdin(&stdin_stream, pool));
      SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));

      /* Use a subpool for the connection to ensure that if SASL is used
       * the pool cleanup handlers that call sasl_dispose() (connection_pool)
       * and sasl_done() (pool) are run in the right order. See issue #3664. */
      connection_pool = svn_pool_create(pool);
      conn = svn_ra_svn_create_conn4(NULL, stdin_stream, stdout_stream,
                                     params.compression_level,
                                     params.zero_copy_limit,
                                     params.error_check_interval,
                                     connection_pool);
      err = serve(conn, &params, connection_pool);
      svn_pool_destroy(connection_pool);

      return err;
    }

#ifdef WIN32
  /* If svnserve needs to run as a Win32 service, then we need to
     coordinate with the Service Control Manager (SCM) before
     continuing.  This function call registers the svnserve.exe
     process with the SCM, waits for the "start" command from the SCM
     (which will come very quickly), and confirms that those steps
     succeeded.

     After this call succeeds, the service is free to run.  At some
     point in the future, the SCM will send a message to the service,
     requesting that it stop.  This is translated into a call to
     winservice_notify_stop().  The service is then responsible for
     cleanly terminating.

     We need to do this before actually starting the service logic
     (opening files, sockets, etc.) because the SCM wants you to
     connect *first*, then do your service-specific logic.  If the
     service process takes too long to connect to the SCM, then the
     SCM will decide that the service is busted, and will give up on
     it.
     */
  if (run_mode == run_mode_service)
    {
      err = winservice_start();
      if (err)
        {
          svn_handle_error2(err, stderr, FALSE, "svnserve: ");

          /* This is the most common error.  It means the user started
             svnserve from a shell, and specified the --service
             argument.  svnserve cannot be started, as a service, in
             this way.  The --service argument is valid only valid if
             svnserve is started by the SCM. */
          if (err->apr_err ==
              APR_FROM_OS_ERROR(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT))
            {
              svn_error_clear(svn_cmdline_fprintf(stderr, pool,
                  _("svnserve: The --service flag is only valid if the"
                    " process is started by the Service Control Manager.\n")));
            }

          svn_error_clear(err);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }

      /* The service is now in the "starting" state.  Before the SCM will
         consider the service "started", this thread must call the
         winservice_running() function. */
    }
#endif /* WIN32 */

  /* Make sure we have IPV6 support first before giving apr_sockaddr_info_get
     APR_UNSPEC, because it may give us back an IPV6 address even if we can't
     create IPV6 sockets. */

#if APR_HAVE_IPV6
#ifdef MAX_SECS_TO_LINGER
  /* ### old APR interface */
  status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, pool);
#else
  status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, APR_PROTO_TCP,
                             pool);
#endif
  if (status == 0)
    {
      apr_socket_close(sock);
      family = APR_UNSPEC;

      if (prefer_v6)
        {
          if (host == NULL)
            host = "::";
          sockaddr_info_flags = APR_IPV6_ADDR_OK;
        }
      else
        {
          if (host == NULL)
            host = "0.0.0.0";
          sockaddr_info_flags = APR_IPV4_ADDR_OK;
        }
    }
#endif

  status = apr_sockaddr_info_get(&sa, host, family, port,
                                 sockaddr_info_flags, pool);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't get address info"));
    }


#ifdef MAX_SECS_TO_LINGER
  /* ### old APR interface */
  status = apr_socket_create(&sock, sa->family, SOCK_STREAM, pool);
#else
  status = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP,
                             pool);
#endif
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't create server socket"));
    }

  /* Prevents "socket in use" errors when server is killed and quickly
   * restarted. */
  status = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't set options on server socket"));
    }

  status = apr_socket_bind(sock, sa);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't bind server socket"));
    }

  status = apr_socket_listen(sock, ACCEPT_BACKLOG);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't listen on server socket"));
    }

#if APR_HAS_FORK
  if (run_mode != run_mode_listen_once && !foreground)
    /* ### ignoring errors... */
    apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);

  apr_signal(SIGCHLD, sigchld_handler);
#endif

#ifdef SIGPIPE
  /* Disable SIGPIPE generation for the platforms that have it. */
  apr_signal(SIGPIPE, SIG_IGN);
#endif

#ifdef SIGXFSZ
  /* Disable SIGXFSZ generation for the platforms that have it, otherwise
   * working with large files when compiled against an APR that doesn't have
   * large file support will crash the program, which is uncool. */
  apr_signal(SIGXFSZ, SIG_IGN);
#endif

  if (pid_filename)
    SVN_ERR(write_pid_file(pid_filename, pool));

#ifdef WIN32
  status = apr_os_sock_get(&winservice_svnserve_accept_socket, sock);
  if (status)
    winservice_svnserve_accept_socket = INVALID_SOCKET;

  /* At this point, the service is "running".  Notify the SCM. */
  if (run_mode == run_mode_service)
    winservice_running();
#endif

  /* Configure FS caches for maximum efficiency with svnserve.
   * For pre-forked (i.e. multi-processed) mode of operation,
   * keep the per-process caches smaller than the default.
   * Also, apply the respective command line parameters, if given. */
  {
    svn_cache_config_t settings = *svn_cache_config_get();

    if (params.memory_cache_size != -1)
      settings.cache_size = params.memory_cache_size;

    settings.single_threaded = TRUE;
    if (handling_mode == connection_mode_thread)
      {
#if APR_HAS_THREADS
        settings.single_threaded = FALSE;
#else
        /* No requests will be processed at all
         * (see "switch (handling_mode)" code further down).
         * But if they were, some other synchronization code
         * would need to take care of securing integrity of
         * APR-based structures. That would include our caches.
         */
#endif
      }

    svn_cache_config_set(&settings);
  }

#if APR_HAS_THREADS
  SVN_ERR(svn_root_pools__create(&connection_pools));

  if (handling_mode == connection_mode_thread)
    {
      /* create the thread pool with a valid range of threads */
      if (max_thread_count < 1)
        max_thread_count = 1;
      if (min_thread_count > max_thread_count)
        min_thread_count = max_thread_count;

      status = apr_thread_pool_create(&threads,
                                      min_thread_count,
                                      max_thread_count,
                                      pool);
      if (status)
        {
          return svn_error_wrap_apr(status, _("Can't create thread pool"));
        }

      /* let idle threads linger for a while in case more requests are
         coming in */
      apr_thread_pool_idle_wait_set(threads, THREADPOOL_THREAD_IDLE_LIMIT);

      /* don't queue requests unless we reached the worker thread limit */
      apr_thread_pool_threshold_set(threads, 0);
    }
  else
    {
      threads = NULL;
    }
#endif

  while (1)
    {
      connection_t *connection = NULL;
      SVN_ERR(accept_connection(&connection, sock, &params, handling_mode,
                                pool));
      if (run_mode == run_mode_listen_once)
        {
          err = serve_socket(connection, connection->pool);
          close_connection(connection);
          return err;
        }

      switch (handling_mode)
        {
        case connection_mode_fork:
#if APR_HAS_FORK
          status = apr_proc_fork(&proc, connection->pool);
          if (status == APR_INCHILD)
            {
              /* the child would't listen to the main server's socket */
              apr_socket_close(sock);

              /* serve_socket() logs any error it returns, so ignore it. */
              svn_error_clear(serve_socket(connection, connection->pool));
              close_connection(connection);
              return SVN_NO_ERROR;
            }
          else if (status != APR_INPARENT)
            {
              err = svn_error_wrap_apr(status, "apr_proc_fork");
              logger__log_error(params.logger, err, NULL, NULL);
              svn_error_clear(err);
            }
#endif
          break;

        case connection_mode_thread:
          /* Create a detached thread for each connection.  That's not a
             particularly sophisticated strategy for a threaded server, it's
             little different from forking one process per connection. */
#if APR_HAS_THREADS
          attach_connection(connection);

          status = apr_thread_pool_push(threads, serve_thread, connection,
                                        0, NULL);
          if (status)
            {
              return svn_error_wrap_apr(status, _("Can't push task"));
            }
#endif
          break;

        case connection_mode_single:
          /* Serve one connection at a time. */
          /* serve_socket() logs any error it returns, so ignore it. */
          svn_error_clear(serve_socket(connection, connection->pool));
        }

      close_connection(connection);
    }

  /* NOTREACHED */
}
コード例 #17
0
ファイル: h2_to_h1.c プロジェクト: ikyaqoob/mod_h2
apr_status_t h2_to_h1_add_header(h2_to_h1 *to_h1,
                                 const char *name, size_t nlen,
                                 const char *value, size_t vlen)
{
    if (H2_HD_MATCH_LIT("transfer-encoding", name, nlen)) {
        if (!apr_strnatcasecmp("chunked", value)) {
            /* This should never arrive here in a HTTP/2 request */
            ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_BADARG, 
                          h2_mplx_get_conn(to_h1->m),
                          "h2_to_h1: 'transfer-encoding: chunked' received");
            return APR_BADARG;
        }
    }
    else if (H2_HD_MATCH_LIT("content-length", name, nlen)) {
        char *end;
        to_h1->content_len = apr_strtoi64(value, &end, 10);
        if (value == end) {
            ap_log_cerror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, 
                          h2_mplx_get_conn(to_h1->m),
                          "h2_request(%d): content-length value not parsed: %s",
                          to_h1->stream_id, value);
            return APR_EINVAL;
        }
        to_h1->remain_len = to_h1->content_len;
        to_h1->chunked = 0;
    }
    else if (H2_HD_MATCH_LIT("content-type", name, nlen)) {
        /* If we see a content-type and have no length (yet),
         * we need to chunk. */
        to_h1->chunked = (to_h1->content_len == -1);
    }
    else if ((to_h1->seen_host && H2_HD_MATCH_LIT("host", name, nlen))
             || H2_HD_MATCH_LIT("expect", name, nlen)
             || H2_HD_MATCH_LIT("upgrade", name, nlen)
             || H2_HD_MATCH_LIT("connection", name, nlen)
             || H2_HD_MATCH_LIT("proxy-connection", name, nlen)
             || H2_HD_MATCH_LIT("keep-alive", name, nlen)
             || H2_HD_MATCH_LIT("http2-settings", name, nlen)) {
        // ignore these.
        return APR_SUCCESS;
    }
    else if (H2_HD_MATCH_LIT("cookie", name, nlen)) {
        const char *existing = apr_table_get(to_h1->headers, "cookie");
        if (existing) {
            /* Cookie headers come separately in HTTP/2, but need
             * to be merged by "; " (instead of default ", ")
             */
            char *hvalue = apr_pstrndup(to_h1->pool, value, vlen);
            char *nval = apr_psprintf(to_h1->pool, "%s; %s", existing, hvalue);
            apr_table_setn(to_h1->headers, "Cookie", nval);
            return APR_SUCCESS;
        }
    }
    else if (H2_HD_MATCH_LIT("host", name, nlen)) {
        to_h1->seen_host = 1;
    }
    
    char *hname = apr_pstrndup(to_h1->pool, name, nlen);
    char *hvalue = apr_pstrndup(to_h1->pool, value, vlen);
    h2_util_camel_case_header(hname, nlen);
    apr_table_mergen(to_h1->headers, hname, hvalue);
    
    return APR_SUCCESS;
}
コード例 #18
0
static int
authenticate_webid_user(request_rec *request) {
    int r = 0;
    authn_webid_config_rec *conf =
        ap_get_module_config(request->per_dir_config, &authn_webid_module);
    if (!conf->authoritative) r = DECLINED;
    else r = HTTP_UNAUTHORIZED;

    /* Check for AuthType WebID */
    const char *current_auth = ap_auth_type(request);
    if (!current_auth || strcasecmp(current_auth, "WebID") != 0) {
        return DECLINED;
    }
    request->ap_auth_type = "WebID";

    /* Check for WebID cached in SSL session */
    const char *subjAltName = NULL;
    {
        void *data = NULL;
        if (apr_pool_userdata_get(&data, UD_WEBID_KEY, request->connection->pool) == APR_SUCCESS && data != NULL) {
            subjAltName = data;
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: using cached URI <%s>", subjAltName);
            if (strlen(subjAltName)) {
                request->user = (char *)subjAltName;
                r = OK;
            }
            return r;
        }
    }
#if AP_MODULE_MAGIC_AT_LEAST(20060101,0)
    apr_array_header_t *subjAltName_list = ssl_ext_list(request->pool, request->connection, 1, "2.5.29.17");
#else
    subjAltName = ssl_ext_lookup(request->pool, request->connection, 1, "2.5.29.17");
#endif

    /* Load X509 Public Key + Exponent */
    char *pkey_n = NULL;
    char *pkey_e = NULL;
    unsigned int pkey_e_i = 0;
#if AP_MODULE_MAGIC_AT_LEAST(20060101,0)
    if (subjAltName_list != NULL) {
#else
    if (subjAltName != NULL) {
#endif
        char *c_cert = NULL;
        BIO *bio_cert = NULL;
        X509 *x509 = NULL;
        EVP_PKEY *pkey = NULL;
        RSA *rsa = NULL;

        BIO *bio = NULL;
        BUF_MEM *bptr = NULL;

        if (NULL != (c_cert = ssl_var_lookup(request->pool, request->server, request->connection, request, "SSL_CLIENT_CERT"))
            && NULL != (bio_cert = BIO_new_mem_buf(c_cert, strlen(c_cert)))
            && NULL != (x509 = PEM_read_bio_X509(bio_cert, NULL, NULL, NULL))
            && NULL != (pkey = X509_get_pubkey(x509))
            && NULL != (rsa = EVP_PKEY_get1_RSA(pkey))) {

            // public key modulus
            bio = BIO_new(BIO_s_mem());
            BN_print(bio, rsa->n);
            BIO_get_mem_ptr(bio, &bptr);
            pkey_n = apr_pstrndup(request->pool, bptr->data, bptr->length);
            BIO_free(bio);

            // public key exponent
            bio = BIO_new(BIO_s_mem());
            BN_print(bio, rsa->e);
            BIO_get_mem_ptr(bio, &bptr);
            pkey_e = apr_pstrndup(request->pool, bptr->data, bptr->length);
            pkey_e_i = apr_strtoi64(pkey_e, NULL, 16);
            BIO_free(bio);
        } else {
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, request, "WebID: invalid client SSL certificate");
        }

        if (rsa)
            RSA_free(rsa);
        if (pkey)
            EVP_PKEY_free(pkey);
        if (x509)
            X509_free(x509);
        if (bio_cert)
            BIO_free(bio_cert);
    }

    if (pkey_n != NULL && pkey_e != NULL) {
#if AP_MODULE_MAGIC_AT_LEAST(20060101,0)
        const char *san;
        char *tok;
        int i;
        for (i = 0; i < subjAltName_list->nelts; i++) {
            san = APR_ARRAY_IDX(subjAltName_list, i, const char*);
            while ((tok = get_list_item(request->pool, &san)) != NULL) {
                if (strncmp(tok, "URI:", 4) == 0) {
                    if (validate_webid(request, tok+4, pkey_n, pkey_e_i) == OK) {
                        subjAltName = tok+4;
                        r = OK;
                        break;
                    }
                }
            }
        }
#else
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: subjectAltName = %s", subjAltName);
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: client pkey.n  = %s", pkey_n);
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: client pkey.e  = %d (%s)", pkey_e_i, pkey_e);
        const char *san = subjAltName;
        char *tok;
        while ((tok = get_list_item(request->pool, &san)) != NULL) {
            if (strncmp(tok, "URI:", 4) == 0) {
                if (validate_webid(request, tok+4, pkey_n, pkey_e_i) == OK) {
                    subjAltName = tok+4;
                    r = OK;
                    break;
                }
            }
        }
#endif
    }

    if (r == OK) {
        ap_log_rerror(APLOG_MARK, APLOG_INFO | APLOG_TOCLIENT, 0, request, "WebID: authentication (%sauthoritative) succeeded for <%s> pubkey: \"%s\", URI: <%s>", conf->authoritative?"":"non-", subjAltName, pkey_n, request->uri);
        request->user = apr_psprintf(request->connection->pool, "%s", subjAltName);
    } else {
        ap_log_rerror(APLOG_MARK, (conf->authoritative?APLOG_WARNING:APLOG_INFO) | APLOG_TOCLIENT, 0, request, "WebID: authentication (%sauthoritative) failed for <%s> pubkey: \"%s\", URI: <%s>", conf->authoritative?"":"non-", subjAltName, pkey_n, request->uri);
        subjAltName = "";
    }
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: setting cached URI <%s>", subjAltName);
    apr_pool_userdata_set(apr_pstrdup(request->connection->pool, subjAltName), UD_WEBID_KEY, NULL, request->connection->pool);

    return r;
}

static void
import_ssl_func() {
    ssl_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
#if AP_MODULE_MAGIC_AT_LEAST(20060101,0)
    ssl_ext_list = APR_RETRIEVE_OPTIONAL_FN(ssl_ext_list);
#else
    ssl_ext_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_ext_lookup);
#endif
}
コード例 #19
0
ファイル: filter.c プロジェクト: svn2github/apache-httpd
void apreq_filter_init_context(ap_filter_t *f)
{
    request_rec *r = f->r;
    struct filter_ctx *ctx = f->ctx;
    apr_bucket_alloc_t *ba = r->connection->bucket_alloc;
    const char *cl_header;

    if (r->method_number == M_GET) {
        /* Don't parse GET (this protects against subrequest body parsing). */
        ctx->body_status = APREQ_ERROR_NODATA;
        return;
    }

    cl_header = apr_table_get(r->headers_in, "Content-Length");

    if (cl_header != NULL) {
        char *dummy;
        apr_uint64_t content_length = apr_strtoi64(cl_header, &dummy, 10);

        if (dummy == NULL || *dummy != 0) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, APLOGNO(02045)
                          "Invalid Content-Length header (%s)", cl_header);
            ctx->body_status = APREQ_ERROR_BADHEADER;
            return;
        }
        else if (content_length > ctx->read_limit) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, APLOGNO(02046)
                          "Content-Length header (%s) exceeds configured "
                          "max_body limit (%" APR_UINT64_T_FMT ")",
                          cl_header, ctx->read_limit);
            ctx->body_status = APREQ_ERROR_OVERLIMIT;
            return;
        }
    }

    if (ctx->parser == NULL) {
        const char *ct_header = apr_table_get(r->headers_in, "Content-Type");

        if (ct_header != NULL) {
            apreq_parser_function_t pf = apreq_parser(ct_header);

            if (pf != NULL) {
                ctx->parser = apreq_parser_make(r->pool, ba, ct_header, pf,
                                                ctx->brigade_limit,
                                                ctx->temp_dir,
                                                ctx->hook_queue,
                                                NULL);
            }
            else {
                ctx->body_status = APREQ_ERROR_NOPARSER;
                return;
            }
        }
        else {
            ctx->body_status = APREQ_ERROR_NOHEADER;
            return;
        }
    }
    else {
        if (ctx->parser->brigade_limit > ctx->brigade_limit)
            ctx->parser->brigade_limit = ctx->brigade_limit;
        if (ctx->temp_dir != NULL)
            ctx->parser->temp_dir = ctx->temp_dir;
        if (ctx->hook_queue != NULL)
            apreq_parser_add_hook(ctx->parser, ctx->hook_queue);
    }

    ctx->hook_queue = NULL;
    ctx->bb    = apr_brigade_create(r->pool, ba);
    ctx->bbtmp = apr_brigade_create(r->pool, ba);
    ctx->spool = apr_brigade_create(r->pool, ba);
    ctx->body  = apr_table_make(r->pool, APREQ_DEFAULT_NELTS);
    ctx->body_status = APR_INCOMPLETE;
}
コード例 #20
0
ファイル: old-and-busted.c プロジェクト: Ranga123/test1
/* Read and parse an old-style 'entries' file in the administrative area
   of PATH, filling in ENTRIES with the contents. The results will be
   allocated in RESULT_POOL, and temporary allocations will be made in
   SCRATCH_POOL.  */
svn_error_t *
svn_wc__read_entries_old(apr_hash_t **entries,
                         const char *dir_abspath,
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool)
{
    char *curp;
    const char *endp;
    svn_wc_entry_t *entry;
    svn_stream_t *stream;
    svn_string_t *buf;

    *entries = apr_hash_make(result_pool);

    /* Open the entries file. */
    SVN_ERR(svn_wc__open_adm_stream(&stream, dir_abspath, SVN_WC__ADM_ENTRIES,
                                    scratch_pool, scratch_pool));
    SVN_ERR(svn_string_from_stream(&buf, stream, scratch_pool, scratch_pool));

    /* We own the returned data; it is modifiable, so cast away... */
    curp = (char *)buf->data;
    endp = buf->data + buf->len;

    /* If the first byte of the file is not a digit, then it is probably in XML
       format. */
    if (curp != endp && !svn_ctype_isdigit(*curp))
        SVN_ERR(parse_entries_xml(dir_abspath, *entries, buf->data, buf->len,
                                  result_pool, scratch_pool));
    else
    {
        int entryno, entries_format;
        const char *val;

        /* Read the format line from the entries file. In case we're in the
           middle of upgrading a working copy, this line will contain the
           original format pre-upgrade. */
        SVN_ERR(read_val(&val, &curp, endp));
        if (val)
            entries_format = (int)apr_strtoi64(val, NULL, 0);
        else
            return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
                                     _("Invalid version line in entries file "
                                       "of '%s'"),
                                     svn_dirent_local_style(dir_abspath,
                                             scratch_pool));
        entryno = 1;

        while (curp != endp)
        {
            svn_error_t *err = read_entry(&entry, &curp, endp,
                                          entries_format, result_pool);
            if (! err)
            {
                /* We allow extra fields at the end of the line, for
                   extensibility. */
                curp = memchr(curp, '\f', endp - curp);
                if (! curp)
                    err = svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
                                           _("Missing entry terminator"));
                if (! err && (curp == endp || *(++curp) != '\n'))
                    err = svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
                                           _("Invalid entry terminator"));
            }
            if (err)
                return svn_error_createf(err->apr_err, err,
                                         _("Error at entry %d in entries file for "
                                           "'%s':"),
                                         entryno,
                                         svn_dirent_local_style(dir_abspath,
                                                 scratch_pool));

            ++curp;
            ++entryno;

            svn_hash_sets(*entries, entry->name, entry);
        }
    }

    /* Fill in any implied fields. */
    return svn_error_trace(resolve_to_defaults(*entries, result_pool));
}
コード例 #21
0
ファイル: dechunk_buckets.c プロジェクト: atkonn/mod_chxj
static apr_status_t serf_dechunk_read(serf_bucket_t *bucket,
                                      apr_size_t requested,
                                      const char **data, apr_size_t *len)
{
    dechunk_context_t *ctx = bucket->data;
    apr_status_t status;

    while (1) {
        switch (ctx->state) {
        case STATE_SIZE:

            /* fetch a line terminated by CRLF */
            status = serf_linebuf_fetch(&ctx->linebuf, ctx->stream,
                                        SERF_NEWLINE_CRLF);
            if (SERF_BUCKET_READ_ERROR(status))
                return status;

            /* if a line was read, then parse it. */
            if (ctx->linebuf.state == SERF_LINEBUF_READY) {
                /* NUL-terminate the line. if it filled the entire buffer,
                   then just assume the thing is too large. */
                if (ctx->linebuf.used == sizeof(ctx->linebuf.line))
                    return APR_FROM_OS_ERROR(ERANGE);
                ctx->linebuf.line[ctx->linebuf.used] = '\0';

                /* convert from HEX digits. */
                ctx->body_left = apr_strtoi64(ctx->linebuf.line, NULL, 16);
                if (errno == ERANGE) {
                    return APR_FROM_OS_ERROR(ERANGE);
                }

                if (ctx->body_left == 0) {
                    /* Just read the last-chunk marker. We're DONE. */
                    ctx->state = STATE_DONE;
                    status = APR_EOF;
                }
                else {
                    /* Got a size, so we'll start reading the chunk now. */
                    ctx->state = STATE_CHUNK;
                }

                /* If we can read more, then go do so. */
                if (!status)
                    continue;
            }
            /* assert: status != 0 */

            /* Note that we didn't actually read anything, so our callers
             * don't get confused.
             */
            *len = 0;

            return status;

        case STATE_CHUNK:

            if (requested > ctx->body_left) {
                requested = ctx->body_left;
            }

            /* Delegate to the stream bucket to do the read. */
            status = serf_bucket_read(ctx->stream, requested, data, len);
            if (SERF_BUCKET_READ_ERROR(status))
                return status;

            /* Some data was read, so decrement the amount left and see
             * if we're done reading this chunk.
             */
            ctx->body_left -= *len;
            if (!ctx->body_left) {
                ctx->state = STATE_TERM;
                ctx->body_left = 2;     /* CRLF */
            }

            /* Return the data we just read. */
            return status;

        case STATE_TERM:
            /* Delegate to the stream bucket to do the read. */
            status = serf_bucket_read(ctx->stream, ctx->body_left, data, len);
            if (SERF_BUCKET_READ_ERROR(status))
                return status;

            /* Some data was read, so decrement the amount left and see
             * if we're done reading the chunk terminator.
             */
            ctx->body_left -= *len;
            if (!ctx->body_left) {
                ctx->state = STATE_SIZE;
            }

            if (status)
                return status;

            break;

        case STATE_DONE:
            /* Just keep returning EOF */
            return APR_EOF;

        default:
            /* Not reachable */
            return APR_EGENERAL;
        }
    }
    /* NOTREACHED */
}
コード例 #22
0
ファイル: old-and-busted.c プロジェクト: Ranga123/test1
/* Allocate an entry from POOL and read it from [*BUF, END).  The
   buffer may be modified in place while parsing.  Return the new
   entry in *NEW_ENTRY.  Advance *BUF to point at the end of the entry
   record.
   The entries file format should be provided in ENTRIES_FORMAT. */
static svn_error_t *
read_entry(svn_wc_entry_t **new_entry,
           char **buf, const char *end,
           int entries_format,
           apr_pool_t *pool)
{
    svn_wc_entry_t *entry = alloc_entry(pool);
    const char *name;

#define MAYBE_DONE if (**buf == '\f') goto done

    /* Find the name and set up the entry under that name. */
    SVN_ERR(read_path(&name, buf, end, pool));
    entry->name = name ? name : SVN_WC_ENTRY_THIS_DIR;

    /* Set up kind. */
    {
        const char *kindstr;
        SVN_ERR(read_val(&kindstr, buf, end));
        if (kindstr)
        {
            if (strcmp(kindstr, ENTRIES_VALUE_FILE) == 0)
                entry->kind = svn_node_file;
            else if (strcmp(kindstr, ENTRIES_VALUE_DIR) == 0)
                entry->kind = svn_node_dir;
            else
                return svn_error_createf
                       (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
                        _("Entry '%s' has invalid node kind"),
                        (name ? name : SVN_WC_ENTRY_THIS_DIR));
        }
        else
            entry->kind = svn_node_none;
    }
    MAYBE_DONE;

    /* Attempt to set revision (resolve_to_defaults may do it later, too) */
    SVN_ERR(read_revnum(&entry->revision, buf, end, pool));
    MAYBE_DONE;

    /* Attempt to set up url path (again, see resolve_to_defaults). */
    SVN_ERR(read_url(&entry->url, buf, end, entries_format, pool));
    MAYBE_DONE;

    /* Set up repository root.  Make sure it is a prefix of url. */
    SVN_ERR(read_url(&entry->repos, buf, end, entries_format, pool));
    if (entry->repos && entry->url
            && ! svn_uri__is_ancestor(entry->repos, entry->url))
        return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
                                 _("Entry for '%s' has invalid repository "
                                   "root"),
                                 name ? name : SVN_WC_ENTRY_THIS_DIR);
    MAYBE_DONE;

    /* Look for a schedule attribute on this entry. */
    {
        const char *schedulestr;
        SVN_ERR(read_val(&schedulestr, buf, end));
        entry->schedule = svn_wc_schedule_normal;
        if (schedulestr)
        {
            if (strcmp(schedulestr, ENTRIES_VALUE_ADD) == 0)
                entry->schedule = svn_wc_schedule_add;
            else if (strcmp(schedulestr, ENTRIES_VALUE_DELETE) == 0)
                entry->schedule = svn_wc_schedule_delete;
            else if (strcmp(schedulestr, ENTRIES_VALUE_REPLACE) == 0)
                entry->schedule = svn_wc_schedule_replace;
            else
                return svn_error_createf(
                           SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
                           _("Entry '%s' has invalid 'schedule' value"),
                           name ? name : SVN_WC_ENTRY_THIS_DIR);
        }
    }
    MAYBE_DONE;

    /* Attempt to set up text timestamp. */
    SVN_ERR(read_time(&entry->text_time, buf, end, pool));
    MAYBE_DONE;

    /* Checksum. */
    SVN_ERR(read_str(&entry->checksum, buf, end, pool));
    MAYBE_DONE;

    /* Setup last-committed values. */
    SVN_ERR(read_time(&entry->cmt_date, buf, end, pool));
    MAYBE_DONE;

    SVN_ERR(read_revnum(&entry->cmt_rev, buf, end, pool));
    MAYBE_DONE;

    SVN_ERR(read_str(&entry->cmt_author, buf, end, pool));
    MAYBE_DONE;

    /* has-props, has-prop-mods, cachable-props, present-props are all
       deprecated. Read any values that may be in the 'entries' file, but
       discard them, and just put default values into the entry. */
    {
        const char *unused_value;

        /* has-props flag. */
        SVN_ERR(read_val(&unused_value, buf, end));
        entry->has_props = FALSE;
        MAYBE_DONE;

        /* has-prop-mods flag. */
        SVN_ERR(read_val(&unused_value, buf, end));
        entry->has_prop_mods = FALSE;
        MAYBE_DONE;

        /* Use the empty string for cachable_props, indicating that we no
           longer attempt to cache any properties. An empty string for
           present_props means that no cachable props are present. */

        /* cachable-props string. */
        SVN_ERR(read_val(&unused_value, buf, end));
        entry->cachable_props = "";
        MAYBE_DONE;

        /* present-props string. */
        SVN_ERR(read_val(&unused_value, buf, end));
        entry->present_props = "";
        MAYBE_DONE;
    }

    /* Is this entry in a state of mental torment (conflict)? */
    {
        SVN_ERR(read_path(&entry->prejfile, buf, end, pool));
        MAYBE_DONE;
        SVN_ERR(read_path(&entry->conflict_old, buf, end, pool));
        MAYBE_DONE;
        SVN_ERR(read_path(&entry->conflict_new, buf, end, pool));
        MAYBE_DONE;
        SVN_ERR(read_path(&entry->conflict_wrk, buf, end, pool));
        MAYBE_DONE;
    }

    /* Is this entry copied? */
    SVN_ERR(read_bool(&entry->copied, ENTRIES_BOOL_COPIED, buf, end));
    MAYBE_DONE;

    SVN_ERR(read_url(&entry->copyfrom_url, buf, end, entries_format, pool));
    MAYBE_DONE;
    SVN_ERR(read_revnum(&entry->copyfrom_rev, buf, end, pool));
    MAYBE_DONE;

    /* Is this entry deleted? */
    SVN_ERR(read_bool(&entry->deleted, ENTRIES_BOOL_DELETED, buf, end));
    MAYBE_DONE;

    /* Is this entry absent? */
    SVN_ERR(read_bool(&entry->absent, ENTRIES_BOOL_ABSENT, buf, end));
    MAYBE_DONE;

    /* Is this entry incomplete? */
    SVN_ERR(read_bool(&entry->incomplete, ENTRIES_BOOL_INCOMPLETE, buf, end));
    MAYBE_DONE;

    /* UUID. */
    SVN_ERR(read_str(&entry->uuid, buf, end, pool));
    MAYBE_DONE;

    /* Lock token. */
    SVN_ERR(read_str(&entry->lock_token, buf, end, pool));
    MAYBE_DONE;

    /* Lock owner. */
    SVN_ERR(read_str(&entry->lock_owner, buf, end, pool));
    MAYBE_DONE;

    /* Lock comment. */
    SVN_ERR(read_str(&entry->lock_comment, buf, end, pool));
    MAYBE_DONE;

    /* Lock creation date. */
    SVN_ERR(read_time(&entry->lock_creation_date, buf, end, pool));
    MAYBE_DONE;

    /* Changelist. */
    SVN_ERR(read_str(&entry->changelist, buf, end, pool));
    MAYBE_DONE;

    /* Keep entry in working copy after deletion? */
    SVN_ERR(read_bool(&entry->keep_local, ENTRIES_BOOL_KEEP_LOCAL, buf, end));
    MAYBE_DONE;

    /* Translated size */
    {
        const char *val;

        /* read_val() returns NULL on an empty (e.g. default) entry line,
           and entry has already been initialized accordingly already */
        SVN_ERR(read_val(&val, buf, end));
        if (val)
            entry->working_size = (apr_off_t)apr_strtoi64(val, NULL, 0);
    }
    MAYBE_DONE;

    /* Depth. */
    {
        const char *result;
        SVN_ERR(read_val(&result, buf, end));
        if (result)
        {
            svn_boolean_t invalid;
            svn_boolean_t is_this_dir;

            entry->depth = svn_depth_from_word(result);

            /* Verify the depth value:
               THIS_DIR should not have an excluded value and SUB_DIR should only
               have excluded value. Remember that infinity value is not stored and
               should not show up here. Otherwise, something bad may have
               happened. However, infinity value itself will always be okay. */
            is_this_dir = !name;
            /* '!=': XOR */
            invalid = is_this_dir != (entry->depth != svn_depth_exclude);
            if (entry->depth != svn_depth_infinity && invalid)
                return svn_error_createf(
                           SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
                           _("Entry '%s' has invalid 'depth' value"),
                           name ? name : SVN_WC_ENTRY_THIS_DIR);
        }
        else
            entry->depth = svn_depth_infinity;

    }
    MAYBE_DONE;

    /* Tree conflict data. */
    SVN_ERR(read_str(&entry->tree_conflict_data, buf, end, pool));
    MAYBE_DONE;

    /* File external URL and revision. */
    {
        const char *str;
        SVN_ERR(read_str(&str, buf, end, pool));
        SVN_ERR(svn_wc__unserialize_file_external(&entry->file_external_path,
                &entry->file_external_peg_rev,
                &entry->file_external_rev,
                str,
                pool));
    }
    MAYBE_DONE;

done:
    *new_entry = entry;
    return SVN_NO_ERROR;
}
コード例 #23
0
ファイル: old-and-busted.c プロジェクト: Ranga123/test1
/* NOTE: this is used for upgrading old XML-based entries file. Be wary of
         removing items.

   ### many attributes are no longer used within the old-style log files.
   ### These attrs need to be recognized for old entries, however. For these
   ### cases, the code will parse the attribute, but not set *MODIFY_FLAGS
   ### for that particular field. MODIFY_FLAGS is *only* used by the
   ### log-based entry modification system, and will go way once we
   ### completely move away from loggy.

   Set *NEW_ENTRY to a new entry, taking attributes from ATTS, whose
   keys and values are both char *.  Allocate the entry and copy
   attributes into POOL as needed. */
static svn_error_t *
atts_to_entry(svn_wc_entry_t **new_entry,
              apr_hash_t *atts,
              apr_pool_t *pool)
{
    svn_wc_entry_t *entry = alloc_entry(pool);
    const char *name;

    /* Find the name and set up the entry under that name. */
    name = svn_hash_gets(atts, ENTRIES_ATTR_NAME);
    entry->name = name ? apr_pstrdup(pool, name) : SVN_WC_ENTRY_THIS_DIR;

    /* Attempt to set revision (resolve_to_defaults may do it later, too)

       ### not used by loggy; no need to set MODIFY_FLAGS  */
    {
        const char *revision_str
            = svn_hash_gets(atts, ENTRIES_ATTR_REVISION);

        if (revision_str)
            entry->revision = SVN_STR_TO_REV(revision_str);
        else
            entry->revision = SVN_INVALID_REVNUM;
    }

    /* Attempt to set up url path (again, see resolve_to_defaults).

       ### not used by loggy; no need to set MODIFY_FLAGS  */
    entry->url = extract_string(atts, ENTRIES_ATTR_URL, pool);
    if (entry->url)
        entry->url = svn_uri_canonicalize(entry->url, pool);

    /* Set up repository root.  Make sure it is a prefix of url.

       ### not used by loggy; no need to set MODIFY_FLAGS  */
    entry->repos = extract_string(atts, ENTRIES_ATTR_REPOS, pool);
    if (entry->repos)
        entry->repos = svn_uri_canonicalize(entry->repos, pool);

    if (entry->url && entry->repos
            && !svn_uri__is_ancestor(entry->repos, entry->url))
        return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
                                 _("Entry for '%s' has invalid repository "
                                   "root"),
                                 name ? name : SVN_WC_ENTRY_THIS_DIR);

    /* Set up kind. */
    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    {
        const char *kindstr
            = svn_hash_gets(atts, ENTRIES_ATTR_KIND);

        entry->kind = svn_node_none;
        if (kindstr)
        {
            if (strcmp(kindstr, ENTRIES_VALUE_FILE) == 0)
                entry->kind = svn_node_file;
            else if (strcmp(kindstr, ENTRIES_VALUE_DIR) == 0)
                entry->kind = svn_node_dir;
            else
                return svn_error_createf
                       (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
                        _("Entry '%s' has invalid node kind"),
                        (name ? name : SVN_WC_ENTRY_THIS_DIR));
        }
    }

    /* Look for a schedule attribute on this entry. */
    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    {
        const char *schedulestr
            = svn_hash_gets(atts, ENTRIES_ATTR_SCHEDULE);

        entry->schedule = svn_wc_schedule_normal;
        if (schedulestr)
        {
            if (strcmp(schedulestr, ENTRIES_VALUE_ADD) == 0)
                entry->schedule = svn_wc_schedule_add;
            else if (strcmp(schedulestr, ENTRIES_VALUE_DELETE) == 0)
                entry->schedule = svn_wc_schedule_delete;
            else if (strcmp(schedulestr, ENTRIES_VALUE_REPLACE) == 0)
                entry->schedule = svn_wc_schedule_replace;
            else if (strcmp(schedulestr, "") == 0)
                entry->schedule = svn_wc_schedule_normal;
            else
                return svn_error_createf(
                           SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
                           _("Entry '%s' has invalid 'schedule' value"),
                           (name ? name : SVN_WC_ENTRY_THIS_DIR));
        }
    }

    /* Is this entry in a state of mental torment (conflict)? */
    entry->prejfile = extract_string_normalize(atts,
                      ENTRIES_ATTR_PREJFILE,
                      pool);
    entry->conflict_old = extract_string_normalize(atts,
                          ENTRIES_ATTR_CONFLICT_OLD,
                          pool);
    entry->conflict_new = extract_string_normalize(atts,
                          ENTRIES_ATTR_CONFLICT_NEW,
                          pool);
    entry->conflict_wrk = extract_string_normalize(atts,
                          ENTRIES_ATTR_CONFLICT_WRK,
                          pool);

    /* Is this entry copied? */
    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    SVN_ERR(do_bool_attr(&entry->copied, atts, ENTRIES_ATTR_COPIED, name));

    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    entry->copyfrom_url = extract_string(atts, ENTRIES_ATTR_COPYFROM_URL, pool);

    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    {
        const char *revstr;

        revstr = svn_hash_gets(atts, ENTRIES_ATTR_COPYFROM_REV);
        if (revstr)
            entry->copyfrom_rev = SVN_STR_TO_REV(revstr);
    }

    /* Is this entry deleted?

       ### not used by loggy; no need to set MODIFY_FLAGS  */
    SVN_ERR(do_bool_attr(&entry->deleted, atts, ENTRIES_ATTR_DELETED, name));

    /* Is this entry absent?

       ### not used by loggy; no need to set MODIFY_FLAGS  */
    SVN_ERR(do_bool_attr(&entry->absent, atts, ENTRIES_ATTR_ABSENT, name));

    /* Is this entry incomplete?

       ### not used by loggy; no need to set MODIFY_FLAGS  */
    SVN_ERR(do_bool_attr(&entry->incomplete, atts, ENTRIES_ATTR_INCOMPLETE,
                         name));

    /* Attempt to set up timestamps. */
    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    {
        const char *text_timestr;

        text_timestr = svn_hash_gets(atts, ENTRIES_ATTR_TEXT_TIME);
        if (text_timestr)
            SVN_ERR(svn_time_from_cstring(&entry->text_time, text_timestr, pool));

        /* Note: we do not persist prop_time, so there is no need to attempt
           to parse a new prop_time value from the log. Certainly, on any
           recent working copy, there will not be a log record to alter
           the prop_time value. */
    }

    /* Checksum. */
    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    entry->checksum = extract_string(atts, ENTRIES_ATTR_CHECKSUM, pool);

    /* UUID.

       ### not used by loggy; no need to set MODIFY_FLAGS  */
    entry->uuid = extract_string(atts, ENTRIES_ATTR_UUID, pool);

    /* Setup last-committed values. */
    {
        const char *cmt_datestr, *cmt_revstr;

        cmt_datestr = svn_hash_gets(atts, ENTRIES_ATTR_CMT_DATE);
        if (cmt_datestr)
        {
            SVN_ERR(svn_time_from_cstring(&entry->cmt_date, cmt_datestr, pool));
        }
        else
            entry->cmt_date = 0;

        cmt_revstr = svn_hash_gets(atts, ENTRIES_ATTR_CMT_REV);
        if (cmt_revstr)
        {
            entry->cmt_rev = SVN_STR_TO_REV(cmt_revstr);
        }
        else
            entry->cmt_rev = SVN_INVALID_REVNUM;

        entry->cmt_author = extract_string(atts, ENTRIES_ATTR_CMT_AUTHOR, pool);
    }

    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    entry->lock_token = extract_string(atts, ENTRIES_ATTR_LOCK_TOKEN, pool);
    entry->lock_owner = extract_string(atts, ENTRIES_ATTR_LOCK_OWNER, pool);
    entry->lock_comment = extract_string(atts, ENTRIES_ATTR_LOCK_COMMENT, pool);
    {
        const char *cdate_str =
            svn_hash_gets(atts, ENTRIES_ATTR_LOCK_CREATION_DATE);
        if (cdate_str)
        {
            SVN_ERR(svn_time_from_cstring(&entry->lock_creation_date,
                                          cdate_str, pool));
        }
    }
    /* ----- end of lock handling.  */

    /* Note: if there are attributes for the (deprecated) has_props,
       has_prop_mods, cachable_props, or present_props, then we're just
       going to ignore them. */

    /* Translated size */
    /* ### not used by loggy; no need to set MODIFY_FLAGS  */
    {
        const char *val = svn_hash_gets(atts, ENTRIES_ATTR_WORKING_SIZE);
        if (val)
        {
            /* Cast to off_t; it's safe: we put in an off_t to start with... */
            entry->working_size = (apr_off_t)apr_strtoi64(val, NULL, 0);
        }
    }

    *new_entry = entry;
    return SVN_NO_ERROR;
}
コード例 #24
0
ファイル: teststr.c プロジェクト: kheradmand/Break
static void string_strtoi64(CuTest *tc)
{
    static const struct {
        int errnum, base;
        const char *in, *end;
        apr_int64_t result;
    } ts[] = {
        
        /* base 10 tests */
        { 0, 10, "123545", NULL, APR_INT64_C(123545) },
        { 0, 10, "   123545", NULL, APR_INT64_C(123545) },
        { 0, 10, "   +123545", NULL, APR_INT64_C(123545) },
        { 0, 10, "-123545", NULL, APR_INT64_C(-123545) },
        { 0, 10, "   00000123545", NULL, APR_INT64_C(123545) },
        { 0, 10, "123545ZZZ", "ZZZ", APR_INT64_C(123545) },
        { 0, 10, "   123545   ", "   ", APR_INT64_C(123545) },

        /* base 16 tests */
        { 0, 16, "1E299", NULL, APR_INT64_C(123545) },
        { 0, 16, "1e299", NULL, APR_INT64_C(123545) },
        { 0, 16, "0x1e299", NULL, APR_INT64_C(123545) },
        { 0, 16, "0X1E299", NULL, APR_INT64_C(123545) },
        { 0, 16, "+1e299", NULL, APR_INT64_C(123545) },
        { 0, 16, "-1e299", NULL, APR_INT64_C(-123545) },
        { 0, 16, "   -1e299", NULL, APR_INT64_C(-123545) },

        /* automatic base detection tests */
        { 0, 0, "123545", NULL, APR_INT64_C(123545) },
        { 0, 0, "0x1e299", NULL, APR_INT64_C(123545) },
        { 0, 0, "  0x1e299", NULL, APR_INT64_C(123545) },
        { 0, 0, "+0x1e299", NULL, APR_INT64_C(123545) },
        { 0, 0, "-0x1e299", NULL, APR_INT64_C(-123545) },

        /* large number tests */
        { 0, 10, "8589934605", NULL, APR_INT64_C(8589934605) },
        { 0, 10, "-8589934605", NULL, APR_INT64_C(-8589934605) },
        { 0, 16, "0x20000000D", NULL, APR_INT64_C(8589934605) },
        { 0, 16, "-0x20000000D", NULL, APR_INT64_C(-8589934605) },
        { 0, 16, "   0x20000000D", NULL, APR_INT64_C(8589934605) },
        { 0, 16, "   0x20000000D", NULL, APR_INT64_C(8589934605) },

        /* error cases */
        { ERANGE, 10, "999999999999999999999999999999999", "", MY_LLONG_MAX },
        { ERANGE, 10, "-999999999999999999999999999999999", "", MY_LLONG_MIN },

#if 0
        /* C99 doesn't require EINVAL for an invalid range. */
        { EINVAL, 99, "", (void *)-1 /* don't care */, 0 },
#endif

        /* some strtoll implementations give EINVAL when no conversion
         * is performed. */
        { -1 /* don't care */, 10, "zzz", "zzz", APR_INT64_C(0) },
        { -1 /* don't care */, 10, "", NULL, APR_INT64_C(0) }

    };
    int n;

    for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {
        char *end = "end ptr not changed";
        apr_int64_t result;
        int errnum;
        
        errno = 0;
        result = apr_strtoi64(ts[n].in, &end, ts[n].base);
        errnum = errno;

        CuAssert(tc,
                 apr_psprintf(p, "for '%s': result was %" APR_INT64_T_FMT 
                              " not %" APR_INT64_T_FMT, ts[n].in,
                              result, ts[n].result),
                 result == ts[n].result);
        
        if (ts[n].errnum != -1) {
            CuAssert(tc,
                     apr_psprintf(p, "for '%s': errno was %d not %d", ts[n].in,
                                  errnum, ts[n].errnum),
                     ts[n].errnum == errnum);
        }

        if (ts[n].end == NULL) {
            /* end must point to NUL terminator of .in */
            CuAssertPtrEquals(tc, ts[n].in + strlen(ts[n].in), end);
        } else if (ts[n].end != (void *)-1) {
            CuAssert(tc,
                     apr_psprintf(p, "for '%s', end was '%s' not '%s'",
                                  ts[n].in, end, ts[n].end),
                     strcmp(ts[n].end, end) == 0);
        }
    }
}
コード例 #25
0
ファイル: apr_strings.c プロジェクト: Ga-vin/apache
APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf)
{
    return apr_strtoi64(buf, NULL, 10);
}
コード例 #26
0
ファイル: h2_request.c プロジェクト: Sp1l/mod_h2
static apr_status_t inspect_clen(h2_request *req, const char *s)
{
    char *end;
    req->content_length = apr_strtoi64(s, &end, 10);
    return (s == end)? APR_EINVAL : APR_SUCCESS;
}
コード例 #27
0
static int
validate_webid(request_rec *request, const char *subjAltName, char *pkey_n, unsigned int pkey_e_i) {
    int r = HTTP_UNAUTHORIZED;

    librdf_world *rdf_world = NULL;
    librdf_storage *rdf_storage = NULL;
    librdf_model *rdf_model = NULL;
    librdf_query *rdf_query = NULL;
    librdf_query_results *rdf_query_results = NULL;

    rdf_world = librdf_new_world();
    if (rdf_world != NULL) {
        librdf_world_open(rdf_world);
        librdf_world_set_logger(rdf_world, (void *)request, ap_rdf_log_proxy);
        rdf_storage = librdf_new_storage(rdf_world, "uri", subjAltName, NULL);
        if (rdf_storage != NULL) {
            rdf_model = librdf_new_model(rdf_world, rdf_storage, NULL);
        } else
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, "WebID: librdf_new_storage returned NULL");
    }

    if (rdf_model != NULL) {
        char *c_query = apr_psprintf(request->pool, SPARQL_WEBID, subjAltName);
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: SPARQL query   = %s", c_query);
        rdf_query = librdf_new_query(rdf_world, "sparql", NULL, (unsigned char*)c_query, NULL);
    } else {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, "WebID: librdf_new_query returned NULL");
    }

    if (rdf_query != NULL) {
        rdf_query_results = librdf_query_execute(rdf_query, rdf_model);
        if (rdf_query_results != NULL) {
            for (; r != OK && librdf_query_results_finished(rdf_query_results)==0; librdf_query_results_next(rdf_query_results)) {
                librdf_node *m_node, *e_node;
                unsigned char *rdf_mod;
                unsigned char *rdf_exp;
                if (r != OK
                    && NULL != (m_node = librdf_query_results_get_binding_value_by_name(rdf_query_results, "m"))
                    && NULL != (e_node = librdf_query_results_get_binding_value_by_name(rdf_query_results, "e"))) {
                    if (librdf_node_get_type(m_node) == LIBRDF_NODE_TYPE_LITERAL
                        && librdf_node_get_type(e_node) == LIBRDF_NODE_TYPE_LITERAL) {
                        rdf_mod = librdf_node_get_literal_value(m_node);
                        rdf_exp = librdf_node_get_literal_value(e_node);
                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: modulus = %s", rdf_mod);
                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: exponent = %s", rdf_exp);
                        if (rdf_exp != NULL
                            && apr_strtoi64((char*)rdf_exp, NULL, 10) == pkey_e_i
                            && matches_pkey(rdf_mod, pkey_n))
                            r = OK;
                        librdf_free_node(m_node);
                        librdf_free_node(e_node);
                    }
                }
            }
            librdf_free_query_results(rdf_query_results);
        } else
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, "WebID: librdf_query_execute returned NULL");
        librdf_free_query(rdf_query);
    } else
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, "WebID: librdf_new_query returned NULL");

    if (rdf_model) librdf_free_model(rdf_model);
    if (rdf_storage) librdf_free_storage(rdf_storage);
    if (rdf_world) librdf_free_world(rdf_world);

    return r;
}