dropbox 0.0.10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,213 +0,0 @@
1
- require 'rubygems'
2
- require 'nokogiri'
3
- require 'mechanize'
4
-
5
- Mechanize.html_parser = Nokogiri::HTML
6
-
7
- # TODO: Tests (mock out expected DropBox output)
8
- # TODO: Directory object, File object
9
-
10
- class DropBox
11
- #before_filter :login_filter, :except => [:login]
12
-
13
- def initialize(email, password, folder_namespace = "")
14
- @email = email
15
- @password = password
16
- @agent = Mechanize.new
17
- @folder_namespace = folder_namespace.gsub(/^\//,"")
18
- @logged_in = false
19
- end
20
-
21
- def agent
22
- @agent
23
- end
24
-
25
- # Lists all the files and folders in a given directory
26
- def index(path = "/")
27
- login_filter
28
- path = namespace_path(path)
29
-
30
- list = @agent.post("/browse2#{path}?ajax=yes", {"d"=> 1, "t" => @token })
31
-
32
- listing = list.search('div.browse-file-box-details').collect do |file|
33
- details = {}
34
- details['name'] = file.at('div.details-filename a').content.strip
35
- details['url'] = file.at('div.details-filename a')["href"]
36
- #details['size'] = file.at('div.details-size a').try(:content).try(:strip)
37
- #details['modified'] = file.at('div.details-modified a').try(:content).try(:strip)
38
-
39
- if match_data = details['url'].match(/^\/browse_plain(.*)$/)
40
- details['directory'] = true
41
- details['path'] = normalize_namespace(match_data[1])
42
- elsif match_data = details['url'].match(%r{^https?://[^/]*/get(.*)$})
43
- details['directory'] = false
44
- details['path'] = normalize_namespace(match_data[1])
45
- elsif match_data = details['url'].match(%r{^https?://[^/]*/u/\d*/(.*)$})
46
- details['directory'] = false
47
- details['path'] = "Public/#{match_data[1]}"
48
- else
49
- raise "could not parse path from Dropbox URL: #{details['url'] }"
50
- end
51
-
52
- details
53
- end
54
-
55
- return listing
56
- end
57
-
58
- alias :list :index
59
-
60
- # Lists the full history for a file on DropBox
61
- def list_history(path)
62
- login_filter
63
-
64
- path = namespace_path(path)
65
-
66
- history = @agent.get("/revisions#{path}")
67
- listing = history.search("table.filebrowser > tr").select{|r| r.search("td").count > 1 }.collect do |r|
68
-
69
- # warning, this is very brittle!
70
- details = {}
71
- details["version"] = r.search("td a").first.content.strip
72
- details["url"] = r.search("td a").first["href"]
73
- details["size"] = r.search("td").last.content.strip
74
- details["modified"] = r.search("td")[2].content.strip
75
- details["version_id"] = details["url"].match(/^.*sjid=([\d]*)$/)[1]
76
- details['path'] = normalize_namespace(details['url'][33..-1])
77
-
78
- details
79
- end
80
-
81
- return listing
82
- end
83
-
84
- # Downloads the specified file from DropBox
85
- def show(path)
86
- require 'pathname'
87
- # change to before filter
88
- login_filter
89
-
90
- # round about way of getting the secure url we need
91
- # path = namespace_path(path)
92
- pathname = Pathname.new(path)
93
- url = self.list(pathname.dirname.to_s).detect{ |f| f["name"] == pathname.basename.to_s }["url"]
94
-
95
- #https://dl-web.dropbox.com/get/testing.txt?w=0ff80d5d&sjid=125987568
96
- @agent.get(url).content
97
- end
98
-
99
- alias :get :show
100
-
101
- # Creates a directory
102
- def create_directory(new_path, destination = "/" )
103
- # change to before filter
104
- login unless @logged_in
105
- destination = namespace_path(destination)
106
- @agent.post("/cmd/new#{destination}",{"to_path"=>new_path, "folder"=>"yes", "t" => @token }).code == "200"
107
- end
108
-
109
- # Uploads a file to DropBox under the given filename
110
- def create(file, destination = "/")
111
- # change to before filter
112
- if @logged_in
113
- home_page = @agent.get('https://www.dropbox.com/home')
114
- else
115
- home_page = login
116
- end
117
-
118
- upload_form = home_page.forms.detect{ |f| f.action == "https://dl-web.dropbox.com/upload" }
119
- upload_form.dest = namespace_path(destination)
120
- upload_form.file_uploads.first.file_name = file if file
121
-
122
- @agent.submit(upload_form).code == "200"
123
- end
124
-
125
- alias :update :create
126
-
127
- # Renames a file or folder in the DropBox
128
- def rename(file, destination)
129
- login_filter
130
- file = namespace_path(file)
131
- destination = namespace_path(destination)
132
- @agent.post("/cmd/rename#{file}", {"to_path"=> destination, "t" => @token }).code == "200"
133
- end
134
-
135
- # Deletes a file/folder from the DropBox (accepts string path or an array of string paths)
136
- def destroy(paths)
137
- login_filter
138
- paths = [paths].flatten
139
- paths = paths.collect { |path| namespace_path(path) }
140
- @agent.post("/cmd/delete", {"files"=> paths, "t" => @token }).code == "200"
141
- end
142
-
143
- # Permanently deletes a file from the DropBox (no history!) accepts arrays, as #destroy does
144
- def purge(paths)
145
- login_filter
146
- paths = [paths].flatten
147
- paths = paths.collect { |path| namespace_path(path) }
148
- @agent.post("/cmd/purge", {"files"=> paths, "t" => @token }).code == "200"
149
- end
150
-
151
- # Will give a hash of the amount of space left on the DropBox, the amound used, the calculated amount free (all as a 1 d.p. rounded GB value) and the percentage used (scraped)
152
- def usage_stats
153
- login_filter
154
-
155
- stats_page = @agent.get("/account")
156
-
157
- stats = stats_page.at('#usage-percent').content.scan(/(\d+(?:\.\d+)?)%\ used\ \((\d+(?:\.\d+)?)([MG])B of (\d+(?:\.\d+)?)GB\)/).collect{ |d|
158
- { :used => d[1].to_f * ((d[2] == "G") ? 1024 : 1),
159
- :total => d[3].to_f * 1024,
160
- :free => (d[3].to_f * 1024 - d[1].to_f * ((d[2] == "G") ? 1024 : 1)),
161
- :percent => Percentage.new(d[0].to_f/100)
162
- }
163
- }[0]
164
-
165
- regular_data = stats_page.at('span.bar-graph-legend.bar-graph-normal').next.content.scan(/\((\d+(?:\.\d+)?)([MG])B/)[0]
166
- stats[:regular_used] = regular_data[0].to_f * ((regular_data[1] == "G") ? 1024 : 1) unless regular_data.nil?
167
-
168
- shared_data = stats_page.at('span.bar-graph-legend.bar-graph-shared').next.content.scan(/\((\d+(?:\.\d+)?)([MG])B/)[0]
169
- stats[:shared_used] = shared_data[0].to_f * ((shared_data[1] == "G") ? 1024 : 1) unless shared_data.nil?
170
-
171
- return stats
172
- end
173
-
174
- private
175
- def namespace_path(path)
176
- # remove the start slash if we have one
177
- path.gsub(/^\//,"")
178
- new_path = if @folder_namespace.empty?
179
- "/#{path}"
180
- else
181
- "/#{@folder_namespace}/#{path}"
182
- end
183
- new_path.gsub("//","/")
184
- end
185
-
186
- def normalize_namespace(file)
187
- file.gsub(/^\/#{@folder_namespace}/,"")
188
- end
189
-
190
- def login
191
- page = @agent.get('https://www.dropbox.com/login')
192
- login_form = page.forms.detect { |f| f.action == "/login" }
193
- login_form.login_email = @email
194
- login_form.login_password = @password
195
-
196
- home_page = @agent.submit(login_form)
197
- # todo check if we are logged in! (ie search for email and "Log out"
198
- @logged_in = true
199
- @token = home_page.at('//script[contains(text(), "TOKEN")]').content.match("TOKEN: '(.*)',$")[1]
200
-
201
- # check if we have our namespace
202
-
203
- home_page
204
- end
205
-
206
- def login_filter
207
- login unless @logged_in
208
- end
209
- end
210
-
211
- # this file doesn't use the standard ruby indent settings, so the following
212
- # modeline will make sure that the whitespace stays consistent.
213
- # vim:noexpandtab tabstop=4 shiftwidth=4