///! FastCGI script that displays a thank-you page with a link to download a
///! custom-generated license.
// Copyright (c) 2018 Teddy Wing
//
// This file is part of DomeKey Web.
//
// DomeKey Web is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// DomeKey Web is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with DomeKey Web. If not, see
// .
extern crate aquatic_prime;
extern crate fastcgi;
extern crate exitcode;
#[macro_use]
extern crate log;
extern crate mysql;
#[macro_use]
extern crate serde_derive;
extern crate license_generator;
use std::borrow::Cow;
use std::io::{Cursor, Read, Write};
use aquatic_prime::AquaticPrime;
use license_generator::database;
use license_generator::errors::*;
use license_generator::logger;
use license_generator::params;
use license_generator::response;
use license_generator::zip;
const PUBLIC_KEY: &'static str = include_str!("../../private/public_key.txt");
const PRIVATE_KEY: &'static str = include_str!("../../private/private_key.txt");
#[derive(Serialize)]
struct LicenseData<'a> {
#[serde(rename = "Name")]
name: &'a str,
#[serde(rename = "Email")]
email: &'a str,
}
trait LicenseValidationResponse {
fn success(&mut self, name: &str, email: &str, secret: &str);
fn error_400(&mut self);
fn error_404(&mut self);
fn error_500(&mut self, error: Option);
}
struct HtmlResponse<'a, W: 'a> {
writer: &'a mut W,
}
impl<'a, W> LicenseValidationResponse for HtmlResponse<'a, W>
where W: 'a + Write {
fn success(&mut self, name: &str, email: &str, secret: &str) {
write!(
self.writer,
"Status: 200
Content-Type: text/html\n\n{}",
format!(
include_str!("../../../thank-you-license-download.html"),
name = name,
email = email,
secret = secret,
)
).unwrap_or(())
}
fn error_400(&mut self) {
let page_400 = include_str!("../../../400.html");
response::set_400(self.writer)
.and_then(|_|
Ok(write!(self.writer, "Content-Type: text/html\n\n{}", page_400)?)
).unwrap_or(())
}
fn error_404(&mut self) {
let page_404 = include_str!("../../../404.html");
response::set_404(self.writer)
.and_then(|_|
Ok(write!(self.writer, "Content-Type: text/html\n\n{}", page_404)?)
).unwrap_or(())
}
fn error_500(&mut self, error: Option) {
if let Some(error) = error {
error!("{}", error);
}
let page_500 = include_str!("../../../internal_error.html");
response::set_500(self.writer)
.and_then(|_|
Ok(write!(self.writer, "Content-Type: text/html\n\n{}", page_500)?)
).unwrap_or(())
}
}
struct ZipResponse<'a, W: 'a> {
writer: &'a mut W,
}
impl<'a, W> LicenseValidationResponse for ZipResponse<'a, W>
where W: 'a + Write {
fn success(&mut self, name: &str, email: &str, _secret: &str) {
let license_data = LicenseData {
name: &name,
email: &email,
};
let aquatic_prime = AquaticPrime::new(&PUBLIC_KEY, &PRIVATE_KEY);
let license = match aquatic_prime.plist(license_data) {
Ok(p) => p,
Err(e) => return self.error_500(Some(e.into())),
};
let mut zip_data = Cursor::new(vec![]);
match zip::license(&mut zip_data, license.as_bytes()) {
Ok(p) => p,
Err(e) => return self.error_500(Some(e.into())),
}
write!(self.writer, "Content-Type: application/zip
Content-Disposition: attachment; filename=\"dome-key-license.zip\"\n\n")
.and_then(|_|
self.writer.write_all(&zip_data.into_inner())
).unwrap_or(());
}
fn error_400(&mut self) {
response::error_400(self.writer);
}
fn error_404(&mut self) {
response::error_404(self.writer);
}
fn error_500(&mut self, error: Option) {
response::error_500(self.writer, error)
}
}
fn query_purchaser(
cx: &mut mysql::PooledConn,
name: &str,
email: &str,
secret: &str,
) -> Result