edango 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Copying.txt +679 -0
  2. data/History.txt +6 -0
  3. data/Manifest.txt +46 -0
  4. data/PostInstall.txt +6 -0
  5. data/README.rdoc +117 -0
  6. data/Rakefile +21 -0
  7. data/bin/edango +34 -0
  8. data/lib/edango.rb +42 -0
  9. data/lib/edango/context.rb +23 -0
  10. data/lib/edango/context/directories.rb +67 -0
  11. data/lib/edango/context/files.rb +37 -0
  12. data/lib/edango/context/language.rb +101 -0
  13. data/lib/edango/context/parameters.rb +44 -0
  14. data/lib/edango/context/services.rb +147 -0
  15. data/lib/edango/di/container.rb +160 -0
  16. data/lib/edango/di/helpers.rb +41 -0
  17. data/lib/edango/di/proxy.rb +54 -0
  18. data/lib/edango/di/service.rb +60 -0
  19. data/lib/edango/di/service_factory.rb +40 -0
  20. data/lib/edango/environment.rb +77 -0
  21. data/lib/edango/executor.rb +64 -0
  22. data/lib/edango/helpers/hash.rb +30 -0
  23. data/lib/edango/helpers/kernel.rb +41 -0
  24. data/lib/edango/helpers/object.rb +65 -0
  25. data/lib/edango/helpers/string.rb +29 -0
  26. data/lib/edango/helpers/symbol.rb +39 -0
  27. data/lib/edango/logic/ticket_extractor.rb +258 -0
  28. data/lib/edango/site/core.rb +182 -0
  29. data/lib/edango/site/public/favicon.ico +0 -0
  30. data/lib/edango/site/public/images/btn-back-help.png +0 -0
  31. data/lib/edango/site/public/images/bullet.png +0 -0
  32. data/lib/edango/site/public/images/ctrl-back.gif +0 -0
  33. data/lib/edango/site/public/images/frm-back-err.png +0 -0
  34. data/lib/edango/site/public/images/frm-back-help.png +0 -0
  35. data/lib/edango/site/public/images/frm-back.png +0 -0
  36. data/lib/edango/site/public/images/logo.png +0 -0
  37. data/lib/edango/site/public/scripts/jquery.js +4376 -0
  38. data/lib/edango/site/public/scripts/jquery.min.js +19 -0
  39. data/lib/edango/site/public/scripts/logic.js +6 -0
  40. data/lib/edango/site/public/styles/layout.css +270 -0
  41. data/lib/edango/site/views/errors.haml +12 -0
  42. data/lib/edango/site/views/help.haml +10 -0
  43. data/lib/edango/site/views/index.haml +27 -0
  44. data/lib/edango/site/views/layout.haml +15 -0
  45. data/lib/edango/site/views/result.haml +10 -0
  46. data/lib/edango/starter.rb +141 -0
  47. metadata +162 -0
