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.
- data/.gitignore +5 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.md +60 -0
- data/Rakefile +41 -0
- data/bin/rffw +16 -0
- data/lib/rffw.rb +7 -0
- data/lib/rffw/app.rb +36 -0
- data/lib/rffw/app/app_handler.rb +59 -0
- data/lib/rffw/app/data/images/bg.png +0 -0
- data/lib/rffw/app/data/index.html +56 -0
- data/lib/rffw/app/data/javascripts/application.js +110 -0
- data/lib/rffw/app/data/stylesheets/style.css +338 -0
- data/lib/rffw/app/data/template.html +42 -0
- data/lib/rffw/app/db.rb +19 -0
- data/lib/rffw/app/description_handler.rb +12 -0
- data/lib/rffw/app/dir_handler.rb +36 -0
- data/lib/rffw/app/record.rb +43 -0
- data/lib/rffw/app/show_handler.rb +25 -0
- data/lib/rffw/app/upload_handler.rb +32 -0
- data/lib/rffw/app/upload_status_handler.rb +40 -0
- data/lib/rffw/app/urlencode_chars.data +224 -0
- data/lib/rffw/app/view_helpers.rb +30 -0
- data/lib/rffw/parser.rb +9 -0
- data/lib/rffw/parser/http_request.rb +137 -0
- data/lib/rffw/parser/http_response.rb +29 -0
- data/lib/rffw/parser/mime_parser.rb +46 -0
- data/lib/rffw/server.rb +15 -0
- data/lib/rffw/server/buffered_client.rb +57 -0
- data/lib/rffw/server/client.rb +53 -0
- data/lib/rffw/server/http_client.rb +49 -0
- data/lib/rffw/server/server.rb +46 -0
- data/lib/rffw/version.rb +3 -0
- data/rffw.db +0 -0
- data/rffw.gemspec +21 -0
- data/test/fixtures/image.jpg +0 -0
- data/test/fixtures/mime_image.data +0 -0
- data/test/fixtures/mime_image.png +0 -0
- data/test/fixtures/post_form_data.http +14 -0
- data/test/fixtures/raw_request.txt +8 -0
- data/test/fixtures/request.http +9 -0
- data/test/fixtures/upload.http +0 -0
- data/test/fixtures/upload_status_request.http +10 -0
- data/test/helper.rb +97 -0
- data/test/test_buffered_client.rb +50 -0
- data/test/test_client.rb +47 -0
- data/test/test_db.rb +21 -0
- data/test/test_http_client.rb +26 -0
- data/test/test_http_request.rb +52 -0
- data/test/test_mime_parser.rb +22 -0
- data/test/test_record.rb +49 -0
- data/test/test_upload_status_handler.rb +18 -0
- data/test/test_uploader_handler.rb +10 -0
- data/test/test_view_helpers.rb +24 -0
- metadata +122 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.2
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
RFFW
|
2
|
+
====
|
3
|
+
|
4
|
+
Recive File From Web Server
|
5
|
+
|
6
|
+
|
7
|
+
USAGE
|
8
|
+
=====
|
9
|
+
|
10
|
+
rffw [(--port|-p) 8080] [(-l|--listen) 127.0.0.1]
|
11
|
+
|
12
|
+
|
13
|
+
INTERNALS
|
14
|
+
=========
|
15
|
+
|
16
|
+
* HTML:
|
17
|
+
_ There is two forms. One for description, and one for the input file.
|
18
|
+
- #input_file_submit.onchange => submit with form[target=hidden_iframe]
|
19
|
+
- On load, generate a random uuid, and assign that uuid to the input and
|
20
|
+
description.
|
21
|
+
- Delay each upload progress check 20 ms after the last one check.
|
22
|
+
- There is no index view.
|
23
|
+
- There seems to be a bug, that causes google chrome to upload the same file
|
24
|
+
twice at the same time.
|
25
|
+
|
26
|
+
* Server (Just a mini abstraction of kernel.select and socket)
|
27
|
+
- Server: Kernel.select.
|
28
|
+
- Client: Kind of overload Socket through delegation.
|
29
|
+
- BufferedClient: Overloads Client to add cache in disk the requests.
|
30
|
+
- HttpClient: Overloads BufferedClient to understand http connections.
|
31
|
+
|
32
|
+
* App
|
33
|
+
- AppHandler: Overloads HttpClient, and acts as an app router.
|
34
|
+
- (DescriptionHandler | ShowHandler | UploadHandler | UploadStatusHandler |
|
35
|
+
DirHandler: Like http actions. They are modules included in AppHandler.
|
36
|
+
- ViewHelpers.
|
37
|
+
- data: html/js/css/img
|
38
|
+
- Db: Overloads DBM. Used as a backend.
|
39
|
+
- Record: Abstraction of Db.
|
40
|
+
* Parser
|
41
|
+
- HttpRequest: StringScanner http request parsers.
|
42
|
+
- HttpRespone: Well... not a parser it self, it generate http responses.
|
43
|
+
- MimeParser: Process Mime attachments.
|
44
|
+
|
45
|
+
USED LIBRARIES
|
46
|
+
==============
|
47
|
+
|
48
|
+
* Ruby: TempDir
|
49
|
+
* Ruby: TCPServer
|
50
|
+
* Ruby: TCPClient
|
51
|
+
* Ruby: Kernel.select
|
52
|
+
|
53
|
+
|
54
|
+
TEST
|
55
|
+
====
|
56
|
+
* The tests, that not cover the full code, were just used as a tool for
|
57
|
+
helping me to develop the code itself. More were written before the code.
|
58
|
+
|
59
|
+
|
60
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << "test"
|
7
|
+
t.test_files = FileList['test/test*.rb']
|
8
|
+
t.verbose = false
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default do
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'rubygems'
|
15
|
+
gem 'minitest'
|
16
|
+
require 'minitest/pride'
|
17
|
+
rescue LoadError, Gem::LoadError
|
18
|
+
$stderr.puts "Minitest gem not found. Usign ruby minitest."
|
19
|
+
end
|
20
|
+
|
21
|
+
base = File.expand_path("..", __FILE__)
|
22
|
+
$:.unshift File.join(base,"lib")
|
23
|
+
$:.unshift File.join(base,'test')
|
24
|
+
Dir[File.expand_path("../test/test_*", __FILE__)].each{|f| require f}
|
25
|
+
MiniTest::Unit.autorun
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Run the server"
|
30
|
+
task :run do
|
31
|
+
exec("ruby -rubygems -I lib bin/rffw")
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
task :commit do
|
36
|
+
system("git add . && git commit -m 'WIP' && git push origin master:master")
|
37
|
+
end
|
38
|
+
|
39
|
+
task :deploy => [:commit] do
|
40
|
+
system(%{ssh soundcloud "sudo su - guillermo ; cd rffw && git pull && sudo killall "})
|
41
|
+
end
|
data/bin/rffw
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rffw'
|
4
|
+
|
5
|
+
params = ARGV.join(" ")
|
6
|
+
|
7
|
+
port = (params[/((\-\-port|\-p) (\d+))/,3] || 8080).to_i
|
8
|
+
listen = (params[/((\-l|\-\-listen) ((\d+)\.(\d+)\.(\d+)\.(\d+)))/,3] || "0.0.0.0").to_i
|
9
|
+
|
10
|
+
if params[/(-h|--help)/]
|
11
|
+
$stderr.puts "#{$0} [(-p|--port) port_number] [(-l|--listen) ip]"
|
12
|
+
$stderr.puts ""
|
13
|
+
exit(-1)
|
14
|
+
end
|
15
|
+
|
16
|
+
RFFW::App.start(port,listen)
|
data/lib/rffw.rb
ADDED
data/lib/rffw/app.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
module RFFW
|
3
|
+
module App
|
4
|
+
require 'rffw/app/db'
|
5
|
+
require 'rffw/app/record'
|
6
|
+
|
7
|
+
require 'rffw/app/view_helpers'
|
8
|
+
require 'rffw/app/upload_handler'
|
9
|
+
require 'rffw/app/upload_status_handler'
|
10
|
+
require 'rffw/app/dir_handler'
|
11
|
+
require 'rffw/app/description_handler'
|
12
|
+
require 'rffw/app/show_handler'
|
13
|
+
|
14
|
+
require 'rffw/app/app_handler'
|
15
|
+
|
16
|
+
def self.start(port = 8080, listen = "127.0.0.1", dir = Dir.pwd)
|
17
|
+
trap("SIGINT") { throw :ctrl_c }
|
18
|
+
@@dir = dir
|
19
|
+
start_db(@@dir)
|
20
|
+
server = RFFW::Server::Server.new( RFFW::App::AppHandler, port, listen )
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.start_db(dir)
|
24
|
+
@@db = Db.new(File.join(dir,'rffw'))
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.db
|
28
|
+
@@db
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.dir
|
32
|
+
@@dir
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module RFFW::App
|
2
|
+
class AppHandler < RFFW::Server::HttpClient
|
3
|
+
include RFFW::Server
|
4
|
+
include RFFW::App::DirHandler
|
5
|
+
include RFFW::App::UploadHandler
|
6
|
+
include RFFW::App::UploadStatusHandler
|
7
|
+
include RFFW::App::DescriptionHandler
|
8
|
+
include RFFW::App::ShowHandler
|
9
|
+
|
10
|
+
attr_reader :request
|
11
|
+
|
12
|
+
def on_data
|
13
|
+
super
|
14
|
+
if request && request.post? && request.path == '/upload'
|
15
|
+
memory_usage = `ps -o rss= -p #{$$}`.to_i
|
16
|
+
$stderr.puts "[#{memory_usage}kB] #{Time.now.utc} #{fileno} (#{self.class.all.size}) UPLOADING A FILE: #{request.upload_progress}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_request(r)
|
21
|
+
memory_usage = `ps -o rss= -p #{$$}`.to_i
|
22
|
+
$stderr.puts "[#{memory_usage}Kb] #{Time.now.utc} #{fileno} (#{self.class.all.size}) > <#{r.inspect}>"
|
23
|
+
|
24
|
+
response = case
|
25
|
+
when ! %w(get post).include?(r.method.downcase)
|
26
|
+
HttpResponse.new("Sorry! Method not allowed.", 405)
|
27
|
+
when r.method.downcase == 'get' && r.path == '/upload_status.js'
|
28
|
+
upload_status_handle(r)
|
29
|
+
when r.method.downcase == "post" && r.path == '/upload'
|
30
|
+
upload_handle(r)
|
31
|
+
when r.method.downcase == "post" && r.path == '/description'
|
32
|
+
description_handle(r)
|
33
|
+
when r.method.downcase == 'get' && r.path == '/show'
|
34
|
+
show_handle(r)
|
35
|
+
when r.method.downcase == "get"
|
36
|
+
dir_handle(r)
|
37
|
+
else
|
38
|
+
HttpResponse.new("No no no... Not found !", 404)
|
39
|
+
end
|
40
|
+
write response
|
41
|
+
|
42
|
+
rescue => e
|
43
|
+
$stderr.puts "#{e.message}\r\n#{e.inspect}\r\n#{e.backtrace.join("\n")}"
|
44
|
+
write HttpResponse.new("#{e.message}\r\n#{e.inspect}\r\n#{e.backtrace.join("\n")}", 505)
|
45
|
+
ensure
|
46
|
+
cleanup!
|
47
|
+
end
|
48
|
+
|
49
|
+
def cleanup!
|
50
|
+
disconeect! unless request.keep_alive?
|
51
|
+
@request = HttpRequest.new('')
|
52
|
+
clear_buffer
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
Binary file
|
@@ -0,0 +1,56 @@
|
|
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&v1' rel='stylesheet' type='text/css'>
|
13
|
+
<link href='http://fonts.googleapis.com/css?family=The+Girl+Next+Door&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
|
+
<form enctype="multipart/form-data" action="/upload" target="uploader" method="post" id="uploader_form">
|
33
|
+
<label>Select a file to upload
|
34
|
+
<input type="file" id="file_input" name="file" tabindex=1>
|
35
|
+
</label>
|
36
|
+
</form>
|
37
|
+
<iframe id="uploader" name="uploader"></iframe>
|
38
|
+
<p id="progress_bar">
|
39
|
+
<span id="porcentage">The progress is <b id="total_uploaded">80%</b>.</span>
|
40
|
+
</p>
|
41
|
+
<form action="/description" method="post" id="description_form">
|
42
|
+
<label>Description
|
43
|
+
<textarea name="description" placeholder="Write here a description" tabindex=2></textarea>
|
44
|
+
</label>
|
45
|
+
<input type="submit" value="Send the file" tabindex=3>
|
46
|
+
</form>
|
47
|
+
</p>
|
48
|
+
</section>
|
49
|
+
<div id="push"></div>
|
50
|
+
</div>
|
51
|
+
|
52
|
+
<footer>
|
53
|
+
<p>You can conact me at <a href="mailto:guillermo@cientifico.net">guillermo@cientifico.net</a>.</p>
|
54
|
+
</footer>
|
55
|
+
</body>
|
56
|
+
</html>
|
@@ -0,0 +1,110 @@
|
|
1
|
+
(function(){
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
Element.prototype.css = function(object){
|
7
|
+
for(property in object){
|
8
|
+
this.style.setProperty(property, object[property]);
|
9
|
+
}
|
10
|
+
};
|
11
|
+
|
12
|
+
Element.prototype.toggle = function(){
|
13
|
+
if (window.getComputedStyle(this, 'display') == "none"){
|
14
|
+
this.show();
|
15
|
+
} else {
|
16
|
+
this.hide();
|
17
|
+
}
|
18
|
+
};
|
19
|
+
|
20
|
+
|
21
|
+
Element.prototype.show = function(){
|
22
|
+
this.style.setProperty("display", "block");
|
23
|
+
};
|
24
|
+
|
25
|
+
Element.prototype.hide = function(){
|
26
|
+
this.style.setProperty("display", "none");
|
27
|
+
};
|
28
|
+
|
29
|
+
|
30
|
+
window.info = function(message){
|
31
|
+
var hover = document.getElementById('drop_the_file');
|
32
|
+
if (message == undefined){
|
33
|
+
hover.classList.remove("show");
|
34
|
+
|
35
|
+
}else{
|
36
|
+
hover.innerHTML = message;
|
37
|
+
hover.classList.add("show");
|
38
|
+
}
|
39
|
+
}
|
40
|
+
window.onload = function(){
|
41
|
+
|
42
|
+
function S4() {
|
43
|
+
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
44
|
+
}
|
45
|
+
function new_guid(){
|
46
|
+
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
47
|
+
}
|
48
|
+
|
49
|
+
document.getElementById("progress_bar").css({"display": "none"});
|
50
|
+
|
51
|
+
|
52
|
+
window.uuid = new_guid();
|
53
|
+
|
54
|
+
form = document.getElementById("uploader_form")
|
55
|
+
form.action = form.action+"?"+window.uuid;
|
56
|
+
|
57
|
+
description_form = document.getElementById("description_form")
|
58
|
+
description_form.action = description_form.action+"?"+window.uuid;
|
59
|
+
|
60
|
+
function check_status(){
|
61
|
+
setTimeout(function(){
|
62
|
+
var req = new XMLHttpRequest();
|
63
|
+
req.open('GET', '/upload_status.js?'+window.uuid, true);
|
64
|
+
req.onreadystatechange = function (aEvt) {
|
65
|
+
if (req.readyState == 4) {
|
66
|
+
if(req.status == 200){
|
67
|
+
|
68
|
+
record = JSON.parse(req.responseText);
|
69
|
+
if (record.progress){
|
70
|
+
var progress = record.progress.split("/");
|
71
|
+
d(progress)
|
72
|
+
var total = parseInt(progress[1]);
|
73
|
+
var partial = parseInt(progress[0]);
|
74
|
+
var porcentage = (100 * partial / total).toFixed();
|
75
|
+
if (porcentage > 100) porcentage = 100;
|
76
|
+
|
77
|
+
document.getElementById("porcentage").css({'width': porcentage+'%'});
|
78
|
+
document.getElementById("total_uploaded").innerHTML = porcentage+'%';
|
79
|
+
check_status();
|
80
|
+
} else {
|
81
|
+
document.getElementById("porcentage").css({'width': '100%'});
|
82
|
+
document.getElementById("total_uploaded").innerHTML = "Uploaded!"
|
83
|
+
}
|
84
|
+
}
|
85
|
+
else {
|
86
|
+
d("Error loading page\n");
|
87
|
+
}
|
88
|
+
}
|
89
|
+
};
|
90
|
+
req.send(null);
|
91
|
+
}, 200);
|
92
|
+
}
|
93
|
+
|
94
|
+
form.onchange = function(){
|
95
|
+
form.submit();
|
96
|
+
document.getElementById("file_input").css({"display": "none"});
|
97
|
+
document.getElementById("progress_bar").css({"display": "block"});
|
98
|
+
check_status();
|
99
|
+
};
|
100
|
+
|
101
|
+
window.d = function(msg){
|
102
|
+
window.console.debug(msg)
|
103
|
+
}
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
}
|
109
|
+
|
110
|
+
})();
|
@@ -0,0 +1,338 @@
|
|
1
|
+
/* @override http://localhost:8080/stylesheets/style.css?v=2 */
|
2
|
+
|
3
|
+
* {
|
4
|
+
font-family: 'Josefin Sans', arial, serif;
|
5
|
+
line-height: 16px;
|
6
|
+
font-size: 14px;
|
7
|
+
margin: 0;
|
8
|
+
padding: 0;
|
9
|
+
color: #002f2f;
|
10
|
+
font-weight: 300;
|
11
|
+
}
|
12
|
+
|
13
|
+
a {
|
14
|
+
-webkit-transition: all 0.2s ease-in-out;
|
15
|
+
-moz-transition: all 0.2s ease-in-out;
|
16
|
+
-o-transition: all 0.2s ease-in-out;
|
17
|
+
transition: all 0.2s ease-in-out;
|
18
|
+
}
|
19
|
+
|
20
|
+
html, body {
|
21
|
+
background: url("/images/bg.png"), #a7a37e;
|
22
|
+
height: 100%;
|
23
|
+
}
|
24
|
+
|
25
|
+
h1 {
|
26
|
+
font-family: 'The Girl Next Door', arial, serif;
|
27
|
+
}
|
28
|
+
|
29
|
+
header {
|
30
|
+
margin: 0 auto;
|
31
|
+
text-align: center;
|
32
|
+
display: block;
|
33
|
+
overflow: hidden;
|
34
|
+
padding-bottom: 12px;
|
35
|
+
}
|
36
|
+
header h1 {
|
37
|
+
padding-left: 12.5%;
|
38
|
+
padding-right: 12.5%;
|
39
|
+
font-size: 56px;
|
40
|
+
line-height: px;
|
41
|
+
margin-top: 32px;
|
42
|
+
}
|
43
|
+
header h2 {
|
44
|
+
font-size: 16px;
|
45
|
+
line-height: 16px;
|
46
|
+
color: #efecca;
|
47
|
+
}
|
48
|
+
|
49
|
+
#progress_bar {
|
50
|
+
background: red ;
|
51
|
+
width: 317px;
|
52
|
+
height: 39px;
|
53
|
+
margin: 0 auto;
|
54
|
+
|
55
|
+
-webkit-border-radius: 10px;
|
56
|
+
-moz-border-radius: 10px;
|
57
|
+
border-radius: 10px;
|
58
|
+
|
59
|
+
background: white;
|
60
|
+
background: white;
|
61
|
+
padding: 0;
|
62
|
+
position: relative;
|
63
|
+
}
|
64
|
+
|
65
|
+
#progress_bar span{
|
66
|
+
display: block;
|
67
|
+
background: #002f2f;
|
68
|
+
height: 39px;
|
69
|
+
width: 50%;
|
70
|
+
-webkit-border-radius: 10px;
|
71
|
+
-moz-border-radius: 10px;
|
72
|
+
border-radius: 10px;
|
73
|
+
|
74
|
+
transition: width 1s linear;
|
75
|
+
|
76
|
+
line-height: 200px;
|
77
|
+
overflow: hidden;
|
78
|
+
}
|
79
|
+
|
80
|
+
#progress_bar {
|
81
|
+
display: none;
|
82
|
+
}
|
83
|
+
#progress_bar span b{
|
84
|
+
position: absolute;
|
85
|
+
top: 0;
|
86
|
+
left: 0;
|
87
|
+
width: 317px;
|
88
|
+
text-align:center;
|
89
|
+
line-height: 39px;
|
90
|
+
vertical-align:middle;
|
91
|
+
font-size: 24px;
|
92
|
+
font-weight:bold;
|
93
|
+
text-shadow: white 0px 0px 2px;
|
94
|
+
}
|
95
|
+
/* Sticky Background */
|
96
|
+
#wrapper {
|
97
|
+
min-height: 100%;
|
98
|
+
height: auto !important;
|
99
|
+
height: 100%;
|
100
|
+
margin: 0 auto -112px;
|
101
|
+
}
|
102
|
+
|
103
|
+
footer, push {
|
104
|
+
height: 80px;
|
105
|
+
overflow: hidden;
|
106
|
+
}
|
107
|
+
|
108
|
+
/* end */
|
109
|
+
section {
|
110
|
+
display: block;
|
111
|
+
margin: 0 auto;
|
112
|
+
}
|
113
|
+
section.center {
|
114
|
+
max-width: 480px;
|
115
|
+
padding: 16px 80px;
|
116
|
+
position: relative;
|
117
|
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #efecca), color-stop(1, #a7a37e));
|
118
|
+
background: -moz-linear-gradient(top, #efecca, #a7a37e);
|
119
|
+
filter: progid:DXImageTransform.Microsoft.Gradient(endColorstr='$bg1', startColorstr='$bg2', gradientType='0');
|
120
|
+
text-align: center;
|
121
|
+
}
|
122
|
+
section.center h1 {
|
123
|
+
text-align: center;
|
124
|
+
font-size: 48px;
|
125
|
+
line-height: 48px;
|
126
|
+
}
|
127
|
+
section.center p {
|
128
|
+
text-align: justify;
|
129
|
+
font-size: 16px;
|
130
|
+
margin-bottom: 16px;
|
131
|
+
font-weight: 500;
|
132
|
+
text-shadow: #a7a37e 0.5px 0.5px 1px;
|
133
|
+
}
|
134
|
+
section.center p em {
|
135
|
+
font-weight: normal;
|
136
|
+
}
|
137
|
+
section.center p strong a, section.center p strong {
|
138
|
+
font-weight: 700;
|
139
|
+
}
|
140
|
+
section.center p a:active, section.center p a:focus {
|
141
|
+
background: #002f2f;
|
142
|
+
color: #a7a37e;
|
143
|
+
outline: 0;
|
144
|
+
text-decoration: none;
|
145
|
+
text-shadow: none;
|
146
|
+
}
|
147
|
+
section.center p a:hover {
|
148
|
+
text-decoration: none;
|
149
|
+
}
|
150
|
+
section.center img {
|
151
|
+
text-align: center;
|
152
|
+
display: block;
|
153
|
+
}
|
154
|
+
section.center h2 {
|
155
|
+
text-align: center;
|
156
|
+
font-size: 32px;
|
157
|
+
line-height: 32px;
|
158
|
+
}
|
159
|
+
section.list, section.posts {
|
160
|
+
background: url(/images/bg.png), #002f2f;
|
161
|
+
max-width: 100%;
|
162
|
+
padding: 32px 0 0;
|
163
|
+
text-align: center;
|
164
|
+
}
|
165
|
+
section.list h1, section.posts h1 {
|
166
|
+
color: #046380;
|
167
|
+
letter-spacing: 10px;
|
168
|
+
margin: 16px 0;
|
169
|
+
}
|
170
|
+
section.wide {
|
171
|
+
background: url(/images/bg.png), #002f2f;
|
172
|
+
width: 100%;
|
173
|
+
padding: 32px 0;
|
174
|
+
}
|
175
|
+
section.wide a {
|
176
|
+
color: #a7a37e;
|
177
|
+
}
|
178
|
+
section.wide > ul {
|
179
|
+
margin: 0 auto;
|
180
|
+
list-style: none;
|
181
|
+
text-align: center;
|
182
|
+
}
|
183
|
+
section.wide > ul li {
|
184
|
+
width: 320px;
|
185
|
+
vertical-align: top;
|
186
|
+
display: inline-block;
|
187
|
+
padding: 0 10px;
|
188
|
+
}
|
189
|
+
section.wide > ul li h1 {
|
190
|
+
text-align: center;
|
191
|
+
font-weight: 300;
|
192
|
+
margin-bottom: 32px;
|
193
|
+
}
|
194
|
+
section.wide > ul li h1 > a {
|
195
|
+
font-size: 40px;
|
196
|
+
line-height: 48px;
|
197
|
+
color: #046380;
|
198
|
+
text-decoration: none;
|
199
|
+
}
|
200
|
+
section.wide > ul li ul li {
|
201
|
+
margin-bottom: 8px;
|
202
|
+
}
|
203
|
+
section.wide > ul li ul, section.wide > ul li ul li, section.wide > ul li ul li a {
|
204
|
+
text-align: left;
|
205
|
+
font-size: 14px;
|
206
|
+
text-decoration: none;
|
207
|
+
color: #e6e2af;
|
208
|
+
}
|
209
|
+
|
210
|
+
#links, #posts {
|
211
|
+
max-width: 1040px;
|
212
|
+
list-style: none;
|
213
|
+
display: inline-block;
|
214
|
+
}
|
215
|
+
#links li, #posts li {
|
216
|
+
display: inline-block;
|
217
|
+
text-align: center;
|
218
|
+
}
|
219
|
+
#links a, #posts a {
|
220
|
+
text-decoration: none;
|
221
|
+
color: #e6e2af;
|
222
|
+
}
|
223
|
+
#links a:hover, #posts a:hover {
|
224
|
+
color: #a7a37e;
|
225
|
+
}
|
226
|
+
|
227
|
+
#links li {
|
228
|
+
width: 160px;
|
229
|
+
}
|
230
|
+
|
231
|
+
#posts li {
|
232
|
+
width: 240px;
|
233
|
+
}
|
234
|
+
|
235
|
+
em {
|
236
|
+
font-style: italic;
|
237
|
+
}
|
238
|
+
|
239
|
+
strong {
|
240
|
+
font-weight: 700;
|
241
|
+
}
|
242
|
+
|
243
|
+
footer {
|
244
|
+
background: url(/images/bg.png), #002f2f;
|
245
|
+
max-width: 100%;
|
246
|
+
padding: 32px 0 0;
|
247
|
+
text-align: center;
|
248
|
+
color: #a7a37e;
|
249
|
+
}
|
250
|
+
footer p {
|
251
|
+
padding: 32px 0;
|
252
|
+
}
|
253
|
+
footer a, footer p {
|
254
|
+
color: #a7a37e;
|
255
|
+
text-decoration: none;
|
256
|
+
}
|
257
|
+
footer a:hover {
|
258
|
+
color: #a7a37e;
|
259
|
+
}
|
260
|
+
|
261
|
+
|
262
|
+
iframe {
|
263
|
+
border: 0;
|
264
|
+
background: transparent;
|
265
|
+
}
|
266
|
+
|
267
|
+
section.center form {
|
268
|
+
font-size: 24px !important;
|
269
|
+
text-align: center;
|
270
|
+
}
|
271
|
+
section.center label {
|
272
|
+
font-size: 24px;
|
273
|
+
line-height: 36px;
|
274
|
+
text-align: center;
|
275
|
+
overflow:hidden;
|
276
|
+
}
|
277
|
+
|
278
|
+
section.center input{
|
279
|
+
font-size: 24px;
|
280
|
+
margin: 0 auto;
|
281
|
+
}
|
282
|
+
section.center input[type=file],
|
283
|
+
section.center textarea{
|
284
|
+
width: 300px;
|
285
|
+
background: white;
|
286
|
+
padding: 9px 5px 9px 12px;
|
287
|
+
line-height: 18px;
|
288
|
+
-webkit-border-radius: 10px;
|
289
|
+
-moz-border-radius: 10px;
|
290
|
+
border-radius: 10px;
|
291
|
+
|
292
|
+
border: 0px;
|
293
|
+
}
|
294
|
+
|
295
|
+
|
296
|
+
section.center input[type=file]:focus,
|
297
|
+
section.center textarea:focus{
|
298
|
+
border: 1px solid #002f2f;
|
299
|
+
outline: none;
|
300
|
+
margin: -1px;
|
301
|
+
}
|
302
|
+
|
303
|
+
|
304
|
+
section.center textarea{
|
305
|
+
width: 100%;
|
306
|
+
font-size: 24px;
|
307
|
+
height: 240px;
|
308
|
+
padding: 6px 5px;
|
309
|
+
line-height: 36px;
|
310
|
+
}
|
311
|
+
|
312
|
+
section.center iframe {
|
313
|
+
width: 0;
|
314
|
+
height: 0;
|
315
|
+
overflow: hidden;
|
316
|
+
}
|
317
|
+
|
318
|
+
section.center input[type=submit] {
|
319
|
+
width: 180px;
|
320
|
+
height: 40px;
|
321
|
+
padding: 20px;
|
322
|
+
margin: 24px 10px;
|
323
|
+
}
|
324
|
+
@media (max-width:640px) {
|
325
|
+
section.center {
|
326
|
+
padding: 16px 12.5%;
|
327
|
+
width: inherit;
|
328
|
+
max-width: inherit;
|
329
|
+
}
|
330
|
+
section.center img {
|
331
|
+
width: 100%;
|
332
|
+
}
|
333
|
+
|
334
|
+
}
|
335
|
+
|
336
|
+
|
337
|
+
|
338
|
+
|