dropbox-sdk 1.0.beta → 1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/CHANGELOG +6 -0
  2. data/cli_example.rb +5 -5
  3. data/lib/dropbox_sdk.rb +198 -115
  4. metadata +10 -27
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 1.1 (2011-10-17)
2
+ * Various bug fixes found during beta period
3
+ * Improved documentation
4
+ * Improved module structure
5
+ * Removed dependency on the oauth module, using plaintext authentication over https
6
+
1
7
  1.0 (2011-8-16)
2
8
  * Backwards compatibility broken
3
9
  - Changed interface
@@ -10,8 +10,8 @@ require 'pp'
10
10
 
11
11
  # You must use your Dropbox App key and secret to use the API.
12
12
  # Find this at https://www.dropbox.com/developers
13
- APP_KEY = ""
14
- APP_SECRET = ""
13
+ APP_KEY = ''
14
+ APP_SECRET = ''
15
15
  ACCESS_TYPE = :app_folder #The two valid values here are :app_folder and :dropbox
16
16
  #The default is :app_folder, but your application might be
17
17
  #set to have full :dropbox access. Check your app at
@@ -46,7 +46,7 @@ class DropboxCLI
46
46
  @session.get_request_token
47
47
 
48
48
  authorize_url = @session.get_authorize_url
49
- puts "Got a request token. Your request token key is #{@session.token} and your token secret is #{@session.secret}"
49
+ puts "Got a request token. Your request token key is #{@session.request_token.key} and your token secret is #{@session.request_token.secret}"
50
50
 
51
51
  # make the user log in and authorize this token
52
52
  puts "AUTHORIZING", authorize_url, "Please visit that web page and hit 'Allow', then hit Enter here."
@@ -56,7 +56,7 @@ class DropboxCLI
56
56
  @session.get_access_token
57
57
 
58
58
  end
59
- puts "You are logged in. Your access token key is #{@session.token} your secret is #{@session.secret}"
59
+ puts "You are logged in. Your access token key is #{@session.access_token.key} your secret is #{@session.access_token.secret}"
60
60
  @client = DropboxClient.new(@session, ACCESS_TYPE)
61
61
  end
62
62
 
@@ -95,7 +95,7 @@ class DropboxCLI
95
95
  end
96
96
  end
97
97
 
98
- def logout
98
+ def logout(command)
99
99
  @session.clear_access_token
100
100
  puts "You are logged out."
101
101
  @client = nil
@@ -1,56 +1,142 @@
1
1
  require 'rubygems'
2
- require 'oauth'
3
- require 'json'
4
2
  require 'uri'
3
+ require 'net/https'
4
+ require 'cgi'
5
+ require 'json'
5
6
  require 'yaml'
6
7
 
7
- DROPBOX_API_SERVER = "api.dropbox.com"
8
- DROPBOX_API_CONTENT_SERVER = "api-content.dropbox.com"
8
+ module Dropbox
9
+ API_SERVER = "api.dropbox.com"
10
+ API_CONTENT_SERVER = "api-content.dropbox.com"
11
+ WEB_SERVER = "www.dropbox.com"
9
12
 
10
- API_VERSION = 1
13
+ API_VERSION = 1
14
+ SDK_VERSION = "1.1"
15
+ end
11
16
 
12
17
  # DropboxSession is responsible for holding OAuth information. It knows how to take your consumer key and secret
13
18
  # and request an access token, an authorize url, and get an access token. You just need to pass it to
14
19
  # DropboxClient after its been authorized.
15
20
  class DropboxSession
16
- def initialize(key, secret)
17
- @consumer_key = key
18
- @consumer_secret = secret
19
- @oauth_conf = {
20
- :site => "https://" + DROPBOX_API_SERVER,
21
- :scheme => :header,
22
- :http_method => :post,
23
- :request_token_url => "/#{API_VERSION}/oauth/request_token",
24
- :access_token_url => "/#{API_VERSION}/oauth/access_token",
25
- :authorize_url => "/#{API_VERSION}/oauth/authorize",
26
- }
27
21
 
