dbox 0.5.3 → 0.6.0

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.
@@ -0,0 +1,184 @@
1
+ # -------------------------------------------------------------------
2
+ # An example webapp that lets you browse and upload files to Dropbox.
3
+ # Demonstrates:
4
+ # - The webapp OAuth process.
5
+ # - The metadata() and put_file() calls.
6
+ #
7
+ # To run:
8
+ # 1. Install Sinatra $ gem install sinatra
9
+ # 2. Launch server $ ruby web_file_browser.rb
10
+ # 3. Browse to http://localhost:4567/
11
+ # -------------------------------------------------------------------
12
+
13
+ require 'rubygems'
14
+ require 'sinatra'
15
+ require 'pp'
16
+ require './lib/dropbox_sdk'
17
+
18
+ # Get your app's key and secret from https://www.dropbox.com/developers/
19
+ APP_KEY = ''
20
+ APP_SECRET = ''
21
+ ACCESS_TYPE = :app_folder #The two valid values here are :app_folder and :dropbox
22
+ #The default is :app_folder, but your application might be
23
+ #set to have full :dropbox access. Check your app at
24
+ #https://www.dropbox.com/developers/apps
25
+
26
+ # -------------------------------------------------------------------
27
+ # OAuth stuff
28
+
29
+ get '/oauth-start' do
30
+ # OAuth Step 1: Get a request token from Dropbox.
31
+ db_session = DropboxSession.new(APP_KEY, APP_SECRET)
32
+ begin
33
+ db_session.get_request_token
34
+ rescue DropboxError => e
35
+ return html_page "Exception in OAuth step 1", "<p>#{h e}</p>"
36
+ end
37
+
38
+ session[:request_db_session] = db_session.serialize
39
+
40
+ # OAuth Step 2: Send the user to the Dropbox website so they can authorize
41
+ # our app. After the user authorizes our app, Dropbox will redirect them
42
+ # to our '/oauth-callback' endpoint.
43
+ auth_url = db_session.get_authorize_url url('/oauth-callback')
44
+ redirect auth_url
45
+ end
46
+
47
+ get '/oauth-callback' do
48
+ # Finish OAuth Step 2
49
+ ser = session[:request_db_session]
50
+ unless ser
51
+ return html_page "Error in OAuth step 2", "<p>Couldn't find OAuth state in session.</p>"
52
+ end
53
+ db_session = DropboxSession.deserialize(ser)
54
+
55
+ # OAuth Step 3: Get an access token from Dropbox.
56
+ begin
57
+ db_session.get_access_token
58
+ rescue DropboxError => e
59
+ return html_page "Exception in OAuth step 3", "<p>#{h e}</p>"
60
+ end
61
+ session.delete(:request_db_session)
62
+ session[:authorized_db_session] = db_session.serialize
63
+ redirect url('/')
64
+ # In this simple example, we store the authorized DropboxSession in the web
65
+ # session hash. A "real" webapp might store it somewhere more persistent.
66
+ end
67
+
68
+ # If we already have an authorized DropboxSession, returns a DropboxClient.
69
+ def get_db_client
70
+ if session[:authorized_db_session]
71
+ db_session = DropboxSession.deserialize(session[:authorized_db_session])
72
+ begin
73
+ return DropboxClient.new(db_session, ACCESS_TYPE)
74
+ rescue DropboxAuthError => e
75
+ # The stored session didn't work. Fall through and start OAuth.
76
+ session[:authorized_db_session].delete
77
+ end
78
+ end
79
+ end
80
+
81
+ # -------------------------------------------------------------------
82
+ # File/folder display stuff
83
+
84
+ get '/' do
85
+ # Get the DropboxClient object. Redirect to OAuth flow if necessary.
86
+ db_client = get_db_client
87
+ unless db_client
88
+ redirect url("/oauth-start")
89
+ end
90
+
91
+ # Call DropboxClient.metadata
92
+ path = params[:path] || '/'
93
+ begin
94
+ entry = db_client.metadata(path)
95
+ rescue DropboxAuthError => e
96
+ session.delete(:authorized_db_session) # An auth error means the db_session is probably bad
97
+ return html_page "Dropbox auth error", "<p>#{h e}</p>"
98
+ rescue DropboxError => e
99
+ if e.http_response.code == '404'
100
+ return html_page "Path not found: #{h path}", ""
101
+ else
102
+ return html_page "Dropbox API error", "<pre>#{h e.http_response}</pre>"
103
+ end
104
+ end
105
+
106
+ if entry['is_dir']
107
+ render_folder(db_client, entry)
108
+ else
109
+ render_file(db_client, entry)
110
+ end
111
+ end
112
+
113
+ def render_folder(db_client, entry)
114
+ # Provide an upload form (so the user can add files to this folder)
115
+ out = "<form action='/upload' method='post' enctype='multipart/form-data'>"
116
+ out += "<label for='file'>Upload file:</label> <input name='file' type='file'/>"
117
+ out += "<input type='submit' value='Upload'/>"
118
+ out += "<input name='folder' type='hidden' value='#{h entry['path']}'/>"
119
+ out += "</form>" # TODO: Add a token to counter CSRF attacks.
120
+ # List of folder contents
121
+ entry['contents'].each do |child|
122
+ cp = child['path'] # child path
123
+ cn = File.basename(cp) # child name
124
+ if (child['is_dir']) then cn += '/' end
125
+ out += "<div><a style='text-decoration: none' href='/?path=#{h cp}'>#{h cn}</a></div>"
126
+ end
127
+
128
+ html_page "Folder: #{entry['path']}", out
129
+ end
130
+
131
+ def render_file(db_client, entry)
132
+ # Just dump out metadata hash
133
+ html_page "File: #{entry['path']}", "<pre>#{h entry.pretty_inspect}</pre>"
134
+ end
135
+
136
+ # -------------------------------------------------------------------
137
+ # File upload handler
138
+
139
+ post '/upload' do
140
+ # Check POST parameter.
141
+ file = params[:file]
142
+ unless file && (temp_file = file[:tempfile]) && (name = file[:filename])
143
+ return html_page "Upload error", "<p>No file selected.</p>"
144
+ end
145
+
146
+ # Get the DropboxClient object.
147
+ db_client = get_db_client
148
+ unless db_client
149
+ return html_page "Upload error", "<p>Not linked with a Dropbox account.</p>"
150
+ end
151
+
152
+ # Call DropboxClient.put_file
153
+ begin
154
+ entry = db_client.put_file("#{params[:folder]}/#{name}", temp_file.read)
155
+ rescue DropboxAuthError => e
156
+ session.delete(:authorized_db_session) # An auth error means the db_session is probably bad
157
+ return html_page "Dropbox auth error", "<p>#{h e}</p>"
158
+ rescue DropboxError => e
159
+ return html_page "Dropbox API error", "<p>#{h e}</p>"
160
+ end
161
+
162
+ html_page "Upload complete", "<pre>#{h entry.pretty_inspect}</pre>"
163
+ end
164
+
165
+ # -------------------------------------------------------------------
166
+
167
+ def html_page(title, body)
168
+ "<html>" +
169
+ "<head><title>#{h title}</title></head>" +
170
+ "<body><h1>#{h title}</h1>#{body}</body>" +
171
+ "</html>"
172
+ end
173
+
174
+ enable :sessions
175
+
176
+ helpers do
177
+ include Rack::Utils
178
+ alias_method :h, :escape_html
179
+ end
180
+
181
+ if APP_KEY == '' or APP_SECRET == ''
182
+ puts "You must set APP_KEY and APP_SECRET at the top of \"#{__FILE__}\"!"
183
+ exit 1
184
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbox
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 5
9
- - 3
10
- version: 0.5.3
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ken Pratt
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-04 00:00:00 Z
18
+ date: 2011-11-24 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: multipart-post
@@ -108,6 +108,7 @@ extra_rdoc_files:
108
108
  - README.md