@@ -0,0 +1,258 @@
1
+ # EDango - torrent ticket extractor.
2
+ # Copyright (C) 2010 Dmitrii Toksaitov
3
+ #
4
+ # This file is part of EDango.
5
+ #
6
+ # EDango is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # EDango is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with EDango. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ module EDango
20
+
21
+ class TicketExtractor
22
+ attr_reader :errors
23
+
24
+ def initialize
25
+ @environment = SERVICES[:environment]
26
+ @options = @environment.options
27
+
28
+ @timer = SERVICES[:timer]
29
+ @time_limit = @options[:time_limit]
30
+
31
+ @errors = []
32
+ end
33
+
34
+ def extract_tickets(url, passkey, specs)
35
+ result = []
36
+
37
+ @errors = []
38
+ @agent = SERVICES[:agent, :init]
39
+
40
+ specs.each do |spec|
41
+ errors_root = @errors
42
+
43
+ @errors << [spec.first]
44
+ @errors = @errors.last
45
+
46
+ begin
47
+ @timer.timeout(@time_limit) do
48
+ result += extract_ticket(url, passkey, spec)
49
+ end
50
+ rescue Timeout::Error => e
51
+ @errors << t(:operation_timed_out)
52
+ end
53
+
54
+ @errors = errors_root
55
+ @errors.pop() if @errors.last.size == 1
56
+ end
57
+
58
+ if specs.empty?
59
+ @errors.unshift([t(:all_specs), t(:no_specs_for_url)])
60
+ end
61
+
62
+ result
63
+ end
64
+
65
+ private
66
+ def extract_ticket(target_url, passkey, specs)
67
+ result = []
68
+
69
+ specs = check_specs(specs)
70
+
71
+ ticket_link_regex = specs[0]
72
+ source_passkey = specs[1]
73
+
74
+ login, password = specs[2]
75
+
76
+ login_url = specs[3]
77
+
78
+ valid? login(login_url, target_url, login, password) do
79
+ ticket_link = find_ticket_link(target_url, ticket_link_regex)
80
+
81
+ raw_ticket = save_raw_ticket(ticket_link)
82
+ ticket = process_ticket(raw_ticket, source_passkey, passkey)
83
+
84
+ result << ticket if ticket
85
+ end
86
+
87
+ result
88
+ end
89
+
90
+ def check_specs(specs)
91
+ ticket_link_regex = check_spec(specs[1], :ticket_link_regex)
92
+ passkey = check_spec(specs[2], :source_passkey)
93
+
94
+ login, password = specs[3]
95
+
96
+ login_url = check_spec(specs[4], :login_url)
97
+
98
+ [ticket_link_regex, passkey, [login, password], login_url]
99
+ end
100
+
101
+ def check_spec(spec, error_key)
102
+ result = spec
103
+
104
+ if spec.nil_or_empty?
105
+ @errors << t("empty_#{error_key}".intern())
106
+ result = nil
107
+ end
108
+
109
+ result
110
+ end
111
+
112
+ def login(login_url, target_url, login, password)
113
+ result = false
114
+
115
+ if login_url and not login or not password
116
+ @errors << t(:empty_login) unless login
117
+ @errors << t(:empty_password) unless password
118
+
119
+ login_url = nil
120
+ elsif not login_url and login and password
121
+ login_url = target_url
122
+ end
123
+
124
+ if login_url
125
+ begin
126
+ @agent.get(login_url) do |page|
127
+ form = page.forms.find { |form| form.action =~ /login/ }
128
+ form.login_username = login
129
+ form.login_password = password
130
+
131
+ login_result = form.click_button()
132
+ raise() unless login_result
133
+ end
134
+ result = true
135
+ rescue Exception => e
136
+ @errors << t(:login_process_failed)
137
+ @environment.log_warning(e.message)
138
+ end
139
+ end
140
+
141
+ result
142
+ end
143
+
144
+ def find_ticket_link(url, link_regex)
145
+ result = nil
146
+
147
+ valid? url, link_regex do
148
+ begin
149
+ link_regex = Regexp.new(link_regex)
150
+
151
+ @agent.get(url) do |page|
152
+ page.links.each do |link|
153
+ (result = link; break) if link.href =~ link_regex
154
+ end
155
+ end
156
+
157
+ unless result
158
+ @errors << t(:ticket_link_not_found)
159
+ end
160
+ rescue Exception => e
161
+ @errors << t(:ticket_page_loading_failed)
162
+ @environment.log_warning(e.message)
163
+ end
164
+ end
165
+
166
+ result
167
+ end
168
+
169
+ def save_raw_ticket(link)
170
+ result = nil
171
+
172
+ if link
173
+ host = SERVICES[:uri].host(link.page.uri)
174
+ times = Time.now.strftime('%H-%M-%S_%m.%d.%Y')
175
+
176
+ file = "raw_ticket_#{host}_#{times}"
177
+ file = File.join(DIRS[:tickets], file)
178
+
179
+ unique_name = file; number = 1
180
+ while File.exists?("#{unique_name}.torrent")
181
+ unique_name = "#{file}_#{number}"
182
+ number += 1
183
+ end
184
+
185
+ file = "#{unique_name}.torrent"
186
+ link.click().save_as(file) rescue nil
187
+
188
+ unless File.exists?(file)
189
+ @errors << t(:raw_ticket_not_saved)
190
+ else
191
+ result = file
192
+ end
193
+ end
194
+
195
+ result
196
+ end
197
+
198
+ def process_ticket(path, source_passkey, passkey)
199
+ result = nil
200
+
201
+ valid? path, passkey, source_passkey do
202
+ begin
203
+ new_path = path.gsub('raw_', '')
204
+
205
+ File.open(new_path, 'w+') do |writer|
206
+ ticket = replace_passkey(read_raw_ticket(path), source_passkey, passkey)
207
+ writer.binmode.write(ticket) if ticket
208
+ end
209
+
210
+ if File.exists?(new_path)
211
+ result = new_path
212
+ else
213
+ raise()
214
+ end
215
+ rescue Exception => e
216
+ @errors << t(:processed_ticket_not_saved)
217
+ @environment.log_warning(e.message)
218
+ end
219
+ end
220
+
221
+ result
222
+ end
223
+
224
+ def read_raw_ticket(path)
225
+ result = nil
226
+
227
+ begin
228
+ File.open(path, 'r') do |io|
229
+ result = io.binmode.read()
230
+ end
231
+ rescue Exception => e
232
+ @errors << t(:raw_ticket_not_opened)
233
+ @environment.log_warning(e.message)
234
+ end
235
+
236
+ result
237
+ end
238
+
239
+ def replace_passkey(raw_ticket, source_passkey, passkey)
240
+ result = nil
241
+
242
+ if raw_ticket
243
+ ticket = raw_ticket.gsub(source_passkey, passkey)
244
+
245
+ if ticket == raw_ticket
246
+ if passkey != source_passkey
247
+ @errors << t(:passkey_not_found)
248
+ end
249
+ else
250
+ result = ticket
251
+ end
252
+ end
253
+
254
+ result
255
+ end
256
+ end
257
+
258
+ end
@@ -0,0 +1,182 @@
1
+ # EDango - torrent ticket extractor.
2
+ # Copyright (C) 2010 Dmitrii Toksaitov
3
+ #
4
+ # This file is part of EDango.
5
+ #
6
+ # EDango is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # EDango is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with EDango. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ module EDango
20
+
21
+ class Core < SERVICES[:web, :raw]
22
+ set :run, true
23
+ set :lock, true
24
+
25
+ set :app_file, DIRS[:site]
26
+ set :root, DIRS[:site]
27
+
28
+ set :public, DIRS[:public]
29
+ set :views, DIRS[:views]
30
+
31
+ set :raise_errors, proc { test? }
32
+ set :dump_errors, proc { test? }
33
+
34
+ enable :sessions
35
+ enable :static
36
+ enable :clean_trace
37
+
38
+ disable :show_exceptions
39
+ disable :methodoverride
40
+
41
+ configure do
42
+ set :options, SERVICES[:environment].options
43
+
44
+ set :environment, (ENV['RACK_ENV'] || options[:environment]).intern()
45
+
46
+ set :sites, options[:sites]
47
+ set :server, options[:servers]
48
+ set :host, options[:host]
49
+ set :port, options[:port]
50
+
51
+ set :logging, options[:server_logging]
52
+
53
+ Rack::Mime::MIME_TYPES['.torrent'] = 'application/x-bittorrent'
54
+
55
+ options[:parameters].each do |param, value|
56
+ self.class.set(param, value)
57
+ end
58
+
59
+ set :errors, {}
60
+ end
61
+
62
+ helpers do
63
+ def error(key, value = nil)
64
+ value ? options.errors[key] = value : options.errors[key]
65
+ end
66
+ alias err error
67
+
68
+ def error?(key)
69
+ options.errors[key] ? true : false
70
+ end
71
+ alias err? error?
72
+
73
+ def clear_errors
74
+ options.errors.clear()
75
+ end
76
+
77
+ def current_jlib
78
+ options.environment == :production ? 'jquery.min.js' : 'jquery.js'
79
+ end
80
+
81
+ def url_input_class
82
+ error?(:in_url) ? 'err-text' : 'normal-text'
83
+ end
84
+
85
+ def passkey_input_class
86
+ error?(:in_passkey) ? 'err-text' : 'normal-text'
87
+ end
88
+
89
+ def emphasize(text, part = ':')
90
+ text.gsub(part, "<em>#{part}</em>")
91
+ end
92
+
93
+ def sanitize(file_name)
94
+ file_name.gsub(%r{\\|/|\.\.}, '') rescue ''
95
+ end
96
+
97
+ def link(ticket_path)
98
+ "tickets/#{file(ticket_path)}"
99
+ end
100
+
101
+ def file(ticket_path)
102
+ File.basename(File.expand_path(ticket_path))
103
+ end
104
+
105
+ def process_root
106
+ @url = request.cookies['url']
107
+ @passkey = request.cookies['passkey']
108
+
109
+ haml(:index)
110
+ ensure
111
+ clear_errors()
112
+ end
113
+
114
+ def extract_tickets(url, passkey)
115
+ unless url.nil_or_empty? or
116
+ passkey.nil_or_empty?
117
+
118
+ sites = options.sites.select do |item|
119
+ url =~ Regexp.new(item.first) rescue false
120
+ end
121
+
122
+ logic = EDango::SERVICES[:logic]
123
+ result = logic.process(url, passkey, sites)
124
+
125
+ unless logic.errors.empty?
126
+ error :in_process, logic.errors
127
+ end
128
+
129
+ result
130
+ end
131
+ end
132
+ end
133
+
134
+ get '/' do
135
+ process_root()
136
+ end
137
+ post '/' do
138
+ process_root()
139
+ end
140
+
141
+ post '/process' do
142
+ url, passkey = params[:url], params[:passkey]
143
+
144
+ response.set_cookie('passkey', passkey)
145
+
146
+ error :in_url, t(:empty_url) if url.nil_or_empty?
147
+ error :in_passkey, t(:empty_passkey) if passkey.nil_or_empty?
148
+
149
+ @tickets = extract_tickets(url, passkey)
150
+
151
+ unless options.errors.empty?
152
+ response.set_cookie('url', url)
153
+
154
+ redirect('/')
155
+ else
156
+ response.delete_cookie('url')
157
+
158
+ haml(:result)
159
+ end
160
+ end
161
+
162
+ get '/tickets/:ticket' do
163
+ file = File.join(EDango::DIRS[:tickets], sanitize(params[:ticket]))
164
+
165
+ if File.directory?(file) or not File.exists?(file)
166
+ error :in_process, [[t(:specified_file), t(:file_not_found)]]
167
+ end
168
+
169
+ unless options.errors.empty?
170
+ redirect('/')
171
+ else
172
+ send_file(file)
173
+ end
174
+ end
175
+
176
+ not_found do
177
+ redirect('/')
178
+ end
179
+
180
+ end
181
+
182
+ end
Binary file