UNPKG

nebulab-dropbox

Version:
1,077 lines (994 loc) 72.8 kB
# Represents a user accessing the application. class Dropbox.Client # Dropbox API client representing an user or an application. # # For an optimal user experience, applications should use a single client for # all Dropbox interactions. # # @param {Object} options the application type and API key; alternatively, # the result of a previous {Dropbox.Client#credentials} call can be passed # in to create a {Dropbox.Client} instance for the same user # @option options {String} key the Dropbox application's key (client # identifier, in OAuth 2.0 vocabulary) # @option options {String} secret the Dropbox application's secret (client # secret, in OAuth 2.0 vocabulary); browser-side applications should not # use this option # @option options {String} token (optional) the user's OAuth 2.0 access token # @option options {String} uid (optional) the user's Dropbox UID # # @see Dropbox.Client#credentials constructor: (options) -> @_serverRoot = options.server or @_defaultServerRoot() if 'maxApiServer' of options @_maxApiServer = options.maxApiServer else @_maxApiServer = @_defaultMaxApiServer() @_authServer = options.authServer or @_defaultAuthServer() @_fileServer = options.fileServer or @_defaultFileServer() @_downloadServer = options.downloadServer or @_defaultDownloadServer() @_notifyServer = options.notifyServer or @_defaultNotifyServer() @onXhr = new Dropbox.Util.EventSource cancelable: true @onError = new Dropbox.Util.EventSource @onAuthStepChange = new Dropbox.Util.EventSource @_xhrOnErrorHandler = (error, callback) => @_handleXhrError error, callback @_oauth = new Dropbox.Util.Oauth options @_uid = options.uid or null @authStep = @_oauth.step() @_driver = null @authError = null @_credentials = null @setupUrls() # @property {Dropbox.Util.EventSource<Dropbox.Util.Xhr>} fires cancelable # events every time when a network request to the Dropbox API server is # about to be sent; if the event is canceled by returning a falsey value # from a listener, the network request is silently discarded; whenever # possible, listeners should restrict themselves to using the xhr property # of the {Dropbox.Util.Xhr} instance passed to them; everything else in the # {Dropbox.Util.Xhr} API is in flux onXhr: null # @property {Dropbox.Util.EventSource<Dropbox.ApiError>} fires non-cancelable # events every time when a network request to the Dropbox API server # results in an error onError: null # @property {Dropbox.Util.EventSource<Dropbox.Client>} fires non-cancelable # events every time this client's authStep property changes; this can be # used to update UI state onAuthStepChange: null # Plugs in the OAuth / application integration code. # # This replaces any driver set up by previous calls to # {Dropbox.Client#authDriver}. On most supported platforms, an OAuth driver # can be configured automatically. # # @param {Dropbox.AuthDriver} driver provides the integration between the # application and the OAuth 2.0 flow used by the Dropbox API # @return {Dropbox.Client} this, for easy call chaining authDriver: (driver) -> @_driver = driver @ # The authenticated user's Dropbx user account ID. # # This user account ID is guaranteed to be consistent across API calls from # the same application (not across applications, though). # # @return {String} a short ID that identifies the user account; null if no # user is authenticated dropboxUid: -> @_uid # Get the client's OAuth credentials. # # @return {Object} a plain object whose properties can be passed to # {Dropbox.Client#setCredentials} or to the {Dropbox.Client} constructor to # reuse this client's login credentials credentials: -> @_computeCredentials() unless @_credentials @_credentials # Authenticates the app's user to Dropbox's API server. # # In most cases, the process will involve sending the user to an # authorization server on the Dropbox servers. If the user clicks "Allow", # the application will be authorized. If the user clicks "Deny", the method # will pass a {Dropbox.AuthError} to its callback, and the error's code will # be {Dropbox.AuthError.ACCESS_DENIED}. # # @param {Object} options (optional) one or more of the options below # @option options {Boolean} interactive if false, the authentication process # will stop and call the callback whenever it would have to wait for an # authorization; true by default; this is useful for determining if the # authDriver has cached credentials available # @param {function(Dropbox.ApiError|Dropbox.AuthError, Dropbox.Client)} # callback (optional) called when the authentication completes; if # successful, the second parameter is this client and the first parameter # is null # @return {Dropbox.Client} this, for easy call chaining authenticate: (options, callback) -> if !callback and typeof options is 'function' callback = options options = null if options and 'interactive' of options interactive = options.interactive else interactive = true unless @_driver or @authStep is DbxClient.DONE Dropbox.AuthDriver.autoConfigure @ unless @_driver throw new Error( 'OAuth driver auto-configuration failed. Call authDriver.') if @authStep is DbxClient.ERROR throw new Error 'Client got in an error state. Call reset() to reuse it!' # _fsmStep helper that transitions the FSM to the next step. # This is repetitive stuff done at the end of each step. _fsmNextStep = => @authStep = @_oauth.step() @authError = @_oauth.error() if @authStep is DbxClient.ERROR @_credentials = null @onAuthStepChange.dispatch @ _fsmStep() # _fsmStep helper that transitions the FSM to the error step. _fsmErrorStep = => @authStep = DbxClient.ERROR @_credentials = null @onAuthStepChange.dispatch @ _fsmStep() # Advances the authentication FSM by one step. oldAuthStep = null _fsmStep = => if oldAuthStep isnt @authStep oldAuthStep = @authStep if @_driver and @_driver.onAuthStepChange @_driver.onAuthStepChange(@, _fsmStep) return switch @authStep when DbxClient.RESET # No credentials. Decide on a state param for OAuth 2 authorization. unless interactive callback null, @ if callback return if @_driver.getStateParam @_driver.getStateParam (stateParam) => # NOTE: the driver might have injected the state param itself if @client.authStep is DbxClient.RESET @_oauth.setAuthStateParam stateParam _fsmNextStep() @_oauth.setAuthStateParam Dropbox.Util.Oauth.randomAuthStateParam() _fsmNextStep() when DbxClient.PARAM_SET # Ask the user for authorization. unless interactive callback null, @ if callback return authUrl = @authorizeUrl() @_driver.doAuthorize authUrl, @_oauth.authStateParam(), @, (queryParams) => @_oauth.processRedirectParams queryParams @_uid = queryParams.uid if queryParams.uid _fsmNextStep() when DbxClient.PARAM_LOADED # Check a previous state parameter. unless @_driver.resumeAuthorize # This switches the client to the PARAM_SET state @_oauth.setAuthStateParam @_oauth.authStateParam() _fsmNextStep() return @_driver.resumeAuthorize @_oauth.authStateParam(), @, (queryParams) => @_oauth.processRedirectParams queryParams @_uid = queryParams.uid if queryParams.uid _fsmNextStep() when DbxClient.AUTHORIZED # Request token authorized, switch it for an access token. @getAccessToken (error, data) => if error @authError = error _fsmErrorStep() else @_oauth.processRedirectParams data @_uid = data.uid _fsmNextStep() when DbxClient.DONE # We have an access token. callback null, @ if callback return when DbxClient.SIGNED_OUT # The user signed out, restart the flow. # The authStep change makes reset() not trigger onAuthStepChange. @authStep = DbxClient.RESET @reset() _fsmStep() when DbxClient.ERROR # An error occurred during authentication. callback @authError, @ if callback return _fsmStep() # Start up the state machine. @ # Checks if this client can perform API calls on behalf of a user. # # @return {Boolean} true if this client has a user's OAuth 2 access token and # can be used to make API calls; false otherwise isAuthenticated: -> @authStep is DbxClient.DONE # Invalidates and forgets the user's Dropbox OAuth 2 access token. # # This should be called when the user explicitly signs off from your # application, to meet the users' expectation that after they sign out, their # access tokens will not be persisted on the machine. # # @param {Object} options (optional) one or more of the options below # @option options {Boolean} mustInvalidate when true, the method will fail if # the API call for invalidating the token fails; by default, the access # token is forgotten and the method reports success even if the API call # fails # @param {function(Dropbox.ApiError)} callback called after the user's # token is forgotten; if successful, the error parameter is null; this # method will always succeed if mustInvalidate isn't true # @return {XMLHttpRequest} the XHR object used for this API call # @throw {Error} if this client doesn't have Dropbox credentials associated # with it; call {Dropbox.Client#isAuthenticated} to find out if a client # has credentials # @see Dropbox.Client#isAuthenticated signOut: (options, callback) -> if !callback and typeof options is 'function' callback = options options = null stopOnXhrError = options and options.mustInvalidate unless @authStep is DbxClient.DONE throw new Error("This client doesn't have a user's token") xhr = new Dropbox.Util.Xhr 'POST', @_urls.signOut xhr.signWithOauth @_oauth @_dispatchXhr xhr, (error) => if error if error.status is Dropbox.ApiError.INVALID_TOKEN # The token was already invalidated. Sweet. error = null else if stopOnXhrError callback error if callback return # The authStep change makes reset() not trigger onAuthStepChange. @authStep = DbxClient.RESET @reset() @authStep = DbxClient.SIGNED_OUT @onAuthStepChange.dispatch @ if @_driver and @_driver.onAuthStepChange @_driver.onAuthStepChange @, -> callback null if callback else callback null if callback # Alias for signOut. # # @see Dropbox.Client#signOut signOff: (options, callback) -> @signOut options, callback # Retrieves information about the logged in user. # # @param {Object} options (optional) the advanced settings below # @option options {Boolean} httpCache if true, the API request will be set to # allow HTTP caching to work; by default, requests are set up to avoid # CORS preflights; setting this option can make sense when making the same # request repeatedly # @param {function(Dropbox.ApiError, Dropbox.AccountInfo, Object)} callback # called with the result of the /account/info HTTP request; if the call # succeeds, the second parameter is a {Dropbox.AccountInfo} instance, the # third parameter is the parsed JSON data behind the {Dropbox.AccountInfo} # instance, and the first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call getAccountInfo: (options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null httpCache = false if options and options.httpCache httpCache = true xhr = new Dropbox.Util.Xhr 'GET', @_urls.accountInfo xhr.signWithOauth @_oauth, httpCache @_dispatchXhr xhr, (error, accountData) -> callback error, Dropbox.AccountInfo.parse(accountData), accountData # Backwards-compatible name of getAccountInfo. # # @deprecated # @see Dropbox.Client#getAccountInfo getUserInfo: (options, callback) -> @getAccountInfo options, callback # Retrieves the contents of a file stored in Dropbox. # # Some options are silently ignored in Internet Explorer 9 and below, due to # insufficient support in its proprietary XDomainRequest replacement for XHR. # Currently, the options are: arrayBuffer, blob, length, start. # # @param {String} path the path of the file to be read, relative to the # user's Dropbox or to the application's folder # @param {Object} options (optional) one or more of the options below # @option options {String} versionTag the tag string for the desired version # of the file contents; the most recent version is retrieved by default # @option options {String} rev alias for "versionTag" that matches the HTTP # API # @option options {Boolean} arrayBuffer if true, the file's contents will be # passed to the callback in an ArrayBuffer; this is the recommended method # of reading non-UTF8 data such as images, as it is well supported across # modern browsers; requires XHR Level 2 support, which is not available in # IE <= 9 # @option options {Boolean} blob if true, the file's contents will be # passed to the callback in a Blob; this is a good method of reading # non-UTF8 data, such as images; requires XHR Level 2 support, which is not # available in IE <= 9 # @option options {Boolean} buffer if true, the file's contents will be # passed to the callback in a node.js Buffer; this only works on node.js # @option options {Boolean} binary if true, the file will be retrieved as a # binary string; the default is an UTF-8 encoded string; this relies on # hacks and should not be used if the environment supports XHR Level 2 API # @option options {Number} length the number of bytes to be retrieved from # the file; if the start option is not present, the last "length" bytes # will be read; by default, the entire file is read # @option options {Number} start the 0-based offset of the first byte to be # retrieved; if the length option is not present, the bytes between # "start" and the file's end will be read; by default, the entire # file is read # @option options {Boolean} httpCache if true, the API request will be set to # allow HTTP caching to work; by default, requests are set up to avoid # CORS preflights; setting this option can make sense when making the same # request repeatedly # @param {function(Dropbox.ApiError, String, Dropbox.File.Stat, # Dropbox.Http.RangeInfo)} callback called with the result of # the /files (GET) HTTP request; the second parameter is the contents of # the file, the third parameter is a {Dropbox.File.Stat} instance # describing the file, and the first parameter is null; if the start # and/or length options are specified, the fourth parameter describes the # subset of bytes read from the file # @return {XMLHttpRequest} the XHR object used for this API call readFile: (path, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null params = {} responseType = 'text' rangeHeader = null httpCache = false if options if options.versionTag params.rev = options.versionTag else if options.rev params.rev = options.rev if options.arrayBuffer responseType = 'arraybuffer' else if options.blob responseType = 'blob' else if options.buffer responseType = 'buffer' else if options.binary responseType = 'b' # See the Dropbox.Util.Xhr.setResponseType docs if options.length if options.start? rangeStart = options.start rangeEnd = options.start + options.length - 1 else rangeStart = '' rangeEnd = options.length rangeHeader = "bytes=#{rangeStart}-#{rangeEnd}" else if options.start? rangeHeader = "bytes=#{options.start}-" httpCache = true if options.httpCache xhr = new Dropbox.Util.Xhr 'GET', "#{@_urls.getFile}/#{@_urlEncodePath(path)}" xhr.setParams(params).signWithOauth @_oauth, httpCache xhr.setResponseType responseType if rangeHeader xhr.setHeader 'Range', rangeHeader if rangeHeader xhr.reportResponseHeaders() @_dispatchXhr xhr, (error, data, metadata, headers) -> if headers rangeInfo = Dropbox.Http.RangeInfo.parse headers['content-range'] else rangeInfo = null callback error, data, Dropbox.File.Stat.parse(metadata), rangeInfo # Store a file into a user's Dropbox. # # @param {String} path the path of the file to be created, relative to the # user's Dropbox or to the application's folder # @param {String, ArrayBuffer, ArrayBufferView, Blob, File, Buffer} data the # contents written to the file; if a File is passed, its name is ignored # @param {Object} options (optional) one or more of the options below # @option options {String} lastVersionTag the identifier string for the # version of the file's contents that was last read by this program, used # for conflict resolution; for best results, use the versionTag attribute # value from the Dropbox.File.Stat instance provided by readFile # @option options {String} parentRev alias for "lastVersionTag" that matches # the HTTP API # @option options {Boolean} noOverwrite if set, the write will not overwrite # a file with the same name that already exists; instead the contents will # be written to a similarly named file (e.g. "notes (1).txt" instead of # "notes.txt") # @param {function(Dropbox.ApiError, Dropbox.File.Stat)} callback called # with the result of the /files (POST) HTTP request; the second parameter # is a {Dropbox.File.Stat} instance describing the newly created file, and # the first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call writeFile: (path, data, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null useForm = Dropbox.Util.Xhr.canSendForms and typeof data is 'object' if useForm @_writeFileUsingForm path, data, options, callback else @_writeFileUsingPut path, data, options, callback # writeFile implementation that uses the POST /files API. # # @private # Use {Dropbox.Client#writeFile} instead of calling this directly. # # This method is more demanding in terms of CPU and browser support, but does # not require CORS preflight, so it always completes in 1 HTTP request. _writeFileUsingForm: (path, data, options, callback) -> # Break down the path into a file/folder name and the containing folder. slashIndex = path.lastIndexOf '/' if slashIndex is -1 fileName = path path = '' else fileName = path.substring slashIndex path = path.substring 0, slashIndex params = { file: fileName } if options if options.noOverwrite params.overwrite = 'false' if options.lastVersionTag params.parent_rev = options.lastVersionTag else if options.parentRev or options.parent_rev params.parent_rev = options.parentRev or options.parent_rev if options.noAutorename params.autorename = 'false' # TODO: locale support would edit the params here xhr = new Dropbox.Util.Xhr 'POST', "#{@_urls.postFile}/#{@_urlEncodePath(path)}" xhr.setParams(params).signWithOauth(@_oauth).setFileField('file', fileName, data, 'application/octet-stream') # NOTE: the Dropbox API docs ask us to replace the 'file' parameter after # signing the request; the hack below works as intended delete params.file @_dispatchXhr xhr, (error, metadata) -> callback error, Dropbox.File.Stat.parse(metadata) if callback # writeFile implementation that uses the /files_put API. # # @private # Use {Dropbox.Client#writeFile} instead of calling this directly. # # This method is less demanding on CPU, and makes fewer assumptions about # browser support, but it takes 2 HTTP requests for binary files, because it # needs CORS preflight. _writeFileUsingPut: (path, data, options, callback) -> params = {} if options if options.noOverwrite params.overwrite = 'false' if options.lastVersionTag params.parent_rev = options.lastVersionTag else if options.parentRev or options.parent_rev params.parent_rev = options.parentRev or options.parent_rev if options.noAutorename params.autorename = 'false' # TODO: locale support would edit the params here xhr = new Dropbox.Util.Xhr 'POST', "#{@_urls.putFile}/#{@_urlEncodePath(path)}" xhr.setBody(data).setParams(params).signWithOauth @_oauth @_dispatchXhr xhr, (error, metadata) -> callback error, Dropbox.File.Stat.parse(metadata) if callback # Atomic step in a resumable file upload. # # @param {String, ArrayBuffer, ArrayBufferView, Blob, File, Buffer} data the # file contents fragment to be uploaded; if a File is passed, its name is # ignored # @param {Dropbox.Http.UploadCursor} cursor (optional) the cursor that tracks # the state of the resumable file upload; the cursor information will not # be updated when the API call completes # @param {function(Dropbox.ApiError, Dropbox.Http.UploadCursor)} callback # called with the result of the /chunked_upload HTTP request; the second # parameter is a {Dropbox.Http.UploadCursor} instance describing the # progress of the upload operation, and the first parameter is null if no # error occurs # @return {XMLHttpRequest} the XHR object used for this API call resumableUploadStep: (data, cursor, callback) -> if cursor params = { offset: cursor.offset } params.upload_id = cursor.tag if cursor.tag else params = { offset: 0 } xhr = new Dropbox.Util.Xhr 'POST', @_urls.chunkedUpload xhr.setBody(data).setParams(params).signWithOauth(@_oauth) @_dispatchXhr xhr, (error, cursor) -> if error and error.status is Dropbox.ApiError.INVALID_PARAM and error.response and error.response.upload_id and error.response.offset callback null, Dropbox.Http.UploadCursor.parse(error.response) else callback error, Dropbox.Http.UploadCursor.parse(cursor) # Finishes a resumable file upload. # # @param {String} path the path of the file to be created, relative to the # user's Dropbox or to the application's folder # @param {Object} options (optional) one or more of the options below # @option options {String} lastVersionTag the identifier string for the # version of the file's contents that was last read by this program, used # for conflict resolution; for best results, use the versionTag attribute # value from the Dropbox.File.Stat instance provided by readFile # @option options {String} parentRev alias for "lastVersionTag" that matches # the HTTP API # @option options {Boolean} noOverwrite if set, the write will not overwrite # a file with the same name that already exists; instead the contents will # be written to a similarly named file (e.g. "notes (1).txt" instead of # "notes.txt") # @param {function(Dropbox.ApiError, Dropbox.File.Stat)} callback called with # the result of the /files (POST) HTTP request; the second parameter is a # {Dropbox.File.Stat} instance describing the newly created file, and the # first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call resumableUploadFinish: (path, cursor, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null params = { upload_id: cursor.tag } if options if options.lastVersionTag params.parent_rev = options.lastVersionTag else if options.parentRev or options.parent_rev params.parent_rev = options.parentRev or options.parent_rev if options.noOverwrite params.overwrite = 'false' # TODO: locale support would edit the params here xhr = new Dropbox.Util.Xhr 'POST', "#{@_urls.commitChunkedUpload}/#{@_urlEncodePath(path)}" xhr.setParams(params).signWithOauth(@_oauth) @_dispatchXhr xhr, (error, metadata) -> callback error, Dropbox.File.Stat.parse(metadata) if callback # Reads the metadata of a file or folder in a user's Dropbox. # # @param {String} path the path to the file or folder whose metadata will be # read, relative to the user's Dropbox or to the application's folder # @param {Object} options (optional) one or more of the options below # @option options {Number} version if set, the call will return the metadata # for the given revision of the file / folder; the latest version is used # by default # @option options {Boolean} removed if set to true, the results will include # files and folders that were deleted from the user's Dropbox # @option options {Boolean} deleted alias for "removed" that matches the HTTP # API; using this alias is not recommended, because it may cause confusion # with JavaScript's delete operation # @option options {Boolean, Number} readDir only meaningful when stat-ing # folders; if this is set, the API call will also retrieve the folder's # contents, which is passed into the callback's third parameter; if this # is a number, it specifies the maximum number of files and folders that # should be returned; the default limit is 10,000 items; if the limit is # exceeded, the call will fail with an error # @option options {String} versionTag the tag string for the desired version # of the file or folder metadata; the most recent version is retrieved by # default # @option options {String} rev alias for "versionTag" that matches the HTTP # API # @option options {String} contentHash used for saving bandwidth when getting # a folder's contents; if this value is specified and it matches the # folder's contents, the call will fail with a # {Dropbox.ApiError.NO_CONTENT} error status; a folder's version identifier # can be obtained from the {Dropbox.File.Stat#contentHash} property of the # Stat instance describing the folder # @option options {String} hash alias for "contentHash" that matches the HTTP # API # @option options {Boolean} httpCache if true, the API request will be set to # allow HTTP caching to work; by default, requests are set up to avoid # CORS preflights; setting this option can make sense when making the same # request repeatedly # @param {function(Dropbox.ApiError, Dropbox.File.Stat, # Array<Dropbox.File.Stat>)} callback called with the result of the # /metadata HTTP request; if the call succeeds, the second parameter is a # {Dropbox.File.Stat} instance describing the file / folder, and the first # parameter is null; if the readDir option is true and the call succeeds, # the third parameter is an array of {Dropbox.File.Stat} instances # describing the folder's entries # @return {XMLHttpRequest} the XHR object used for this API call stat: (path, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null params = {} httpCache = false if options if options.versionTag params.rev = options.versionTag else if options.rev params.rev = options.rev if options.contentHash params.hash = options.contentHash else if options.hash params.hash = options.hash if options.removed or options.deleted params.include_deleted = 'true' if options.readDir params.list = 'true' if options.readDir isnt true params.file_limit = options.readDir.toString() if options.cacheHash params.hash = options.cacheHash if options.httpCache httpCache = true params.include_deleted ||= 'false' params.list ||= 'false' # TODO: locale support would edit the params here xhr = new Dropbox.Util.Xhr 'GET', "#{@_urls.metadata}/#{@_urlEncodePath(path)}" xhr.setParams(params).signWithOauth @_oauth, httpCache @_dispatchXhr xhr, (error, metadata) -> stat = Dropbox.File.Stat.parse metadata if metadata?.contents entries = for entry in metadata.contents Dropbox.File.Stat.parse(entry) else entries = undefined callback error, stat, entries # Lists the files and folders inside a folder in a user's Dropbox. # # @param {String} path the path to the folder whose contents will be # retrieved, relative to the user's Dropbox or to the application's # folder # @param {Object} options (optional) one or more of the options below # @option options {Boolean} removed if set to true, the results will include # files and folders that were deleted from the user's Dropbox # @option options {Boolean} deleted alias for "removed" that matches the HTTP # API; using this alias is not recommended, because it may cause confusion # with JavaScript's delete operation # @option options {Boolean, Number} limit the maximum number of files and # folders that should be returned; the default limit is 10,000 items; if # the limit is exceeded, the call will fail with an error # @option options {String} versionTag the tag string for the desired version # of the file or folder metadata; the most recent version is retrieved by # default # @option options {String} contentHash used for saving bandwidth when getting # a folder's contents; if this value is specified and it matches the # folder's contents, the call will fail with a # {Dropbox.ApiError.NO_CONTENT} error status; a folder's version identifier # can be obtained from the {Dropbox.File.Stat#contentHash} property of the # Stat instance describing the folder # @option options {Boolean} httpCache if true, the API request will be set to # allow HTTP caching to work; by default, requests are set up to avoid # CORS preflights; setting this option can make sense when making the same # request repeatedly # @param {function(Dropbox.ApiError, Array<String>, Dropbox.File.Stat, # Array<Dropbox.File.Stat>)} callback called with the result of the # /metadata HTTP request; if the call succeeds, the second parameter is an # array containing the names of the files and folders in the given folder, # the third parameter is a {Dropbox.File.Stat} instance describing the # folder, the fourth parameter is an array of {Dropbox.File.Stat} instances # describing the folder's entries, and the first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call readdir: (path, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null statOptions = { readDir: true } if options if options.limit? statOptions.readDir = options.limit if options.versionTag statOptions.versionTag = options.versionTag else if options.rev statOptions.versionTag = options.rev if options.contentHash statOptions.contentHash = options.contentHash else if options.hash statOptions.contentHash = options.hash if options.removed or options.deleted statOptions.removed = options.removed or options.deleted if options.httpCache statOptions.httpCache = options.httpCache @stat path, statOptions, (error, stat, entry_stats) -> if entry_stats entries = (entry_stat.name for entry_stat in entry_stats) else entries = null callback error, entries, stat, entry_stats # Alias for "stat" that matches the HTTP API. # # @see Dropbox.Client#stat metadata: (path, options, callback) -> @stat path, options, callback # Creates a publicly readable URL to a file or folder in the user's Dropbox. # # @param {String} path the path to the file or folder that will be linked to; # the path is relative to the user's Dropbox or to the application's # folder # @param {Object} options (optional) one or more of the options below # @option options {Boolean} download if set, the URL will be a direct # download URL, instead of the usual Dropbox preview URLs; direct # download URLs are short-lived (currently 4 hours), whereas regular URLs # virtually have no expiration date (currently set to 2030); no direct # download URLs can be generated for directories # @option options {Boolean} downloadHack if set, a long-living download URL # will be generated by asking for a preview URL and using the officially # documented hack at https://www.dropbox.com/help/201 to turn the preview # URL into a download URL # @option options {Boolean} long if set, the URL will not be shortened using # Dropbox's shortner; the download and downloadHack options imply long # @option options {Boolean} longUrl synonym for long; makes life easy for # RhinoJS users # @param {function(Dropbox.ApiError, Dropbox.File.ShareUrl)} callback called # with the result of the /shares or /media HTTP request; if the call # succeeds, the second parameter is a {Dropbox.File.ShareUrl} instance, # and the first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call makeUrl: (path, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null # NOTE: cannot use options.long; normally, the CoffeeScript compiler # escapes keywords for us; although long isn't really a keyword, the # Rhino VM thinks it is; this hack can be removed when the bug below # is fixed: # https://github.com/mozilla/rhino/issues/93 if options and (options['long'] or options.longUrl or options.downloadHack) params = { short_url: 'false' } else params = {} path = @_urlEncodePath path url = "#{@_urls.shares}/#{path}" isDirect = false useDownloadHack = false if options if options.downloadHack isDirect = true useDownloadHack = true else if options.download isDirect = true url = "#{@_urls.media}/#{path}" # TODO: locale support would edit the params here xhr = new Dropbox.Util.Xhr('POST', url).setParams(params). signWithOauth @_oauth @_dispatchXhr xhr, (error, urlData) => if useDownloadHack and urlData?.url urlData.url = urlData.url.replace @_authServer, @_downloadServer callback error, Dropbox.File.ShareUrl.parse(urlData, isDirect) # Retrieves the revision history of a file in a user's Dropbox. # # @param {String} path the path to the file whose revision history will be # retrieved, relative to the user's Dropbox or to the application's # folder # @param {Object} options (optional) one or more of the options below # @option options {Number} limit if specified, the call will return at most # this many versions # @option options {Boolean} httpCache if true, the API request will be set to # allow HTTP caching to work; by default, requests are set up to avoid # CORS preflights; setting this option can make sense when making the same # request repeatedly # @param {function(Dropbox.ApiError, Array<Dropbox.File.Stat>)} callback # called with the result of the /revisions HTTP request; if the call # succeeds, the second parameter is an array with one {Dropbox.File.Stat} # instance per file version, and the first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call history: (path, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null params = {} httpCache = false if options if options.limit? params.rev_limit = options.limit if options.httpCache httpCache = true xhr = new Dropbox.Util.Xhr 'GET', "#{@_urls.revisions}/#{@_urlEncodePath(path)}" xhr.setParams(params).signWithOauth @_oauth, httpCache @_dispatchXhr xhr, (error, versions) -> if versions stats = (Dropbox.File.Stat.parse(metadata) for metadata in versions) else stats = undefined callback error, stats # Alias for "history" that matches the HTTP API. # # @see Dropbox.Client#history revisions: (path, options, callback) -> @history path, options, callback # Computes a URL that generates a thumbnail for a file in the user's Dropbox. # # @param {String} path the path to the file whose thumbnail image URL will be # computed, relative to the user's Dropbox or to the application's # folder # @param {Object} options (optional) one or more of the options below # @option options {Boolean} png if true, the thumbnail's image will be a PNG # file; the default thumbnail format is JPEG # @option options {String} format value that gets passed directly to the API; # this is intended for newly added formats that the API may not support; # use options such as "png" when applicable # @option options {String} size specifies the image's dimensions; this # gets passed directly to the API; currently, the following values are # supported: 'small' (32x32), 'medium' (64x64), 'large' (128x128), # 's' (64x64), 'm' (128x128), 'l' (640x480), 'xl' (1024x768); the default # value is "small" # @return {String} a URL to an image that can be used as the thumbnail for # the given file thumbnailUrl: (path, options) -> xhr = @thumbnailXhr path, options xhr.addOauthParams(@_oauth).paramsToUrl().url # Retrieves the image data of a thumbnail for a file in the user's Dropbox. # # This method is intended to be used with low-level painting APIs. Whenever # possible, it is easier to place the result of thumbnailUrl in a DOM # element, and rely on the browser to fetch the file. # # @param {String} path the path to the file whose thumbnail image URL will be # computed, relative to the user's Dropbox or to the application's # folder # @param {Object} options (optional) one or more of the options below # @option options {Boolean} png if true, the thumbnail's image will be a PNG # file; the default thumbnail format is JPEG # @option options {String} format value that gets passed directly to the API; # this is intended for newly added formats that the API may not support; # use options such as "png" when applicable # @option options {String} size specifies the image's dimensions; this # gets passed directly to the API; currently, the following values are # supported: 'small' (32x32), 'medium' (64x64), 'large' (128x128), # 's' (64x64), 'm' (128x128), 'l' (640x480), 'xl' (1024x768); the default # value is "small" # @option options {Boolean} arrayBuffer if true, the file's contents will be # passed to the callback in an ArrayBuffer; this is the recommended method # of reading thumbnails, as it is well supported across modern browsers; # requires XHR Level 2 support, which is not available in IE <= 9 # @option options {Boolean} blob if true, the file's contents will be # passed to the callback in a Blob; requires XHR Level 2 support, which is # not available in IE <= 9 # @option options {Boolean} buffer if true, the file's contents will be # passed to the callback in a node.js Buffer; this only works on node.js # @param {function(?Dropbox.ApiError, String|Blob, Dropbox.File.Stat)} # callback called with the result of the /thumbnails HTTP request; if the # call succeeds, the second parameter is the image data as a String or # Blob, the third parameter is a {Dropbox.File.Stat} instance describing # the thumbnailed file, and the first argument is null # @return {XMLHttpRequest} the XHR object used for this API call readThumbnail: (path, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null responseType = 'b' if options responseType = 'blob' if options.blob responseType = 'arraybuffer' if options.arrayBuffer responseType = 'buffer' if options.buffer xhr = @thumbnailXhr path, options xhr.setResponseType(responseType).signWithOauth(@_oauth) @_dispatchXhr xhr, (error, data, metadata) -> callback error, data, Dropbox.File.Stat.parse(metadata) # Sets up an XHR for reading a thumbnail for a file in the user's Dropbox. # # @private # Call {Dropbox.Client#thumbnailUrl} or {Dropbox.Client#readThumbnail} # instead of using this directly. # # @see Dropbox.Client#thumbnailUrl # @return {Dropbox.Util.Xhr} an XMLHttpRequest wrapper configured for # fetching the thumbnail; the {Dropbox.Util.Xhr} instance does not have # OAuth credentials applied to it, and the caller is responsible for # calling {Dropbox.Util.Xhr#signWithOauth} before using it thumbnailXhr: (path, options) -> params = {} if options if options.format params.format = options.format else if options.png params.format = 'png' if options.size # Can we do something nicer here? params.size = options.size xhr = new Dropbox.Util.Xhr 'GET', "#{@_urls.thumbnails}/#{@_urlEncodePath(path)}" xhr.setParams params # Reverts a file's contents to a previous version. # # This is an atomic, bandwidth-optimized equivalent of reading the file # contents at the given file version (readFile), and then using it to # overwrite the file (writeFile). # # @param {String} path the path to the file whose contents will be reverted # to a previous version, relative to the user's Dropbox or to the # application's folder # @param {String} versionTag the tag of the version that the file will be # reverted to; maps to the "rev" parameter in the HTTP API # @param {function(Dropbox.ApiError, Dropbox.File.Stat)} callback called with # the result of the /restore HTTP request; if the call succeeds, the second # parameter is a {Dropbox.File.Stat} instance describing the file after the # revert operation, and the first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call revertFile: (path, versionTag, callback) -> xhr = new Dropbox.Util.Xhr 'POST', "#{@_urls.restore}/#{@_urlEncodePath(path)}" xhr.setParams(rev: versionTag).signWithOauth @_oauth @_dispatchXhr xhr, (error, metadata) -> callback error, Dropbox.File.Stat.parse(metadata) if callback # Alias for "revertFile" that matches the HTTP API. # # @see Dropbox.Client#revertFile restore: (path, versionTag, callback) -> @revertFile path, versionTag, callback # Finds files / folders whose name match a pattern, in the user's Dropbox. # # @param {String} path the path that will serve as the root of the search, # relative to the user's Dropbox or to the application's folder # @param {String} namePattern the string that file / folder names must # contain in order to match the search criteria # @param {Object} options (optional) one or more of the options below # @option options {Number} limit if specified, the call will return at most # this many versions # @option options {Boolean} removed if set to true, the results will include # files and folders that were deleted from the user's Dropbox; the default # limit is the maximum value of 1,000 # @option options {Boolean} deleted alias for "removed" that matches the HTTP # API; using this alias is not recommended, because it may cause confusion # with JavaScript's delete operation # @option options {Boolean} httpCache if true, the API request will be set to # allow HTTP caching to work; by default, requests are set up to avoid # CORS preflights; setting this option can make sense when making the same # request repeatedly # @param {function(Dropbox.ApiError, Array<Dropbox.File.Stat>)} callback # called with the result of the /search HTTP request; if the call succeeds, # the second parameter is an array with one {Dropbox.File.Stat} instance # per search result, and the first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call findByName: (path, namePattern, options, callback) -> if (not callback) and (typeof options is 'function') callback = options options = null params = { query: namePattern } httpCache = false if options if options.limit? params.file_limit = options.limit if options.removed or options.deleted params.include_deleted = true if options.httpCache httpCache = true xhr = new Dropbox.Util.Xhr 'GET', "#{@_urls.search}/#{@_urlEncodePath(path)}" xhr.setParams(params).signWithOauth @_oauth, httpCache @_dispatchXhr xhr, (error, results) -> if results stats = (Dropbox.File.Stat.parse(metadata) for metadata in results) else stats = undefined callback error, stats # Alias for "findByName" that matches the HTTP API. # # @see Dropbox.Client#findByName search: (path, namePattern, options, callback) -> @findByName path, namePattern, options, callback # Creates a reference used to copy a file to another user's Dropbox. # # @param {String} path the path to the file whose contents will be # referenced, relative to the uesr's Dropbox or to the application's # folder # @param {function(Dropbox.ApiError, Dropbox.File.CopyReference)} callback # called with the result of the /copy_ref HTTP request; if the call # succeeds, the second parameter is a {Dropbox.File.CopyReference} # instance, and the first parameter is null # @return {XMLHttpRequest} the XHR object used for this API call makeCopyReference: (path, callback) -> xhr = new Dropbox.Util.Xhr 'GET', "#{@_urls.copyRef}/#{@_urlEncodePath(path)}" xhr.signWithOauth @_oauth @_dispatchXhr xhr, (error, refData) -> callback error, Dropbox.File.CopyReference.parse(refData) # Alias for "makeCopyReference" that matches the HTTP API. # # @see Dropbox.Client#makeCopyReference copyRef: (path, callback) -> @makeCopyReference path, callback # Fetches a list of changes in the user's Dropbox since the last call. # # This method is intended to make full sync implementations easier and more # performant. Each call returns a cursor that can be used in a future call # to obtain all the changes that happened in the user's Dropbox (or # application directory) between the two calls. # # @param {Dropbox.Http.PulledChanges, String} cursor (optional) the result of # a previous {Dropbox.Client#pullChanges} call, or a string containing a # tag representing the Dropbox state that is used as the baseline for the # change list; this should either be the {Dropbox.Http.PulledChanges} # obtained from a previous call to {Dropbox.Client#pullChanges}, the return # value of {Dropbox.Http.PulledChanges#cursor}, or null / omitted on the # first call to {Dropbox.Client#pullChanges} # @param {function(Dropbox.ApiError, Dropbox.Http.PulledChanges)} callback # called with the result of the /delta HTTP request; if the call # succeeds, the second parameter is a {Dropbox.Http.PulledChanges} # describing the changes to the user's Dropbox since the pullChanges call # that produced the given cursor, and the first parameter is null # @return {XMLHttpRequest}