28
- @consumer = OAuth::Consumer.new(@consumer_key, @consumer_secret, @oauth_conf)
29
- @access_token = nil
22
+ def initialize(consumer_key, consumer_secret)
23
+ @consumer_key = consumer_key
24
+ @consumer_secret = consumer_secret
30
25
  @request_token = nil
26
+ @access_token = nil
31
27
  end
32
28
 
33
- # This gets a request token. Callbacks are excluded, and any arguments provided are passed on
34
- # to the oauth gem's get_request_token call.
35
- def get_request_token(*args)
36
- begin
37
- @request_token ||= @consumer.get_request_token({:exclude_callback => true}, *args)
38
- rescue OAuth::Unauthorized => e
39
- raise DropboxAuthError.new("Could not get request token, unauthorized. Is your app key and secret correct? #{e}")
29
+ private
30
+
31
+ def do_http(uri, auth_token, request) # :nodoc:
32
+ http = Net::HTTP.new(uri.host, uri.port)
33
+ http.use_ssl = true
34
+
35
+ request.add_field('Authorization', build_auth_header(auth_token))
36
+
37
+ #We use this to better understand how developers are using our SDKs.
38
+ request['User-Agent'] = "OfficialDropboxRubySDK/#{Dropbox::SDK_VERSION}"
39
+
40
+ http.request(request)
41
+ end
42
+
43
+ def build_auth_header(token) # :nodoc:
44
+ header = "OAuth oauth_version=\"1.0\", oauth_signature_method=\"PLAINTEXT\", " +
45
+ "oauth_consumer_key=\"#{URI.escape(@consumer_key)}\", "
46
+ if token
47
+ key = URI.escape(token.key)
48
+ secret = URI.escape(token.secret)
49
+ header += "oauth_token=\"#{key}\", oauth_signature=\"#{URI.escape(@consumer_secret)}&#{secret}\""
50
+ else
51
+ header += "oauth_signature=\"#{URI.escape(@consumer_secret)}&\""
52
+ end
53
+ header
54
+ end
55
+
56
+ def do_get_with_token(url, token, headers=nil) # :nodoc:
57
+ uri = URI.parse(url)
58
+ do_http(uri, token, Net::HTTP::Get.new(uri.request_uri))
59
+ end
60
+
61
+ public
62
+
63
+ def do_get(url, headers=nil) # :nodoc:
64
+ assert_authorized
65
+ do_get_with_token(url, @access_token)
66
+ end
67
+
68
+ def do_http_with_body(uri, request, body)
69
+ if body != nil
70
+ if body.is_a?(Hash)
71
+ form_data = {}
72
+ body.each {|k,v| form_data[k.to_s] = v if !v.nil?}
73
+ request.set_form_data(form_data)
74
+ elsif body.respond_to?(:read)
75
+ if body.respond_to?(:length)
76
+ request["Content-Length"] = body.length.to_s
77
+ elsif body.respond_to?(:stat) && body.stat.respond_to?(:size)
78
+ request["Content-Length"] = body.stat.size.to_s
79
+ else
80
+ raise ArgumentError, "Don't know how to handle 'body' (responds to 'read' but not to 'length' or 'stat.size')."
81
+ end
82
+ request.body_stream = body
83
+ else
84
+ s = body.to_s
85
+ request["Content-Length"] = s.length
86
+ request.body = s
87
+ end
88
+ end
89
+ do_http(uri, @access_token, request)
90
+ end
91
+
92
+ def do_post(url, headers=nil, body=nil) # :nodoc:
93
+ assert_authorized
94
+ uri = URI.parse(url)
95
+ do_http_with_body(uri, Net::HTTP::Post.new(uri.request_uri, headers), body)
96
+ end
97
+
98
+ def do_put(url, headers=nil, body=nil) # :nodoc:
99
+ assert_authorized
100
+ uri = URI.parse(url)
101
+ do_http_with_body(uri, Net::HTTP::Put.new(uri.request_uri, headers), body)
102
+ end
103
+
104
+
105
+ def get_token(url_end, input_token, error_message_prefix) #: nodoc:
106
+ response = do_get_with_token("https://#{Dropbox::API_SERVER}:443/#{Dropbox::API_VERSION}/oauth#{url_end}", input_token)
107
+ if not response.kind_of?(Net::HTTPSuccess) # it must be a 200
108
+ raise DropboxAuthError.new("#{error_message_prefix} Server returned #{response.code}: #{response.message}.", response)
109
+ end
110
+ parts = CGI.parse(response.body)
111
+ if !parts.has_key? "oauth_token" and parts["oauth_token"].length != 1
112
+ raise DropboxAuthError.new("Invalid response from #{url_end}: missing \"oauth_token\" parameter: #{response.body}", response)
40
113
  end
