static int get_range_common(ne_session *sess, const char *req_uri, const char *brange, char *buf, ssize_t *bytes_read) { ne_request *req = ne_request_create(sess, "GET", req_uri); const ne_status *status; int ret; ne_add_request_header(req, "Range", brange); ne_add_request_header(req, "Accept-Ranges", "bytes"); ret = dispatch_to_buffer(sess, req, buf, brange, bytes_read); status = ne_get_status(req); if (ret == NE_OK && status->code == 416) { /* connection is terminated too early with Apache/1.3, so we check * this even if ret == NE_ERROR... */ ne_set_error(sess, "Range is not satisfiable"); ret = NE_ERROR; } else if (ret == NE_OK) { if (status->klass == 2 && status->code != 206) { ne_set_error(sess, "Resource does not support ranged GET requests"); ret = NE_ERROR; } else if (status->klass != 2) { ret = NE_ERROR; } } ne_request_destroy(req); return ret; }
char* create_rawx_request_common(ne_request **req, ne_request_param_t *param, GError **err) { ne_request *request = NULL; char str_req_id[LIMIT_LENGTH_REQID]; if (NULL == param->session || NULL == param->method || NULL == param->cPath) { GSETERROR(err, "Invalid parameter"); *req = NULL; return NULL; } if (NULL == (request = ne_request_create (param->session, param->method, param->cPath))) { GSETERROR(err, "cannot create a new WebDAV request (%s)", ne_get_error(param->session)); *req = NULL; return NULL; } /* add additionnal headers */ ne_add_request_header (request, RAWX_HEADER_PREFIX "container-id", param->containerid); ne_add_request_header (request, RAWX_HEADER_PREFIX "content-path", param->contentpath); ne_print_request_header(request, RAWX_HEADER_PREFIX "content-size", "%"G_GINT64_FORMAT, param->contentsize); ne_print_request_header(request, RAWX_HEADER_PREFIX "content-chunksnb", "%u", param->chunknb); ne_print_request_header(request, RAWX_HEADER_PREFIX "chunk-pos", "%u", param->chunkpos); ne_print_request_header(request, RAWX_HEADER_PREFIX "chunk-size", "%"G_GINT64_FORMAT, param->chunksize); /* Add request header */ add_req_id_header(request, str_req_id, sizeof(str_req_id)-1); *req = request; return g_strdup(str_req_id); }
static int copy_or_move(ne_session *sess, int is_move, int overwrite, int depth, const char *src, const char *dest) { ne_request *req = ne_request_create( sess, is_move?"MOVE":"COPY", src ); /* 2518 S8.9.2 says only use Depth: infinity with MOVE. */ if (!is_move) { ne_add_depth_header(req, depth); } #ifdef NE_HAVE_DAV if (is_move) { ne_lock_using_resource(req, src, NE_DEPTH_INFINITE); } ne_lock_using_resource(req, dest, NE_DEPTH_INFINITE); /* And we need to be able to add members to the destination's parent */ ne_lock_using_parent(req, dest); #endif if (ne_get_session_flag(sess, NE_SESSFLAG_RFC4918)) { ne_add_request_header(req, "Destination", dest); } else { ne_print_request_header(req, "Destination", "%s://%s%s", ne_get_scheme(sess), ne_get_server_hostport(sess), dest); } ne_add_request_header(req, "Overwrite", overwrite?"T":"F"); return ne_simple_request(sess, req); }
static Hbf_State _hbf_transfer_no_chunk(ne_session *session, hbf_transfer_t *transfer, const char *verb) { int res; const ne_status* req_status; ne_request *req = ne_request_create(session, verb ? verb : "PUT", transfer->url); if (!req) return HBF_MEMORY_FAIL; ne_add_request_header( req, "Content-Type", "application/octet-stream"); ne_set_request_body_fd(req, transfer->fd, 0, transfer->stat_size); DEBUG_HBF("HBF: chunking not supported for %s", transfer->url); res = ne_request_dispatch(req); req_status = ne_get_status( req ); if (res == NE_OK && req_status->klass == 2) { ne_request_destroy(req); return HBF_SUCCESS; } if( transfer->error_string ) free( transfer->error_string ); transfer->error_string = strdup( ne_get_error(session) ); transfer->status_code = req_status->code; ne_request_destroy(req); return HBF_FAIL; }
int ne_get_range(ne_session *sess, const char *uri, ne_content_range *range, int fd) { ne_request *req = ne_request_create(sess, "GET", uri); const ne_status *status; int ret; char brange[64]; if (range->end == -1) { ne_snprintf(brange, sizeof brange, "bytes=%" NE_FMT_OFF_T "-", range->start); } else { ne_snprintf(brange, sizeof brange, "bytes=%" NE_FMT_OFF_T "-%" NE_FMT_OFF_T, range->start, range->end); } ne_add_request_header(req, "Range", brange); ne_add_request_header(req, "Accept-Ranges", "bytes"); ret = dispatch_to_fd(req, fd, brange); status = ne_get_status(req); if (ret == NE_OK && status->code == 416) { /* connection is terminated too early with Apache/1.3, so we check * this even if ret == NE_ERROR... */ ne_set_error(sess, _("Range is not satisfiable")); ret = NE_ERROR; } else if (ret == NE_OK) { if (status->klass == 2 && status->code != 206) { ne_set_error(sess, _("Resource does not support ranged GETs.")); ret = NE_ERROR; } else if (status->klass != 2) { ret = NE_ERROR; } } ne_request_destroy(req); return ret; }
static ne_request* _build_request(ne_session *http_session, const gchar *path_url) { ne_request *http_request; http_request = ne_request_create(http_session, "GET", path_url); ne_add_request_header(http_request, "User-Agent", "HoneyComb-gridagent-httpconf"); return http_request; }
static void add_timeout_header(ne_request *req, long timeout) { if (timeout == NE_TIMEOUT_INFINITE) { ne_add_request_header(req, "Timeout", "Infinite"); } else if (timeout == NE_TIMEOUT_CLOSE_TO_INFINITE){ ne_print_request_header(req,"Timeout","Infinite, Second-%ld", 3600); } else if (timeout != NE_TIMEOUT_INVALID && timeout > 0) { ne_print_request_header(req, "Timeout", "Second-%ld", timeout); } /* just ignore it if timeout == 0 or invalid. */ }
/* * this hook is called just after a request has been created, before its sent. * Here it is used to set the proxy connection header if available. */ static void request_created_hook(ne_request *req, void *userdata, const char *method, const char *requri) { (void) userdata; (void) method; (void) requri; if( !req ) return; if(dav_session.proxy_type) { /* required for NTLM */ ne_add_request_header(req, "Proxy-Connection", "Keep-Alive"); } }
char* create_rawx_request_common(ne_request **req, ne_request_param_t *param, GError **err) { ne_request *request = NULL; char str_req_id[1024]; memset(str_req_id, 0x00, sizeof(str_req_id)); if (NULL == param->session || NULL == param->method || NULL == param->cPath) { GSETERROR(err, "Invalid parameter"); *req = NULL; return NULL; } if (NULL == (request = ne_request_create (param->session, param->method, param->cPath))) { GSETERROR(err, "cannot create a new WebDAV request (%s)", ne_get_error(param->session)); *req = NULL; return NULL; } /* add additionnal headers */ ne_add_request_header (request, "containerid", param->containerid); ne_add_request_header (request, "contentpath", param->contentpath); ne_print_request_header(request, "chunkpos", "%u", param->chunkpos); ne_print_request_header(request, "chunknb", "%u", param->chunknb); ne_print_request_header(request, "chunksize", "%"G_GINT64_FORMAT, param->chunksize); ne_print_request_header(request, "contentsize", "%"G_GINT64_FORMAT, param->contentsize); gscstat_tags_start(GSCSTAT_SERVICE_RAWX, GSCSTAT_TAGS_REQPROCTIME); /* Add request header */ add_req_id_header(request, str_req_id, sizeof(str_req_id)-1); *req = request; return g_strdup(str_req_id); }
void ne_add_depth_header(ne_request *req, int depth) { const char *value; switch(depth) { case NE_DEPTH_ZERO: value = "0"; break; case NE_DEPTH_ONE: value = "1"; break; default: value = "infinity"; break; } ne_add_request_header(req, "Depth", value); }
static gboolean _ne_request(const char *host, int port, const char *target, const char *method, GSList *headers, GError **err) { GRID_TRACE("%s", __FUNCTION__); gboolean result = FALSE; ne_session* session = ne_session_create("http", host, port); ne_set_connect_timeout(session, 10); ne_set_read_timeout(session, 30); GRID_DEBUG("%s http://%s:%d%s", method, host, port, target); ne_request* req = ne_request_create(session, method, target); if (NULL != req) { for (GSList *l = headers; l; l = l->next) { gchar **toks = g_strsplit(l->data, ":", 2); ne_add_request_header(req, toks[0], toks[1]); g_strfreev(toks); } switch (ne_request_dispatch(req)) { case NE_OK: if (ne_get_status(req)->klass != 2) { *err = NEWERROR(0, "cannot %s '%s' (%s)", method, target, ne_get_error(session)); } else { result = TRUE; } break; case NE_AUTH: case NE_CONNECT: case NE_TIMEOUT: case NE_ERROR: default: *err = NEWERROR(0, "unexpected error from the WebDAV server (%s)", ne_get_error(session)); break; } ne_request_destroy(req); } else { // This should be an assertion *err = NEWERROR(0, "Failed to create request"); } ne_session_destroy (session); return result; }
ne_decompress *ne_decompress_reader(ne_request *req, ne_accept_response acpt, ne_block_reader rdr, void *userdata) { ne_decompress *ctx = ne_calloc(sizeof *ctx); ne_add_request_header(req, "Accept-Encoding", "gzip"); ne_add_response_body_reader(req, gz_acceptor, gz_reader, ctx); ctx->reader = rdr; ctx->userdata = userdata; ctx->session = ne_get_session(req); ctx->request = req; ctx->acceptor = acpt; ne__reqhook_pre_send(req, gz_pre_send, ctx); return ctx; }
char* create_rawx_request_from_chunk(ne_request **p_req, ne_session *session, const char *method, gs_chunk_t *chunk, GByteArray *system_metadata, GError **err) { char str_ci[STRLEN_CHUNKID], cPath[CI_FULLPATHLEN], *str_req_id; ne_request_param_t *params = new_request_param(); if (NULL == chunk) { GSETERROR(err, "No chunk given"); return NULL; } params->session = session; params->method = g_strdup(method); chunk_getpath (chunk, cPath, sizeof(cPath)); params->cPath = g_strdup(cPath); params->containerid = g_strdup(C1_IDSTR(chunk->content)); params->contentpath = g_strdup(C1_PATH(chunk->content)); params->chunkpos = chunk->ci->position; params->chunknb = chunk->ci->nb; params->chunksize = chunk->ci->size; params->contentsize = chunk->content->info.size; str_req_id = create_rawx_request_common(p_req, params, err); free_request_param(params); if (*p_req) { if (system_metadata && system_metadata->data && system_metadata->len>0) add_req_system_metadata_header(*p_req, system_metadata); chunk_id2str(chunk, str_ci, sizeof(str_ci)); GRID_DEBUG("chunkid=%s", str_ci); ne_add_request_header(*p_req, "chunkid", str_ci); return str_req_id; } g_free(str_req_id); return NULL; }
int ne_acl_set(ne_session *sess, const char *uri, ne_acl_entry *entries, int numentries) { int ret; ne_request *req = ne_request_create(sess, "ACL", uri); ne_buffer *body = acl_body(entries, numentries); #ifdef NE_HAVE_DAV ne_lock_using_resource(req, uri, 0); #endif ne_set_request_body_buffer(req, body->data, ne_buffer_size(body)); ne_add_request_header(req, "Content-Type", NE_XML_MEDIA_TYPE); ret = ne_request_dispatch(req); ne_buffer_destroy(body); if (ret == NE_OK && ne_get_status(req)->code == 207) { ret = NE_ERROR; } ne_request_destroy(req); return ret; }
svn_error_t * svn_ra_neon__request_dispatch(int *code_p, svn_ra_neon__request_t *req, apr_hash_t *extra_headers, const char *body, int okay_1, int okay_2, apr_pool_t *pool) { ne_xml_parser *error_parser; const ne_status *statstruct; /* add any extra headers passed in by caller. */ if (extra_headers != NULL) { apr_hash_index_t *hi; for (hi = apr_hash_first(pool, extra_headers); hi; hi = apr_hash_next(hi)) { const void *key; void *val; apr_hash_this(hi, &key, NULL, &val); ne_add_request_header(req->ne_req, (const char *) key, (const char *) val); } } /* Certain headers must be transmitted unconditionally with every request; see issue #3255 ("mod_dav_svn does not pass client capabilities to start-commit hooks") for why. It's okay if one of these headers was already added via extra_headers above -- they are all idempotent headers. Note that at most one could have been sent via extra_headers, because extra_headers is a hash and the key would be the same for all of them: "DAV". In a just and righteous world, extra_headers would be an array, not a hash, so that callers could send the same header with different values too. But, apparently, that hasn't been necessary yet. */ ne_add_request_header(req->ne_req, "DAV", SVN_DAV_NS_DAV_SVN_DEPTH); ne_add_request_header(req->ne_req, "DAV", SVN_DAV_NS_DAV_SVN_MERGEINFO); ne_add_request_header(req->ne_req, "DAV", SVN_DAV_NS_DAV_SVN_LOG_REVPROPS); if (body) ne_set_request_body_buffer(req->ne_req, body, strlen(body)); /* attach a standard <D:error> body parser to the request */ error_parser = error_parser_create(req); if (req->ne_sess == req->sess->ne_sess) /* We're consuming 'session 1' */ req->sess->main_session_busy = TRUE; /* run the request, see what comes back. */ req->rv = ne_request_dispatch(req->ne_req); if (req->ne_sess == req->sess->ne_sess) /* We're done consuming 'session 1' */ req->sess->main_session_busy = FALSE; /* Save values from the request */ statstruct = ne_get_status(req->ne_req); req->code_desc = apr_pstrdup(pool, statstruct->reason_phrase); req->code = statstruct->code; /* If we see a successful request that used authentication, we should store the credentials for future use. */ if (req->sess->auth_used && statstruct->code < 400) { req->sess->auth_used = FALSE; SVN_ERR(svn_ra_neon__maybe_store_auth_info(req->sess, pool)); } if (code_p) *code_p = req->code; if (!req->marshalled_error) SVN_ERR(req->err); /* If the status code was one of the two that we expected, then go ahead and return now. IGNORE any marshalled error. */ if (req->rv == NE_OK && (req->code == okay_1 || req->code == okay_2)) return SVN_NO_ERROR; /* Any other errors? Report them */ SVN_ERR(req->err); SVN_ERR(svn_ra_neon__check_parse_error(req->method, error_parser, req->url)); /* We either have a neon error, or some other error that we didn't expect. */ return generate_error(req, pool); }
static ne_request *s3_new_request(const S3 *s3,const char *method,const char *bucket,const char *key,const char *params,const char *content_type) { ne_buffer *date, *signing_string, *request_str; ne_request *req; char *sig, *p; time_t t; if(!s3) return NULL; if(!method) return NULL; if(!bucket) return NULL; if(!s3->session) return NULL; // create some string buffers date = ne_buffer_create(); signing_string = ne_buffer_create(); request_str = ne_buffer_create(); // get the time t = time(NULL); ne_buffer_zappend(date,asctime(gmtime(&t))); if(date->data[date->used - 2] == '\n') date->data[date->used - 2] = 0; ne_buffer_altered(date); // create request if(key) ne_buffer_concat(request_str,"/",bucket,"/",key,NULL); else ne_buffer_concat(request_str,"/",bucket,NULL); if(params && params[0] != 0) { ne_buffer_zappend(request_str,"?"); ne_buffer_zappend(request_str,params); } req = ne_request_create(s3->session,method,request_str->data); // Add date header ne_add_request_header(req,"Date",date->data); // Add content-type header if(content_type) ne_add_request_header(req,"Content-Type",content_type); else content_type = ""; // construct signing string p = strrchr(request_str->data,'?'); if(p) { *p = 0; ne_buffer_altered(request_str); } ne_buffer_concat(signing_string,method,"\n\n",content_type,"\n",date->data,"\n",request_str->data,NULL); // sign the string sig = s3_sign_string(s3,signing_string->data); // construct signed header ne_print_request_header(req,"Authorization","AWS %s:%s",s3->access_id,sig); ne_buffer_destroy(date); ne_buffer_destroy(signing_string); ne_buffer_destroy(request_str); free(sig); return req; }
svn_error_t * svn_ra_neon__exchange_capabilities(svn_ra_neon__session_t *ras, apr_pool_t *pool) { svn_ra_neon__request_t* req; svn_error_t *err = SVN_NO_ERROR; ne_xml_parser *parser = NULL; options_ctx_t oc = { 0 }; const char *msg; int status_code; oc.pool = pool; oc.cdata = svn_stringbuf_create("", pool); req = svn_ra_neon__request_create(ras, "OPTIONS", ras->url->data, pool); /* ### Use a symbolic name somewhere for this MIME type? */ ne_add_request_header(req->ne_req, "Content-Type", "text/xml"); /* Create a parser to read the normal response body */ parser = svn_ra_neon__xml_parser_create(req, ne_accept_2xx, start_element, svn_ra_neon__xml_collect_cdata, end_element, &oc); /* Run the request and get the resulting status code. */ if ((err = svn_ra_neon__request_dispatch(&status_code, req, NULL, "<?xml version=\"1.0\" " "encoding=\"utf-8\"?>" "<D:options xmlns:D=\"DAV:\">" "<D:activity-collection-set/>" "</D:options>", 200, 0, pool))) goto cleanup; /* Was there an XML parse error somewhere? */ msg = ne_xml_get_error(parser); if (msg && *msg) { err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, _("The %s request returned invalid XML " "in the response: %s (%s)"), "OPTIONS", msg, ras->url->data); goto cleanup; } /* We asked for, and therefore expect, to have found an activity collection in the response. */ if (oc.activity_coll == NULL) { err = svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL, _("The OPTIONS response did not include the " "requested activity-collection-set; this often " "means that the URL is not WebDAV-enabled")); goto cleanup; } ras->act_coll = apr_pstrdup(ras->pool, oc.activity_coll->data); parse_capabilities(req->ne_req, ras, pool); cleanup: svn_ra_neon__request_destroy(req); return err; }
/* Try to send the HTTP request to the Icecast server, and if possible deals with * all the probable redirections (HTTP status code == 3xx) */ static gint gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src, ne_session ** ses, ne_request ** req, gint64 offset, gboolean do_redir) { ne_session *session = NULL; ne_request *request = NULL; gchar **c; gint res; gint http_status = 0; guint request_count = 0; do { if (src->proxy.host && src->proxy.port) { session = ne_session_create (src->uri.scheme, src->uri.host, src->uri.port); ne_session_proxy (session, src->proxy.host, src->proxy.port); } else if (src->proxy.host || src->proxy.port) { /* both proxy host and port must be specified or none */ return HTTP_REQUEST_WRONG_PROXY; } else { session = ne_session_create (src->uri.scheme, src->uri.host, src->uri.port); } if (src->connect_timeout > 0) { ne_set_connect_timeout (session, src->connect_timeout); } if (src->read_timeout > 0) { ne_set_read_timeout (session, src->read_timeout); } ne_set_session_flag (session, NE_SESSFLAG_ICYPROTO, 1); ne_ssl_set_verify (session, ssl_verify_callback, src); request = ne_request_create (session, "GET", src->query_string); if (src->user_agent) { ne_add_request_header (request, "User-Agent", src->user_agent); } for (c = src->cookies; c != NULL && *c != NULL; ++c) { GST_INFO ("Adding header Cookie : %s", *c); ne_add_request_header (request, "Cookies", *c); } if (src->iradio_mode) ne_add_request_header (request, "icy-metadata", "1"); if (offset > 0) { ne_print_request_header (request, "Range", "bytes=%" G_GINT64_FORMAT "-", offset); } res = ne_begin_request (request); if (res == NE_OK) { /* When the HTTP status code is 3xx, it is not the SHOUTcast streaming content yet; * Reload the HTTP request with a new URI value */ http_status = ne_get_status (request)->code; if (STATUS_IS_REDIRECTION (http_status) && do_redir) { const gchar *redir; /* the new URI value to go when redirecting can be found on the 'Location' HTTP header */ redir = ne_get_response_header (request, "Location"); if (redir != NULL) { ne_uri_free (&src->uri); gst_neonhttp_src_set_location (src, redir, NULL); GST_LOG_OBJECT (src, "Got HTTP Status Code %d", http_status); GST_LOG_OBJECT (src, "Using 'Location' header [%s]", src->uri.host); } } } if ((res != NE_OK) || (offset == 0 && http_status != 200) || (offset > 0 && http_status != 206 && !STATUS_IS_REDIRECTION (http_status))) { ne_request_destroy (request); request = NULL; ne_close_connection (session); ne_session_destroy (session); session = NULL; if (offset > 0 && http_status != 206 && !STATUS_IS_REDIRECTION (http_status)) { src->seekable = FALSE; } } /* if - NE_OK */ if (STATUS_IS_REDIRECTION (http_status) && do_redir) { ++request_count; GST_LOG_OBJECT (src, "redirect request_count is now %d", request_count); if (request_count < MAX_HTTP_REDIRECTS_NUMBER && do_redir) { GST_INFO_OBJECT (src, "Redirecting to %s", src->uri.host); } else { GST_WARNING_OBJECT (src, "Will not redirect, try again with a " "different URI or redirect location %s", src->uri.host); } /* FIXME: when not redirecting automatically, shouldn't we post a * redirect element message on the bus? */ } /* do the redirect, go back to send another HTTP request now using the 'Location' */ } while (do_redir && (request_count < MAX_HTTP_REDIRECTS_NUMBER) && STATUS_IS_REDIRECTION (http_status)); if (session) { *ses = session; *req = request; } return res; }
Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const char *verb ) { Hbf_State state = HBF_TRANSFER_SUCCESS; int cnt; if( ! session ) { state = HBF_SESSION_FAIL; } if( ! transfer ) { state = HBF_SPLITLIST_FAIL; } if( ! verb ) { state = HBF_PARAM_FAIL; } if(state == HBF_TRANSFER_SUCCESS) { DEBUG_HBF("%s request to %s", verb, transfer->url); } for( cnt=0; state == HBF_TRANSFER_SUCCESS && cnt < transfer->block_cnt; cnt++ ) { /* cnt goes from O to block_cnt, but block_id starts at start_id and wrap around * That way if we have not finished uploaded when we reach block_cnt, we re-upload * the beginning of the file that the server did not have in cache anymore. */ int block_id = (cnt + transfer->start_id) % transfer->block_cnt; hbf_block_t *block = transfer->block_arr[block_id]; char *transfer_url = NULL; if( ! block ) state = HBF_PARAM_FAIL; if( transfer->abort_cb ) { int do_abort = (transfer->abort_cb)(transfer->user_data); if( do_abort ) { state = HBF_USER_ABORTED; transfer->start_id = block_id % transfer->block_cnt; } } if( state == HBF_TRANSFER_SUCCESS ) { transfer_url = get_transfer_url( transfer, block_id ); if( ! transfer_url ) { state = HBF_PARAM_FAIL; } } if( state == HBF_TRANSFER_SUCCESS ) { if( transfer->block_cnt > 1 && cnt > 0 ) { /* The block count is > 1, check size and mtime before transmitting. */ state = hbf_validate_source_file(transfer); if( state == HBF_SOURCE_FILE_CHANGE ) { /* The source file has changed meanwhile */ } } } if( state == HBF_TRANSFER_SUCCESS || state == HBF_SUCCESS ) { ne_request *req = ne_request_create(session, verb, transfer_url); if( req ) { char buf[21]; snprintf(buf, sizeof(buf), "%"PRId64, transfer->stat_size); ne_add_request_header(req, "OC-Total-Length", buf); if( transfer->oc_header_modtime > 0 ) { snprintf(buf, sizeof(buf), "%"PRId64, transfer->oc_header_modtime); ne_add_request_header(req, "X-OC-Mtime", buf); } if( transfer->previous_etag ) { ne_add_request_header(req, "If-Match", transfer->previous_etag); } if( transfer->block_cnt > 1 ) { ne_add_request_header(req, "OC-Chunked", "1"); snprintf(buf, sizeof(buf), "%"PRId64, transfer->threshold); ne_add_request_header(req, "OC-Chunk-Size", buf); } ne_add_request_header( req, "Content-Type", "application/octet-stream"); state = _hbf_dav_request(transfer, req, transfer->fd, block ); if( state != HBF_TRANSFER_SUCCESS && state != HBF_SUCCESS) { if( transfer->error_string ) free( transfer->error_string ); transfer->error_string = strdup( ne_get_error(session) ); transfer->start_id = block_id % transfer->block_cnt; /* Set the code of the last transmission. */ state = HBF_FAIL; transfer->status_code = transfer->block_arr[block_id]->http_result_code; } ne_request_destroy(req); if (transfer->block_cnt > 1 && state == HBF_SUCCESS && cnt == 0) { /* Success on the first chunk is suspicious. It could happen that the server did not support chunking */ int rc = ne_delete(session, transfer_url); if (rc == NE_OK && _hbf_http_error_code(session) == 204) { /* If delete suceeded, it means some proxy strips the OC_CHUNKING header start again without chunking: */ free( transfer_url ); return _hbf_transfer_no_chunk(session, transfer, verb); } } if (state == HBF_TRANSFER_SUCCESS && transfer->chunk_finished_cb) { transfer->chunk_finished_cb(transfer, block_id, transfer->user_data); } } else { state = HBF_MEMORY_FAIL; } } free( transfer_url ); } /* do the source file validation finally (again). */ if( state == HBF_TRANSFER_SUCCESS ) { /* This means that no etag was returned on one of the chunks to indicate * that the upload was finished. */ state = HBF_TRANSFER_NOT_ACKED; } return state; }
static csync_vio_method_handle_t *owncloud_open(const char *durl, int flags, mode_t mode) { char *uri = NULL; char *dir = NULL; char getUrl[PATH_MAX]; int put = 0; int rc = NE_OK; #ifdef _WIN32 int gtp = 0; char tmpname[13]; #endif struct transfer_context *writeCtx = NULL; csync_stat_t statBuf; memset( getUrl, '\0', PATH_MAX ); (void) mode; /* unused on webdav server */ DEBUG_WEBDAV(( "=> open called for %s\n", durl )); uri = _cleanPath( durl ); if( ! uri ) { DEBUG_WEBDAV(("Failed to clean path for %s\n", durl )); errno = EACCES; rc = NE_ERROR; } if( rc == NE_OK ) dav_connect( durl ); if (flags & O_WRONLY) { put = 1; } if (flags & O_RDWR) { put = 1; } if (flags & O_CREAT) { put = 1; } if( rc == NE_OK && put ) { /* check if the dir name exists. Otherwise return ENOENT */ dir = c_dirname( durl ); if (dir == NULL) { errno = ENOMEM; return NULL; } DEBUG_WEBDAV(("Stating directory %s\n", dir )); if( c_streq( dir, _lastDir )) { DEBUG_WEBDAV(("Dir %s is there, we know it already.\n", dir)); } else { if( owncloud_stat( dir, (csync_vio_method_handle_t*)(&statBuf) ) == 0 ) { DEBUG_WEBDAV(("Directory of file to open exists.\n")); SAFE_FREE( _lastDir ); _lastDir = c_strdup(dir); } else { DEBUG_WEBDAV(("Directory %s of file to open does NOT exist.\n", dir )); /* the directory does not exist. That is an ENOENT */ errno = ENOENT; SAFE_FREE( dir ); return NULL; } } } writeCtx = c_malloc( sizeof(struct transfer_context) ); writeCtx->bytes_written = 0; if( rc == NE_OK ) { /* open a temp file to store the incoming data */ #ifdef _WIN32 memset( tmpname, '\0', 13 ); gtp = GetTempPath( PATH_MAX, getUrl ); DEBUG_WEBDAV(("win32 tmp path: %s\n", getUrl )); if ( gtp > MAX_PATH || (gtp == 0) ) { DEBUG_WEBDAV(("Failed to compute Win32 tmp path, trying /tmp\n")); strcpy( getUrl, "/tmp/"); } strcpy( tmpname, "csync.XXXXXX" ); if( c_tmpname( tmpname ) == 0 ) { _fmode = _O_BINARY; strcat( getUrl, tmpname ); writeCtx->tmpFileName = c_strdup( getUrl ); writeCtx->fd = open( writeCtx->tmpFileName, O_RDWR | O_CREAT | O_EXCL, 0600 ); } else { writeCtx->fd = -1; } #else writeCtx->tmpFileName = c_strdup( "/tmp/csync.XXXXXX" ); writeCtx->fd = mkstemp( writeCtx->tmpFileName ); #endif DEBUG_WEBDAV(("opening temp directory %s: %d\n", writeCtx->tmpFileName, writeCtx->fd )); if( writeCtx->fd == -1 ) { DEBUG_WEBDAV(("Failed to open temp file, errno = %d\n", errno )); rc = NE_ERROR; /* errno is set by the mkstemp call above. */ } } if( rc == NE_OK && put) { DEBUG_WEBDAV(("PUT request on %s!\n", uri)); /* reset the write buffer */ writeCtx->bytes_written = 0; writeCtx->fileWritten = 0; /* flag to indicate if contents was pushed to file */ writeCtx->req = ne_request_create(dav_session.ctx, "PUT", uri); writeCtx->method = "PUT"; } if( rc == NE_OK && ! put ) { writeCtx->req = 0; writeCtx->method = "GET"; /* Download the data into a local temp file. */ /* the download via the get function requires a full uri */ snprintf( getUrl, PATH_MAX, "%s://%s%s", ne_get_scheme( dav_session.ctx), ne_get_server_hostport( dav_session.ctx ), uri ); DEBUG_WEBDAV(("GET request on %s\n", getUrl )); #define WITH_HTTP_COMPRESSION #ifdef WITH_HTTP_COMPRESSION writeCtx->req = ne_request_create( dav_session.ctx, "GET", getUrl ); /* Allow compressed content by setting the header */ ne_add_request_header( writeCtx->req, "Accept-Encoding", "gzip,deflate" ); /* hook called before the content is parsed to set the correct reader, * either the compressed- or uncompressed reader. */ ne_hook_post_headers( dav_session.ctx, install_content_reader, writeCtx ); /* actually do the request */ rc = ne_request_dispatch(writeCtx->req ); /* possible return codes are: * NE_OK, NE_AUTH, NE_CONNECT, NE_TIMEOUT, NE_ERROR (from ne_request.h) */ if( rc != NE_OK || (rc == NE_OK && ne_get_status(writeCtx->req)->klass != 2) ) { DEBUG_WEBDAV(("request_dispatch failed with rc=%d\n", rc )); if( rc == NE_OK ) rc = NE_ERROR; errno = EACCES; } /* delete the hook again, otherwise they get chained as they are with the session */ ne_unhook_post_headers( dav_session.ctx, install_content_reader, writeCtx ); /* if the compression handle is set through the post_header hook, delete it. */ if( writeCtx->decompress ) { ne_decompress_destroy( writeCtx->decompress ); } /* delete the request in any case */ ne_request_destroy(writeCtx->req); #else DEBUG_WEBDAV(("GET Compression not supported!\n")); rc = ne_get( dav_session.ctx, getUrl, writeCtx->fd ); /* FIX_ESCAPE? */ #endif if( rc != NE_OK ) { DEBUG_WEBDAV(("Download to local file failed: %d.\n", rc)); errno = EACCES; } if( close( writeCtx->fd ) == -1 ) { DEBUG_WEBDAV(("Close of local download file failed.\n")); writeCtx->fd = -1; rc = NE_ERROR; errno = EACCES; } writeCtx->fd = -1; } if( rc != NE_OK ) { SAFE_FREE( writeCtx ); } SAFE_FREE( uri ); SAFE_FREE( dir ); return (csync_vio_method_handle_t *) writeCtx; }
static gboolean _rawx_update_chunk_attrs(chunk_id_t *cid, GSList *attrs, GError **err) { ne_session *s = NULL; ne_request *r = NULL; int ne_rc; gboolean result = FALSE; gchar dst[128]; guint16 port = 0; GString *req_str = NULL; char idstr[65]; if (!addr_info_get_addr(&(cid->addr), dst, sizeof(dst), &port)) return result; s = ne_session_create("http", dst, port); if (!s) { GSETERROR(err, "Failed to create session to rawx %s:%d", dst, port); return result; } ne_set_connect_timeout(s, 10); ne_set_read_timeout(s, 30); req_str =g_string_new("/rawx/chunk/set/"); bzero(idstr, sizeof(idstr)); buffer2str(&(cid->id), sizeof(cid->id), idstr, sizeof(idstr)); req_str = g_string_append(req_str, idstr); GRID_TRACE("Calling %s", req_str->str); r = ne_request_create (s, "GET", req_str->str); if (!r) { goto end_attr; } for (; attrs != NULL; attrs = attrs->next) { struct chunk_attr_s *attr = attrs->data; ne_add_request_header(r, attr->key, attr->val); } switch (ne_rc = ne_request_dispatch(r)) { case NE_OK: result = TRUE; break; case NE_ERROR: GSETCODE(err, 500, "Request NE_ERROR"); break; case NE_TIMEOUT: GSETCODE(err, 500, "Request Timeout"); break; case NE_CONNECT: GSETCODE(err, 500, "Request Connection timeout"); break; default: GSETCODE(err, 500, "Request failed"); break; } end_attr: if (NULL != req_str) g_string_free(req_str, TRUE); if (NULL != r) ne_request_destroy (r); if (NULL != s) ne_session_destroy (s); return result; }
/* See doc string for svn_ra_neon__parsed_request. */ static svn_error_t * parsed_request(svn_ra_neon__request_t *req, svn_ra_neon__session_t *ras, const char *method, const char *url, const char *body, apr_file_t *body_file, void set_parser(ne_xml_parser *parser, void *baton), svn_ra_neon__startelm_cb_t startelm_cb, svn_ra_neon__cdata_cb_t cdata_cb, svn_ra_neon__endelm_cb_t endelm_cb, void *baton, apr_hash_t *extra_headers, int *status_code, svn_boolean_t spool_response, apr_pool_t *pool) { ne_xml_parser *success_parser = NULL; spool_reader_baton_t spool_reader_baton; if (body == NULL) SVN_ERR(svn_ra_neon__set_neon_body_provider(req, body_file)); /* ### use a symbolic name somewhere for this MIME type? */ ne_add_request_header(req->ne_req, "Content-Type", "text/xml"); /* create a parser to read the normal response body */ success_parser = svn_ra_neon__xml_parser_create(req, NULL, startelm_cb, cdata_cb, endelm_cb, baton); /* if our caller is interested in having access to this parser, call the SET_PARSER callback with BATON. */ if (set_parser != NULL) set_parser(success_parser, baton); /* Register the "main" accepter and body-reader with the request -- the one to use when the HTTP status is 2XX. If we are spooling the response to disk first, we use our custom spool reader. */ if (spool_response) { /* Blow the temp-file away as soon as we eliminate the entire request */ SVN_ERR(svn_io_open_unique_file3(&spool_reader_baton.spool_file, &spool_reader_baton.spool_file_name, NULL, svn_io_file_del_on_pool_cleanup, req->pool, pool)); spool_reader_baton.req = req; svn_ra_neon__add_response_body_reader(req, ne_accept_2xx, spool_reader, &spool_reader_baton); } else attach_ne_body_reader(req, ne_accept_2xx, cancellation_callback, get_cancellation_baton(req, ne_xml_parse_v, success_parser, pool)); /* run the request and get the resulting status code. */ SVN_ERR(svn_ra_neon__request_dispatch( status_code, req, extra_headers, body, (strcmp(method, "PROPFIND") == 0) ? 207 : 200, 0, pool)); if (spool_response) { /* All done with the temporary file we spooled the response into. */ (void) apr_file_close(spool_reader_baton.spool_file); /* The success parser may set an error value in req->err */ SVN_RA_NEON__REQ_ERR (req, parse_spool_file(ras, spool_reader_baton.spool_file_name, success_parser, req->pool)); if (req->err) { svn_error_compose(req->err, svn_error_createf (SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, _("Error reading spooled %s request response"), method)); return req->err; } } SVN_ERR(svn_ra_neon__check_parse_error(method, success_parser, url)); return SVN_NO_ERROR; }
gs_status_t rawx_delete (gs_chunk_t *chunk, GError **err) { char str_req_id [1024]; char str_addr [STRLEN_ADDRINFO]; char str_ci [STRLEN_CHUNKID]; char cPath [CI_FULLPATHLEN]; char str_hash[STRLEN_CHUNKHASH]; ne_request *request=NULL; ne_session *session=NULL; memset(str_req_id, 0x00, sizeof(str_req_id)); if (!chunk || !chunk->ci || !chunk->content) { GSETERROR (err,"Invalid parameter (bad chunk structure)"); goto error_label; } addr_info_to_string (&(chunk->ci->id.addr), str_addr, sizeof(str_addr)); chunk_id2str(chunk, str_ci, sizeof(str_ci)); chunk_getpath (chunk, cPath, sizeof(cPath)); DEBUG("about to delete %s on %s", str_ci, cPath); gscstat_tags_start(GSCSTAT_SERVICE_RAWX, GSCSTAT_TAGS_REQPROCTIME); session = rawx_opensession (chunk, err); if (!session) { GSETERROR (err, "Cannot open a webdav session"); goto error_label; } /*Create a webdav request*/ do { request = ne_request_create (session, RAWX_DELETE, cPath); if (!request) { GSETERROR (err, "cannot create a %s WebDAV request", RAWX_DELETE); goto error_label; } } while (0); chunk_id2str (chunk, str_ci, sizeof(str_ci)); chunk_gethash (chunk, str_hash, sizeof(str_hash)); /* Add request header */ add_req_id_header(request, str_req_id, sizeof(str_req_id)-1); ne_add_request_header (request, "chunkid", str_ci); ne_add_request_header (request, "chunkhash", str_hash); ne_add_request_header (request, "containerid", C1_IDSTR(chunk->content)); ne_add_request_header (request, "contentpath", chunk->content->info.path); ne_print_request_header(request, "chunkpos", "%"G_GUINT32_FORMAT, chunk->ci->position); ne_print_request_header(request, "chunknb", "%"G_GUINT32_FORMAT, chunk->ci->nb); ne_print_request_header(request, "chunksize", "%"G_GINT64_FORMAT, chunk->ci->size); ne_print_request_header(request, "contentsize", "%"G_GINT64_FORMAT, chunk->content->info.size); /*now perform the request*/ switch (ne_request_dispatch (request)) { case NE_OK: if (ne_get_status(request)->klass != 2) { GSETERROR (err, "cannot delete '%s' (%s) (ReqId:%s)", cPath, ne_get_error(session), str_req_id); goto error_label; } DEBUG("chunk deletion finished (success) : %s", cPath); break; case NE_AUTH: case NE_CONNECT: case NE_TIMEOUT: case NE_ERROR: GSETERROR (err, "unexpected error from the WebDAV server (%s) (ReqId:%s)", ne_get_error(session), str_req_id); goto error_label; } ne_request_destroy (request); ne_session_destroy (session); TRACE("%s deleted (ReqId:%s)", cPath, str_req_id); gscstat_tags_end(GSCSTAT_SERVICE_RAWX, GSCSTAT_TAGS_REQPROCTIME); return 1; error_label: TRACE("could not delete %s", cPath); if (request) ne_request_destroy (request); if (session) ne_session_destroy (session); gscstat_tags_end(GSCSTAT_SERVICE_RAWX, GSCSTAT_TAGS_REQPROCTIME); return 0; }
int ne_lock(ne_session *sess, struct ne_lock *lock) { ne_request *req = ne_request_create(sess, "LOCK", lock->uri.path); ne_buffer *body = ne_buffer_create(); ne_xml_parser *parser = ne_xml_create(); int ret, parse_failed; struct lock_ctx ctx; memset(&ctx, 0, sizeof ctx); ctx.cdata = ne_buffer_create(); ctx.req = req; ne_xml_push_handler(parser, lk_startelm, lk_cdata, lk_endelm, &ctx); /* Create the body */ ne_buffer_concat(body, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" EOL "<lockinfo xmlns='DAV:'>" EOL " <lockscope>", lock->scope==ne_lockscope_exclusive? "<exclusive/>":"<shared/>", "</lockscope>" EOL "<locktype><write/></locktype>", NULL); if (lock->owner) { ne_buffer_concat(body, "<owner>", lock->owner, "</owner>" EOL, NULL); } ne_buffer_zappend(body, "</lockinfo>" EOL); ne_set_request_body_buffer(req, body->data, ne_buffer_size(body)); /* ne_add_request_header(req, "Content-Type", NE_XML_MEDIA_TYPE); */ /* Just to test whether sever accepts both text/xml and application/xml */ ne_add_request_header(req, "Content-Type", "text/xml"); ne_add_depth_header(req, lock->depth); add_timeout_header(req, lock->timeout); /* TODO: * By 2518, we need this only if we are creating a lock-null resource. * Since we don't KNOW whether the lock we're given is a lock-null * or not, we cover our bases. */ ne_lock_using_parent(req, lock->uri.path); /* This one is clearer from 2518 sec 8.10.4. */ ne_lock_using_resource(req, lock->uri.path, lock->depth); ret = ne_xml_dispatch_request(req, parser); ne_buffer_destroy(body); ne_buffer_destroy(ctx.cdata); parse_failed = ne_xml_failed(parser); if (ret == NE_OK && ne_get_status(req)->klass == 2) { if (ctx.token == NULL) { ret = NE_ERROR; ne_set_error(sess, _("No Lock-Token header given")); } else if (parse_failed) { ret = NE_ERROR; ne_set_error(sess, "%s", ne_xml_get_error(parser)); } else if (ne_get_status(req)->code == 207) { ret = NE_ERROR; /* TODO: set the error string appropriately */ } else if (ctx.found) { /* it worked: copy over real lock details if given. */ if (lock->token) ne_free(lock->token); lock->token = ctx.token; ctx.token = NULL; if (ctx.active.timeout != NE_TIMEOUT_INVALID) lock->timeout = ctx.active.timeout; lock->scope = ctx.active.scope; lock->type = ctx.active.type; if (ctx.active.depth >= 0) lock->depth = ctx.active.depth; if (ctx.active.owner) { if (lock->owner) ne_free(lock->owner); lock->owner = ctx.active.owner; ctx.active.owner = NULL; } } else { ret = NE_ERROR; ne_set_error(sess, _("Response missing activelock for %s"), ctx.token); } } else if (ret == NE_OK /* && status != 2xx */) { ret = NE_ERROR; } ne_lock_free(&ctx.active); if (ctx.token) ne_free(ctx.token); ne_request_destroy(req); ne_xml_destroy(parser); return ret; }
/* Gets a file from the owncloud url to the open file descriptor. */ static int owncloud_get(csync_vio_method_handle_t *flocal, csync_vio_method_handle_t *fremote, csync_vio_file_stat_t *vfs) { int rc = 0; int neon_stat; const ne_status *status; int fd; struct transfer_context *write_ctx = (struct transfer_context*) fremote; (void) vfs; /* stat information of the source file */ fd = csync_vio_getfd(flocal); if (fd == -1) { errno = EINVAL; return -1; } /* GET a file to the open file descriptor */ if( write_ctx == NULL ) { errno = EINVAL; return -1; } if( write_ctx->req == NULL ) { errno = EINVAL; return -1; } DEBUG_WEBDAV(" -- GET on %s", write_ctx->url); write_ctx->fd = fd; /* Allow compressed content by setting the header */ ne_add_request_header( write_ctx->req, "Accept-Encoding", "gzip,deflate" ); /* hook called before the content is parsed to set the correct reader, * either the compressed- or uncompressed reader. */ ne_hook_post_headers( dav_session.ctx, install_content_reader, write_ctx ); neon_stat = ne_request_dispatch(write_ctx->req ); /* possible return codes are: * NE_OK, NE_AUTH, NE_CONNECT, NE_TIMEOUT, NE_ERROR (from ne_request.h) */ if( neon_stat != NE_OK ) { set_errno_from_neon_errcode(neon_stat); DEBUG_WEBDAV("Error GET: Neon: %d, errno %d", neon_stat, errno); rc = -1; } else { status = ne_get_status( write_ctx->req ); if( status->klass != 2 ) { DEBUG_WEBDAV("sendfile request failed with http status %d!", status->code); set_errno_from_http_errcode( status->code ); /* decide if soft error or hard error that stops the whole sync. */ /* Currently all problems concerning one file are soft errors */ if( status->klass == 4 /* Forbidden and stuff, soft error */ ) { rc = 1; } else if( status->klass == 5 /* Server errors and such */ ) { rc = 1; /* No Abort on individual file errors. */ } else { rc = 1; } } else { DEBUG_WEBDAV("http request all cool, result code %d (%s)", status->code, status->reason_phrase ? status->reason_phrase : "<empty>"); } } /* delete the hook again, otherwise they get chained as they are with the session */ ne_unhook_post_headers( dav_session.ctx, install_content_reader, write_ctx ); /* if the compression handle is set through the post_header hook, delete it. */ if( write_ctx->decompress ) { ne_decompress_destroy( write_ctx->decompress ); } return rc; }
/** * \brief Send HTTP request over a session * * The function creates HTTP request, sends it and reads-out the response. * * \param[in] session HTTP session * \param[in] method Request method * \param[in] uri Request URI * \param[in] ct Request content type (optional, \c NULL accepted) * \param[in] req_body Request body (optional, \c NULL is accepted) * \param[out] resp_body Response body (optional, \c NULL is accepted) * * \return HTTP status code if response was sent, 0 on send error */ static int send_http_request( ne_session *session, const char *method, const char *uri, const char *ct, ne_buffer *req_body, ne_buffer *resp_body) { int resp_code = 0; ne_request *req = NULL; /* Create request */ req = ne_request_create(session, method, uri); /* Neon claims that request creation is always successful */ assert(NULL != req); do { /* Pragmatic do ... while (0) loop allowing breaks on error */ const ne_status *req_st; /* Set Content-Type */ if (NULL != ct) ne_add_request_header(req, "Content-Type", ct); /* Set request body */ if (NULL != req_body) /* BEWARE: The terminating '\0' byte is "used", too */ ne_set_request_body_buffer(req, req_body->data, req_body->used - 1); /* Send request */ int status = ne_begin_request(req); if (NE_OK != status) { break; } /* Read response */ assert(NE_OK == status); for (;;) { char buff[512]; ssize_t read; read = ne_read_response_block(req, buff, sizeof(buff)); /* Read failure */ if (0 > read) { status = NE_ERROR; break; } if (0 == read) break; if (NULL != resp_body) ne_buffer_append(resp_body, buff, read); } if (NE_OK != status) { break; } /* Request served */ ne_end_request(req); /* Get response code */ req_st = ne_get_status(req); assert(NULL != req_st); resp_code = req_st->code; } while (0); /* end of do ... while (0) pragmatic loop */ if (NULL != req) ne_request_destroy(req); return resp_code; }