dbox 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
-