109
109
  files:
110
110
  - .document
111
+ - History.txt
111
112
  - LICENSE.txt
112
113
  - README.md
113
114
  - Rakefile
@@ -117,23 +118,24 @@ files:
117
118
  - dbox.gemspec
118
119
  - lib/dbox.rb
119
120
  - lib/dbox/api.rb
121
+ - lib/dbox/cacert.pem
120
122
  - lib/dbox/database.rb
121
123
  - lib/dbox/db.rb
122
124
  - lib/dbox/loggable.rb
123
125
  - lib/dbox/parallel_tasks.rb
124
126
  - lib/dbox/syncer.rb
127
+ - lib/dbox/utils.rb
125
128
  - sample_polling_script.rb
126
129
  - spec/dbox_spec.rb
127
130
  - spec/spec_helper.rb
128
- - vendor/dropbox-client-ruby/LICENSE
129
- - vendor/dropbox-client-ruby/README
130
- - vendor/dropbox-client-ruby/Rakefile
131
- - vendor/dropbox-client-ruby/config/testing.json.example
132
- - vendor/dropbox-client-ruby/lib/dropbox.rb
133
- - vendor/dropbox-client-ruby/manifest
134
- - vendor/dropbox-client-ruby/test/authenticator_test.rb
135
- - vendor/dropbox-client-ruby/test/client_test.rb
136
- - vendor/dropbox-client-ruby/test/util.rb
131
+ - vendor/dropbox-ruby-sdk/CHANGELOG
132
+ - vendor/dropbox-ruby-sdk/LICENSE
133
+ - vendor/dropbox-ruby-sdk/README
134
+ - vendor/dropbox-ruby-sdk/cli_example.rb
135
+ - vendor/dropbox-ruby-sdk/dropbox_controller.rb
136
+ - vendor/dropbox-ruby-sdk/gemspec.rb
137
+ - vendor/dropbox-ruby-sdk/lib/dropbox_sdk.rb
138
+ - vendor/dropbox-ruby-sdk/web_file_browser.rb
137
139
  homepage: http://github.com/kenpratt/dbox
