Read and decode key file
[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 <message>]", get_exe_name());
66 }
67
68 fn read_key() -> String {
69 use url::percent_encoding::percent_decode;
70 let mut key = String::new();
71 File::open(consts::FILE_KEY)
72 .expect(&format!("Failed to open key file: {}", consts::FILE_KEY))
73 .read_to_string(&mut key)
74 .expect(&format!("Failed to read key file: {}", consts::FILE_KEY));
75
76 String::from(
77 percent_decode(key.as_bytes())
78 .decode_utf8()
79 .expect(&format!("Failed to decode key file: {}", consts::FILE_KEY))
80 )
81 }
82
83 fn main() -> std::io::Result<()> {
84 let args: Vec<String> = args().collect();
85
86 let key = read_key();
87
88 if args.iter().any(|arg| arg == "--help") {
89 print_usage();
90 return Ok(());
91 } else if let Some((position_arg_encrypt, _)) = args.iter().find_position(|arg| arg == &"--encrypt") {
92 match args.iter().nth(position_arg_encrypt + 1) {
93 Some(mess_to_encrypt) => {
94 let encrypted_mess = crypto::encrypt(&key, mess_to_encrypt);
95 println!("Encrypted message: {}", encrypted_mess);
96 }
97 None => print_usage()
98 }
99
100 return Ok(());
101 }
102
103 println!("Starting RUP as web server...");
104
105 let config: Config = {
106 let f = File::open(consts::FILE_CONF).expect(&format!("Failed to open configuration file {}", consts::FILE_CONF));
107 match from_reader(f) {
108 Ok(c) => c,
109 Err(e) => panic!("Failed to load config: {}", e)
110 }
111 };
112
113 println!("Configuration: {:?}", config);
114
115 let mut listenfd = ListenFd::from_env();
116 let mut server =
117 HttpServer::new(
118 || {
119 App::new()
120 .wrap(middleware::Compress::default())
121 .wrap(middleware::Logger::default())
122 .service(web::resource("/").to(main_page))
123 .service(fs::Files::new("/static", "static").show_files_listing())
124 }
125 );
126
127 server =
128 if let Some(l) = listenfd.take_tcp_listener(0).unwrap() {
129 server.listen(l).unwrap()
130 } else {
131 server.bind(&format!("0.0.0.0:{}", config.port)).unwrap()
132 };
133
134 server.run()
135 }