Exemple #1
0
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;
}
Exemple #2
0
/* 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;
}
Exemple #3
0
/* 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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
/**
 *  \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;
}
Exemple #7
0
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);
}
Exemple #8
0
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;
}
Exemple #9
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;
}