Beispiel #1
0
static void dav_append_prop(apr_pool_t *pool,
                            const char *name, const char *value,
                            apr_text_header *phdr)
{
    const char *s;
    const char *lang = value;

    /* skip past the xml:lang value */
    value += strlen(lang) + 1;

    if (*value == '\0') {
        /* the property is an empty value */
        if (*name == ':') {
            /* "no namespace" case */
            s = apr_psprintf(pool, "<%s/>" DEBUG_CR, name+1);
        }
        else {
            s = apr_psprintf(pool, "<ns%s/>" DEBUG_CR, name);
        }
    }
    else if (*lang != '\0') {
        if (*name == ':') {
            /* "no namespace" case */
            s = apr_psprintf(pool, "<%s xml:lang=\"%s\">%s</%s>" DEBUG_CR,
                             name+1, lang, value, name+1);
        }
        else {
            s = apr_psprintf(pool, "<ns%s xml:lang=\"%s\">%s</ns%s>" DEBUG_CR,
                             name, lang, value, name);
        }
    }
    else if (*name == ':') {
        /* "no namespace" case */
        s = apr_psprintf(pool, "<%s>%s</%s>" DEBUG_CR, name+1, value, name+1);
    }
    else {
        s = apr_psprintf(pool, "<ns%s>%s</ns%s>" DEBUG_CR, name, value, name);
    }

    apr_text_append(pool, phdr, s);
}
Beispiel #2
0
const char *Unparse(apr_pool_t *pool, struct Type *type) {
    if (type == NULL)
        return "?";
    else switch (type->primitive) {
        case typename_P: return "#";
        case union_P: return apr_psprintf(pool, "(%s)", Unparse(pool, &type->data.signature));
        case string_P: return "*";
        case selector_P: return ":";
        case block_P: return "@?";
        case object_P: return type->name == NULL ? "@" : apr_psprintf(pool, "@\"%s\"", type->name);
        case boolean_P: return "B";
        case uchar_P: return "C";
        case uint_P: return "I";
        case ulong_P: return "L";
        case ulonglong_P: return "Q";
        case ushort_P: return "S";

        case array_P: {
            const char *value = Unparse(pool, type->data.data.type);
            return apr_psprintf(pool, "[%"APR_SIZE_T_FMT"%s]", type->data.data.size, value);
        } break;

        case pointer_P: return apr_psprintf(pool, "^%s", type->data.data.type == NULL ? "v" : Unparse(pool, type->data.data.type));
        case bit_P: return apr_psprintf(pool, "b%"APR_SIZE_T_FMT"", type->data.data.size);
        case char_P: return "c";
        case double_P: return "d";
        case float_P: return "f";
        case int_P: return "i";
        case long_P: return "l";
        case longlong_P: return "q";
        case short_P: return "s";
        case void_P: return "v";
        case struct_P: return apr_psprintf(pool, "{%s=%s}", type->name == NULL ? "?" : type->name, Unparse(pool, &type->data.signature));
    }

    _assert(false);
    return NULL;
}
Beispiel #3
0
void oss_get_bucket_uri(const oss_request_options_t *options, 
                        const aos_string_t *bucket,
                        aos_http_request_t *req)
{
    int32_t proto_len;
    const char *raw_endpoint_str;
    aos_string_t raw_endpoint;

    generate_proto(options, req);

    proto_len = strlen(req->proto);
    raw_endpoint_str = aos_pstrdup(options->pool, 
            &options->config->endpoint) + proto_len;
    raw_endpoint.len = options->config->endpoint.len - proto_len;
    raw_endpoint.data = options->config->endpoint.data + proto_len;

    if (is_valid_ip(raw_endpoint_str)) {
        req->resource = apr_psprintf(options->pool, "%.*s", 
                bucket->len, bucket->data);
    } else {
        req->resource = apr_psprintf(options->pool, "%.*s/", 
                bucket->len, bucket->data);
    }
    
    if (options->config->is_cname || 
        is_valid_ip(raw_endpoint_str))
    {
        req->host = apr_psprintf(options->pool, "%.*s", 
                raw_endpoint.len, raw_endpoint.data);
        req->uri = apr_psprintf(options->pool, "%.*s", bucket->len, 
                                bucket->data);
    } else {
        req->host = apr_psprintf(options->pool, "%.*s.%.*s", 
                bucket->len, bucket->data, 
                raw_endpoint.len, raw_endpoint.data);
        req->uri = apr_psprintf(options->pool, "%s", "");
    }
}
Beispiel #4
0
apr_status_t http_send_custom_response(nproxy_connection_t * conn, http_resp_codes_t error_code) {
    size_t t;
    int clen;
    int e_code;
    char *tpl = NULL;
    char *e_msg = NULL;
    char *e_text = NULL;
    char *e_detail = NULL;
    char *payload = NULL;
    char found = 0;
    char timebuf[APR_RFC822_DATE_LEN];
    char *additional_headers = "";
    const char *tmp = NULL;
    nproxy_connection_side_t *side;
    apr_status_t rv;
    apr_size_t len;

    const char *fallback_error =
        "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
        "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
        "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
        "<html>\n" "<head><title>%d %s</title></head>\n" "<body>\n" "<h1>%d %s</h1>\n" "<p>%s</p>\n" "<hr />\n" "<p><em>Generated by NProxy</em></p>\n" "</body>\n" "</html>\n";

    side = conn->browser;

    apr_rfc822_date(timebuf, apr_time_now());

    for (t = 0; t < sizeof(ec) / sizeof(ec[0]); t++) {
        if (error_code == ec[t].code) {
            e_code = ec[t].number;
            e_msg = ec[t].string;
            found = 1;
            break;
        }
    }

    if (!found) {
        e_msg = "Error code string not found.";
        e_code = error_code;
    }

    e_detail = "No details, sorry.";

    if ((tmp = nproxy_connection_get_variable(conn, "additional_headers"))) {
        if (!zstr(tmp)) {
            additional_headers = (char *) tmp;
        }
    }
    if ((tmp = nproxy_connection_get_variable(conn, "custom_cause"))) {
        if (!zstr(tmp)) {
            e_msg = (char *) tmp;
        }
    }
    if ((tmp = nproxy_connection_get_variable(conn, "custom_detail"))) {
        if (!zstr(tmp)) {
            e_detail = (char *) tmp;
        }
    }

    tmp = nproxy_connection_get_variable(conn, "custom_template");
    tpl = find_template(conn, e_code, tmp);

    if (tpl != NULL) {
        if (conn->requests != NULL) {
            nproxy_connection_set_variable(conn, "req_method", conn->requests->method);
            nproxy_connection_set_variable(conn, "req_host", conn->requests->host);
            nproxy_connection_set_variable(conn, "req_port", apr_psprintf(conn->pool, "%d", conn->requests->port));
            nproxy_connection_set_variable(conn, "req_url", conn->requests->url);
        }
        nproxy_connection_set_variable(conn, "resp_errno", apr_psprintf(conn->pool, "%d", e_code));
        nproxy_connection_set_variable(conn, "resp_cause", e_msg);
        nproxy_connection_set_variable(conn, "resp_detail", e_detail);
        nproxy_connection_set_variable(conn, "package", "NProxy");
        e_text = parse_template(conn, tpl);
    }

    if (zstr(e_text)) {
        e_text = apr_psprintf(conn->pool, fallback_error, e_code, e_msg, e_code, e_msg, e_detail);
    }

    clen = strlen(e_text);

    payload = apr_psprintf(conn->pool,
                           "%s %d %s\r\n"
                           "Content-Type: text/html\r\n"
                           "Connection: close\r\n"
                           "Proxy-Connection: close\r\n" "Content-Length: %d\r\n" "Date: %s\r\n" "%s" "\r\n" "%s", "HTTP/1.0", e_code, e_msg, clen, timebuf, additional_headers, e_text);

    len = strlen(payload);
    rv = apr_socket_send(side->sock, payload, &len);
    if (rv == APR_STATUS_SUCCESS) {
        if (conn->requests != NULL) {
            conn->requests->bytes_in += len;
            conn->requests->response_headers.resp_code = error_code;
        }
    } else {
        rv = APR_STATUS_ERROR;
    }

    return rv;
}
Beispiel #5
0
void * APR_THREAD_FUNC sync_dir(apr_thread_t* thread, void* ptr){
	int files_synced = 0;
	int status;
	apr_status_t rv;
	const char* dbd_error;
	List* file_list;

	music_file* song;

	dir_sync_thread_t* dir_sync = (dir_sync_thread_t*) ptr;
	apr_pool_t* pool;
	
	db_config_t* db_config = dir_sync->db_config;
	char error_message[256];

	//Create sub pool used for sync
	rv = apr_pool_create_ex(&pool, dir_sync->pool, NULL, NULL);
	if(rv != APR_SUCCESS){
		error_messages_add(dir_sync->error_messages, ERROR ,"Memory Pool Error", apr_strerror(rv, error_message, sizeof(error_message)));
		return 0;
	}

	file_list = apr_pcalloc(pool, sizeof(List));
	dir_sync->dir->stats->num_files = apr_pcalloc(pool, sizeof(int));

	if(db_config->connected != 1){
		error_messages_add(dir_sync->error_messages, ERROR, "Database not connected","ERROR ERROR");
		return 0;
	}

	count_table_rows();


	read_dir(pool, file_list, dir_sync->dir->path, dir_sync->dir->stats->num_files,  dir_sync->error_messages);

	if ((file_list == NULL || dir_sync->dir->stats->num_files == NULL )&& (*dir_sync->dir->stats->num_files ) > 0 ){
		error_messages_add(dir_sync->error_messages, ERROR, "Killing Sync Thread", "");
		return 0;
	}

	status = apr_dbd_transaction_start(db_config->dbd_driver, pool, db_config->dbd_handle,&(db_config->transaction));
	if(status != 0){
		dbd_error = apr_dbd_error(db_config->dbd_driver, db_config->dbd_handle, status);
		error_messages_add(dir_sync->error_messages,ERROR, "Database error start transaction", dbd_error);
		return 0;
	}
	while(file_list->file.path){
		  song = apr_pcalloc(pool, sizeof(music_file));
		  song->file = &(file_list->file);
		  switch(song->file->type){
#ifdef WITH_FLAC
		  	  case FLAC:{
		  		status = read_flac_level1(pool, song);
		  		if (status == 0){
		  			song->file->type_string = "flac";
		  		}
		  		break;
		  	  }
#endif
#ifdef WITH_OGG
		  	  case OGG:{
		  		status = read_ogg(pool, song);
		  		if (status == 0){
		  			song->file->type_string = "ogg";
		  		}
		  		break;
		  	  }
#endif
#ifdef WITH_MP3
		  	  case MP3:{
		  		  status = read_id3(pool,song);
			  	if (status == 0){
			  		song->file->type_string = "mp3";
			  	}
			  	break;
		  	  }
#endif
		  	 default:{
		  		  status = -1;
		  		  break;
		  	  }
		  }



		  if (status == 0 && song){
			  //We have song get musicbrainz ids
			  //status = get_musicbrainz_release_id(pool, song, dir_sync->error_messages);
			  //Update or Insert song
			  if (db_config->connected == 1){
				  status = sync_song(pool, db_config, song);
				  if (status != 0){
					error_messages_add(dir_sync->error_messages, ERROR, apr_psprintf(pool,"Failed to sync song:"),  apr_psprintf(pool, "(%d) Song title: %s Song artist: %s song album:%s song file path: %s",status, song->title, song->artist, song->album, song->file->path));
				  }
			  }else{
				  //Lost connection kill thread
				  error_messages_add(dir_sync->error_messages, ERROR, "Failed to sync song:",  "Lost connection to database");
				  return 0;
			  }
		  }
		  //Calculate the percent of files synchronized
		  dir_sync->dir->stats->sync_progress =(float) files_synced*100 / (*(dir_sync->dir->stats->num_files) - 1);
		  dir_sync->dir->stats->files_scanned = files_synced;
		  files_synced++;
		  file_list = file_list->next;
	}
	status = apr_dbd_transaction_end(db_config->dbd_driver, pool, db_config->transaction);
	if(status != 0){
		dbd_error = apr_dbd_error(db_config->dbd_driver, db_config->dbd_handle, status);
		error_messages_add(dir_sync->error_messages, ERROR, "Database error couldn't end transaction",dbd_error);
		return 0;
	}

	apr_pool_clear(pool);
	return 0;
}
Beispiel #6
0
/*
 * get the full path to the metadata file for a specified issuer and directory
 */