114
+ if !parts.has_key? "oauth_token_secret" and parts["oauth_token_secret"].length != 1
115
+ raise DropboxAuthError.new("Invalid response from #{url_end}: missing \"oauth_token\" parameter: #{response.body}", response)
116
+ end
117
+
118
+ OAuthToken.new(parts["oauth_token"][0], parts["oauth_token_secret"][0])
119
+ end
120
+
121
+ # This returns a request token. Requests one from the dropbox server using the provided application key and secret if nessecary.
122
+ def get_request_token()
123
+ @request_token ||= get_token("/request_token", nil, "Error getting request token. Is your app key and secret correctly set?")
41
124
  end
42
125
 
43
126
  # This returns a URL that your user must visit to grant
44
127
  # permissions to this application.
45
- def get_authorize_url(callback=nil, *args)
46
- get_request_token(*args)
128
+ def get_authorize_url(callback=nil)
129
+ get_request_token()
47
130
 
48
- url = @request_token.authorize_url
131
+ url = "/#{Dropbox::API_VERSION}/oauth/authorize?oauth_token=#{URI.escape(@request_token.key)}"
49
132
  if callback
50
- url += "&oauth_callback=" + URI.escape(callback)
133
+ url += "&oauth_callback=#{URI.escape(callback)}"
134
+ end
135
+ if @locale
136
+ url += "&locale=#{URI.escape(@locale)}"
51
137
  end
52
138
 
53
- "https://www.dropbox.com" + url
139
+ "https://#{Dropbox::WEB_SERVER}#{url}"
54
140
  end
55
141
 
56
142
  # Clears the access_token
@@ -58,51 +144,48 @@ class DropboxSession
58
144
  @access_token = nil
59
145
  end
60
146
 
147
+ # Returns the request token, or nil if one hasn't been acquired yet.
148
+ def request_token
149
+ @request_token
150
+ end
151
+
152
+ # Returns the access token, or nil if one hasn't been acquired yet.
153
+ def access_token
154
+ @access_token
155
+ end
156
+
61
157
  # Given a saved request token and secret, set this location's token and secret
62
158
  # * token - this is the request token
63
159
  # * secret - this is the request token secret
64
160
  def set_request_token(key, secret)
65
- @request_token = OAuth::RequestToken.new(@consumer, key, secret)
161
+ @request_token = OAuthToken.new(key, secret)
66
162
  end
67
163
 
68
164
  # Given a saved access token and secret, you set this Session to use that token and secret
69
165
  # * token - this is the access token
70
166
  # * secret - this is the access token secret
71
167
  def set_access_token(key, secret)
72
- @access_token = OAuth::AccessToken.from_hash(@consumer, {:oauth_token => key, :oauth_token_secret => secret})
73
- end
74
-
75
- def check_authorized
76
- ##this check is applied before the token and secret methods
77
- raise DropboxError.new('Session does not yet have a request token') unless authorized?
78
- end
79
-
80
- # Returns the current oauth access or request token.
81
- def token
82
- (@access_token || @request_token).token
83
- end
84
-
85
- # Returns the current oauth access or request token secret.
86
- def secret
87
- (@access_token || @request_token).secret
168
+ @access_token = OAuthToken.new(key, secret)
88
169
  end
89
170
 
90
171
  # Returns the access token. If this DropboxSession doesn't yet have an access_token, it requests one
91
172
  # using the request_token generate from your app's token and secret. This request will fail unless
92
- # your user has got to the authorize_url and approved your request
173
+ # your user has gone to the authorize_url and approved your request
93
174
  def get_access_token
