726fcf8e0707c7dd70f01640540c6b1355d0cb50
4 extern crate percent_encoding
;
6 use listenfd
::ListenFd
;
8 use actix_web
::{ get
, web
, Responder
, middleware
, App
, HttpServer
, HttpRequest
, HttpResponse
, web
::Query
};
11 use std
::{ sync
::Mutex
, fs
::File
, path
::Path
, env
::args
, io
::prelude
::* };
12 use ron
::{ de
::from_reader
, ser
::{ to_string_pretty
, PrettyConfig
} };
13 use serde
::{ Deserialize
, Serialize
};
15 use itertools
::Itertools
;
23 #[template(path = "main.html")]
28 #[derive(Deserialize)]
34 async
fn main_page(key_shared
: web
::Data
<Mutex
<String
>>, query
: Query
<Request
>) -> impl Responder
{
35 let key
= key_shared
.lock().unwrap();
40 match crypto
::decrypt(&*key
, b
) {
42 Err(_e
) => String
::from(consts
::DEFAULT_MESSAGE
) // TODO: log error.
44 None
=> String
::from(consts
::DEFAULT_MESSAGE
)
47 MainTemplate
{ sentence
: m
}
50 #[derive(Debug, Deserialize, Serialize)]
55 const DEFAULT_CONFIG
: Config
= Config
{ port
: 8082 };
57 fn get_exe_name() -> String
{
58 let first_arg
= std
::env
::args().next().unwrap();
59 let sep
: &[_
] = &['
\\'
, '
/'
];
60 first_arg
[first_arg
.rfind(sep
).unwrap()+1..].to_string()
63 fn load_config() -> Config
{
64 // unwrap_or_else(|_| panic!("Failed to open configuration file {}", consts::FILE_CONF));
65 match File
::open(consts
::FILE_CONF
) {
66 Ok(file
) => from_reader(file
).unwrap_or_else(|_
| panic!("Failed to open configuration file {}", consts
::FILE_CONF
)),
68 let mut file
= File
::create(consts
::FILE_CONF
) .unwrap();
69 file
.write_all(to_string_pretty(&DEFAULT_CONFIG
, PrettyConfig
::new()).unwrap().as_bytes()).unwrap(); // We do not use 'to_writer' because it can't pretty format the output.
75 fn read_key() -> String
{
76 let mut key
= String
::new();
77 File
::open(consts
::FILE_KEY
)
78 .unwrap_or_else(|_
| panic!("Failed to open key file: {}", consts
::FILE_KEY
))
79 .read_to_string(&mut key
)
80 .unwrap_or_else(|_
| panic!("Failed to read key file: {}", consts
::FILE_KEY
));
83 percent_encoding
::percent_decode(key
.replace('
\n'
, "").as_bytes())
85 .unwrap_or_else(|_
| panic!("Failed to decode key file: {}", consts
::FILE_KEY
))
89 fn write_key(key
: &str) {
90 let percent_encoded
= percent_encoding
::utf8_percent_encode(key
, percent_encoding
::NON_ALPHANUMERIC
).to_string();
91 let mut file
= File
::create(consts
::FILE_KEY
).unwrap();
92 file
.write_all(percent_encoded
.as_bytes()).unwrap();
96 async
fn main() -> std
::io
::Result
<()> {
98 // If the key file doesn't exist then create a new one with a random key in it.
99 if !Path
::new(consts
::FILE_KEY
).exists() {
100 let new_key
= crypto
::generate_key();
102 println!("A key has been generated here: {}", consts
::FILE_KEY
);
109 if process_args(&key
) { return Ok(()) }
111 println!("Starting RUP as web server...");
113 let config
= load_config();
115 println!("Configuration: {:?}", config
);
117 let key_shared
= web
::Data
::new(Mutex
::new(key
));
119 let mut listenfd
= ListenFd
::from_env();
124 .app_data(key_shared
.clone())
125 .wrap(middleware
::Compress
::default())
126 .wrap(middleware
::Logger
::default())
128 .service(fs
::Files
::new("/static", "static").show_files_listing())
133 if let Some(l
) = listenfd
.take_tcp_listener(0).unwrap() {
134 server
.listen(l
).unwrap()
136 server
.bind(&format!("0.0.0.0:{}", config
.port
)).unwrap()
142 fn process_args(key
: &str) -> bool
{
145 println!(" {} [--help] [--encrypt <plain-text> | --decrypt <cipher-text>]", get_exe_name());
148 let args
: Vec
<String
> = args().collect();
150 if args
.iter().any(|arg
| arg
== "--help") {
153 } else if let Some((position_arg_encrypt
, _
)) = args
.iter().find_position(|arg
| arg
== &"--encrypt") {
154 match args
.get(position_arg_encrypt
+ 1) {
155 Some(mess_to_encrypt
) => {
156 // Encrypt to version 2 (version 1 is obsolete).
157 match crypto
::encrypt(&key
, mess_to_encrypt
, 2) {
158 Ok(encrypted_mess
) => {
159 let encrypted_mess_encoded
= percent_encoding
::utf8_percent_encode(&encrypted_mess
, percent_encoding
::NON_ALPHANUMERIC
).to_string();
160 println!("Encrypted message percent-encoded: {}", encrypted_mess_encoded
); },
162 println!("Unable to encrypt: {:?}", error
)
165 None
=> print_usage()
169 } else if let Some((position_arg_decrypt
, _
)) = args
.iter().find_position(|arg
| arg
== &"--decrypt") {
170 match args
.get(position_arg_decrypt
+ 1) {
171 Some(cipher_text
) => {
172 let cipher_text_decoded
= percent_encoding
::percent_decode(cipher_text
.as_bytes()).decode_utf8().expect("Unable to decode encoded cipher text");
173 match crypto
::decrypt(&key
, &cipher_text_decoded
) {
175 println!("Decrypted message: {}", plain_text
),
177 println!("Unable to decrypt: {:?}", error
)
180 None
=> print_usage()