static const char *oidc_metadata_file_path(request_rec *r, oidc_cfg *cfg,
		const char *issuer, const char *type) {
	return apr_psprintf(r->pool, "%s/%s.%s", cfg->metadata_dir,
			oidc_metadata_issuer_to_filename(r, issuer), type);
}
Beispiel #7
0
void ap_mpm_child_main(apr_pool_t *pconf)
{
    ap_listen_rec *lr = NULL;
    int requests_this_child = 0;
    int rv = 0;
    unsigned long ulTimes;
    int my_pid = getpid();
    ULONG rc, c;
    HQUEUE workq;
    apr_pollset_t *pollset;
    int num_listeners;
    TID server_maint_tid;
    void *sb_mem;

    /* Stop Ctrl-C/Ctrl-Break signals going to child processes */
    DosSetSignalExceptionFocus(0, &ulTimes);
    set_signals();

    /* Create pool for child */
    apr_pool_create(&pchild, pconf);

    ap_run_child_init(pchild, ap_server_conf);

    /* Create an event semaphore used to trigger other threads to shutdown */
    rc = DosCreateEventSem(NULL, &shutdown_event, 0, FALSE);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "unable to create shutdown semaphore, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Gain access to the scoreboard. */
    rc = DosGetNamedSharedMem(&sb_mem, ap_scoreboard_fname,
                              PAG_READ|PAG_WRITE);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "scoreboard not readable in child, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    ap_calc_scoreboard_size();
    ap_init_scoreboard(sb_mem);

    /* Gain access to the accpet mutex */
    rc = DosOpenMutexSem(NULL, &ap_mpm_accept_mutex);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "accept mutex couldn't be accessed in child, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Find our pid in the scoreboard so we know what slot our parent allocated us */
    for (child_slot = 0; ap_scoreboard_image->parent[child_slot].pid != my_pid && child_slot < HARD_SERVER_LIMIT; child_slot++);

    if (child_slot == HARD_SERVER_LIMIT) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
                     "child pid not found in scoreboard, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    ap_my_generation = ap_scoreboard_image->parent[child_slot].generation;
    memset(ap_scoreboard_image->servers[child_slot], 0, sizeof(worker_score) * HARD_THREAD_LIMIT);

    /* Set up an OS/2 queue for passing connections & termination requests
     * to worker threads
     */
    rc = DosCreateQueue(&workq, QUE_FIFO, apr_psprintf(pchild, "/queues/httpd/work.%d", my_pid));

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "unable to create work queue, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Create initial pool of worker threads */
    for (c = 0; c < ap_min_spare_threads; c++) {
//        ap_scoreboard_image->servers[child_slot][c].tid = _beginthread(worker_main, NULL, 128*1024, (void *)c);
    }

    /* Start maintenance thread */
    server_maint_tid = _beginthread(server_maintenance, NULL, 32768, NULL);

    /* Set up poll */
    for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) {
        num_listeners++;
    }

    apr_pollset_create(&pollset, num_listeners, pchild, 0);

    for (lr = ap_listeners; lr != NULL; lr = lr->next) {
        apr_pollfd_t pfd = { 0 };

        pfd.desc_type = APR_POLL_SOCKET;
        pfd.desc.s = lr->sd;
        pfd.reqevents = APR_POLLIN;
        pfd.client_data = lr;
        apr_pollset_add(pollset, &pfd);
    }

    /* Main connection accept loop */
    do {
        apr_pool_t *pconn;
        worker_args_t *worker_args;
        int last_poll_idx = 0;

        apr_pool_create(&pconn, pchild);
        worker_args = apr_palloc(pconn, sizeof(worker_args_t));
        worker_args->pconn = pconn;

        if (num_listeners == 1) {
            rv = apr_socket_accept(&worker_args->conn_sd, ap_listeners->sd, pconn);
        } else {
            const apr_pollfd_t *poll_results;
            apr_int32_t num_poll_results;

            rc = DosRequestMutexSem(ap_mpm_accept_mutex, SEM_INDEFINITE_WAIT);

            if (shutdown_pending) {
                DosReleaseMutexSem(ap_mpm_accept_mutex);
                break;
            }

            rv = APR_FROM_OS_ERROR(rc);

            if (rv == APR_SUCCESS) {
                rv = apr_pollset_poll(pollset, -1, &num_poll_results, &poll_results);
                DosReleaseMutexSem(ap_mpm_accept_mutex);
            }

            if (rv == APR_SUCCESS) {
                if (last_poll_idx >= num_listeners) {
                    last_poll_idx = 0;
                }

                lr = poll_results[last_poll_idx++].client_data;
                rv = apr_socket_accept(&worker_args->conn_sd, lr->sd, pconn);
                last_poll_idx++;
            }
        }

        if (rv != APR_SUCCESS) {
            if (!APR_STATUS_IS_EINTR(rv)) {
                ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
                             "apr_socket_accept");
                clean_child_exit(APEXIT_CHILDFATAL);
            }
        } else {
            DosWriteQueue(workq, WORKTYPE_CONN, sizeof(worker_args_t), worker_args, 0);
            requests_this_child++;
        }

        if (ap_max_requests_per_child != 0 && requests_this_child >= ap_max_requests_per_child)
            break;
    } while (!shutdown_pending && ap_my_generation == ap_scoreboard_image->global->running_generation);

    ap_scoreboard_image->parent[child_slot].quiescing = 1;
    DosPostEventSem(shutdown_event);
    DosWaitThread(&server_maint_tid, DCWW_WAIT);

    if (is_graceful) {
        char someleft;

        /* tell our worker threads to exit */
        for (c=0; c<HARD_THREAD_LIMIT; c++) {
            if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                DosWriteQueue(workq, WORKTYPE_EXIT, 0, NULL, 0);
            }
        }

        do {
            someleft = 0;

            for (c=0; c<HARD_THREAD_LIMIT; c++) {
                if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                    someleft = 1;
                    DosSleep(1000);
                    break;
                }
            }
        } while (someleft);
    } else {
        DosPurgeQueue(workq);

        for (c=0; c<HARD_THREAD_LIMIT; c++) {
            if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                DosKillThread(ap_scoreboard_image->servers[child_slot][c].tid);
            }
        }
    }

    apr_pool_destroy(pchild);
}
Beispiel #8
0
/**
 * Open a stream. Used for PUT
 * @param resource The resource to open
 * @param mode     The mode (basically, trucate or random, which we don't support)
 * @param stream   Where to put the created structure
 * @return         NULL on success
 */
static dav_error *dav_ns_open_stream(const dav_resource *resource,
                                      dav_stream_mode mode,
                                      dav_stream **stream)
{
  dav_resource_private     *info;
  unsigned                  has_range;
  const char               *range, *length;
  int                       e;

  info = resource->info;
  
  /* Must be writable (if we are here, they want to write) */
  if (!(info->d_conf->flags & DAV_NS_WRITE))
    return dav_shared_new_error(info->request, NULL, HTTP_FORBIDDEN,
                                "Configured as read-only endpoint (%s)",
                                resource->uri);

  /* If content-length is 0, call create instead of put! */
  length = apr_table_get(info->request->headers_in, "content-length");
  if (length != NULL) {
    size_t clen = atol(length);
    if (clen == 0) {
      ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0,
                    info->request,
                    "PUT with content-length 0. Creating ns entry.");

      if (dmlite_create(info->ctx, info->sfn, 0644) != 0)
        return dav_shared_new_error(info->request, info->ctx, 0,
                                    "Could not create empty file %s", info->sfn);

      *stream = (dav_stream*)calloc(1, sizeof(dav_stream));

      return NULL;
    }
  }

  /* NS alone doesn't support PUTs with content! */
  if (info->s_conf->type == DAV_NS_NODE_LFC)
    return dav_shared_new_error(info->request, NULL, HTTP_NOT_IMPLEMENTED,
                                "LFC does not support PUTs");

  /*  Range header? */
  range = apr_table_get(info->request->headers_in, "content-range");
  has_range = (range != NULL);
  if (has_range) {
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0,
                  info->request,
                  "Range: %s", range);
  }

  /* If token not set, call dm_put and see where do we have to go */
  if (info->space_token != NULL) {
    dmlite_any* any = dmlite_any_new_string(info->space_token);
    e = dmlite_set(info->ctx, "SpaceToken", any);
    dmlite_any_free(any);
    if (e)
      return dav_shared_new_error(info->request, info->ctx, 0,
                                 "Could not set the space token %s", info->space_token);
  }
  
  dmlite_location *location; 
  location = dmlite_put(info->ctx, info->sfn);
  switch (dmlite_errno(info->ctx)) {
    case 0:
      break;
    case DM_INVALID_VALUE:
      return dav_shared_new_error(info->request, info->ctx, HTTP_BAD_REQUEST,
                                  "Can not get the space token %s",
                                  info->space_token);
    default:
      return dav_shared_new_error(info->request, info->ctx, 0, "Can not put %s",
                                  info->sfn);
  }      

  /* Redirect */
  info->redirect = apr_psprintf(resource->pool, "%s://%s%s%s",
                                info->d_conf->redir_scheme,
                                location->chunks[0].host,
                                location->chunks[0].path,
                                dav_shared_build_extra(resource->pool,
                                                       location->chunks[0].extra));

  ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0,
                info->request,
                "PUT request to be done in %s",
                info->redirect);

  apr_table_set(info->request->headers_out,
                "Location", info->redirect);
  
  dmlite_location_free(info->ctx, location);
  
  /* Standard says 301/302, but some clients will retry in that case with a GET.
   * 307 is unambiguous */
  return dav_new_error(resource->pool, HTTP_TEMPORARY_REDIRECT, 0,
                       info->redirect);
}
Beispiel #9
0
/**
 * Get an ETag
 * @param resource The resource from where retrieve the tag
 * @return         The tag value
 */
static const char *dav_ns_getetag(const dav_resource *resource)
{
  return apr_psprintf(resource->pool, "%lx-%lx",
                      (unsigned long)resource->info->stat.stat.st_ino,
                      (unsigned long)resource->info->stat.stat.st_mtime);
}
svn_error_t *
svn_ra_neon__get_location_segments(svn_ra_session_t *session,
                                   const char *path,
                                   svn_revnum_t peg_revision,
                                   svn_revnum_t start_rev,
                                   svn_revnum_t end_rev,
                                   svn_location_segment_receiver_t receiver,
                                   void *receiver_baton,
                                   apr_pool_t *pool)