94
- if @access_token.nil?
95
- if @request_token.nil?
96
- raise DropboxAuthError.new("No request token. You must set this or get an authorize url first.")
97
- end
175
+ return @access_token if authorized?
98
176
 
99
- begin
100
- @access_token = @request_token.get_access_token
101
- rescue OAuth::Unauthorized => e
102
- raise DropboxAuthError.new("Could not get access token, unauthorized. Did you go to authorize_url? #{e}")
103
- end
177
+ if @request_token.nil?
178
+ raise DropboxAuthError.new("No request token. You must set this or get an authorize url first.")
179
+ end
180
+
181
+ @access_token = get_token("/access_token", @request_token, "Couldn't get access token.")
182
+ end
183
+
184
+ # If we have an access token, then do nothing. If not, throw a RuntimeError.
185
+ def assert_authorized
186
+ unless authorized?
187
+ raise RuntimeError.new('Session does not yet have a request token')
104
188
  end
105
- @access_token
106
189
  end
107
190
 
108
191
  # Returns true if this Session has been authorized and has an access_token.
@@ -112,24 +195,24 @@ class DropboxSession
112
195
 
113
196
  # serialize the DropboxSession.
114
197
  # At DropboxSession's state is capture in three key/secret pairs. Consumer, request, and access.
115
- # This takes the form of an array that is then converted to yaml
198
+ # Serialize returns these in a YAML string, generated from a converted array of the form:
116
199
  # [consumer_key, consumer_secret, request_token.token, request_token.secret, access_token.token, access_token.secret]
117
200
  # access_token is only included if it already exists in the DropboxSesssion
118
201
  def serialize
119
202
  toreturn = []
120
203
  if @access_token
121
- toreturn.push @access_token.secret, @access_token.token
204
+ toreturn.push @access_token.secret, @access_token.key
122
205
  end
123
206
 
124
- get_request_token unless @request_token
207
+ get_request_token
125
208
 
126
- toreturn.push @request_token.secret, @request_token.token
209
+ toreturn.push @request_token.secret, @request_token.key
127
210
  toreturn.push @consumer_secret, @consumer_key
128
211
 
129
212
  toreturn.to_yaml
130
213
  end
131
214
 
132
- # Takes a serialized DropboxSession and returns a new DropboxSession object
215
+ # Takes a serialized DropboxSession YAML String and returns a new DropboxSession object
133
216
  def self.deserialize(ser)
134
217
  ser = YAML::load(ser)
135
218
  session = DropboxSession.new(ser.pop, ser.pop)
@@ -143,6 +226,22 @@ class DropboxSession
143
226
  end
144
227
 
145
228
 
229
+ # A class that represents either an OAuth request token or an OAuth access token.
230
+ class OAuthToken
231
+ def initialize(key, secret)
232
+ @key = key
233
+ @secret = secret
234
+ end
235
+
236
+ def key
237
+ @key
238
+ end
239
+
240
+ def secret
241
+ @secret
242
+ end
243
+ end
244
+
146
245
 
147
246
  # This is the usual error raised on any Dropbox related Errors
148
247
  class DropboxError < RuntimeError
@@ -179,15 +278,7 @@ class DropboxClient
179
278
  # Initialize a new DropboxClient. You need to get it a session which either has been authorized. See
180
279
  # documentation on DropboxSession for how to authorize it.
181
280
  def initialize(session, root="app_folder", locale=nil)
182
- if not session.authorized?
183
- begin
184
- ## attempt to get an access token and authorize the session
185
- session.get_access_token
186
- rescue OAuth::Unauthorized => e
187
- raise DropboxAuthError.new("Could not initialize. Failed to get access token from Session. Error was: #{ e.message }")
188
- # If this was raised, the user probably didn't go to auth.get_authorize_url
189
- end
190
- end
281
+ session.get_access_token
191
282
 
192
283
  @root = root.to_s # If they passed in a symbol, make it a string
193
284
 
@@ -196,15 +287,12 @@ class DropboxClient
196
287
  end
197
288
  if @root == "app_folder"
