Example #1
0
/* 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;
}
Example #2
0
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;
}
Example #3
0
/* 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;
}
Example #4
0
/*
 * perform one transfer of one block.
 * returns HBF_TRANSFER_SUCCESS if the transfer of this block was a success
 * returns HBF_SUCCESS if the server aknoweldge that he received all the blocks
 */
static int _hbf_dav_request(hbf_transfer_t *transfer, ne_request *req, int fd, hbf_block_t *blk ) {
    Hbf_State state = HBF_TRANSFER_SUCCESS;
    int res;
    const ne_status *req_status = NULL;
    const char *etag = NULL;

    (void) transfer;

    if( ! (blk && req) ) return HBF_PARAM_FAIL;

    ne_set_request_body_fd(req, fd, blk->start, blk->size);
    DEBUG_HBF("Block: %d , Start: %" PRId64 " and Size: %" PRId64 "", blk->seq_number, blk->start, blk->size );
    res = ne_request_dispatch(req);

    req_status = ne_get_status( req );

    switch(res) {
    case NE_OK:
        blk->state = HBF_TRANSFER_FAILED;
        state = HBF_FAIL;
        etag = 0;
        if( req_status->klass == 2 ) {
            state = HBF_TRANSFER_SUCCESS;
            blk->state = HBF_TRANSFER_SUCCESS;
            etag = ne_get_response_header(req, "ETag");
            if (etag && etag[0]) {
                /* When there is an etag, it means the transfer was complete */
                state = HBF_SUCCESS;

                if( etag[0] == '"' && etag[ strlen(etag)-1] == '"') {
                     int len = strlen( etag )-2;
                     blk->etag = malloc( len+1 );
                     strncpy( blk->etag, etag+1, len );
                     blk->etag[len] = '\0';
                } else {
                    blk->etag = strdup( etag );
                }
            } else {
                /* DEBUG_HBF("OOOOOOOO No etag returned!"); */
            }

            /* check if the server was able to set the mtime already. */
            etag = ne_get_response_header(req, "X-OC-MTime");
            if( etag && strcmp(etag, "accepted") == 0 ) {
                /* the server acknowledged that the mtime was set. */
                transfer->modtime_accepted = 1;
            }

            etag = ne_get_response_header(req, "OC-FileID");
            if( etag ) {
                transfer->file_id = strdup( etag );
            }
        }
        break;
    case NE_AUTH:
            state = HBF_AUTH_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
            break;
        case NE_PROXYAUTH:
            state = HBF_PROXY_AUTH_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
        break;
        case NE_CONNECT:
            state = HBF_CONNECT_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
        break;
        case NE_TIMEOUT:
            state = HBF_TIMEOUT_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
            break;
        case NE_ERROR:
            state = HBF_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
            break;
    }

    blk->http_result_code = req_status->code;
    if( req_status->reason_phrase ) {
        blk->http_error_msg = strdup(req_status->reason_phrase);
    }

    return state;
}
Example #5
0
/*
 * Puts a file read from the open file descriptor to the ownCloud URL.
*/
static int owncloud_put(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;
  csync_stat_t sb;
  struct transfer_context *write_ctx = (struct transfer_context*) fremote;
  int fd;
  ne_request *request = NULL;

  fd = csync_vio_getfd(flocal);
  if (fd == -1) {
      errno = EINVAL;
      return -1;
  }

  if( write_ctx == NULL ) {
      errno = EINVAL;
      return -1;
  }
  request = write_ctx->req;

  if( request == NULL) {
    errno = EINVAL;
    return -1;
  }

  /* stat the source-file to get the file size. */
  if( fstat( fd, &sb ) == 0 ) {
    if( sb.st_size != vfs->size ) {
      DEBUG_WEBDAV("WRN: Stat size differs from vfs size!");
    }
    /* Attach the request to the file descriptor */
    ne_set_request_body_fd(request, fd, 0, sb.st_size);
    DEBUG_WEBDAV("Put file size: %lld, variable sizeof: %ld", (long long int) sb.st_size,
                 sizeof(sb.st_size));

    /* Start the request. */
    neon_stat = ne_request_dispatch( write_ctx->req );
    set_errno_from_neon_errcode( neon_stat );

    status = ne_get_status( request );
    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", status->code);
    }
  } else {
    DEBUG_WEBDAV("Could not stat file descriptor");
    rc = 1;
  }

  return rc;
}
Example #6
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;
}