138
140
  licenses:
139
141
  - MIT
@@ -1,17 +0,0 @@
1
- Forked from Ruby client at https://www.dropbox.com/developers/releases
2
-
3
- Getting started with the Dropbox ruby library:
4
- 1. Make sure you have rake and rubygems installed on your system.
5
- 1b. Some of the gems below may need to be compiled locally, so make sure you
6
- have any necessary source code around as well.
7
- e.g. 'apt-get install ruby1.x-dev libxml2-dev libxslt1-dev' on ubuntu
8
- 2. Install oauth from rubygems
9
- 3. Install multipart-post from rubygems
10
- 4. Install json from rubygems
11
- 5. Install mechanize from rubygems
12
- 6. Install shoulda from rubygems
13
- 7. Copy config/testing.json.example to config/testing.json
14
- 8. In config/testing.json enter your application's consumer key, secret key,
15
- and your test user email and password.
16
- 9. Run 'rake test_units' to make sure all the tests pass.
17
- 10. Start developing your Dropbox API application!
@@ -1,41 +0,0 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/gempackagetask'
4
- require 'rubygems'
5
-
6
- manifest = File.readlines('manifest').map! { |x| x.chomp! }
7
-
8
- spec = Gem::Specification.new do |s|
9
- s.name = %q{dropbox}
10
- s.version = '1.0'
11
-
12
- s.authors = ["Dropbox, Inc."]
13
- s.date = Time.now.utc.strftime('%Y-%m-%d')
14
- s.description = "Dropbox REST API Client Library"
15
- s.email = %q{support@dropbox.com}
16
- s.executables = %w()
17
- s.extensions = %w()
18
-
19
- s.files = manifest
20
- s.homepage = %q{http://developers.dropbox.com/}
21
-
22
- summary = %q{Dropbox REST API Client Library}
23
- s.require_paths = %w(lib)
24
- s.summary = summary
25
- end
26
-
27
- task :default => [:test_units]
28
-
29
- desc "Run basic tests"
30
- Rake::TestTask.new("test_units") { |t|
31
- t.pattern = 'test/*_test.rb'
32
- t.verbose = true
33
- t.warning = true
34
- }
35
-
36
- Rake::GemPackageTask.new(spec) do |pkg|
37
- pkg.need_zip = true
38
- pkg.need_tar = true
39
- end
40
-
41
-
@@ -1,16 +0,0 @@
1
- {
2
- "server": "api.dropbox.com",
3
- "content_server": "api-content.dropbox.com",
4
- "port": 80,
5
- "request_token_url": "http://api.dropbox.com/0/oauth/request_token",
6
- "access_token_url": "http://api.dropbox.com/0/oauth/access_token",
7
- "authorization_url": "http://www.dropbox.com/0/oauth/authorize",
8
- "consumer_key": "YOUR CONSUMER KEY",
9
- "consumer_secret": "YOUR CONSUMER SECRET",
10
- "verifier": "",
11
- "testing_user": "USER TO TEST WITH",
12
- "testing_password": "PASSWORD",
13
- "root": "dropbox"
14
- }
15
-
16
-
@@ -1,259 +0,0 @@
1
- require 'rubygems'
2
- require 'oauth'
3
- require 'json'
4
- require 'uri'
5
- require 'net/http/post/multipart'
6
-
7
- class Authenticator
8
-
9
- def initialize(config, key=nil, secret=nil, is_request=false, server=nil)
10
- @consumer_key = config['consumer_key']
11
- @consumer_secret = config['consumer_secret']
12
- @config = config
13
- @oauth_conf = {
14
- :site => "http://" + (server || config["server"]),
15
- :scheme => :header,
16
- :http_method => :post,
17
- :request_token_url => config["request_token_url"],
18
- :access_token_url => config["access_token_url"],
19
- :authorize_url => config["authorization_url"],
20
- }
21
-
22
- @consumer = OAuth::Consumer.new @consumer_key, @consumer_secret, @oauth_conf
23
-
24
- @access_token = nil
25
- @request_token = nil
26
-
27
- if key and secret
28
- if is_request then
29
- @request_token = OAuth::RequestToken.new(@consumer, key, secret)
30
- else
31
- @access_token = OAuth::AccessToken.new(@consumer, key, secret)
32
- end
33
- end
34
- end
35
-
36
- attr_reader :config
37
-
38
- def Authenticator.load_config(path)
39
- open(path) do |f|
40
- return JSON.parse(f.read())
41
- end
42
- end
43
-
44
- def get_request_token(*args)
45
- @request_token = @consumer.get_request_token(*args)
46
- return @request_token.authorize_url
47
- end
48
-
49
- def get_access_token
50
- if @access_token == nil
51
- @access_token = @request_token.get_access_token
52
- end
53
-
54
- return @access_token
55
- end
56
-
57
- def authorized?
58
- !!@access_token
59
- end
60
-
61
- def token
62
- return (@access_token || @request_token).token
63
- end
64
-
65
- def secret
66
- return (@access_token || @request_token).secret
67
- end
68
-
69
- def sign(request, request_options = {})
70
- return @consumer.sign!(request, @access_token || @request_token, request_options)
71
- end
72
-
73
- def clone(host)
74
- return Authenticator.new(@config, token(), secret(), !authorized?, host)
75
- end
76
- end
77
-
78
- # maybe subclass or monkey patch trusted into the oauth stuff
79
-
80
-
81
- API_VERSION = 0
82
-
83
-
84
- class DropboxError < RuntimeError
85
- end
86
-
87
- class DropboxClient
88
- attr_reader :token
89
-
90
- def initialize(api_host, content_host, port, auth)
91
- @api_host = api_host
92
- @content_host = content_host
93
- @port = port.to_i
94
- @auth = auth
95
- @token = auth.get_access_token
96
- end
97
-
98
- def initialize_copy(other)
99
- @token = other.token.clone()
100
- @token.consumer = @token.consumer.clone()
101
- @token.consumer.http = nil
102
- end
103
-
104
- def parse_response(response, callback=nil)
105
- if response.kind_of?(Net::HTTPServerError)
106
- raise DropboxError.new("Invalid response #{response}\n#{response.body}")
107
- elsif not response.kind_of?(Net::HTTPSuccess)
108
- return response
109
- end
110
-
111
- if callback
112
- return response.body
113
- else
114
- begin
115
- return JSON.parse(response.body)
116
- rescue JSON::ParserError
117
- return response.body
118
- end
119
- end
120
- end
121
-
122
-
123
- def account_info(status_in_response=false, callback=nil)
124
- response = @token.get build_url(@api_host, @port, "/account/info")
125
- return parse_response(response, callback)
126
- end
127
-
128
- def put_file(root, to_path, name, file_obj)
129
- path = "/files/#{root}#{to_path}"
130
- oauth_params = {"file" => name}
131
- auth = @auth.clone(@content_host)
132
-
133
- url = URI.parse(build_url(@content_host, @port, path))
134
-
135
- oauth_fake_req = Net::HTTP::Post.new(url.path)
136
- oauth_fake_req.set_form_data({ "file" => name })
137
- auth.sign(oauth_fake_req)
138
-
139
- oauth_sig = oauth_fake_req.to_hash['authorization']
140
-
141
- req = Net::HTTP::Post::Multipart.new(url.path, {
142
- "file" => UploadIO.new(file_obj, "application/octet-stream", name),
143
- })
144
- req['authorization'] = oauth_sig.join(", ")
145
-
146
- res = Net::HTTP.start(url.host, url.port) do |http|
147
- return parse_response(http.request(req))
148
- end
149
- end
150
-
151
- def get_file(root, from_path, destination_io=nil)
152
- path = "/files/#{root}#{from_path}"
153
-
154
- if destination_io
155
- url = URI.parse(build_url(@content_host, @port, path))
156
-
157
- # if a destination is given, stream the response into it
158
- Net::HTTP.start(url.host, url.port) do |http|
159
- # build the request
160
- req = Net::HTTP::Get.new(url.path, {})
161
- auth = @auth.clone(@content_host)
162
- auth.sign(req)
163
-
164
- # make the request
165
- http.request(req) do |response|
166
- if response.kind_of?(Net::HTTPServerError)
167
- raise DropboxError.new("Invalid response #{response}\n#{response.body}")
168
- elsif not response.kind_of?(Net::HTTPSuccess)
169
- return response
170
- else
171
- # stream to given io
172
- response.read_body {|segment| destination_io << segment }
173
- return true
174
- end
175
- end
176
- end
177
- else
178
- response = @token.get(build_url(@content_host, @port, path))
179
- return parse_response(response, true)
180
- end
181
- end
182
-
183
- def file_copy(root, from_path, to_path, callback=nil)
184
- params = {
185
- "root" => root,
186
- "from_path" => from_path,
187
- "to_path" => to_path,
188
- "callback" => callback
189
- }
190
- response = @token.post(build_url(@api_host, @port, "/fileops/copy"), params)
191
- return parse_response(response, callback)
192
- end
193
-
194
- def file_create_folder(root, path, callback=nil)
195
- params = {
196
- "root" => root,
197
- "path" => path,
198
- "callback" => callback
199
- }
200
- response = @token.post(build_url(@api_host, @port, "/fileops/create_folder"), params)
201
-
202
- return parse_response(response, callback)
203
- end
204
-
205
- def file_delete(root, path, callback=nil)
206
- params = {
207
- "root" => root,
208
- "path" => path,
209
- "callback" => callback
210
- }
211
- response = @token.post(build_url(@api_host, @port, "/fileops/delete"), params)
212
- return parse_response(response, callback)
213
- end
214
-
215
- def file_move(root, from_path, to_path, callback=nil)
216
- params = {
217
- "root" => root,
218
- "from_path" => from_path,
219
- "to_path" => to_path,
220
- "callback" => callback
221
- }
222
- response = @token.post(build_url(@api_host, @port, "/fileops/move"), params)
223
- return parse_response(response, callback)
224
- end
225
-
226
- def metadata(root, path, file_limit=10000, hash=nil, list=true, status_in_response=false, callback=nil)
227
- params = {
228
- "file_limit" => file_limit.to_s,
229
- "list" => list ? "true" : "false",
230
- "status_in_response" => status_in_response ? "true" : "false"
231
- }
232
- params["hash"] = hash if hash
233
- params["callback"] = callback if callback
234
-
235
- response = @token.get build_url(@api_host, @port, "/metadata/#{root}#{path}", params=params)
236
- return parse_response(response, callback)
237
- end
238
-
239
- def links(root, path)
240
- full_path = "/links/#{root}#{path}"
241
- return build_url(@api_host, @port, full_path)
242
- end
243
-
244
- def build_url(host, port, url, params=nil)
245
- port = port == 80 ? nil : port
246
- versioned_url = "/#{API_VERSION}#{url}"
247
-
248
- target = URI::Generic.new("http", nil, host, port, nil, versioned_url, nil, nil, nil)
249
-
250
- if params
251
- target.query = params.collect {|k,v| URI.escape(k) + "=" + URI.escape(v) }.join("&")
252
- end
253
-
254
- return target.to_s
255
- end
256
-
257
-
258
- end
259
-