198
289
  #App Folder is the name of the access type, but for historical reasons
199
- #sandbox is the URL root compontent that indicates this
290
+ #sandbox is the URL root component that indicates this
200
291
  @root = "sandbox"
201
292
  end
202
293
 
203
294
  @locale = locale
204
295
  @session = session
205
- @token = session.get_access_token
206
-
207
- #There's no gurantee that @token is still valid, so be sure to handle any DropboxAuthErrors that can be raised
208
296
  end
209
297
 
210
298
  # Parse response. You probably shouldn't be calling this directly. This takes responses from the server
@@ -236,7 +324,6 @@ class DropboxClient
236
324
  rescue JSON::ParserError
237
325
  raise DropboxError.new("Unable to parse JSON response", response)
238
326
  end
239
-
240
327
  end
241
328
 
242
329
 
@@ -245,7 +332,7 @@ class DropboxClient
245
332
  # For a detailed description of what this call returns, visit:
246
333
  # https://www.dropbox.com/developers/docs#account-info
247
334
  def account_info()
248
- response = @token.get build_url("/account/info")
335
+ response = @session.do_get build_url("/account/info")
249
336
  parse_response(response)
250
337
  end
251
338
 
@@ -254,7 +341,7 @@ class DropboxClient
254
341
  # Arguments:
255
342
  # * to_path: The directory path to upload the file to. If the destination
256
343
  # directory does not yet exist, it will be created.
257
- # * file_obj: A file-like object to upload. If you would like, you can
344
+ # * file_obj: A file-like object to upload. If you would like, you can
258
345
  # pass a string as file_obj.
259
346
  # * overwrite: Whether to overwrite an existing file at the given path. [default is False]
260
347
  # If overwrite is False and a file already exists there, Dropbox
@@ -275,14 +362,13 @@ class DropboxClient
275
362
  # * a Hash containing the metadata of the newly uploaded file. The file may have a different name if it conflicted.
276
363
  #
277
364
  # Simple Example
278
- # client = DropboxClient(session, "app_folder")
365
+ # client = DropboxClient(session, :app_folder)
279
366
  # #session is a DropboxSession I've already authorized
280
367
  # client.put_file('/test_file_on_dropbox', open('/tmp/test_file'))
281
368
  # This will upload the "/tmp/test_file" from my computer into the root of my App's app folder
282
369
  # and call it "test_file_on_dropbox".
283
370
  # The file will not overwrite any pre-existing file.
284
371
  def put_file(to_path, file_obj, overwrite=false, parent_rev=nil)
285
-
286
372
  path = "/files_put/#{@root}#{format_path(to_path)}"
287
373
 
288
374
  params = {
@@ -291,9 +377,9 @@ class DropboxClient
291
377
 
292
378
  params['parent_rev'] = parent_rev unless parent_rev.nil?
293
379
 
294
- response = @token.put(build_url(path, params, content_server=true),
295
- file_obj,
296
- "Content-Type" => "application/octet-stream")
380
+ response = @session.do_put(build_url(path, params, content_server=true),
381
+ {"Content-Type" => "application/octet-stream"},
382
+ file_obj)
297
383
 
298
384
  parse_response(response)
299
385
  end
@@ -311,7 +397,7 @@ class DropboxClient
311
397
  params['rev'] = rev.to_s if rev
312
398
 
313
399
  path = "/files/#{@root}#{format_path(from_path)}"
314
- response = @token.get(build_url(path, params, content_server=true))
400
+ response = @session.do_get build_url(path, params, content_server=true)
315
401
 
316
402
  parse_response(response, raw=true)
317
403
  end
@@ -336,7 +422,7 @@ class DropboxClient
336
422
  "from_path" => format_path(from_path, false),
337
423
  "to_path" => format_path(to_path, false),
338
424
  }
339
- response = @token.get(build_url("/fileops/copy", params))
425
+ response = @session.do_post build_url("/fileops/copy", params)
340
426
  parse_response(response)
341
427
  end
342
428
 
@@ -352,9 +438,9 @@ class DropboxClient
352
438
  def file_create_folder(path)
