aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2018-10-23 06:56:08 +0200
committerTeddy Wing2018-10-23 06:56:08 +0200
commitadc4a2f7a84967541d9da3c2f8edb2814a59ab59 (patch)
tree3c8a1afccbae5b2ea993912745733b5e7cf80f4a
parentaaca041a3eb0938ca00314aeb0ca1799d3804ba5 (diff)
downloaddome-key-map-adc4a2f7a84967541d9da3c2f8edb2814a59ab59.tar.bz2
trial: Implement `do_trial()`
This function serves as the entry point to all trial functionality. When called, it will try to determine the number of days remaining in the trial. * If the trial period is in progress, the number of days remaining will be printed. * If an error is encountered involving the trial file, or the trial has expired, an error message is printed and the program exits. * Finally, if an unrelated error occurs, print the error without exiting. Change `DateTime<Local>`s to `DateTime<FixedOffset>`s in order to have uniform date types. Otherwise we run into trouble when comparing dates and when querying functions with different date typs. TODO: This fails the tests (unless your local timezone is UTC presumably) because the local time gets stripped of its offset and the correct offset gets reapplied, incorrectly shifting the time. Figure out a way to have uniform datetime types without muffing up the timezone offsets.
-rw-r--r--Cargo.toml1
-rw-r--r--src/lib.rs1
-rw-r--r--src/trial.rs107
3 files changed, 90 insertions, 19 deletions
diff --git a/Cargo.toml b/Cargo.toml
index cf827ac..5867226 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,6 +9,7 @@ cocoa = "0.18.0"
combine = "3.4.0"
core-graphics = "0.17.2"
error-chain = "0.12.0"
+exitcode = "1.1.2"
foreign-types = "0.3.2"
getopts = "0.2.18"
libc = "0.2.43"
diff --git a/src/lib.rs b/src/lib.rs
index 27fc7a7..92399dc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,6 +10,7 @@ extern crate core_graphics;
#[macro_use]
extern crate error_chain;
+extern crate exitcode;
extern crate foreign_types;
extern crate getopts;
extern crate libc;
diff --git a/src/trial.rs b/src/trial.rs
index c37cd1f..5e398fe 100644
--- a/src/trial.rs
+++ b/src/trial.rs
@@ -3,6 +3,7 @@ use std::io::{self, Read, Write};
use std::result;
use chrono::{DateTime, FixedOffset, Local, TimeZone};
+use exitcode;
use magic_crypt::{self, MagicCrypt};
use xdg;
@@ -17,10 +18,47 @@ const KEY: &'static str = "TODO SECRET";
/// Entry point to the trial handler.
fn do_trial() {
+ // Try to read trial start from file
+ let date = match get_trial_start() {
+ Ok(date) => date,
+ Err(e) => {
+ match e.kind() {
+ ErrorKind::Io(e) if e.kind() == io::ErrorKind::NotFound =>
+ match initialize_trial_start() {
+ Ok(date) => date,
+ Err(e) => {
+ eprintln!("{}", e);
+ ::std::process::exit(exitcode::IOERR);
+ },
+ },
+ DurationError => return trial_expired(),
+ e => {
+ eprintln!("{}", e);
+ ::std::process::exit(exitcode::SOFTWARE);
+ },
+ }
+ }
+ };
+ // If the file doesn't exist, create it
+ // Print the number of days remaining
+ // If no more days remain, exit the program with error EX_NOPERM
+
+ match days_remaining_from_now(date) {
+ Ok(remaining) => print_trial_days(remaining),
+ DurationError => trial_expired(),
+ Err(e) => (),
+ }
+}
+
+fn trial_expired() {
+ println!("Your trial has expired");
+
+ ::std::process::exit(exitcode::NOPERM)
}
-fn initialize_trial_start() -> Result<()> {
- let encoded_time = encode_datetime(Local::now());
+fn initialize_trial_start() -> Result<DateTime<FixedOffset>> {
+ let now = datetime_local_to_fixed_offset(Local::now());
+ let encoded_time = encode_datetime(now);
let xdg_dirs = xdg::BaseDirectories::with_prefix("dome-key")
.chain_err(|| "failed to get XDG base directories")?;
@@ -32,7 +70,7 @@ fn initialize_trial_start() -> Result<()> {
.open(trial_path)
{
Ok(f) => Ok(f),
- Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return Ok(()),
+ Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return Ok(now),
Err(e) => Err(e),
}
.chain_err(|| "failed to create trial file")?;
@@ -40,7 +78,12 @@ fn initialize_trial_start() -> Result<()> {
write!(&mut trial_file, "{}", encoded_time)
.chain_err(|| "failed to write to trial file")?;
- Ok(())
+ Ok(now)
+}
+
+fn datetime_local_to_fixed_offset(d: DateTime<Local>) -> DateTime<FixedOffset> {
+ let offset = FixedOffset::from_offset(d.offset());
+ DateTime::<FixedOffset>::from_utc(d.naive_local(), offset)
}
/// Decrypts the time string from the trial file and returns it as a
@@ -60,11 +103,13 @@ fn get_trial_start() -> Result<DateTime<FixedOffset>> {
}
fn print_trial_days(days: u8) {
+ // TODO: Come up with a label
+ println!("{}", days);
}
fn days_remaining(
- start: DateTime<Local>,
- now: DateTime<Local>,
+ start: DateTime<FixedOffset>,
+ now: DateTime<FixedOffset>,
days_available: u8,
) -> result::Result<u8, DurationError> {
let duration = (now.date() - start.date()).num_days() as u8;
@@ -79,12 +124,16 @@ fn days_remaining(
}
fn days_remaining_from_now(
- start: DateTime<Local>
+ start: DateTime<FixedOffset>
) -> result::Result<u8, DurationError> {
- days_remaining(start, Local::now(), DAYS_REMAINING)
+ days_remaining(
+ start,
+ datetime_local_to_fixed_offset(Local::now()),
+ DAYS_REMAINING
+ )
}
-fn encode_datetime(d: DateTime<Local>) -> String {
+fn encode_datetime(d: DateTime<FixedOffset>) -> String {
let iv = initialization_vector();
let mut mc = MagicCrypt::new(KEY, magic_crypt::SecureBit::Bit64, Some(&iv));
@@ -128,8 +177,12 @@ mod tests {
#[test]
fn days_remaining_counts_days_remaining_from_start_date() {
let remaining = days_remaining(
- Local.ymd(2018, 10, 1).and_hms(23, 1, 0),
- Local.ymd(2018, 10, 1).and_hms(23, 30, 0),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 10, 1).and_hms(23, 1, 0)
+ ),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 10, 1).and_hms(23, 30, 0)
+ ),
30,
);
@@ -139,8 +192,12 @@ mod tests {
#[test]
fn days_remaining_with_middle_date() {
let remaining = days_remaining(
- Local.ymd(2018, 10, 1).and_hms(23, 1, 0),
- Local.ymd(2018, 10, 22).and_hms(15, 0, 0),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 10, 1).and_hms(23, 1, 0)
+ ),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 10, 22).and_hms(15, 0, 0)
+ ),
30,
);
@@ -150,8 +207,12 @@ mod tests {
#[test]
fn days_remaining_on_last_day_is_0() {
let remaining = days_remaining(
- Local.ymd(2018, 10, 1).and_hms(23, 1, 0),
- Local.ymd(2018, 10, 31).and_hms(23, 30, 0),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 10, 1).and_hms(23, 1, 0)
+ ),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 10, 31).and_hms(23, 30, 0)
+ ),
30,
);
@@ -161,8 +222,12 @@ mod tests {
#[test]
fn days_remaining_on_day_following_last_day_is_negative_duration_error() {
let remaining = days_remaining(
- Local.ymd(2018, 10, 1).and_hms(23, 1, 0),
- Local.ymd(2018, 11, 1).and_hms(0, 0, 0),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 10, 1).and_hms(23, 1, 0)
+ ),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 11, 1).and_hms(0, 0, 0)
+ ),
30,
);
@@ -172,8 +237,12 @@ mod tests {
#[test]
fn days_remaining_after_last_day_is_negative_duration_error() {
let remaining = days_remaining(
- Local.ymd(2018, 10, 1).and_hms(23, 1, 0),
- Local.ymd(2018, 11, 5).and_hms(0, 0, 0),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 10, 1).and_hms(23, 1, 0)
+ ),
+ datetime_local_to_fixed_offset(
+ Local.ymd(2018, 11, 5).and_hms(0, 0, 0)
+ ),
30,
);