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; }
static GByteArray* _download_to_gba(ne_session *session, const gchar *path_url, GError **error) { GByteArray *gba; ne_request *http_request; DEBUG("About to download [%s] into a memory buffer", path_url); gba = g_byte_array_new(); http_request = _build_request(session, path_url); ne_add_response_body_reader(http_request, ne_accept_2xx, read_to_gba, gba); switch (ne_request_dispatch(http_request)) { case NE_OK: if (ne_get_status(http_request)->klass != 2) { GSETERROR (error, "Failed to download '%s': %s", path_url, ne_get_error(session)); g_byte_array_free(gba, TRUE); gba = NULL; } break; case NE_AUTH: case NE_CONNECT: case NE_TIMEOUT: case NE_ERROR: default: GSETERROR(error,"Failed download '%s': %s", path_url, ne_get_error(session)); g_byte_array_free(gba, TRUE); gba = NULL; break; } ne_request_destroy(http_request); return gba; }
int ne_getmodtime(ne_session *sess, const char *uri, time_t *modtime) { ne_request *req = ne_request_create(sess, "HEAD", uri); const char *value; int ret; ret = ne_request_dispatch(req); value = ne_get_response_header(req, "Last-Modified"); if (ret == NE_OK && ne_get_status(req)->klass != 2) { *modtime = -1; ret = NE_ERROR; } else if (value) { *modtime = ne_httpdate_parse(value); } else { *modtime = -1; } ne_request_destroy(req); return ret; }
int ne_xml_dispatch_request(ne_request *req, ne_xml_parser *parser) { int ret; do { int parseit = 0; ret = ne_begin_request(req); if (ret) break; if (ne_get_status(req)->klass == 2) { ne_content_type ctype; if (ne_get_content_type(req, &ctype) == 0) { parseit = media_type_is_xml(&ctype); ne_free(ctype.value); } } if (parseit) ret = ne_xml_parse_response(req, parser); else ret = ne_discard_response(req); if (ret == NE_OK) ret = ne_end_request(req); } while (ret == NE_RETRY); return ret; }
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; }
void get(const StringSlice& url, WriteTarget out) { static int inited = ne_sock_init(); if (inited != 0) { throw Exception("ne_sock_init()"); } CString cstr(url); ne_uri uri = {}; if (ne_uri_parse(cstr.data(), &uri)) { throw Exception("ne_uri_parse()"); } if (uri.port == 0) { uri.port = ne_uri_defaultport(uri.scheme); } unique_ptr<ne_uri, decltype(&ne_uri_free)> uri_free(&uri, ne_uri_free); unique_ptr<ne_session, decltype(&ne_session_destroy)> sess( ne_session_create(uri.scheme, uri.host, uri.port), ne_session_destroy); unique_ptr<ne_request, decltype(&ne_request_destroy)> req( ne_request_create(sess.get(), "GET", uri.path), ne_request_destroy); ne_userdata userdata = {out}; ne_add_response_body_reader(req.get(), accept, reader, &userdata); auto err = ne_request_dispatch(req.get()); if (err != NE_OK) { throw Exception("ne_request_dispatch()"); } auto* st = ne_get_status(req.get()); if (st->code != 200) { throw Exception(st->code); } }
int s3_delete_object(S3 *s3,const char *bucket,const char *key) { ne_request *req; int err, retry; if(!s3) return -1; if(!bucket) return -1; s3_begin_session(s3); req = s3_new_request(s3,"DELETE",bucket,key,NULL,NULL); // send to server do { err = ne_begin_request(req); if(err != NE_OK) err = -EIO; else { if(ne_get_status(req)->code != 204) { s3_handle_error_response(s3,req); err = -EACCES; } retry = ne_end_request(req); } } while(retry == NE_RETRY); ne_request_destroy(req); s3_end_session(s3); return err; }
static int large_get(void) { ne_request *req = ne_request_create(i_session, "GET", path); char buffer[BLOCKSIZE], origin[BLOCKSIZE * 2]; long long progress = 0; ssize_t offset = 0; ssize_t bytes; memcpy(origin, block, BLOCKSIZE); memcpy(origin + BLOCKSIZE, block, BLOCKSIZE); ONNREQ("begin large GET request", ne_begin_request(req)); ONNREQ("failed GET request", ne_get_status(req)->klass != 2); while ((bytes = ne_read_response_block(req, buffer, BLOCKSIZE)) > 0) { ONV(memcmp(origin + offset, buffer, bytes), ("byte mismatch at %" NE_FMT_LONG_LONG, progress)); offset = (offset + bytes) % BLOCKSIZE; progress += bytes; } ONNREQ("failed reading GET response", bytes < 0); ONNREQ("end large GET request", ne_end_request(req)); ne_request_destroy(req); return OK; }
/* Dispatch a GET request REQ, writing the response body to FD fd. If * RANGE is non-NULL, then it is the value of the Range request * header, e.g. "bytes=1-5". Returns an NE_* error code. */ static int dispatch_to_fd(ne_request *req, int fd, const char *range) { ne_session *const sess = ne_get_session(req); const ne_status *const st = ne_get_status(req); int ret; do { const char *value; ret = ne_begin_request(req); if (ret != NE_OK) break; value = ne_get_response_header(req, "Content-Range"); /* For a 206 response, check that a Content-Range header is * given which matches the Range request header. */ if (range && st->code == 206 && (value == NULL || strncmp(value, "bytes ", 6) != 0 || strcmp(range + 6, value + 6))) { ne_set_error(sess, _("Response did not include requested range")); return NE_ERROR; } if ((range && st->code == 206) || (!range && st->klass == 2)) { ret = ne_read_response_to_fd(req, fd); } else { ret = ne_discard_response(req); } if (ret == NE_OK) ret = ne_end_request(req); } while (ret == NE_RETRY); return ret; }
/* PUT's from fd to URI */ int ne_put(ne_session *sess, const char *uri, int fd) { ne_request *req; struct stat st; int ret; if (fstat(fd, &st)) { int errnum = errno; char buf[200]; ne_set_error(sess, _("Could not determine file size: %s"), ne_strerror(errnum, buf, sizeof buf)); return NE_ERROR; } req = ne_request_create(sess, "PUT", uri); #ifdef NE_HAVE_DAV ne_lock_using_resource(req, uri, 0); ne_lock_using_parent(req, uri); #endif ne_set_request_body_fd(req, fd, 0, st.st_size); ret = ne_request_dispatch(req); if (ret == NE_OK && ne_get_status(req)->klass != 2) ret = NE_ERROR; ne_request_destroy(req); return ret; }
/* Perform a conditional PUT request with given If: header value, * placing response status-code in *code and class in *klass. Fails * if requests cannot be dispatched. */ static int conditional_put(const char *ifhdr, int *klass, int *code) { ne_request *req; req = ne_request_create(i_session, "PUT", res); ne_set_request_body_fd(req, i_foo_fd, 0, i_foo_len); ne_print_request_header(req, "If", "%s", ifhdr); ONMREQ("PUT", res, ne_request_dispatch(req)); if (code) *code = ne_get_status(req)->code; if (klass) *klass = ne_get_status(req)->klass; ne_request_destroy(req); return OK; }
int any_2xx_request(ne_session *sess, const char *uri) { ne_request *req = ne_request_create(sess, "GET", uri); int ret = ne_request_dispatch(req); int klass = ne_get_status(req)->klass; ne_request_destroy(req); ONV(ret != NE_OK || klass != 2, ("request failed: %s", ne_get_error(sess))); return ret; }
int s3_get_bucket(S3 *s3,const char *bucket, const char *prefix,const char *marker,int max_keys,const char *delimiter, const S3KeyInfoCallback *key_info_cb) { ne_request *req; int err, retry; ne_buffer *params; if(!s3) return -1; if(!bucket) return -1; params = ne_buffer_create(); if(prefix) ne_buffer_concat(params,"prefix=",prefix,"/&",NULL); if(marker) ne_buffer_concat(params,"marker=",marker,"&",NULL); if(max_keys >= 0) { char mk[16]; snprintf(mk,16,"%d",max_keys); mk[15] = 0; ne_buffer_concat(params,"max_keys=",max_keys,"&",NULL); } if(delimiter) ne_buffer_concat(params,"delimiter=",delimiter,"&",NULL); s3_begin_session(s3); req = s3_new_request(s3,"GET",bucket,NULL,params->data,NULL); ne_buffer_destroy(params); // send to server do { err = ne_begin_request(req); if(err != NE_OK) err = -EIO; else { if(ne_get_status(req)->code != 200) { s3_handle_error_response(s3,req); err = -EACCES; } else { s3->key_info.key_info_cb = key_info_cb; s3_parse_xml_response(s3, req, s3_xml_key_info_startelm, s3_xml_key_info_cdata, s3_xml_key_info_endelm, &s3->key_info ); } retry = ne_end_request(req); } } while(retry == NE_RETRY); ne_request_destroy(req); s3_end_session(s3); return err; }
int s3_head_object(S3 *s3,const char *bucket,const char *key,S3ObjectInfo *oi) { ne_request *req; int err; if(!s3) return -1; if(!bucket) return -1; s3_begin_session(s3); req = s3_new_request(s3,"HEAD",bucket,key,NULL,NULL); // send to server err = ne_request_dispatch(req); if(err != NE_OK) err = -EIO; if(ne_get_status(req)->code != 200) { s3_handle_error_response(s3,req); if(ne_get_status(req)->code == 404) err = -ENOENT; else err = -EACCES; } else if(oi) { const char *str; str = ne_get_response_header(req,"Content-Length"); if(str) oi->content_length = strtol(str,NULL,10); str = ne_get_response_header(req,"Content-Type"); if(str) { strncpy(oi->content_type,str,31); oi->content_type[31] = 0; } str = ne_get_response_header(req,"ETag"); if(str) { strncpy(oi->etag,str,79); oi->etag[79] = 0; } } ne_request_destroy(req); s3_end_session(s3); return err; }
int s3_get_object(S3 *s3,const char *bucket,const char *key,const S3WriteCallback *wcb) { ne_request *req; int err, retry; if(!s3) return -1; if(!bucket) return -1; if(!wcb) return -1; s3_begin_session(s3); req = s3_new_request(s3,"GET",bucket,key,NULL,NULL); // send to server do { err = ne_begin_request(req); if(err != NE_OK) err = -EIO; else { if(ne_get_status(req)->code != 200) { s3_handle_error_response(s3,req); if(ne_get_status(req)->code == 404) err = -ENOENT; else err = -EACCES; } else { char buffer[4096]; size_t bytes_read; while((bytes_read = ne_read_response_block(req,buffer,4096)) > 0) { wcb->callback(wcb->userdata,buffer,bytes_read); } } retry = ne_end_request(req); } } while(retry == NE_RETRY); ne_request_destroy(req); s3_end_session(s3); return err; }
int any_2xx_request_body(ne_session *sess, const char *uri) { ne_request *req = ne_request_create(sess, "GET", uri); #define BSIZE 5000 char *body = memset(ne_malloc(BSIZE), 'A', BSIZE); int ret; ne_set_request_body_buffer(req, body, BSIZE); ret = ne_request_dispatch(req); ne_free(body); ONV(ret != NE_OK || ne_get_status(req)->klass != 2, ("request failed: %s", ne_get_error(sess))); ne_request_destroy(req); return ret; }
/* Get to given fd */ int ne_get(ne_session *sess, const char *uri, int fd) { ne_request *req = ne_request_create(sess, "GET", uri); int ret; ret = dispatch_to_fd(req, fd, NULL); if (ret == NE_OK && ne_get_status(req)->klass != 2) { ret = NE_ERROR; } ne_request_destroy(req); return ret; }
/* Dispatch a GET request REQ, writing the response body to FD fd. If * RANGE is non-NULL, then it is the value of the Range request * header, e.g. "bytes=1-5". Returns an NE_* error code. */ static int dispatch_to_fd(ne_request *req, int fd, const char *range) { ne_session *const sess = ne_get_session(req); const ne_status *const st = ne_get_status(req); int ret; do { const char *value; ret = ne_begin_request(req); if (ret != NE_OK) break; value = ne_get_response_header(req, "Content-Range"); /* For a 206 response, check that a Content-Range header is * given which matches the Range request header. */ if (range && st->code == 206) { int err = 0; if (value == NULL || strncmp(value, "bytes ", 6) != 0) { err++; } else { /* If the response gives a range begin-end/total, limit * the comparison to the range itself. */ int len = strlen(value); char *cp = strchr(value, '/'); if (cp != NULL) len = (int)(cp - value); len -= 6; if (strncmp(range + 6, value + 6, len)) err++; } if (err) { ne_set_error(sess, _("Response did not include requested range")); return NE_ERROR; } } if ((range && st->code == 206) || (!range && st->klass == 2)) { ret = ne_read_response_to_fd(req, fd); } else { ret = ne_discard_response(req); } if (ret == NE_OK) ret = ne_end_request(req); } while (ret == NE_RETRY); return ret; }
int ne_options(ne_session *sess, const char *uri, ne_server_capabilities *caps) { ne_request *req = ne_request_create(sess, "OPTIONS", uri); int ret = ne_request_dispatch(req); const char *header = ne_get_response_header(req, "DAV"); if (header) parse_dav_header(header, caps); if (ret == NE_OK && ne_get_status(req)->klass != 2) { ret = NE_ERROR; } ne_request_destroy(req); return ret; }
/* Get to given fd */ int ne_post(ne_session *sess, const char *uri, int fd, const char *buffer) { ne_request *req = ne_request_create(sess, "POST", uri); int ret; ne_set_request_body_buffer(req, buffer, strlen(buffer)); ret = dispatch_to_fd(req, fd, NULL); if (ret == NE_OK && ne_get_status(req)->klass != 2) { ret = NE_ERROR; } ne_request_destroy(req); return ret; }
int ne_lock_refresh(ne_session *sess, struct ne_lock *lock) { ne_request *req = ne_request_create(sess, "LOCK", lock->uri.path); ne_xml_parser *parser = ne_xml_create(); int ret; struct lock_ctx ctx; memset(&ctx, 0, sizeof ctx); ctx.cdata = ne_buffer_create(); ctx.req = req; ctx.token = lock->token; /* Handle the response and update *lock appropriately. */ ne_xml_push_handler(parser, lk_startelm, lk_cdata, lk_endelm, &ctx); /* For a lock refresh, submitting only this lock token must be * sufficient. */ ne_print_request_header(req, "If", "(<%s>)", lock->token); add_timeout_header(req, lock->timeout); ret = ne_xml_dispatch_request(req, parser); if (ret == NE_OK) { if (ne_get_status(req)->klass != 2) { ret = NE_ERROR; /* and use default session error */ } else if (ne_xml_failed(parser)) { ret = NE_ERROR; ne_set_error(sess, "%s", ne_xml_get_error(parser)); } else if (!ctx.found) { ne_set_error(sess, _("No activelock for <%s> returned in " "LOCK refresh response"), lock->token); ret = NE_ERROR; } else /* success! */ { /* update timeout for passed-in lock structure. */ lock->timeout = ctx.active.timeout; } } ne_lock_free(&ctx.active); ne_buffer_destroy(ctx.cdata); ne_request_destroy(req); ne_xml_destroy(parser); return ret; }
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 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; }
static int large_put(void) { ne_request *req = ne_request_create(i_session, "PUT", path); int count, ret; #ifdef NE_LFS ne_set_request_body_provider64(req, TOTALSIZE, provider, &count); #else ne_set_request_body_provider(req, TOTALSIZE, provider, &count); #endif ret = ne_request_dispatch(req); ONNREQ("large PUT request", ret || ne_get_status(req)->klass != 2); ne_request_destroy(req); return OK; }
int ne_xml_dispatch_request(ne_request *req, ne_xml_parser *parser) { int ret; do { ret = ne_begin_request(req); if (ret) break; if (ne_get_status(req)->klass == 2) ret = ne_xml_parse_response(req, parser); else ret = ne_discard_response(req); if (ret == NE_OK) ret = ne_end_request(req); } while (ret == NE_RETRY); return ret; }
/* sends a small segment of the file from a high offset. */ static int send_high_offset(void) { int ret, fd = open64(SPARSE, O_RDONLY); ne_session *sess; ne_request *req; ONN("could not open sparse file", fd < 0); CALL(make_session(&sess, serve_check_body, NULL)); req = ne_request_create(sess, "PUT", "/sparse"); ne_set_request_body_fd64(req, fd, point, strlen(data)); ret = ne_request_dispatch(req); CALL(await_server()); ONV(ret != NE_OK || ne_get_status(req)->klass != 2, ("request failed: %s", ne_get_error(sess))); ne_request_destroy(req); ne_session_destroy(sess); close(fd); return OK; }
int s3_put_object(S3 *s3,const char *bucket,const char *key,const char *content_type,int content_length,const S3ReadCallback *rcb) { ne_request *req; int err, retry; if(!s3) return -1; if(!bucket) return -1; if(!rcb) return -1; s3_begin_session(s3); req = s3_new_request(s3,"PUT",bucket,key,NULL,content_type); ne_print_request_header(req,"Content-Length","%d",content_length); #ifdef NE_LFS ne_set_request_body_provider64(req,content_length,rcb->callback,rcb->userdata); #else ne_set_request_body_provider(req,content_length,rcb->callback,rcb->userdata); #endif //ne_set_request_body_buffer(req,"hello",5); // send to server do { err = ne_begin_request(req); if(err != NE_OK) err = -EIO; else { if(ne_get_status(req)->code != 200) { s3_handle_error_response(s3,req); err = -EACCES; } retry = ne_end_request(req); } } while(retry == NE_RETRY); ne_request_destroy(req); s3_end_session(s3); return err; }
/* Normally, this module uses get and put. But for creation of new files * with owncloud_creat, write is still needed. */ static ssize_t owncloud_write(csync_vio_method_handle_t *fhandle, const void *buf, size_t count) { struct transfer_context *writeCtx; int rc = 0; int neon_stat; const ne_status *status; writeCtx = (struct transfer_context*) fhandle; if (fhandle == NULL) { errno = EBADF; rc = -1; } ne_set_request_body_buffer(writeCtx->req, buf, count ); /* Start the request. */ neon_stat = ne_request_dispatch( writeCtx->req ); set_errno_from_neon_errcode( neon_stat ); status = ne_get_status( writeCtx->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("write request all ok, result code %d", status->code); } return rc; }
static int dispatch_to_buffer(ne_session *sess, ne_request *req, char *buf, const char *range, ssize_t *bytes_read) { const ne_status *const st = ne_get_status(req); int ret; size_t rlen; /* length of bytespec after "bytes=" */ rlen = range ? strlen(range + 6) : 0; do { const char *value; ret = ne_begin_request(req); if (ret != NE_OK) break; value = ne_get_response_header(req, "Content-Range"); /* For a 206 response, check that a Content-Range header is * given which matches the Range request header. */ if (range && st->code == 206 && (value == NULL || strncmp(value, "bytes ", 6) != 0 || strncmp(range + 6, value + 6, rlen) || (range[5 + rlen] != '-' && value[6 + rlen] != '/'))) { ne_set_error(sess, "Response did not include requested range"); return NE_ERROR; } if ((range && st->code == 206) || (!range && st->klass == 2)) { ret = ne_read_response_to_buf(req, buf, bytes_read); } else { ret = ne_discard_response(req); } if (ret == NE_OK) ret = ne_end_request(req); } while (ret == NE_RETRY); return ret; }
int ne_unlock(ne_session *sess, const struct ne_lock *lock) { ne_request *req = ne_request_create(sess, "UNLOCK", lock->uri.path); int ret; ne_print_request_header(req, "Lock-Token", "<%s>", lock->token); /* UNLOCK of a lock-null resource removes the resource from the * parent collection; so an UNLOCK may modify the parent * collection. (somewhat counter-intuitive, and not easily derived * from 2518.) */ ne_lock_using_parent(req, lock->uri.path); ret = ne_request_dispatch(req); if (ret == NE_OK && ne_get_status(req)->klass != 2) { ret = NE_ERROR; } ne_request_destroy(req); return ret; }