b86ce5762185ed4e6c7683037f2b692f9620cf7d
[rup.git] / src / main.rs
1 extern crate actix_web;
2 extern crate listenfd;
3 extern crate askama;
4
5 use listenfd::ListenFd;
6 use actix_files as fs;
7 use actix_web::{web, middleware, App, HttpServer, HttpResponse, Responder, Result, web::Query};
8 use askama::Template;
9
10 use std::io::prelude::*;
11 use ron::de::from_reader;
12 use serde::Deserialize;
13 use std::{fs::File, env::args};
14
15 use itertools::Itertools;
16
17 mod consts;
18 mod crypto;
19
20 #[derive(Template)]
21 #[template(path = "main.html")]
22 struct MainTemplate<'a> {
23 sentence: &'a str,
24 }
25
26 #[derive(Deserialize)]
27 pub struct Request {
28 m: Option<String>
29 }
30
31 static DEFAULT_MESSAGE: &str = "Marc, roule un pet'!";
32 static KEY: &str = "secret";
33
34 fn main_page(query: Query<Request>) -> Result<HttpResponse> {
35 let m =
36 match &query.m {
37 Some(b) =>
38 match crypto::decrypt(KEY, b) {
39 Some(m) => m,
40 None => String::from(DEFAULT_MESSAGE)
41 },
42 None => String::from(DEFAULT_MESSAGE)
43 };
44
45 let hello = MainTemplate { sentence: &m };
46
47 let s = hello.render().unwrap();
48 Ok(HttpResponse::Ok().content_type("text/html").body(s))
49 }
50
51 #[derive(Debug, Deserialize)]
52 struct Config {
53 port: u16
54 }
55
56 fn get_exe_name() -> String {
57 let first_arg = std::env::args().nth(0).unwrap();
58 //dbg!(&first_arg);
59 let sep: &[_] = &['\\', '/'];
60 first_arg[first_arg.rfind(sep).unwrap()+1..].to_string()
61 }
62
63 fn print_usage() {
64 println!("Usage:");
65 println!(" {} [--help] [--encrypt <plain-text>|--decrypt <cipher-text>]", get_exe_name());
66 }
67
68 fn read_key() -> String {
69 let mut key = String::new();
70 File::open(consts::FILE_KEY)
71 .expect(&format!("Failed to open key file: {}", consts::FILE_KEY))
72 .read_to_string(&mut key)
73 .expect(&format!("Failed to read key file: {}", consts::FILE_KEY));
74
75 String::from(
76 url::percent_encoding::percent_decode(key.as_bytes())
77 .decode_utf8()
78 .expect(&format!("Failed to decode key file: {}", consts::FILE_KEY))
79 )
80 }
81
82 fn main() -> std::io::Result<()> {
83 let args: Vec<String> = args().collect();
84
85 let key = read_key();
86
87 if args.iter().any(|arg| arg == "--help") {
88 print_usage();
89 return Ok(());
90 } else if let Some((position_arg_encrypt, _)) = args.iter().find_position(|arg| arg == &"--encrypt") {
91 match args.iter().nth(position_arg_encrypt + 1) {
92 Some(mess_to_encrypt) => {
93
94 let encrypted_mess = crypto::encrypt(&key, mess_to_encrypt);
95 let encrypted_mess_encoded = url::percent_encoding::utf8_percent_encode(&encrypted_mess, url::percent_encoding::DEFAULT_ENCODE_SET).to_string();
96 println!("Encrypted message percent-encoded: {}", encrypted_mess_encoded);
97 }
98 None => print_usage()
99 }
100
101 return Ok(());
102 } else if let Some((position_arg_decrypt, _)) = args.iter().find_position(|arg| arg == &"--decrypt") {
103 match args.iter().nth(position_arg_decrypt + 1) {
104 Some(cipher_text) => {
105 let cipher_text_decoded = url::percent_encoding::percent_decode(cipher_text.as_bytes()).decode_utf8().expect("Unable to decode encoded cipher text");
106 let plain_text = crypto::decrypt(&key, &cipher_text_decoded).unwrap();
107 println!("Decrypted message: {}", plain_text);
108 }
109 None => print_usage()
110 }
111
112 return Ok(());
113 }
114
115 println!("Starting RUP as web server...");
116
117 let config: Config = {
118 let f = File::open(consts::FILE_CONF).expect(&format!("Failed to open configuration file {}", consts::FILE_CONF));
119 match from_reader(f) {
120 Ok(c) => c,
121 Err(e) => panic!("Failed to load config: {}", e)
122 }
123 };
124
125 println!("Configuration: {:?}", config);
126
127 let mut listenfd = ListenFd::from_env();
128 let mut server =
129 HttpServer::new(
130 || {
131 App::new()
132 .wrap(middleware::Compress::default())
133 .wrap(middleware::Logger::default())
134 .service(web::resource("/").to(main_page))
135 .service(fs::Files::new("/static", "static").show_files_listing())
136 }
137 );
138
139 server =
140 if let Some(l) = listenfd.take_tcp_listener(0).unwrap() {
141 server.listen(l).unwrap()
142 } else {
143 server.bind(&format!("0.0.0.0:{}", config.port)).unwrap()
144 };
145
146 server.run()
147 }