353
439
  params = {
354
440
  "root" => @root,
355
- "path" => format_path(from_path, false),
441
+ "path" => format_path(path, false),
356
442
  }
357
- response = @token.get(build_url("/fileops/create_folder", params))
443
+ response = @session.do_post build_url("/fileops/create_folder", params)
358
444
 
359
445
  parse_response(response)
360
446
  end
@@ -371,9 +457,9 @@ class DropboxClient
371
457
  def file_delete(path)
372
458
  params = {
373
459
  "root" => @root,
374
- "path" => format_path(from_path, false),
460
+ "path" => format_path(path, false),
375
461
  }
376
- response = @token.get(build_url("/fileops/delete", params))
462
+ response = @session.do_post build_url("/fileops/delete", params)
377
463
  parse_response(response)
378
464
  end
379
465
 
@@ -394,7 +480,7 @@ class DropboxClient
394
480
  "from_path" => format_path(from_path, false),
395
481
  "to_path" => format_path(to_path, false),
396
482
  }
397
- response = @token.post(build_url("/fileops/move", params))
483
+ response = @session.do_post build_url("/fileops/move", params)
398
484
  parse_response(response)
399
485
  end
400
486
 
@@ -425,7 +511,7 @@ class DropboxClient
425
511
 
426
512
  params["hash"] = hash if hash
427
513
 
428
- response = @token.get build_url("/metadata/#{@root}#{format_path(path)}", params=params)
514
+ response = @session.do_get build_url("/metadata/#{@root}#{format_path(path)}", params=params)
429
515
  if response.kind_of? Net::HTTPRedirection
430
516
  raise DropboxNotModified.new("metadata not modified")
431
517
  end
@@ -447,16 +533,14 @@ class DropboxClient
447
533
  # inside path. For a detailed description of what this call returns, visit:
448
534
  # https://www.dropbox.com/developers/docs#search
449
535
  def search(path, query, file_limit=10000, include_deleted=false)
450
-
451
536
  params = {
452
537
  'query' => query,
453
538
  'file_limit' => file_limit.to_s,
454
539
  'include_deleted' => include_deleted.to_s
455
540
  }
456
541
 
457
- response = @token.get(build_url("/search/#{@root}#{format_path(path)}", params))
542
+ response = @session.do_get build_url("/search/#{@root}#{format_path(path)}", params)
458
543
  parse_response(response)
459
-
460
544
  end
461
545
 
462
546
  # Retrive revisions of a file
@@ -478,7 +562,7 @@ class DropboxClient
478
562
  'rev_limit' => rev_limit.to_s
479
563
  }
480
564
 
481
- response = @token.get(build_url("/revisions/#{@root}#{format_path(path)}", params))
565
+ response = @session.do_get build_url("/revisions/#{@root}#{format_path(path)}", params)
482
566
  parse_response(response)
483
567
 
484
568
  end
@@ -498,7 +582,7 @@ class DropboxClient
498
582
  'rev' => rev.to_s
499
583
  }
500
584
 
501
- response = @token.get(build_url("/restore/#{@root}#{format_path(path)}", params))
585
+ response = @session.do_post build_url("/restore/#{@root}#{format_path(path)}", params)
502
586
  parse_response(response)
503
587
  end
504
588
 
@@ -515,7 +599,7 @@ class DropboxClient
515
599
  # * A Hash object that looks like the following:
516
600
  # {'url': 'https://dl.dropbox.com/0/view/wvxv1fw6on24qw7/file.mov', 'expires': 'Thu, 16 Sep 2011 01:01:25 +0000'}
517
601
  def media(path)
518
- response = @token.get(build_url("/media/#{@root}#{format_path(path)}"))
602
+ response = @session.do_get build_url("/media/#{@root}#{format_path(path)}")
519
603
  parse_response(response)
520
604
  end
521
605
 
@@ -534,7 +618,7 @@ class DropboxClient
534
618
  # For a detailed description of what this call returns, visit:
535
619
  # https://www.dropbox.com/developers/docs#share
536
620
  def shares(path)
537
- response = @token.get(build_url("/shares/#{@root}#{format_path(path)}"))
621
+ response = @session.do_get build_url("/shares/#{@root}#{format_path(path)}")
538
622
  parse_response(response)
