1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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
|
extern crate fastcgi;
#[macro_use]
extern crate log;
extern crate mysql;
extern crate simplelog;
extern crate license_generator;
use std::env;
use std::fs::OpenOptions;
use std::io::{Read, Write};
use simplelog::{Config, LevelFilter, WriteLogger};
use license_generator::database;
use license_generator::errors::*;
use license_generator::params;
use license_generator::purchaser::Purchaser;
use license_generator::request;
use license_generator::response;
fn log_request(req: &fastcgi::Request, post_params: &str) {
info!(
"{method} {path} {query} - {protocol} - {user_agent} - {remote_addr} | {forwarded_for} / {post_params}",
method = req.param("REQUEST_METHOD")
.unwrap_or("REQUEST_METHOD".into()),
path = req.param("SCRIPT_NAME")
.unwrap_or("SCRIPT_NAME".into()),
query = req.param("QUERY_STRING")
.unwrap_or("QUERY_STRING".into()),
protocol = req.param("SERVER_PROTOCOL")
.unwrap_or("SERVER_PROTOCOL".into()),
user_agent = req.param("HTTP_USER_AGENT")
.unwrap_or("HTTP_USER_AGENT".into()),
remote_addr = req.param("REMOTE_ADDR")
.unwrap_or("REMOTE_ADDR".into()),
forwarded_for = req.param("HTTP_X_FORWARDED_FOR")
.unwrap_or("HTTP_X_FORWARDED_FOR".into()),
post_params = post_params,
);
}
fn main() -> Result<()> {
let log_file_path = env::var("LOG_FILE")
.chain_err(|| "LOG_FILE environment variable not found")?;
let log_file = OpenOptions::new()
.append(true)
.create(true)
.open(log_file_path)?;
let mut log_config = Config::default();
log_config.time_format = Some("%+");
WriteLogger::init(LevelFilter::Info, log_config, log_file)?;
let mut cx = match database::get_database_connection()
.chain_err(|| "failed to create a database connection")
{
Ok(cx) => cx,
Err(e) => {
error!("{}", e);
return Err(e);
},
};
let test_purchaser = Purchaser::new("Shiki", "shiki@example.com");
match test_purchaser.insert(&mut cx) {
Ok(_) => (),
Err(e) => error!("{}", e),
}
fastcgi::run(|mut req| {
let mut params = String::new();
match req.stdin().read_to_string(&mut params) {
Ok(_) => (),
Err(e) => error!("{}", e),
}
log_request(&req, ¶ms);
match req.param("REQUEST_METHOD") {
Some(method) => {
if method != "POST" {
response::set_405(&mut req.stdout(), "POST")
.unwrap_or(());
write!(&mut req.stdout(), "Content-Type: text/plain
405 Method Not Allowed")
.unwrap_or(());
return;
}
},
None => {
response::set_500(&mut req.stdout()).unwrap_or(());
write!(&mut req.stdout(), "Content-Type: text/plain
500 Internal Server Error")
.unwrap_or(());
return;
},
};
let ps = params::parse(¶ms);
let is_verified = match request::verified(&ps) {
Ok(v) => v,
Err(e) => {
error!("{}", e);
response::set_500(&mut req.stdout()).unwrap_or(());
write!(&mut req.stdout(), "Content-Type: text/plain
500 Internal Server Error")
.unwrap_or(());
return;
},
};
if is_verified {
write!(&mut req.stdout(), "Content-Type: text/plain
200 OK")
.unwrap_or(());
return;
}
response::set_403(&mut req.stdout()).unwrap_or(());
write!(&mut req.stdout(), "Content-Type: text/plain
403 Forbidden: Invalid request signature")
.unwrap_or(());
});
Ok(())
}
|