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_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; }
/* 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; }
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; }
static int netxml_alarm_subscribe(const char *page) { int ret, port = -1, secret = -1; char buf[LARGEBUF], *s; ne_request *request; ne_sock_addr *addr; const ne_inet_addr *ai; char resp_buf[LARGEBUF]; /* Clear response buffer */ memset(resp_buf, 0, sizeof(resp_buf)); upsdebugx(2, "%s: %s", __func__, page); sock = ne_sock_create(); if (gethostname(buf, sizeof(buf)) == 0) { dstate_setinfo("driver.hostname", "%s", buf); } else { dstate_setinfo("driver.hostname", "<unknown>"); } #ifdef HAVE_NE_SOCK_CONNECT_TIMEOUT ne_sock_connect_timeout(sock, timeout); #endif ne_sock_read_timeout(sock, 1); netxml_get_page(subdriver->configure); snprintf(buf, sizeof(buf), "<?xml version=\"1.0\"?>\n"); snprintfcat(buf, sizeof(buf), "<Subscribe>\n"); snprintfcat(buf, sizeof(buf), "<Class>%s v%s</Class>\n", progname, DRIVER_VERSION); snprintfcat(buf, sizeof(buf), "<Type>connected socket</Type>\n"); snprintfcat(buf, sizeof(buf), "<HostName>%s</HostName>\n", dstate_getinfo("driver.hostname")); snprintfcat(buf, sizeof(buf), "<XMLClientParameters>\n"); snprintfcat(buf, sizeof(buf), "<ShutdownDuration>%d</ShutdownDuration>\n", shutdown_duration); if( shutdown_timer > 0 ) { snprintfcat(buf, sizeof(buf), "<ShutdownTimer>%d</ShutdownTimer>\r\n", shutdown_timer); } else { snprintfcat(buf, sizeof(buf), "<ShutdownTimer>NONE</ShutdownTimer>\n"); } snprintfcat(buf, sizeof(buf), "<AutoConfig>LOCAL</AutoConfig>\n"); snprintfcat(buf, sizeof(buf), "<OutletGroup>1</OutletGroup>\n"); snprintfcat(buf, sizeof(buf), "</XMLClientParameters>\n"); snprintfcat(buf, sizeof(buf), "<Warning></Warning>\n"); snprintfcat(buf, sizeof(buf), "</Subscribe>\n"); /* now send subscription message setting all the proper flags */ request = ne_request_create(session, "POST", page); ne_set_request_body_buffer(request, buf, strlen(buf)); /* as the NMC reply is not xml standard compliant let's parse it this way */ do { #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(timeout+1); #endif ret = ne_begin_request(request); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(0); #endif if (ret != NE_OK) { break; } ret = ne_read_response_block(request, resp_buf, sizeof(resp_buf)); if (ret == NE_OK) { ret = ne_end_request(request); } } while (ret == NE_RETRY); ne_request_destroy(request); /* due to different formats used by the various NMCs, we need to\ break up the reply in lines and parse each one separately */ for (s = strtok(resp_buf, "\r\n"); s != NULL; s = strtok(NULL, "\r\n")) { upsdebugx(2, "%s: parsing %s", __func__, s); if (!strncasecmp(s, "<Port>", 6) && (sscanf(s+6, "%u", &port) != 1)) { return NE_RETRY; } if (!strncasecmp(s, "<Secret>", 8) && (sscanf(s+8, "%u", &secret) != 1)) { return NE_RETRY; } } if ((port == -1) || (secret == -1)) { upsdebugx(2, "%s: parsing initial subcription failed", __func__); return NE_RETRY; } /* Resolve the given hostname. 'flags' must be zero. Hex * string IPv6 addresses (e.g. `::1') may be enclosed in brackets * (e.g. `[::1]'). */ addr = ne_addr_resolve(uri.host, 0); /* Returns zero if name resolution was successful, non-zero on * error. */ if (ne_addr_result(addr) != 0) { upsdebugx(2, "%s: name resolution failure on %s: %s", __func__, uri.host, ne_addr_error(addr, buf, sizeof(buf))); ne_addr_destroy(addr); return NE_RETRY; } for (ai = ne_addr_first(addr); ai != NULL; ai = ne_addr_next(addr)) { upsdebugx(2, "%s: connecting to host %s port %d", __func__, ne_iaddr_print(ai, buf, sizeof(buf)), port); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(timeout+1); #endif ret = ne_sock_connect(sock, ai, port); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(0); #endif if (ret == NE_OK) { upsdebugx(2, "%s: connection to %s open on fd %d", __func__, uri.host, ne_sock_fd(sock)); break; } } ne_addr_destroy(addr); if (ai == NULL) { upsdebugx(2, "%s: failed to create listening socket", __func__); return NE_RETRY; } snprintf(buf, sizeof(buf), "<Subscription Identification=\"%u\"></Subscription>", secret); ret = ne_sock_fullwrite(sock, buf, strlen(buf) + 1); if (ret != NE_OK) { upsdebugx(2, "%s: send failed: %s", __func__, ne_sock_error(sock)); return NE_RETRY; } ret = ne_sock_read(sock, buf, sizeof(buf)); if (ret < 1) { upsdebugx(2, "%s: read failed: %s", __func__, ne_sock_error(sock)); return NE_RETRY; } if (strcasecmp(buf, "<Subscription Answer=\"ok\"></Subscription>")) { upsdebugx(2, "%s: subscription rejected", __func__); return NE_RETRY; } upslogx(LOG_INFO, "NSM connection to '%s' established", uri.host); return NE_OK; }
/** * \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; }
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 int owncloud_close(csync_vio_method_handle_t *fhandle) { struct transfer_context *writeCtx; csync_stat_t st; int rc; int ret = 0; size_t len = 0; writeCtx = (struct transfer_context*) fhandle; if (fhandle == NULL) { errno = EBADF; ret = -1; } /* handle the PUT request, means write to the WebDAV server */ if( ret != -1 && strcmp( writeCtx->method, "PUT" ) == 0 ) { /* if there is a valid file descriptor, close it, reopen in read mode and start the PUT request */ if( writeCtx->fd > -1 ) { if( writeCtx->fileWritten && writeCtx->bytes_written > 0 ) { /* was content written to file? */ /* push the rest of the buffer to file as well. */ DEBUG_WEBDAV(("Write remaining %lu bytes to disk.\n", (unsigned long) writeCtx->bytes_written )); len = write( writeCtx->fd, _buffer, writeCtx->bytes_written ); if( len != writeCtx->bytes_written ) { DEBUG_WEBDAV(("WRN: write wrote wrong number of remaining bytes\n")); } writeCtx->bytes_written = 0; } if( close( writeCtx->fd ) < 0 ) { DEBUG_WEBDAV(("Could not close file %s\n", writeCtx->tmpFileName )); errno = EBADF; ret = -1; } /* and open it again to read from */ #ifdef _WIN32 _fmode = _O_BINARY; #endif if( writeCtx->fileWritten ) { DEBUG_WEBDAV(("Putting file through file cache.\n")); /* we need to go the slow way and close and open the file and read from fd. */ if (( writeCtx->fd = open( writeCtx->tmpFileName, O_RDONLY )) < 0) { errno = EIO; ret = -1; } else { if (fstat( writeCtx->fd, &st ) < 0) { DEBUG_WEBDAV(("Could not stat file %s\n", writeCtx->tmpFileName )); errno = EIO; ret = -1; } /* successfully opened for read. Now start the request via ne_put */ ne_set_request_body_fd( writeCtx->req, writeCtx->fd, 0, st.st_size ); rc = ne_request_dispatch( writeCtx->req ); if( close( writeCtx->fd ) == -1 ) { errno = EBADF; ret = -1; } if (rc == NE_OK) { if ( ne_get_status( writeCtx->req )->klass != 2 ) { DEBUG_WEBDAV(("Error - PUT status value no 2xx\n")); errno = EIO; ret = -1; } } else { DEBUG_WEBDAV(("Error - put request on close failed: %d!\n", rc )); errno = EIO; ret = -1; } } } else { /* all content is in the buffer. */ DEBUG_WEBDAV(("Putting file through memory cache.\n")); ne_set_request_body_buffer( writeCtx->req, _buffer, writeCtx->bytes_written ); rc = ne_request_dispatch( writeCtx->req ); if( rc == NE_OK ) { if ( ne_get_status( writeCtx->req )->klass != 2 ) { DEBUG_WEBDAV(("Error - PUT status value no 2xx\n")); errno = EIO; ret = -1; } } else { DEBUG_WEBDAV(("Error - put request from memory failed: %d!\n", rc )); errno = EIO; ret = -1; } } } ne_request_destroy( writeCtx->req ); } else { /* Its a GET request, not much to do in close. */ if( writeCtx->fd > -1) { if( close( writeCtx->fd ) == -1 ) { errno = EBADF; ret = -1; } } } /* Remove the local file. */ unlink( writeCtx->tmpFileName ); /* free mem. Note that the request mem is freed by the ne_request_destroy call */ SAFE_FREE( writeCtx->tmpFileName ); SAFE_FREE( writeCtx ); return ret; }
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; }