539
623
  end
540
624
 
@@ -560,14 +644,14 @@ class DropboxClient
560
644
 
561
645
  url = build_url("/thumbnails/#{@root}#{from_path}", params, content_server=true)
562
646
 
563
- response = @token.get(url)
647
+ response = @session.do_get url
564
648
  parse_response(response, raw=true)
565
649
  end
566
650
 
567
651
  def build_url(url, params=nil, content_server=false) # :nodoc:
568
652
  port = 443
569
- host = content_server ? DROPBOX_API_CONTENT_SERVER : DROPBOX_API_SERVER
570
- versioned_url = "/#{API_VERSION}#{url}"
653
+ host = content_server ? Dropbox::API_CONTENT_SERVER : Dropbox::API_SERVER
654
+ versioned_url = "/#{Dropbox::API_VERSION}#{url}"
571
655
 
572
656
  target = URI::Generic.new("https", nil, host, port, nil, versioned_url, nil, nil, nil)
573
657
 
@@ -585,23 +669,22 @@ class DropboxClient
585
669
 
586
670
  target.to_s
587
671
  end
588
- end
589
672
 
673
+ #From the oauth spec plus "/". Slash should not be ecsaped
674
+ RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~\/]/
590
675
 
591
- #From the oauth spec plus "/". Slash should not be ecsaped
592
- RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~\/]/
676
+ def format_path(path, escape=true) # :nodoc:
677
+ path = path.gsub(/\/+/,"/")
678
+ # replace multiple slashes with a single one
593
679
 
594
- def format_path(path, escape=true) # :nodoc:
595
- path = path.gsub(/\/+/,"/")
596
- # replace multiple slashes with a single one
680
+ path = path.gsub(/^\/?/,"/")
681
+ # ensure the path starts with a slash
597
682
 
598
- path = path.gsub(/^\/?/,"/")
599
- # ensure the path starts with a slash
683
+ path.gsub(/\/?$/,"")
684
+ # ensure the path doesn't end with a slash
600
685
 
601
- path.gsub(/\/?$/,"")
602
- # ensure the path doesn't end with a slash
686
+ return URI.escape(path, RESERVED_CHARACTERS) if escape
687
+ path
688
+ end
603
689
 
604
- return URI.escape(path, RESERVED_CHARACTERS) if escape
605
- path
606
690
  end
607
-
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dropbox-sdk
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31098137
5
- prerelease: 4
4
+ hash: 13
5
+ prerelease:
6
6
  segments:
7
7
  - 1
8
- - 0
9
- - beta
10
- version: 1.0.beta
8
+ - 1
9
+ version: "1.1"
11
10
  platform: ruby
12
11
  authors:
13
12
  - Dropbox, Inc.
@@ -15,10 +14,10 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2011-09-28 00:00:00 Z
17
+ date: 2011-10-28 00:00:00 Z
19
18
  dependencies:
20
19
  - !ruby/object:Gem::Dependency
21
- name: oauth
20
+ name: json
22
21
  prerelease: false
23
22
  requirement: &id001 !ruby/object:Gem::Requirement
24
23
  none: false
@@ -31,20 +30,6 @@ dependencies:
31
30
  version: "0"
32
31
  type: :runtime
33
32
  version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: json
36
- prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
46
- type: :runtime
47
- version_requirements: *id002
48
33
  description: " A library that provides a plain function-call interface to the\n Dropbox API web endpoints.\n"
49
34
  email:
50
35
  - support-api@dropbox.com
@@ -82,14 +67,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
82
67
  required_rubygems_version: !ruby/object:Gem::Requirement
83
68
  none: false
84
69
  requirements:
85
- - - ">"
70
+ - - ">="
86
71
  - !ruby/object:Gem::Version
87
- hash: 25
72
+ hash: 3
88
73
  segments:
89
- - 1
90
- - 3
91
- - 1
92
- version: 1.3.1
74
+ - 0
75
+ version: "0"
93
76
  requirements: []
94
77
 
95
78
  rubyforge_project: