rffw 0.0.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 (55) hide show
  1. data/.gitignore +5 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +4 -0
  4. data/README.md +60 -0
  5. data/Rakefile +41 -0
  6. data/bin/rffw +16 -0
  7. data/lib/rffw.rb +7 -0
  8. data/lib/rffw/app.rb +36 -0
  9. data/lib/rffw/app/app_handler.rb +59 -0
  10. data/lib/rffw/app/data/images/bg.png +0 -0
  11. data/lib/rffw/app/data/index.html +56 -0
  12. data/lib/rffw/app/data/javascripts/application.js +110 -0
  13. data/lib/rffw/app/data/stylesheets/style.css +338 -0
  14. data/lib/rffw/app/data/template.html +42 -0
  15. data/lib/rffw/app/db.rb +19 -0
  16. data/lib/rffw/app/description_handler.rb +12 -0
  17. data/lib/rffw/app/dir_handler.rb +36 -0
  18. data/lib/rffw/app/record.rb +43 -0
  19. data/lib/rffw/app/show_handler.rb +25 -0
  20. data/lib/rffw/app/upload_handler.rb +32 -0
  21. data/lib/rffw/app/upload_status_handler.rb +40 -0
  22. data/lib/rffw/app/urlencode_chars.data +224 -0
  23. data/lib/rffw/app/view_helpers.rb +30 -0
  24. data/lib/rffw/parser.rb +9 -0
  25. data/lib/rffw/parser/http_request.rb +137 -0
  26. data/lib/rffw/parser/http_response.rb +29 -0
  27. data/lib/rffw/parser/mime_parser.rb +46 -0
  28. data/lib/rffw/server.rb +15 -0
  29. data/lib/rffw/server/buffered_client.rb +57 -0
  30. data/lib/rffw/server/client.rb +53 -0
  31. data/lib/rffw/server/http_client.rb +49 -0
  32. data/lib/rffw/server/server.rb +46 -0
  33. data/lib/rffw/version.rb +3 -0
  34. data/rffw.db +0 -0
  35. data/rffw.gemspec +21 -0
  36. data/test/fixtures/image.jpg +0 -0
  37. data/test/fixtures/mime_image.data +0 -0
  38. data/test/fixtures/mime_image.png +0 -0
  39. data/test/fixtures/post_form_data.http +14 -0
  40. data/test/fixtures/raw_request.txt +8 -0
  41. data/test/fixtures/request.http +9 -0
  42. data/test/fixtures/upload.http +0 -0
  43. data/test/fixtures/upload_status_request.http +10 -0
  44. data/test/helper.rb +97 -0
  45. data/test/test_buffered_client.rb +50 -0
  46. data/test/test_client.rb +47 -0
  47. data/test/test_db.rb +21 -0
  48. data/test/test_http_client.rb +26 -0
  49. data/test/test_http_request.rb +52 -0
  50. data/test/test_mime_parser.rb +22 -0
  51. data/test/test_record.rb +49 -0
  52. data/test/test_upload_status_handler.rb +18 -0
  53. data/test/test_uploader_handler.rb +10 -0
  54. data/test/test_view_helpers.rb +24 -0
  55. metadata +122 -0
@@ -0,0 +1,42 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="description" content="Recive files from webserver">
8
+ <meta name="author" content="Guillermo Álvarez Fernández <guillermo@cientifico.net>">
9
+
10
+ <title>rffw</title>
11
+
12
+ <link href='http://fonts.googleapis.com/css?family=Josefin+Sans:light,lightitalic,regular,regularitalic,bold&amp;v1' rel='stylesheet' type='text/css'>
13
+ <link href='http://fonts.googleapis.com/css?family=The+Girl+Next+Door&amp;v1' rel='stylesheet' type='text/css'>
14
+
15
+ <link rel="stylesheet" href="/stylesheets/style.css?v=2">
16
+ <script type="text/javascript" charset="utf-8" src="/javascripts/application.js"></script>
17
+
18
+ <style>
19
+
20
+ </style>
21
+ </head>
22
+ <body>
23
+
24
+ <div id="wrapper">
25
+
26
+ <header>
27
+ <h1>rffw</h1>
28
+ <h2>Recive files from webserver</h2>
29
+ </header>
30
+ <section class="center">
31
+ <p>
32
+ THE_BODYer
33
+ </p>
34
+ </section>
35
+ <div id="push"></div>
36
+ </div>
37
+
38
+ <footer>
39
+ <p>You can conact me at <a href="mailto:guillermo@cientifico.net">guillermo@cientifico.net</a>.</p>
40
+ </footer>
41
+ </body>
42
+ </html>
@@ -0,0 +1,19 @@
1
+ require 'dbm'
2
+ require 'yaml'
3
+
4
+ class RFFW::App::Db < DBM
5
+
6
+ class OnlyHashAllowed < StandardError ; end
7
+
8
+ EMPTY_MARSHAKED_HASH = Marshal.dump({})
9
+
10
+ def [](key)
11
+ value = Marshal.load(super(key) || EMPTY_MARSHAKED_HASH)
12
+ value.is_a?(Hash) ? value : {}
13
+ end
14
+
15
+ def []=(key,value)
16
+ raise OnlyHashAllowed unless value.is_a?(Hash)
17
+ super(key, Marshal.dump(value))
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ module RFFW::App::DescriptionHandler
2
+ include RFFW::Parser
3
+ include RFFW::App
4
+
5
+ def description_handle(request)
6
+ Record.update_or_create_by_id(request.query, request.post_form_data)
7
+ to_path = "/show?#{request.query}"
8
+ HttpResponse.new("Redirect to #{to_path}", 302, {"Location" => to_path})
9
+ end
10
+
11
+
12
+ end
@@ -0,0 +1,36 @@
1
+ module RFFW::App::DirHandler
2
+ include RFFW::Parser
3
+
4
+ def dir_handle(request)
5
+ file = request.path == '/' ? '/index.html' : request.path
6
+ if file = file_info(file)
7
+ mime, content = file
8
+ HttpResponse.new(content, 200, {"Content-Type" => mime}, request.keep_alive? ? "1.1" : "1.0")
9
+ else
10
+ HttpResponse.new("File not found", 404)
11
+ end
12
+ end
13
+
14
+ protected
15
+
16
+ def file_info(file)
17
+ file_path = File.expand_path("../data/#{file}",__FILE__)
18
+ if File.file?(file_path)
19
+ content = File.read(file_path)
20
+ mime = get_mime(file_path)
21
+ [mime,content]
22
+ else
23
+ nil
24
+ end
25
+ end
26
+
27
+ def get_mime(file)
28
+ case file.split('.').last.downcase
29
+ when 'png' then 'image/png'
30
+ when 'html' then 'text/html'
31
+ when 'js' then 'application/javascript'
32
+ when 'css' then 'text/css'
33
+ else 'text/html'
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+ class RFFW::App::Record
2
+
3
+ ATTRIBUTES = %w(mime_type filename description)
4
+
5
+ attr_reader :id
6
+ attr_accessor :attributes
7
+
8
+ def initialize(id, hash = {})
9
+ @id = id
10
+ @attributes = hash
11
+ end
12
+
13
+ def new?
14
+ RFFW::App.db[id].empty?
15
+ end
16
+
17
+ def self.find_by_id(id)
18
+ new(id, RFFW::App.db[id])
19
+ end
20
+
21
+ def self.update_or_create_by_id(id, hash, body = nil)
22
+ find_by_id(id).tap{ |record|
23
+ record.body = body unless body.nil?
24
+ record.attributes = record.attributes.merge(hash) unless hash.nil?
25
+ RFFW::App.db[id] = record.attributes
26
+ }
27
+ end
28
+
29
+ def body=(body)
30
+ File.open(@id,'w'){|f| f.write body}
31
+ end
32
+
33
+ ATTRIBUTES.each do |attr_name|
34
+ define_method(attr_name.to_sym) do
35
+ @attributes[attr_name]
36
+ end
37
+ end
38
+
39
+
40
+ def body
41
+ File.read(@id) if File.file?(@id)
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ module RFFW::App::ShowHandler
2
+ include RFFW::Parser
3
+ include RFFW::App
4
+ include RFFW::App::ViewHelpers
5
+
6
+ def show_handle(request)
7
+ id, options = request.query.split("&")
8
+ record = Record.find_by_id(id) unless id.nil?
9
+ return HttpResponse.new(in_template("not found"), 404) if !record || record.new?
10
+
11
+ if options == "download"
12
+ HttpResponse.new(record.body.force_encoding("BINARY"), 200, {"Content-Type" => record.mime_type})
13
+ else
14
+ body = "<h1><a href=\"/show?#{record.id}&download\">#{record.filename}</a></h1><p>#{strip_tags(uri_unescape(record.description))}</p>"
15
+ HttpResponse.new(in_template(body))
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def in_template(content)
22
+ File.read(File.expand_path("../data/template.html",__FILE__)).gsub("THE_BODYer", content)
23
+ end
24
+
25
+ end
@@ -0,0 +1,32 @@
1
+ module RFFW::App::UploadHandler
2
+ include RFFW::Parser
3
+ include RFFW::App
4
+
5
+ def upload_handle(request)
6
+ if request.query.nil? || request.query.empty?
7
+ HttpResponse.new("File not found", 404)
8
+ else
9
+ id = request.query
10
+ attachment = request.attachments.first
11
+ if attachment
12
+ Record.update_or_create_by_id(id, {"mime_type" => attachment.content_type, "filename" => attachment.filename}, attachment.to_s)
13
+ HttpResponse.new("So... Ok. Excelent.",202)
14
+ else
15
+ HttpResponse.new("415 Unsupported Media Type", 415)
16
+ end
17
+ end
18
+ end
19
+
20
+ def uploading_data?
21
+ request && request.post? && request.path == "/upload"
22
+ end
23
+
24
+ def uploads_for_query(query)
25
+ self.class.select do |socket|
26
+ socket.respond_to?(:uploading_data?) &&
27
+ socket.uploading_data? &&
28
+ socket.request.query == query
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,40 @@
1
+ module RFFW::App::UploadStatusHandler
2
+ include RFFW::Parser
3
+ include RFFW::App::UploadHandler
4
+
5
+ def upload_status_handle(request)
6
+ uploads = uploads_for_id(request.query)
7
+
8
+ attributes = Record.find_by_id(request.query).attributes || {}
9
+ attributes["progress"] = uploads.first.request.upload_progress if uploads.any?
10
+
11
+ if attributes.keys.any?
12
+ HttpResponse.new(hash_to_json(attributes).to_s, 200)
13
+ else
14
+ HttpResponse.new("Not found upload.", 404)
15
+ end
16
+ end
17
+
18
+
19
+ protected
20
+
21
+ def hash_to_json(hash)
22
+ values = hash.map{|k,v| %{"#{escape_json(k.to_s)}": "#{escape_json(v.to_s)}"} }.join(", ")
23
+ "{ #{values} }"
24
+ end
25
+
26
+ def escape_json(code)
27
+ code.gsub('"','\"')
28
+ end
29
+
30
+ def uploads_for_id(id)
31
+ RFFW::App::AppHandler.select do |connection|
32
+ connection.is_a?(RFFW::App::AppHandler) &&
33
+ connection.respond_to?(:request) &&
34
+ connection.request &&
35
+ connection.request.post? &&
36
+ connection.request.path == "/upload" &&
37
+ connection.request.query == request.query
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,224 @@
1
+
2
+ !
3
+ "
4
+ #
5
+ $
6
+ %
7
+ &
8
+ '
9
+ (
10
+ )
11
+ *
12
+ +
13
+ ,
14
+ -
15
+ .
16
+ /
17
+ 0
18
+ 1
19
+ 2
20
+ 3
21
+ 4
22
+ 5
23
+ 6
24
+ 7
25
+ 8
26
+ 9
27
+ :
28
+ ;
29
+ <
30
+ =
31
+ >
32
+ ?
33
+ @
34
+ A
35
+ B
36
+ C
37
+ D
38
+ E
39
+ F
40
+ G
41
+ H
42
+ I
43
+ J
44
+ K
45
+ L
46
+ M
47
+ N
48
+ O
49
+ P
50
+ Q
51
+ R
52
+ S
53
+ T
54
+ U
55
+ V
56
+ W
57
+ X
58
+ Y
59
+ Z
60
+ [
61
+ \
62
+ ]
63
+ ^
64
+ _
65
+ `
66
+ a
67
+ b
68
+ c
69
+ d
70
+ e
71
+ f
72
+ g
73
+ h
74
+ i
75
+ j
76
+ k
77
+ l
78
+ m
79
+ n
80
+ o
81
+ p
82
+ q
83
+ r
84
+ s
85
+ t
86
+ u
87
+ v
88
+ w
89
+ x
90
+ y
91
+ z
92
+ {
93
+ |
94
+ }
95
+ ~
96
+
97
+
98
+
99
+
100
+ ƒ
101
+
102
+
103
+
104
+
105
+ ˆ
106
+
107
+ Š
108
+
109
+ Œ
110
+
111
+ Ž
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+ ˜
122
+
123
+ š
124
+
125
+ œ
126
+
127
+ ž
128
+ Ÿ
129
+
130
+ ¡
131
+ ¢
132
+ £
133
+
134
+ ¥
135
+ |
136
+ §
137
+ ¨
138
+ ©
139
+ ª
140
+ «
141
+ ¬
142
+ ¯
143
+ ®
144
+ ¯
145
+ °
146
+ ±
147
+ ²
148
+ ³
149
+ ´
150
+ µ
151
+
152
+ ·
153
+ ¸
154
+ ¹
155
+ º
156
+ »
157
+ ¼
158
+ ½
159
+ ¾
160
+ ¿
161
+ À
162
+ Á
163
+ Â
164
+ Ã
165
+ Ä
166
+ Å
167
+ Æ
168
+ Ç
169
+ È
170
+ É
171
+ Ê
172
+ Ë
173
+ Ì
174
+ Í
175
+ Î
176
+ Ï
177
+ Ð
178
+ Ñ
179
+ Ò
180
+ Ó
181
+ Ô
182
+ Õ
183
+ Ö
184
+
185
+ Ø
186
+ Ù
187
+ Ú
188
+ Û
189
+ Ü
190
+ Ý
191
+ Þ
192
+ ß
193
+ à
194
+ á
195
+ â
196
+ ã
197
+ ä
198
+ å
199
+ æ
200
+ ç
201
+ è
202
+ é
203
+ ê
204
+ ë
205
+ ì
206
+ í
207
+ î
208
+ ï
209
+ ð
210
+ ñ
211
+ ò
212
+ ó
213
+ ô
214
+ õ
215
+ ö
216
+ ÷
217
+ ø
218
+ ù
219
+ ú
220
+ û
221
+ ü
222
+ ý
223
+ þ
224
+ ÿ