示例#1
0
/* 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;
}
示例#2
0
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;
}