{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body;
  svn_error_t *err;
  get_location_segments_baton_t request_baton;
  const char *bc_url;
  const char *bc_relative;
  const char *bc;
  int status_code = 0;
  apr_pool_t *subpool = svn_pool_create(pool);

  /* Build the request body. */
  request_body = svn_stringbuf_create("", subpool);
  svn_stringbuf_appendcstr(request_body,
                           "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                           DEBUG_CR "<S:get-location-segments xmlns:S=\""
                           SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">" DEBUG_CR);

  /* Tack on the path... */
  svn_stringbuf_appendcstr(request_body, "<S:path>");
  svn_stringbuf_appendcstr(request_body, apr_xml_quote_string(subpool, path, 0));
  svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);

  /* ...and maybe a peg revision... */
  if (SVN_IS_VALID_REVNUM(peg_revision))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:peg-revision>%ld</S:peg-revision>"
                                  DEBUG_CR, peg_revision));

  /* ...and maybe a start revision... */
  if (SVN_IS_VALID_REVNUM(start_rev))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:start-revision>%ld</S:start-revision>"
                                  DEBUG_CR, start_rev));

  /* ...and maybe an end revision. */
  if (SVN_IS_VALID_REVNUM(end_rev))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:end-revision>%ld</S:end-revision>"
                                  DEBUG_CR, end_rev));

  svn_stringbuf_appendcstr(request_body, "</S:get-location-segments>");

  request_baton.receiver = receiver;
  request_baton.receiver_baton = receiver_baton;
  request_baton.subpool = svn_pool_create(subpool);

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from the PEG_REVISION.  */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, peg_revision,
                                         subpool));
  bc = svn_path_url_add_component2(bc_url, bc_relative, subpool);

  err = svn_ra_neon__parsed_request(ras, "REPORT", bc,
                                    request_body->data, NULL, NULL,
                                    gls_start_element, NULL, NULL,
                                    &request_baton, NULL, &status_code,
                                    FALSE, subpool);
  svn_pool_destroy(request_baton.subpool);
  svn_pool_destroy(subpool);

  /* Map status 501: Method Not Implemented to our not implemented error.
     1.0.x servers and older don't support this report. */
  if (status_code == 501)
    return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                             _("'%s' REPORT not implemented"),
                             "get-location-segments");

  return err;
}
Beispiel #11
0
svn_error_t * svn_ra_neon__get_log(svn_ra_session_t *session,
                                   const apr_array_header_t *paths,
                                   svn_revnum_t start,
                                   svn_revnum_t end,
                                   int limit,
                                   svn_boolean_t discover_changed_paths,
                                   svn_boolean_t strict_node_history,
                                   svn_boolean_t include_merged_revisions,
                                   const apr_array_header_t *revprops,
                                   svn_log_entry_receiver_t receiver,
                                   void *receiver_baton,
                                   apr_pool_t *pool)
{
  /* The Plan: Send a request to the server for a log report.
   * Somewhere in mod_dav_svn, there will be an implementation, R, of
   * the `svn_log_entry_receiver_t' function type.  Some other
   * function in mod_dav_svn will use svn_repos_get_logs() to loop R
   * over the log messages, and the successive invocations of R will
   * collectively transmit the report back here, where we parse the
   * report and invoke RECEIVER (which is an entirely separate
   * instance of `svn_log_entry_receiver_t') on each individual
   * message in that report.
   */

  int i;
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body = svn_stringbuf_create("", pool);
  svn_boolean_t want_custom_revprops;
  struct log_baton lb;
  svn_string_t bc_url, bc_relative;
  const char *final_bc_url;
  svn_revnum_t use_rev;
  svn_error_t *err;

  /* ### todo: I don't understand why the static, file-global
     variables shared by update and status are called `report_head'
     and `report_tail', instead of `request_head' and `request_tail'.
     Maybe Greg can explain?  Meanwhile, I'm tentatively using
     "request_*" for my local vars below. */

  static const char log_request_head[]
    = "<S:log-report xmlns:S=\"" SVN_XML_NAMESPACE "\">" DEBUG_CR;

  static const char log_request_tail[] = "</S:log-report>" DEBUG_CR;

  /* Construct the request body. */
  svn_stringbuf_appendcstr(request_body, log_request_head);
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:start-revision>%ld"
                                        "</S:start-revision>", start));
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:end-revision>%ld"
                                        "</S:end-revision>", end));
  if (limit)
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:limit>%d</S:limit>", limit));
    }

  if (discover_changed_paths)
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:discover-changed-paths/>"));
    }

  if (strict_node_history)
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:strict-node-history/>"));
    }

  if (include_merged_revisions)
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:include-merged-revisions/>"));
    }

  if (revprops)
    {
      lb.want_author = lb.want_date = lb.want_message = FALSE;
      want_custom_revprops = FALSE;
      for (i = 0; i < revprops->nelts; i++)
        {
          char *name = APR_ARRAY_IDX(revprops, i, char *);
          svn_stringbuf_appendcstr(request_body, "<S:revprop>");
          svn_stringbuf_appendcstr(request_body, name);
          svn_stringbuf_appendcstr(request_body, "</S:revprop>");
          if (strcmp(name, SVN_PROP_REVISION_AUTHOR) == 0)
            lb.want_author = TRUE;
          else if (strcmp(name, SVN_PROP_REVISION_DATE) == 0)
            lb.want_date = TRUE;
          else if (strcmp(name, SVN_PROP_REVISION_LOG) == 0)
            lb.want_message = TRUE;
          else
            want_custom_revprops = TRUE;
        }
    }
  else
    {
Beispiel #12
0
          svn_stringbuf_appendcstr(request_body, name);
          svn_stringbuf_appendcstr(request_body, "</S:revprop>");
          if (strcmp(name, SVN_PROP_REVISION_AUTHOR) == 0)
            lb.want_author = TRUE;
          else if (strcmp(name, SVN_PROP_REVISION_DATE) == 0)
            lb.want_date = TRUE;
          else if (strcmp(name, SVN_PROP_REVISION_LOG) == 0)
            lb.want_message = TRUE;
          else
            want_custom_revprops = TRUE;
        }
    }
  else
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:all-revprops/>"));
      lb.want_author = lb.want_date = lb.want_message = TRUE;
      want_custom_revprops = TRUE;
    }

  if (want_custom_revprops)
    {
      svn_boolean_t has_log_revprops;
      SVN_ERR(svn_ra_neon__has_capability(session, &has_log_revprops,
                                          SVN_RA_CAPABILITY_LOG_REVPROPS, pool));
      if (!has_log_revprops)
        return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL,
                                _("Server does not support custom revprops"
                                  " via log"));
    }
Beispiel #13
0
/**
 *	Performs the make, if necessary
 */
static int make_fixup(request_rec *r) {
	if (!r)
		return HTTP_INTERNAL_SERVER_ERROR;
	if (r->prev)
		return DECLINED; // We're running in a sub-request, ignore.
		
	dir_cfg* cfg=ap_get_module_config(r->per_dir_config,&make_module);
	if (!cfg->onoff) // Is module turned on?
		return DECLINED;
		
	const char* docroot=ap_document_root(r);

	if (cfg->debug) {
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:onoff:%d",cfg->onoff);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:sourceRoot:%s",cfg->sourceRoot);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makefileName:%s",cfg->makefileName);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makeProgram:%s",cfg->makeProgram);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makeOptions:%s",cfg->makeOptions);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:includeFileTypes:%s",cfg->includeFileTypes);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:excludeFileTypes:%s",cfg->excludeFileTypes);
		// ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:excludeRegex:%s",cfg->excludeRegex);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:errorURI:%s",cfg->errorURI);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:errorCSS:%s",cfg->errorCSS);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: DocumentRoot:%s",docroot);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: URI:%s",r->uri);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Canonical Filename:%s",r->canonical_filename);
	}
	
	// Determine if this is a request I care about, i.e., the following is true:
	// The file type is in MakeIncludeFileTypes (if specified) and is not in MakeExcludeFileTypes (if specified)
	if (cfg->includeFileTypes || cfg->excludeFileTypes) {
		// Get file extension
		char* fname=basename(r->canonical_filename);
		char* ext=strchr(fname,'.');
		if (ext) {
			if (cfg->includeFileTypes && !strcasestr(cfg->includeFileTypes,ext)) {
				return DECLINED;
			}
			if (cfg->excludeFileTypes && strcasestr(cfg->excludeFileTypes,ext)) {
				return DECLINED;
			}
		}
	}
		
	// Locate Makefile: The Makefile should be in SourceRoot/REL_PATH/Makefile
	char relpath[256];
	char makefile[256];
	char make_target[256];

	// Determine the relative path part of r->canonical_filename, i.e., the part with the DocumentRoot removed
	strncpy(relpath,r->canonical_filename+strlen(docroot),sizeof(relpath)-1);
	// Truncate it before the basename
	char* p=strrchr(relpath,'/');
	if (p)
		*++p='\0';
	else {
		relpath[0]='/';
		relpath[1]='\0';
	}

	if (cfg->debug) {
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: relpath:%s",relpath);
	}
	
	int bFoundMakefile=FALSE;
	int bGiveUp=FALSE;
	
	do
	{
		// Determine the make target, i.e., the basename of r->canonical_filename
		strncpy(make_target,r->canonical_filename+strlen(docroot)+strlen(relpath),sizeof(make_target)-1);
		make_target[sizeof(make_target)-1]='\0';

		if (strlen(cfg->sourceRoot))
			strncpy(makefile,cfg->sourceRoot,sizeof(makefile)-1);
		else
			strncpy(makefile,docroot,sizeof(makefile)-1);
		strncat(makefile,relpath,sizeof(makefile)-strlen(makefile)-1);
		strncat(makefile,cfg->makefileName,sizeof(makefile)-strlen(makefile)-1);
		makefile[sizeof(makefile)-1]='\0';
	
		// If Makefile not found, ignore it (we only care if there •is* a Makefile)
		struct stat ss;
		if (!stat(makefile,&ss))
			bFoundMakefile=TRUE;
		else
		{
			if (cfg->debug)
				ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Makefile not found:%s. Trying parent directory...",makefile);
			
			// Go up one dir until we find a Makefile (but don't go past cfg->sourceRoot)
			// Take a directory off relpath, move it to the start of make_target and retry looking for the Makefile
			// Find 2nd-to-last / in relpath, that's the start of the last directory name
			char* p=strrchr(relpath,'/');
			if (p)
			{
				do
					--p;
				while (p>=relpath && *p!='/');
				
				if (p>=relpath)
					*(p+1)='\0';
				else
					bGiveUp=TRUE;
			}
			else
				bGiveUp=TRUE;
		}
	}
	while (bFoundMakefile==FALSE && bGiveUp==FALSE);
	
	if (bFoundMakefile==FALSE) // Never found a Makefile
	{
		if (cfg->debug)
			ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Unable to find a Makefile named:%s",cfg->makefileName);
		return DECLINED;
	}

	if (cfg->debug) {
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: relpath:%s",relpath);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: makefile:%s",makefile);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make_target:%s",make_target);
	}

	// Build make command
	char* cmd=apr_psprintf(r->pool,"WWWDOCROOT=%s WWWRELPATH=%s %s -f %s -C %s %s %s 2>&1",
		docroot,
		relpath,
		cfg->makeProgram,
		cfg->makefileName,
		(const char*)dirname(makefile),
		cfg->makeOptions,
		make_target);

	if (cfg->debug)
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cmd:%s",cmd);
	
	// Run Makefile to make target
	FILE* makep=popen(cmd,"r");
	if (!makep) { // If launching make fails, output errors from make and return HTTP error
		if (cfg->debug)
			ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: failed to popen:%s",cmd);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	// Compile regex
	regex_t regex;
	char* regexstr=apr_psprintf(r->pool,
		"^make:[[:space:]]+\\*\\*\\*[[:space:]]+No[[:space:]]+rule[[:space:]]+to[[:space:]]+make[[:space:]]+target[[:space:]]+`%s'\\.[[:space:]]+Stop\\.",
		make_target
		);
	if (regcomp(&regex,regexstr,REG_EXTENDED)) {
		if (cfg->debug)
			ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: regcomp failed");
		return HTTP_INTERNAL_SERVER_ERROR;
	}
	
	int bSilentFail=FALSE;

	// Read output of make
	size_t make_output_size=10240; // TODO: allow the buffer to grow beyond 10K
	char* make_output=apr_palloc(r->pool,make_output_size);
	make_output[0]='\0';
	make_output_size--;
	p=make_output; // reuse p
	do {
		const char* newp=fgets(p,make_output_size,makep);
		if (newp) {
			if (cfg->debug)
				ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make output:%s",newp);
			make_output_size-=strlen(newp);
			p+=strlen(newp);
			
			if (regexec(&regex,newp,0,0,0)==0) {
				if (cfg->debug)
					ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: regex match:%s",newp);
				bSilentFail=TRUE;
			}

		}
	}
	while (!feof(makep) && make_output_size>1);
	
	if (!make_output_size) {
		if (cfg->debug)
			ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make output exceeded max length");
		// TODO: add appropriate message to make_output
	}

	int ret=pclose(makep);
	
	if (cfg->debug)
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make exit code:%d",WEXITSTATUS(ret));
	
	if (WEXITSTATUS(ret)) {// make did not complete successfully, output make's output and tell Apache to stop.
		if (bSilentFail) {
			if (cfg->debug)
				ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: silently failing.");
			return DECLINED;
		}
		
		// Store make_output in request_rec so that the handler can display it 
		apr_table_set(r->notes,"make_output",make_output);
		// Redirect to our own content handler
		ap_internal_redirect(cfg->errorURI,r);
		return OK;
	}
	
    return DECLINED;
}
Beispiel #14
0
/**
 * \brief return filename for given tile
 * 
 * \param tile the tile to get the key from
 * \param path pointer to a char* that will contain the filename
 * \param r 
 * \private \memberof mapcache_cache_tiff
 */
static void _mapcache_cache_tiff_tile_key(mapcache_context *ctx, mapcache_tile *tile, char **path) {
   mapcache_cache_tiff *dcache = (mapcache_cache_tiff*)tile->tileset->cache;
   *path = dcache->filename_template;

   /*
    * generic template substitutions
    */
   if(strstr(*path,"{tileset}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{tileset}",
            tile->tileset->name);
   if(strstr(*path,"{grid}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{grid}",
            tile->grid_link->grid->name);
   if(tile->dimensions && strstr(*path,"{dim}")) {
      char *dimstring="";
      const apr_array_header_t *elts = apr_table_elts(tile->dimensions);
      int i = elts->nelts;
      while(i--) {
         apr_table_entry_t *entry = &(APR_ARRAY_IDX(elts,i,apr_table_entry_t));
         const char *dimval = mapcache_util_str_sanitize(ctx->pool,entry->val,"/.",'#');
         dimstring = apr_pstrcat(ctx->pool,dimstring,"#",dimval,NULL);
      }
      *path = mapcache_util_str_replace(ctx->pool,*path, "{dim}", dimstring);
   }
   
   
   while(strstr(*path,"{z}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{z}",
            apr_psprintf(ctx->pool,dcache->z_fmt,tile->z));
   /*
    * x and y replacing, when the tiff files are numbered with an increasing
    * x,y scheme (adjacent tiffs have x-x'=1 or y-y'=1
    */
   while(strstr(*path,"{div_x}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{div_x}",
            apr_psprintf(ctx->pool,dcache->div_x_fmt,tile->x/dcache->count_x));
   while(strstr(*path,"{div_y}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{div_y}",
            apr_psprintf(ctx->pool,dcache->div_y_fmt,tile->y/dcache->count_y));
   while(strstr(*path,"{inv_div_y}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_div_y}",
            apr_psprintf(ctx->pool,dcache->inv_div_y_fmt,(tile->grid_link->grid->levels[tile->z]->maxy - tile->y - 1)/dcache->count_y));
   while(strstr(*path,"{inv_div_x}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_div_x}",
            apr_psprintf(ctx->pool,dcache->inv_div_x_fmt,(tile->grid_link->grid->levels[tile->z]->maxx - tile->x - 1)/dcache->count_x));
   
   /*
    * x and y replacing, when the tiff files are numbered with the index
    * of their bottom-left tile
    * adjacent tiffs have x-x'=count_x or y-y'=count_y
    */
   while(strstr(*path,"{x}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{x}",
            apr_psprintf(ctx->pool,dcache->x_fmt,tile->x/dcache->count_x*dcache->count_x));
   while(strstr(*path,"{y}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{y}",
            apr_psprintf(ctx->pool,dcache->y_fmt,tile->y/dcache->count_y*dcache->count_y));
   while(strstr(*path,"{inv_y}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_y}",
            apr_psprintf(ctx->pool,dcache->inv_y_fmt,(tile->grid_link->grid->levels[tile->z]->maxy - tile->y - 1)/dcache->count_y*dcache->count_y));
   while(strstr(*path,"{inv_x}"))
      *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_x}",
            apr_psprintf(ctx->pool,dcache->inv_x_fmt,(tile->grid_link->grid->levels[tile->z]->maxx - tile->x - 1)/dcache->count_x*dcache->count_y));
   if(!*path) {
      ctx->set_error(ctx,500, "failed to allocate tile key");
   }
}
Beispiel #15
0
/* Make an unversioned copy of the versioned file at FROM_ABSPATH.  Copy it
 * to the destination path TO_ABSPATH.
 *
 * If REVISION is svn_opt_revision_working, copy the working version,
 * otherwise copy the base version.
 *
 * Expand the file's keywords according to the source file's 'svn:keywords'
 * property, if present.  If copying a locally modified working version,
 * append 'M' to the revision number and use '(local)' for the author.
 *
 * Translate the file's line endings according to the source file's
 * 'svn:eol-style' property, if present.  If NATIVE_EOL is not NULL, use it
 * in place of the native EOL style.  Throw an error if the source file has
 * inconsistent line endings and EOL translation is attempted.
 *
 * Set the destination file's modification time to the source file's
 * modification time if copying the working version and the working version
 * is locally modified; otherwise set it to the versioned file's last
 * changed time.
 *
 * Set the destination file's 'executable' flag according to the source
 * file's 'svn:executable' property.
 */
static svn_error_t *
copy_one_versioned_file(const char *from_abspath,
                        const char *to_abspath,
                        svn_client_ctx_t *ctx,
                        const svn_opt_revision_t *revision,
                        const char *native_eol,
                        svn_boolean_t ignore_keywords,
                        apr_pool_t *scratch_pool)
{
  apr_hash_t *kw = NULL;
  svn_subst_eol_style_t style;
  apr_hash_t *props;
  svn_string_t *eol_style, *keywords, *executable, *special;
  const char *eol = NULL;
  svn_boolean_t local_mod = FALSE;
  apr_time_t tm;
  svn_stream_t *source;
  svn_stream_t *dst_stream;
  const char *dst_tmp;
  svn_error_t *err;
  svn_boolean_t is_deleted;
  svn_wc_context_t *wc_ctx = ctx->wc_ctx;

  SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, wc_ctx, from_abspath,
                                         scratch_pool));

  /* Don't export 'deleted' files and directories unless it's a
     revision other than WORKING.  These files and directories
     don't really exist in WORKING. */
  if (revision->kind == svn_opt_revision_working && is_deleted)
    return SVN_NO_ERROR;

  if (revision->kind != svn_opt_revision_working)
    {
      /* Only export 'added' files when the revision is WORKING. This is not
         WORKING, so skip the 'added' files, since they didn't exist
         in the BASE revision and don't have an associated text-base.

         'replaced' files are technically the same as 'added' files.
         ### TODO: Handle replaced nodes properly.
         ###       svn_opt_revision_base refers to the "new"
         ###       base of the node. That means, if a node is locally
         ###       replaced, export skips this node, as if it was locally
         ###       added, because svn_opt_revision_base refers to the base
         ###       of the added node, not to the node that was deleted.
         ###       In contrast, when the node is copied-here or moved-here,
         ###       the copy/move source's content will be exported.
         ###       It is currently not possible to export the revert-base
         ###       when a node is locally replaced. We need a new
         ###       svn_opt_revision_ enum value for proper distinction
         ###       between revert-base and commit-base.

         Copied-/moved-here nodes have a base, so export both added and
         replaced files when they involve a copy-/move-here.

         We get all this for free from evaluating SOURCE == NULL:
       */
      SVN_ERR(svn_wc_get_pristine_contents2(&source, wc_ctx, from_abspath,
                                            scratch_pool, scratch_pool));
      if (source == NULL)
        return SVN_NO_ERROR;

      SVN_ERR(svn_wc_get_pristine_props(&props, wc_ctx, from_abspath,
                                        scratch_pool, scratch_pool));
    }
  else
    {
      svn_wc_status3_t *status;

      /* ### hmm. this isn't always a specialfile. this will simply open
         ### the file readonly if it is a regular file. */
      SVN_ERR(svn_subst_read_specialfile(&source, from_abspath, scratch_pool,
                                         scratch_pool));

      SVN_ERR(svn_wc_prop_list2(&props, wc_ctx, from_abspath, scratch_pool,
                                scratch_pool));
      SVN_ERR(svn_wc_status3(&status, wc_ctx, from_abspath, scratch_pool,
                             scratch_pool));
      if (status->text_status != svn_wc_status_normal)
        local_mod = TRUE;
    }

  /* We can early-exit if we're creating a special file. */
  special = apr_hash_get(props, SVN_PROP_SPECIAL,
                         APR_HASH_KEY_STRING);
  if (special != NULL)
    {
      /* Create the destination as a special file, and copy the source
         details into the destination stream. */
      SVN_ERR(svn_subst_create_specialfile(&dst_stream, to_abspath,
                                           scratch_pool, scratch_pool));
      return svn_error_trace(
        svn_stream_copy3(source, dst_stream, NULL, NULL, scratch_pool));
    }


  eol_style = apr_hash_get(props, SVN_PROP_EOL_STYLE,
                           APR_HASH_KEY_STRING);
  keywords = apr_hash_get(props, SVN_PROP_KEYWORDS,
                          APR_HASH_KEY_STRING);
  executable = apr_hash_get(props, SVN_PROP_EXECUTABLE,
                            APR_HASH_KEY_STRING);

  if (eol_style)
    SVN_ERR(get_eol_style(&style, &eol, eol_style->data, native_eol));

  if (local_mod)
    {
      /* Use the modified time from the working copy of
         the file */
      SVN_ERR(svn_io_file_affected_time(&tm, from_abspath, scratch_pool));
    }
  else
    {
      SVN_ERR(svn_wc__node_get_changed_info(NULL, &tm, NULL, wc_ctx,
                                            from_abspath, scratch_pool,
                                            scratch_pool));
    }

  if (keywords)
    {
      svn_revnum_t changed_rev;
      const char *suffix;
      const char *url;
      const char *author;

      SVN_ERR(svn_wc__node_get_changed_info(&changed_rev, NULL, &author,
                                            wc_ctx, from_abspath, scratch_pool,
                                            scratch_pool));

      if (local_mod)
        {
          /* For locally modified files, we'll append an 'M'
             to the revision number, and set the author to
             "(local)" since we can't always determine the
             current user's username */
          suffix = "M";
          author = _("(local)");
        }
      else
        {
          suffix = "";
        }

      SVN_ERR(svn_wc__node_get_url(&url, wc_ctx, from_abspath,
                                   scratch_pool, scratch_pool));

      SVN_ERR(svn_subst_build_keywords2
              (&kw, keywords->data,
               apr_psprintf(scratch_pool, "%ld%s", changed_rev, suffix),
               url, tm, author, scratch_pool));
    }

  /* For atomicity, we translate to a tmp file and then rename the tmp file
     over the real destination. */
  SVN_ERR(svn_stream_open_unique(&dst_stream, &dst_tmp,
                                 svn_dirent_dirname(to_abspath, scratch_pool),
                                 svn_io_file_del_none, scratch_pool,
                                 scratch_pool));

  /* If some translation is needed, then wrap the output stream (this is
     more efficient than wrapping the input). */
  if (eol || (kw && (apr_hash_count(kw) > 0)))
    dst_stream = svn_subst_stream_translated(dst_stream,
                                             eol,
                                             FALSE /* repair */,
                                             kw,
                                             ! ignore_keywords /* expand */,
                                             scratch_pool);

  /* ###: use cancel func/baton in place of NULL/NULL below. */
  err = svn_stream_copy3(source, dst_stream, NULL, NULL, scratch_pool);

  if (!err && executable)
    err = svn_io_set_file_executable(dst_tmp, TRUE, FALSE, scratch_pool);

  if (!err)
    err = svn_io_set_file_affected_time(tm, dst_tmp, scratch_pool);

  if (err)
    return svn_error_compose_create(err, svn_io_remove_file2(dst_tmp, FALSE,
                                                             scratch_pool));

  /* Now that dst_tmp contains the translated data, do the atomic rename. */
  SVN_ERR(svn_io_file_rename(dst_tmp, to_abspath, scratch_pool));

  if (ctx->notify_func2)
    {
      svn_wc_notify_t *notify = svn_wc_create_notify(to_abspath,
                                      svn_wc_notify_update_add, scratch_pool);
      notify->kind = svn_node_file;
      (*ctx->notify_func2)(ctx->notify_baton2, notify, scratch_pool);
    }

  return SVN_NO_ERROR;
}
Beispiel #16
0
apr_status_t
serf__handle_digest_auth(int code,
                         serf_request_t *request,
                         serf_bucket_t *response,
                         const char *auth_hdr,
                         const char *auth_attr,
                         void *baton,
                         apr_pool_t *pool)
{
    char *attrs;
    char *nextkv;
    const char *realm_name = NULL;
    const char *nonce = NULL;
    const char *algorithm = NULL;
    const char *qop = NULL;
    const char *opaque = NULL;
    const char *key;
    serf_connection_t *conn = request->conn;
    serf_context_t *ctx = conn->ctx;
    serf__authn_info_t *authn_info = (code == 401) ? &ctx->authn_info :
        &ctx->proxy_authn_info;
    digest_authn_info_t *digest_info = (code == 401) ? conn->authn_baton :
        conn->proxy_authn_baton;
    apr_status_t status;
    apr_pool_t *cred_pool;
    char *username, *password;

    /* Can't do Digest authentication if there's no callback to get
       username & password. */
    if (!ctx->cred_cb) {
        return SERF_ERROR_AUTHN_FAILED;
    }

    /* Need a copy cuz we're going to write NUL characters into the string.  */
    attrs = apr_pstrdup(pool, auth_attr);

    /* We're expecting a list of key=value pairs, separated by a comma.
       Ex. realm="SVN Digest",
       nonce="f+zTl/leBAA=e371bd3070adfb47b21f5fc64ad8cc21adc371a5",
       algorithm=MD5, qop="auth" */
    for ( ; (key = apr_strtok(attrs, ",", &nextkv)) != NULL; attrs = NULL) {
        char *val;

        val = strchr(key, '=');
        if (val == NULL)
            continue;
        *val++ = '\0';

        /* skip leading spaces */
        while (*key && *key == ' ')
            key++;

        /* If the value is quoted, then remove the quotes.  */
        if (*val == '"') {
            apr_size_t last = strlen(val) - 1;

            if (val[last] == '"') {
                val[last] = '\0';
                val++;
            }
        }

        if (strcmp(key, "realm") == 0)
            realm_name = val;
        else if (strcmp(key, "nonce") == 0)
            nonce = val;
        else if (strcmp(key, "algorithm") == 0)
            algorithm = val;
        else if (strcmp(key, "qop") == 0)
            qop = val;
        else if (strcmp(key, "opaque") == 0)
            opaque = val;

        /* Ignore all unsupported attributes. */
    }

    if (!realm_name) {
        return SERF_ERROR_AUTHN_MISSING_ATTRIBUTE;
    }

    authn_info->realm = apr_psprintf(conn->pool, "<%s://%s:%d> %s",
                                     conn->host_info.scheme,
                                     conn->host_info.hostname,
                                     conn->host_info.port,
                                     realm_name);

    /* Ask the application for credentials */
    apr_pool_create(&cred_pool, pool);
    status = (*ctx->cred_cb)(&username, &password, request, baton,
                             code, authn_info->scheme->name,
                             authn_info->realm, cred_pool);
    if (status) {
        apr_pool_destroy(cred_pool);
        return status;
    }

    digest_info->header = (code == 401) ? "Authorization" :
                                          "Proxy-Authorization";

    /* Store the digest authentication parameters in the context relative
       to this connection, so we can use it to create the Authorization header
       when setting up requests. */
    digest_info->pool = conn->pool;
    digest_info->qop = apr_pstrdup(digest_info->pool, qop);
    digest_info->nonce = apr_pstrdup(digest_info->pool, nonce);
    digest_info->cnonce = NULL;
    digest_info->opaque = apr_pstrdup(digest_info->pool, opaque);
    digest_info->algorithm = apr_pstrdup(digest_info->pool, algorithm);
    digest_info->realm = apr_pstrdup(digest_info->pool, realm_name);
    digest_info->username = apr_pstrdup(digest_info->pool, username);
    digest_info->digest_nc++;

    digest_info->ha1 = build_digest_ha1(username, password, digest_info->realm,
                                        digest_info->pool);

    apr_pool_destroy(cred_pool);

    /* If the handshake is finished tell serf it can send as much requests as it
       likes. */
    serf_connection_set_max_outstanding_requests(conn, 0);

    return APR_SUCCESS;
}
Beispiel #17
0
apr_status_t
serf__validate_response_digest_auth(peer_t peer,
                                    int code,
                                    serf_connection_t *conn,
                                    serf_request_t *request,
                                    serf_bucket_t *response,
                                    apr_pool_t *pool)
{
    const char *key;
    char *auth_attr;
    char *nextkv;
    const char *rspauth = NULL;
    const char *qop = NULL;
    const char *nc_str = NULL;
    serf_bucket_t *hdrs;
    digest_authn_info_t *digest_info = (peer == HOST) ? conn->authn_baton :
        conn->proxy_authn_baton;

    hdrs = serf_bucket_response_get_headers(response);

    /* Need a copy cuz we're going to write NUL characters into the string.  */
    if (peer == HOST)
        auth_attr = apr_pstrdup(pool,
            serf_bucket_headers_get(hdrs, "Authentication-Info"));
    else
        auth_attr = apr_pstrdup(pool,
            serf_bucket_headers_get(hdrs, "Proxy-Authentication-Info"));

    /* If there's no Authentication-Info header there's nothing to validate. */
    if (! auth_attr)
        return APR_SUCCESS;

    /* We're expecting a list of key=value pairs, separated by a comma.
       Ex. rspauth="8a4b8451084b082be6b105e2b7975087",
       cnonce="346531653132652d303033392d3435", nc=00000007,
       qop=auth */
    for ( ; (key = apr_strtok(auth_attr, ",", &nextkv)) != NULL; auth_attr = NULL) {
        char *val;

        val = strchr(key, '=');
        if (val == NULL)
            continue;
        *val++ = '\0';

        /* skip leading spaces */
        while (*key && *key == ' ')
            key++;

        /* If the value is quoted, then remove the quotes.  */
        if (*val == '"') {
            apr_size_t last = strlen(val) - 1;

            if (val[last] == '"') {
                val[last] = '\0';
                val++;
            }
        }

        if (strcmp(key, "rspauth") == 0)
            rspauth = val;
        else if (strcmp(key, "qop") == 0)
            qop = val;
        else if (strcmp(key, "nc") == 0)
            nc_str = val;
    }

    if (rspauth) {
        const char *ha2, *tmp, *resp_hdr_hex;
        unsigned char resp_hdr[APR_MD5_DIGESTSIZE];
        const char *req_uri = request->auth_baton;

        ha2 = build_digest_ha2(req_uri, "", qop, pool);
        tmp = apr_psprintf(pool, "%s:%s:%s:%s:%s:%s",
                           digest_info->ha1, digest_info->nonce, nc_str,
                           digest_info->cnonce, digest_info->qop, ha2);
        apr_md5(resp_hdr, tmp, strlen(tmp));
        resp_hdr_hex =  hex_encode(resp_hdr, pool);

        /* Incorrect response-digest in Authentication-Info header. */
        if (strcmp(rspauth, resp_hdr_hex) != 0) {
            return SERF_ERROR_AUTHN_FAILED;
        }
    }

    return APR_SUCCESS;
}
Beispiel #18
0
static const char *make_token(char type, ra_svn_edit_baton_t *eb,
                              apr_pool_t *pool)
{
  return apr_psprintf(pool, "%c%d", type, eb->next_token++);
}
Beispiel #19
0
/**
 * Get the location of the file
 * @param info Input/output parameter. sfn must be set. location will be set.
 * @param pool Pool for memory allocation
 * @return NULL on success
 */
dav_error *dav_ns_get_location(dav_resource_private *info,
                               apr_pool_t *pool)
{
  dmlite_replica *replicas;
  unsigned        n_replicas, i;
  char           *referrer, *p;
  dmlite_url      url;

  /* If there is a rejected list, this is a fallback */
  if ((info->s_conf->type == DAV_NS_NODE_LFC) &&
      (info->forbidden_str != NULL || info->notfound_str != NULL)) {
    int64_t *rejected_ids, id;
    int      n_forbidden = 0, n_notfound = 0, n_total = 0;

    /* Count first to allocate */
    if (info->forbidden_str != NULL) {
      n_forbidden = 1;
      for (i = 0; info->forbidden_str[i] != '\0'; ++i) {
        if (info->forbidden_str[i] == ',')
          ++n_forbidden;
      }
    }
    if (info->notfound_str != NULL) {
      n_notfound = 1;
      for (i = 0; info->notfound_str[i] != '\0'; ++i) {
        if (info->notfound_str[i] == ',')
          ++n_notfound;
      }
    }

    /* Build rejected list */
    n_total      = n_forbidden + n_notfound;
    rejected_ids = apr_pcalloc(pool, sizeof(int64_t) * n_total);
    i            = 0;

    p = (char*)info->forbidden_str;
    while (p != NULL && *p != '\0') {
      errno = 0;
      id    = strtol(p, &p, 0);
      if (errno == 0)
        rejected_ids[i++] = id;
      if (*p != '\0')
        ++p;
    }

    p = (char*)info->notfound_str;
    while (p != NULL && *p != '\0') {
      errno = 0;
      id    = strtol(p, &p, 0);
      if (errno == 0)
        rejected_ids[i++] = id;
      if (*p != '\0')
        ++p;
    }

    dmlite_any* any = dmlite_any_new_long_array(n_total, rejected_ids);    
    i = dmlite_set(info->ctx, "ExcludeReplicas", any);
    dmlite_any_free(any);
    if (i != 0) {
      return dav_shared_new_error(info->request, info->ctx, 0,
                                  "Error on fall-back method");
    }
  }

  /* Logic here depends on the node type */
  dmlite_location *location;
  switch (info->s_conf->type) {
    case DAV_NS_NODE_HEAD:
      /* Ask for the best one */
      location = dmlite_get(info->ctx, info->sfn);
      switch(dmlite_errno(info->ctx)) {
        case 0:
          break;
        case DM_FORBIDDEN:
          info->redirect = dav_shared_build_aggregation_url(info->request->pool,
                                                            info->n_replicas,
                                                            (const char**)info->replicas,
                                                            info->replicas_ids,
                                                            info->forbidden_str,
                                                            info->notfound_str,
                                                            info->r_id, -1);
          if (info->redirect != NULL) {
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
                          info->request,
                          "Access forbidden for %s, forwarded to %s",
                          info->sfn, info->redirect);
            return NULL;
          }
        default:
          return dav_shared_new_error(info->request, info->ctx, 0, NULL);
      }
      
      /* Destination URL */
      info->redirect = apr_psprintf(pool, "%s://%s%s%s",
                                    info->d_conf->redir_scheme,
                                    location->chunks[0].host,
                                    location->chunks[0].path,
                                    dav_shared_build_extra(pool, location->chunks[0].extra));
      
      dmlite_location_free(info->ctx, location);
      break;
      
    /* LFC wants the whole list */
    case DAV_NS_NODE_LFC:
      if (dmlite_getreplicas(info->ctx, info->sfn, &n_replicas, &replicas) != 0)
        return dav_shared_new_error(info->request, info->ctx, 0, NULL);

      /* Initialize */
      info->n_replicas    = n_replicas + 1;
      info->forbidden_str = NULL;
      info->notfound_str  = NULL;

      /* Build the referrer */
      referrer = apr_psprintf(pool, "%s://%s:%u%s",
                              info->d_conf->redir_scheme,
                              info->request->hostname,
                              info->request->server->port,
                              info->request->uri);

      /* Build the replica list, skipping the first */
      info->replicas     = apr_pcalloc(pool, sizeof(char*) * info->n_replicas);
      info->replicas_ids = apr_pcalloc(pool, sizeof(int64_t) * info->n_replicas);
      for (i = 0; i < n_replicas && i < info->d_conf->max_replicas; ++i) {
        dmlite_parse_url(replicas[i].rfn, &url);
        info->replicas[i]     = dav_shared_build_url(pool, &url, info->d_conf->redir_scheme);
        info->replicas_ids[i] = replicas[i].replicaid;
      }

      /* Append ourselves */
      info->replicas[i]     = referrer;
      info->replicas_ids[i] = -1;

      /* Build the definitive URL */
      info->redirect = dav_shared_build_aggregation_url(info->request->pool,
                                                        info->n_replicas,
                                                        (const char**)info->replicas,
                                                        info->replicas_ids,
                                                        info->forbidden_str,
                                                        info->notfound_str,
                                                        -1, -1);

      /* Clean up */
      dmlite_replicas_free(info->ctx, n_replicas, replicas);

      break;
    default:
      return dav_shared_new_error(info->request, NULL, HTTP_INTERNAL_SERVER_ERROR,
                                  "Invalid node type configured");
  }

  return NULL;
}
Beispiel #20
0
static void dbd_pgsql_bbind(apr_pool_t *pool, apr_dbd_prepared_t * statement,
                            const void **values,
                            const char **val, int *len, int *fmt)
{
    int i, j;
    apr_dbd_type_e type;

    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
        type = (values[j] == NULL ? APR_DBD_TYPE_NULL : statement->types[i]);

        switch (type) {
        case APR_DBD_TYPE_TINY:
            val[i] = apr_itoa(pool, *(char*)values[j]);
            break;
        case APR_DBD_TYPE_UTINY:
            val[i] = apr_itoa(pool, *(unsigned char*)values[j]);
            break;
        case APR_DBD_TYPE_SHORT:
            val[i] = apr_itoa(pool, *(short*)values[j]);
            break;
        case APR_DBD_TYPE_USHORT:
            val[i] = apr_itoa(pool, *(unsigned short*)values[j]);
            break;
        case APR_DBD_TYPE_INT:
            val[i] = apr_itoa(pool, *(int*)values[j]);
            break;
        case APR_DBD_TYPE_UINT:
            val[i] = apr_itoa(pool, *(unsigned int*)values[j]);
            break;
        case APR_DBD_TYPE_LONG:
            val[i] = apr_ltoa(pool, *(long*)values[j]);
            break;
        case APR_DBD_TYPE_ULONG:
            val[i] = apr_ltoa(pool, *(unsigned long*)values[j]);
            break;
        case APR_DBD_TYPE_LONGLONG:
            val[i] = apr_psprintf(pool, "%" APR_INT64_T_FMT,
                                  *(apr_int64_t*)values[j]);
            break;
        case APR_DBD_TYPE_ULONGLONG:
            val[i] = apr_psprintf(pool, "%" APR_UINT64_T_FMT,
                                  *(apr_uint64_t*)values[j]);
            break;
        case APR_DBD_TYPE_FLOAT:
            val[i] = apr_psprintf(pool, "%f", *(float*)values[j]);
            break;
        case APR_DBD_TYPE_DOUBLE:
            val[i] = apr_psprintf(pool, "%lf", *(double*)values[j]);
            break;
        case APR_DBD_TYPE_STRING:
        case APR_DBD_TYPE_TEXT:
        case APR_DBD_TYPE_TIME:
        case APR_DBD_TYPE_DATE:
        case APR_DBD_TYPE_DATETIME:
        case APR_DBD_TYPE_TIMESTAMP:
        case APR_DBD_TYPE_ZTIMESTAMP:
            val[i] = values[j];
            break;
        case APR_DBD_TYPE_BLOB:
        case APR_DBD_TYPE_CLOB:
            val[i] = (char*)values[j];
            len[i] = *(apr_size_t*)values[++j];
            fmt[i] = 1;

            /* skip table and column */
            j += 2;
            break;
        case APR_DBD_TYPE_NULL:
        default:
            val[i] = NULL;
            break;
        }
    }

    return;
}
Beispiel #21
0
static void worker_main(void *vpArg)
{
    long conn_id;
    conn_rec *current_conn;
    apr_pool_t *pconn;
    apr_allocator_t *allocator;
    apr_bucket_alloc_t *bucket_alloc;
    worker_args_t *worker_args;
    HQUEUE workq;
    PID owner;
    int rc;
    REQUESTDATA rd;
    ULONG len;
    BYTE priority;
    int thread_slot = (int)vpArg;
    EXCEPTIONREGISTRATIONRECORD reg_rec = { NULL, thread_exception_handler };
    ap_sb_handle_t *sbh;

    /* Trap exceptions in this thread so we don't take down the whole process */
    DosSetExceptionHandler( &reg_rec );

    rc = DosOpenQueue(&owner, &workq,
                      apr_psprintf(pchild, "/queues/httpd/work.%d", getpid()));

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "unable to open work queue, exiting");
        ap_scoreboard_image->servers[child_slot][thread_slot].tid = 0;
    }

    conn_id = ID_FROM_CHILD_THREAD(child_slot, thread_slot);
    ap_update_child_status_from_indexes(child_slot, thread_slot, SERVER_READY,
                                        NULL);

    apr_allocator_create(&allocator);
    apr_allocator_max_free_set(allocator, ap_max_mem_free);
    bucket_alloc = apr_bucket_alloc_create_ex(allocator);

    while (rc = DosReadQueue(workq, &rd, &len, (PPVOID)&worker_args, 0, DCWW_WAIT, &priority, NULLHANDLE),
           rc == 0 && rd.ulData != WORKTYPE_EXIT) {
        pconn = worker_args->pconn;
        ap_create_sb_handle(&sbh, pconn, child_slot, thread_slot);
        current_conn = ap_run_create_connection(pconn, ap_server_conf,
                                                worker_args->conn_sd, conn_id,
                                                sbh, bucket_alloc);

        if (current_conn) {
            ap_process_connection(current_conn, worker_args->conn_sd);
            ap_lingering_close(current_conn);
        }

        apr_pool_destroy(pconn);
        ap_update_child_status_from_indexes(child_slot, thread_slot,
                                            SERVER_READY, NULL);
    }

    ap_update_child_status_from_indexes(child_slot, thread_slot, SERVER_DEAD,
                                        NULL);

    apr_bucket_alloc_destroy(bucket_alloc);
    apr_allocator_destroy(allocator);
}
Beispiel #22
0
/* Set up startup-time initialization */
static int vlimit_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
    VLIMIT_DEBUG_SYSLOG("vlimit_init: ", MODULE_NAME " " MODULE_VERSION " started.", p);

    if(apr_file_open(&vlimit_log_fp, VLIMIT_LOG_FILE, APR_WRITE|APR_APPEND|APR_CREATE,
           APR_OS_DEFAULT, p) != APR_SUCCESS){
        return OK;
    }

    apr_status_t status;
    apr_size_t retsize;
    apr_size_t shm_size;
    int t;

    SHM_DATA *shm_data = NULL;

    shm_size = (apr_size_t) (sizeof(shm_data) + sizeof(shm_data->file_stat_shm) + sizeof(shm_data->ip_stat_shm)) * (conf_counter + 1);

    //Create global mutex
    status = apr_global_mutex_create(&vlimit_mutex, NULL, APR_LOCK_DEFAULT, p);
    if(status != APR_SUCCESS){
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Error creating global mutex.", p);
        return status;
    }
#ifdef AP_NEED_SET_MUTEX_PERMS
    status = unixd_set_global_mutex_perms(vlimit_mutex);
    if(status != APR_SUCCESS){
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Error xrent could not set permissions on global mutex.", p);
        return status;
    }
#endif

    if(apr_global_mutex_child_init(&vlimit_mutex, NULL, p))
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "global mutex attached.", p);

    /* If there was a memory block already assigned.. destroy it */
    if (shm) {
        status = apr_shm_destroy(shm);
        if (status != APR_SUCCESS) {
            VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Couldn't destroy old memory block", p);
            return status;
        } else {
            VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Old Shared memory block, destroyed.", p);
        }
    }

    /* Create shared memory block */
    status = apr_shm_create(&shm, shm_size, NULL, p);
    if (status != APR_SUCCESS) {
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Error creating shm block", p);
        return status;
    }


    /* Check size of shared memory block */
    retsize = apr_shm_size_get(shm);
    if (retsize != shm_size) {
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Error allocating shared memory block", p);
        return status;
    }
    /* Init shm block */
    shm_base = apr_shm_baseaddr_get(shm);
    if (shm_base == NULL) {
        VLIMIT_DEBUG_SYSLOG("vlimit_init", "Error creating status block.", p);
        return status;
    }
    memset(shm_base, 0, retsize);

    vlimit_debug_log_buf = apr_psprintf(p
        , "Memory Allocated %d bytes (each conf takes %d bytes) MaxClient:%d"
        , (int) retsize
        , (int) (sizeof(shm_data) + sizeof(shm_data->file_stat_shm) + sizeof(shm_data->ip_stat_shm))
        , MAX_CLIENTS
    );
    VLIMIT_DEBUG_SYSLOG("vlimit_init: ", vlimit_debug_log_buf, p);

    if (retsize < (sizeof(shm_data) * conf_counter)) {
        VLIMIT_DEBUG_SYSLOG("vlimit_init ", "Not enough memory allocated!! Giving up" , p);
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    int i;

    for (t = 0; t <= conf_counter; t++) {
        shm_data = shm_base + t;
        for (i = 0; i < MAX_CLIENTS; i++) {
            shm_data->file_stat_shm[i].filename[0] = '\0';
            shm_data->ip_stat_shm[i].address[0]    = '\0';
            shm_data->file_stat_shm[i].counter     = 0;
            shm_data->ip_stat_shm[i].counter       = 0;
        }
    }

    vlimit_debug_log_buf = apr_psprintf(p
        , "%s Version %s - Initialized [%d Conf]"
        , MODULE_NAME
        , MODULE_VERSION
        , conf_counter
    );
    VLIMIT_DEBUG_SYSLOG("vlimit_init: ", vlimit_debug_log_buf, p);

    return OK;
}
Beispiel #23
0
static apr_file_t *ap_open_log(apr_pool_t *p, server_rec *s, const char *base, log_options *ls, apr_time_t tm) {
    if (*base == '|') {
        /* We have piped log handling here because once log rotation has been
         * enabled we become responsible for /all/ transfer log output server
         * wide. That's a consequence of the way the log output hooks in
         * mod_log_config are implemented. Unfortunately this means we have to
         * duplicate functionality from mod_log_config. Note that we don't
         * support the buffered logging mode that mlc implements.
         */
        piped_log *pl;

        if (ls->enabled) {
            /* Can't rotate a piped log */
            ls->enabled = 0;
            ap_log_error(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, s,
                            "disabled log rotation for piped log %s.", base);
        }

        if (pl = ap_open_piped_log(p, base + 1), NULL == pl) {
           return NULL;
        }

        return ap_piped_log_write_fd(pl);
    }
    else
    {
        apr_file_t *fd;
        apr_status_t rv;
        const char *name = ap_server_root_relative(p, base);

        if (NULL == name) {
            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s,
                            "invalid transfer log path %s.", base);
            return NULL;
        }

        if (ls->enabled) {
            apr_time_t log_time = tm - ls->offset;
            if (strchr(base, '%') != NULL) {
                apr_time_exp_t e;

                apr_time_exp_gmt(&e, log_time);
                name = ap_pstrftime(p, name, &e);
            }
            else
            {
                /* Synthesize the log name using the specified time in seconds as a
                 * suffix.  We subtract the offset here because it was added when
                 * quantizing the time but we want the name to reflect the actual
                 * time when the log rotated. We don't reverse the local time
                 * adjustment because, presumably, if you've specified local time
                 * logging you want the filenames to use local time.
                 */
                name = apr_psprintf(p, "%s.%" APR_TIME_T_FMT, name, apr_time_sec(log_time));
            }
        }

        if (rv = apr_file_open(&fd, name, xfer_flags, xfer_perms, p), APR_SUCCESS != rv) {
            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                            "could not open transfer log file %s.", name);
            return NULL;
        }

        return fd;
    }
}
Beispiel #24
0
static int vlimit_response_end(request_rec *r) {

    int counter_stat = -2;

    VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", "start", r->pool);

    vlimit_config *cfg =
        (vlimit_config *) ap_get_module_config(r->per_dir_config, &vlimit_module);

    SHM_DATA *limit_stat;
    limit_stat = shm_base + cfg->conf_id;

    // vlimit_mutex lock
    VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", "vlimit_mutex locked.", r->pool);
    if (apr_global_mutex_lock(vlimit_mutex) != APR_SUCCESS) {
        VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", "vlimit_mutex lock failed.", r->pool);
        return OK;
    }

    if (cfg->conf_id != 0 && cfg->file_match == 1) {
        VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", "type FILE: file_count--", r->pool);
        if (get_file_counter(limit_stat, r) > 0)
            counter_stat = dec_file_counter(limit_stat, r);
        if (get_file_counter(limit_stat, r) == 0)
            unset_file_counter(limit_stat, r);
        cfg->file_match = 0;
        if (counter_stat != -2)
            vlimit_logging("RESULT: END DEC", r, cfg, limit_stat);
    }

    if (cfg->conf_id != 0 && cfg->ip_match == 1) {
        VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", "type IP: ip_count--", r->pool);
        if (get_ip_counter(limit_stat, r) > 0)
            counter_stat = dec_ip_counter(limit_stat, r);
        if (get_ip_counter(limit_stat, r) == 0)
            unset_ip_counter(limit_stat, r);
        cfg->ip_match = 0;
        if (counter_stat != -2)
            vlimit_logging("RESULT: END DEC", r, cfg, limit_stat);
    }

    // vlimit_mutex unlock
    VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", "vlimit_mutex unlocked.", r->pool);
    if (apr_global_mutex_unlock(vlimit_mutex) != APR_SUCCESS) {
        VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", "vlimit_mutex unlock failed.", r->pool);
        return OK;
    }

    vlimit_debug_log_buf = apr_psprintf(r->pool
        , "conf_id: %d name: %s  uri: %s ip_count: %d/%d file_count: %d/%d"
        , cfg->conf_id
        , r->server->server_hostname
        , r->filename
        , get_ip_counter(limit_stat, r)
        , cfg->ip_limit
        , get_file_counter(limit_stat, r)
        , cfg->file_limit
    );
    VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", vlimit_debug_log_buf, r->pool);
    VLIMIT_DEBUG_SYSLOG("vlimit_response_end: ", "end", r->pool);
    return OK;
}
Beispiel #25
0
/*
 * register the client with the OP using Dynamic Client Registration
 */
static apr_byte_t oidc_metadata_client_register(request_rec *r, oidc_cfg *cfg,
		oidc_provider_t *provider, json_t **j_client, const char **response) {

	/* get a handle to the directory config */
	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
			&auth_openidc_module);

	/* assemble the JSON registration request */
	json_t *data = json_object();
	json_object_set_new(data, "client_name",
			json_string(provider->client_name));
	json_object_set_new(data, "redirect_uris",
			json_pack("[s]", cfg->redirect_uri));

	json_t *response_types = json_array();
	apr_array_header_t *flows = oidc_proto_supported_flows(r->pool);
	int i;
	for (i = 0; i < flows->nelts; i++) {
		json_array_append_new(response_types,
				json_string(((const char**) flows->elts)[i]));
	}
	json_object_set_new(data, "response_types", response_types);

	if (provider->client_contact != NULL) {
		json_object_set_new(data, "contacts",
				json_pack("[s]", provider->client_contact));
	}

	if (provider->client_jwks_uri) {
		json_object_set_new(data, "jwks_uri",
				json_string(provider->client_jwks_uri));
	} else if (cfg->public_keys != NULL) {
		json_object_set_new(data, "jwks_uri",
				json_string(
						apr_psprintf(r->pool, "%s?jwks=rsa",
								cfg->redirect_uri)));
	}

	if (provider->id_token_signed_response_alg != NULL) {
		json_object_set_new(data, "id_token_signed_response_alg",
				json_string(provider->id_token_signed_response_alg));
	}
	if (provider->id_token_encrypted_response_alg != NULL) {
		json_object_set_new(data, "id_token_encrypted_response_alg",
				json_string(provider->id_token_encrypted_response_alg));
	}
	if (provider->id_token_encrypted_response_enc != NULL) {
		json_object_set_new(data, "id_token_encrypted_response_enc",
				json_string(provider->id_token_encrypted_response_enc));
	}

	if (provider->userinfo_signed_response_alg != NULL) {
		json_object_set_new(data, "userinfo_signed_response_alg",
				json_string(provider->userinfo_signed_response_alg));
	}
	if (provider->userinfo_encrypted_response_alg != NULL) {
		json_object_set_new(data, "userinfo_encrypted_response_alg",
				json_string(provider->userinfo_encrypted_response_alg));
	}
	if (provider->userinfo_encrypted_response_enc != NULL) {
		json_object_set_new(data, "userinfo_encrypted_response_enc",
				json_string(provider->userinfo_encrypted_response_enc));
	}

	json_object_set_new(data, "initiate_login_uri",
			json_string(cfg->redirect_uri));

	json_object_set_new(data, "logout_uri",
			json_string(
					apr_psprintf(r->pool, "%s?logout=%s", cfg->redirect_uri,
							OIDC_GET_STYLE_LOGOUT_PARAM_VALUE)));

	if (cfg->default_slo_url != NULL) {
		json_object_set_new(data, "post_logout_redirect_uris",
				json_pack("[s]", cfg->default_slo_url));
	}

	if (provider->registration_endpoint_json != NULL) {

		json_error_t json_error;
		json_t *json = json_loads(provider->registration_endpoint_json, 0,
				&json_error);

		if (json == NULL) {

			oidc_error(r, "JSON parsing returned an error: %s",
					json_error.text);

		} else {

			if (!json_is_object(json)) {

				oidc_error(r, "parsed JSON did not contain a JSON object");

			} else {

				const char *key;
				json_t *value;
				json_object_foreach(json, key, value) {
					json_object_set(data, key, value);
				}

			}

			json_decref(json);
		}
Beispiel #26
0
/* Generic function to check a request against a config. */
static int vlimit_check_limit(request_rec *r, vlimit_config *cfg)
{

    const char *header_name;

    int ip_count     = 0;
    int file_count   = 0;
    int counter_stat = 0;

    if (!ap_is_initial_req(r)) {
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "SKIPPED: Initial Reqeusts.", r->pool);
        return DECLINED;
    }

    if (cfg->ip_limit <= 0 && cfg->file_limit <= 0) {
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "SKIPPED: cfg->ip_limit <= 0 && cfg->file_limit <= 0", r->pool);
        return DECLINED;
    }

    header_name = apr_table_get(r->headers_in, "HOST");

    vlimit_debug_log_buf = apr_psprintf(r->pool, "client info: address=(%s) header_name=(%s)"
        , r->connection->remote_ip
        , header_name
    );
    VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", vlimit_debug_log_buf, r->pool);

    SHM_DATA *limit_stat;
    limit_stat = shm_base + cfg->conf_id;
    
    if (make_ip_slot_list(limit_stat, r) != -1)
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "make_ip_slot_list exec. create list(" VLIMIT_IP_STAT_FILE ").", r->pool);

    if (make_file_slot_list(limit_stat, r) != -1)
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "make_file_slot_list exec. create list(" VLIMIT_FILE_STAT_FILE ").", r->pool);

    if (check_virtualhost_name(r)) {
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "header_name != server_hostname. return OK.", r->pool);
        return OK;
    }

    // vlimit_mutex lock
    VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "vlimit_mutex locked.", r->pool);
    if (apr_global_mutex_lock(vlimit_mutex) != APR_SUCCESS) {
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "vlimit_mutex lock failed.", r->pool);
        return OK;
    }

    if (cfg->file_limit > 0) {
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "type File: file_count++", r->pool);
        counter_stat = inc_file_counter(limit_stat, r);
        if (counter_stat == -1) {
            VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "file counter slot full. maxclients?", r->pool);
            return HTTP_SERVICE_UNAVAILABLE;
        }
        file_count = get_file_counter(limit_stat, r);
        cfg->file_match = 1;
    } else if (cfg->ip_limit > 0) {
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "type IP: ip_count++", r->pool);
        counter_stat = inc_ip_counter(limit_stat, r);
        if (counter_stat == -1) {
            VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "ip counter slot full. maxclients?", r->pool);
            return HTTP_SERVICE_UNAVAILABLE;
        }
        ip_count = get_ip_counter(limit_stat, r);
        cfg->ip_match = 1;
    }

    // vlimit_mutex unlock
    VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "vlimit_mutex unlocked.", r->pool);
    if (apr_global_mutex_unlock(vlimit_mutex) != APR_SUCCESS){
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "vlimit_mutex unlock failed.", r->pool);
        return OK;
    }

    vlimit_debug_log_buf = apr_psprintf(r->pool
        , "conf_id: %d name: %s  uri: %s  ip_count: %d/%d file_count: %d/%d"
        , cfg->conf_id
        , r->server->server_hostname
        , r->filename
        , ip_count
        , cfg->ip_limit
        , file_count
        , cfg->file_limit
    );
    VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", vlimit_debug_log_buf, r->pool);

    if (cfg->ip_limit > 0 && ip_count > cfg->ip_limit) {
        vlimit_debug_log_buf = apr_psprintf(r->pool
            , "Rejected, too many connections from this host(%s) to the file(%s) by VlimitIP[ip_limig=(%d) docroot=(%s)]."
            , r->connection->remote_ip
            , header_name
            , cfg->ip_limit
            , cfg->full_path
        );
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", vlimit_debug_log_buf, r->pool);

        if (counter_stat != -2)
            vlimit_logging("RESULT: 503 INC", r, cfg, limit_stat);

        return HTTP_SERVICE_UNAVAILABLE;

    } else if (cfg->file_limit > 0 && file_count > cfg->file_limit) {
        vlimit_debug_log_buf = apr_psprintf(r->pool
            , "Rejected, too many connections to the file(%s) by VlimitFile[limit=(%d) docroot=(%s)]."
            , header_name
            , cfg->file_limit
            , cfg->full_path
        );
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", vlimit_debug_log_buf, r->pool);

        if (counter_stat != -2)
            vlimit_logging("RESULT: 503 INC", r, cfg, limit_stat);

        return HTTP_SERVICE_UNAVAILABLE;
        //return HTTP_NOT_FOUND;

    } else {
        VLIMIT_DEBUG_SYSLOG("vlimit_check_limit: ", "OK: Passed all checks", r->pool);

        if (counter_stat != -2)
            vlimit_logging("RESULT:  OK INC", r, cfg, limit_stat);

        return OK;
    }

    return OK;
}
Beispiel #27
0
static char *parse_template(nproxy_connection_t * conn, const char *file) {
    apr_file_t *f;
    char b[4096];
    apr_size_t blen;
    apr_status_t status;
     /**/ char *in_p = NULL;
    nn_buffer_t *bufferin;
    size_t out_size;
    char *out_p = NULL;
    nn_buffer_t *bufferout;

    bufferin = nn_buffer_init(conn->pool, 0, 4096);
    if (!bufferin) {
        return NULL;
    }

    bufferout = nn_buffer_init(conn->pool, 0, 4096);
    if (bufferout == NULL) {
        return NULL;
    }

    if (APR_STATUS_SUCCESS != apr_file_open(&f, file, APR_READ, 0, conn->pool)) {
        nn_log(NN_LOG_ERROR, "Cannot open template file %s", file);
        return NULL;
    }

    do {
        blen = sizeof(b);
        status = apr_file_read(f, b, &blen);
        if (blen > 0) {
            if (nn_buffer_append(bufferin, b, blen) != APR_STATUS_SUCCESS) {
                return NULL;
            }
        }
    } while (blen > 0);
    apr_file_close(f);

    if (status != APR_EOF) {
        /* An error occurred reading the file */
        nn_log(NN_LOG_ERROR, "Error reading template file %s", file);
        return NULL;
    }

    /* Now we have the full content of the file. We must start evaluating our substitutions. */
    nn_buffer_get_char(bufferin, &in_p);
    if (in_p == NULL) {
        return NULL;
    }

    if (conn->var_hash) {
        apr_hash_index_t *hi;

        for (hi = apr_hash_first(conn->pool, conn->var_hash); hi; hi = apr_hash_next(hi)) {
            apr_ssize_t vlen;
            const char *var = NULL;
            char *val = NULL;

            apr_hash_this(hi, (const void **) &var, &vlen, (void *) &val);

            if (!zstr(var) && !zstr(val)) {
                char *s1 = NULL;

                s1 = apr_psprintf(conn->pool, "{%s}", var);

                nn_buffer_get_char(bufferin, &in_p);
                if (in_p) {
                    nn_buffer_reset(bufferout);
                    do_subst(in_p, bufferout, s1, val);

                    out_size = nn_buffer_get_char(bufferout, &out_p);
                    if (out_size && out_p) {
                        nn_buffer_reset(bufferin);
                        nn_buffer_append(bufferin, out_p, out_size);
                    }
                }
            }

        }
    }

    /* We won't destroy the buffer, it will be deleted with the pool */
    nn_buffer_get_char(bufferin, &in_p);

    return in_p;
}
Beispiel #28
0
/* ----------------------------------------- */
static int vlimit_handler(request_rec *r)
{
    /* get configuration information */
    vlimit_config *cfg =
        (vlimit_config *) ap_get_module_config(r->per_dir_config, &vlimit_module);

    int result;
    char *real_path_dir = (char *)apr_pcalloc(r->pool, sizeof(char *) * PATH_MAX + 1);

    vlimit_debug_log_buf = apr_psprintf(r->pool
        , "cfg->ip_limit=(%d) cfg->file_limit=(%d) cfg->full_path=(%s)"
        , cfg->ip_limit
        , cfg->file_limit
        , cfg->full_path
    );
    VLIMIT_DEBUG_SYSLOG("vlimit_handler: ", vlimit_debug_log_buf, r->pool);

    /* full_path check */
    if (cfg->full_path != NULL) {
        if (access(r->filename, F_OK) != 0) {
            real_path_dir = apr_pstrdup(r->pool, r->filename);
        } else if (realpath_for_vlimit(r->filename, real_path_dir, PATH_MAX, r->pool) == NULL) {
            vlimit_debug_log_buf = apr_psprintf(r->pool
                , "realpath_for_vlimit was failed. path=(%s)"
                , r->filename
            );
            VLIMIT_DEBUG_SYSLOG("vlimit_handler: ", vlimit_debug_log_buf, r->pool);
            return DECLINED;
       }

        if (strcmp(cfg->full_path, real_path_dir) != 0) {

            vlimit_debug_log_buf = apr_psprintf(r->pool
                , "full_path not match cfg->full_path=(%s) <=> real_path_dir=(%s)"
                , cfg->full_path
                , real_path_dir     
            );
            VLIMIT_DEBUG_SYSLOG("vlimit_handler: ", vlimit_debug_log_buf, r->pool);
            VLIMIT_DEBUG_SYSLOG("vlimit_handler: ", "full_path not match end...", r->pool);

            return DECLINED;
        }

        vlimit_debug_log_buf = apr_psprintf(r->pool
            , "full_path match cfg->full_path=(%s) <=> real_path_dir=(%s)"
            , cfg->full_path
            , real_path_dir     
        );
        VLIMIT_DEBUG_SYSLOG("vlimit_handler: ", vlimit_debug_log_buf, r->pool);
    } else {
        vlimit_debug_log_buf = apr_psprintf(r->pool
            , "full_path not found. cfg->full_path=(%s)"
            , cfg->full_path
        );
        VLIMIT_DEBUG_SYSLOG("vlimit_handler: ", vlimit_debug_log_buf, r->pool);
    }

    VLIMIT_DEBUG_SYSLOG("vlimit_handler: ", "Entering normal handler", r->pool);
    result = vlimit_check_limit(r, cfg);
    VLIMIT_DEBUG_SYSLOG("vlimit_handler: ", "Exiting normal handler", r->pool);

    return result;
}
/*
** Append the specified lock(s) to the set of locks on this resource.
**
** If "make_indirect" is true (non-zero), then the specified lock(s)
** should be converted to an indirect lock (if it is a direct lock)
** before appending. Note that the conversion to an indirect lock does
** not alter the passed-in lock -- the change is internal the
** append_locks function.
**
** Multiple locks are specified using the lock->next links.
*/
static dav_error *
append_locks(dav_lockdb *lockdb,
             const dav_resource *resource,
             int make_indirect,
             const dav_lock *lock)
{
  dav_lockdb_private *info = lockdb->info;
  svn_lock_t *slock;
  svn_error_t *serr;
  dav_error *derr;

  /* If the resource's fs path is unreadable, we don't allow a lock to
     be created on it. */
  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
                                     resource->pool))
    return dav_svn__new_error(resource->pool, HTTP_FORBIDDEN,
                              DAV_ERR_LOCK_SAVE_LOCK,
                              "Path is not accessible.");

  if (lock->next)
    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST,
                              DAV_ERR_LOCK_SAVE_LOCK,
                              "Tried to attach multiple locks to a resource.");

  /* RFC2518bis (section 7.4) doesn't require us to support
     'lock-null' resources at all.  Instead, it asks that we treat
     'LOCK nonexistentURL' as a PUT (followed by a LOCK) of a 0-byte file.  */
  if (! resource->exists)
    {
      svn_revnum_t rev, new_rev;
      svn_fs_txn_t *txn;
      svn_fs_root_t *txn_root;
      const char *conflict_msg;
      dav_svn_repos *repos = resource->info->repos;
      apr_hash_t *revprop_table = apr_hash_make(resource->pool);
      apr_hash_set(revprop_table, SVN_PROP_REVISION_AUTHOR,
                   APR_HASH_KEY_STRING, svn_string_create(repos->username,
                                                          resource->pool));

      if (resource->info->repos->is_svn_client)
        return dav_svn__new_error(resource->pool, HTTP_METHOD_NOT_ALLOWED,
                                  DAV_ERR_LOCK_SAVE_LOCK,
                                  "Subversion clients may not lock "
                                  "nonexistent paths.");

      else if (! resource->info->repos->autoversioning)
        return dav_svn__new_error(resource->pool, HTTP_METHOD_NOT_ALLOWED,
                                  DAV_ERR_LOCK_SAVE_LOCK,
                                  "Attempted to lock non-existent path; "
                                  "turn on autoversioning first.");

      /* Commit a 0-byte file: */

      if ((serr = svn_fs_youngest_rev(&rev, repos->fs, resource->pool)))
        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                    "Could not determine youngest revision",
                                    resource->pool);

      if ((serr = svn_repos_fs_begin_txn_for_commit2(&txn, repos->repos, rev,
                                                     revprop_table,
                                                     resource->pool)))
        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                    "Could not begin a transaction",
                                    resource->pool);

      if ((serr = svn_fs_txn_root(&txn_root, txn, resource->pool)))
        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                    "Could not begin a transaction",
                                    resource->pool);

      if ((serr = svn_fs_make_file(txn_root, resource->info->repos_path,
                                   resource->pool)))
        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                    "Could not create empty file.",
                                    resource->pool);

      if ((serr = dav_svn__attach_auto_revprops(txn,
                                                resource->info->repos_path,
                                                resource->pool)))
        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                    "Could not create empty file.",
                                    resource->pool);

      serr = svn_repos_fs_commit_txn(&conflict_msg, repos->repos,
                                     &new_rev, txn, resource->pool);
      if (SVN_IS_VALID_REVNUM(new_rev))
        {
          /* ### Log an error in post commit FS processing? */
          svn_error_clear(serr);
        }
      else
        {
          svn_error_clear(svn_fs_abort_txn(txn, resource->pool));
          if (serr)
            return dav_svn__convert_err(serr, HTTP_CONFLICT,
                                        apr_psprintf(resource->pool,
                                                     "Conflict when "
                                                     "committing '%s'.",
                                                     conflict_msg),
                                        resource->pool);
          else
            return dav_svn__new_error(resource->pool,
                                      HTTP_INTERNAL_SERVER_ERROR,
                                      0,
                                      "Commit failed but there was no error "
                                      "provided.");
        }
    }

  /* Convert the dav_lock into an svn_lock_t. */
  derr = dav_lock_to_svn_lock(&slock, lock, resource->info->repos_path,
                              info, resource->info->repos->is_svn_client,
                              resource->pool);
  if (derr)
    return derr;

  /* Now use the svn_lock_t to actually perform the lock. */
  serr = svn_repos_fs_lock(&slock,
                           resource->info->repos->repos,
                           slock->path,
                           slock->token,
                           slock->comment,
                           slock->is_dav_comment,
                           slock->expiration_date,
                           info->working_revnum,
                           info->lock_steal,
                           resource->pool);

  if (serr && serr->apr_err == SVN_ERR_FS_NO_USER)
    {
      svn_error_clear(serr);
      return dav_svn__new_error(resource->pool, HTTP_UNAUTHORIZED,
                                DAV_ERR_LOCK_SAVE_LOCK,
                                "Anonymous lock creation is not allowed.");
    }
  else if (serr)
    return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                "Failed to create new lock.",
                                resource->pool);


  /* A standard webdav LOCK response doesn't include any information
     about the creation date.  We send it in a custom header, so that
     svn clients can fill in svn_lock_t->creation_date.  A generic DAV
     client should just ignore the header. */
  apr_table_setn(info->r->headers_out, SVN_DAV_CREATIONDATE_HEADER,
                 svn_time_to_cstring(slock->creation_date, resource->pool));

  /* A standard webdav LOCK response doesn't include any information
     about the owner of the lock.  ('DAV:owner' has nothing to do with
     authorization, it's just a comment that we map to
     svn_lock_t->comment.)  We send the owner in a custom header, so
     that svn clients can fill in svn_lock_t->owner.  A generic DAV
     client should just ignore the header. */
  apr_table_setn(info->r->headers_out, SVN_DAV_LOCK_OWNER_HEADER,
                 slock->owner);

  /* Log the locking as a 'high-level' action. */
  dav_svn__operational_log(resource->info,
                           svn_log__lock_one_path(slock->path, info->lock_steal,
                                                  resource->info->r->pool));

  return 0;
}
Beispiel #30
0
static const char *
build_auth_header(digest_authn_info_t *digest_info,
                  const char *path,
                  const char *method,
                  apr_pool_t *pool)
{
    char *hdr;
    const char *ha2;
    const char *response;
    unsigned char response_hdr[APR_MD5_DIGESTSIZE];
    const char *response_hdr_hex;
    apr_status_t status;

    ha2 = build_digest_ha2(path, method, digest_info->qop, pool);

    hdr = apr_psprintf(pool,
                       "Digest realm=\"%s\","
                       " username=\"%s\","
                       " nonce=\"%s\","
                       " uri=\"%s\"",
                       digest_info->realm, digest_info->username,
                       digest_info->nonce,
                       path);

    if (digest_info->qop) {
        if (! digest_info->cnonce)
            digest_info->cnonce = random_cnonce(digest_info->pool);

        hdr = apr_psprintf(pool, "%s, nc=%08x, cnonce=\"%s\", qop=\"%s\"",
                           hdr,
                           digest_info->digest_nc,
                           digest_info->cnonce,
                           digest_info->qop);

        /* Build the response header:
           MD5 hash of the combined HA1 result, server nonce (nonce),
           request counter (nc), client nonce (cnonce),
           quality of protection code (qop) and HA2 result. */
        response = apr_psprintf(pool, "%s:%s:%08x:%s:%s:%s",
                                digest_info->ha1, digest_info->nonce,
                                digest_info->digest_nc,
                                digest_info->cnonce, digest_info->qop, ha2);
    } else {
        /* Build the response header:
           MD5 hash of the combined HA1 result, server nonce (nonce)
           and HA2 result. */
        response = apr_psprintf(pool, "%s:%s:%s",
                                digest_info->ha1, digest_info->nonce, ha2);
    }

    status = apr_md5(response_hdr, response, strlen(response));
    response_hdr_hex = hex_encode(response_hdr, pool);

    hdr = apr_psprintf(pool, "%s, response=\"%s\"", hdr, response_hdr_hex);

    if (digest_info->opaque) {
        hdr = apr_psprintf(pool, "%s, opaque=\"%s\"", hdr,
                           digest_info->opaque);
    }
    if (digest_info->algorithm) {
        hdr = apr_psprintf(pool, "%s, algorithm=\"%s\"", hdr,
                           digest_info->algorithm);
    }

    return hdr;
}