pause, obfuscation, challenge

This commit is contained in:
cscherr 2025-04-16 15:52:40 +02:00
parent 197ad9dabf
commit fcd9a961f0
Signed by: cscherrNT
GPG key ID: 8E2B45BC51A27EA7
7 changed files with 99 additions and 12 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
target
challenge

6
CHALLENGE-NOTES.txt Normal file
View file

@ -0,0 +1,6 @@
I am so smart i made a program in which i can hide my password! Behold my
smartness, now I never have to use a passwoord manager again!
I also needed to know how much i worked today, so i made a lil program to
calculate that for me because i am a cool hacker and the websites are too clicky
clacky.

1
CHALLENGE-SOLUTION.txt Normal file
View file

@ -0,0 +1 @@
./timars -t 01:14 -f 00:00 -p 13:37

7
Cargo.lock generated
View file

@ -11,6 +11,12 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "obfstr"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0d354e9a302760d07e025701d40534f17dd1fe4c4db955b4e3bd2907c63bdee"
[[package]]
name = "proc-macro2"
version = "1.0.95"
@ -65,6 +71,7 @@ name = "timars"
version = "0.1.0"
dependencies = [
"getopts",
"obfstr",
"thiserror",
]

View file

@ -12,4 +12,5 @@ repository = "https://git.cscherr.de/PlexSheep/rs-base"
[dependencies]
getopts = "0.2.21"
obfstr = "0.4.4"
thiserror = "2.0.12"

7
prepare-challenge.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
EXPORT_DIR="challenge"
mkdir -p $EXPORT_DIR
cargo build --release
cp ./target/release/timars $EXPORT_DIR/timars
cp CHALLENGE-NOTES.txt $EXPORT_DIR/notes.txt

View file

@ -1,11 +1,18 @@
use std::fmt::Display;
use std::ops::Sub;
use std::io::Write;
use std::ops::{Neg, Sub};
use std::str::FromStr;
use getopts::Options;
use thiserror::Error;
const FLAG: &str = "FlÂG{E1nb38V9a3V5e86HzlY27UFAErIP5mA34kES9fbu}";
const T1337: Timestamp = Timestamp {
hour: 13,
minute: 37,
};
const TONE: Timestamp = Timestamp { hour: 1, minute: 0 };
const TTHREE: Timestamp = Timestamp { hour: 3, minute: 0 };
const TZERO: Timestamp = Timestamp { hour: 0, minute: 0 };
fn options() -> Options {
let mut opts = Options::new();
@ -17,32 +24,41 @@ fn options() -> Options {
"HH:MM",
);
opts.reqopt("t", "to", "calculate time until this time", "HH:MM");
opts.optopt(
"p",
"pause",
"remove this much time from the result",
"HH:MM",
);
opts.optflag("h", "help", "print this help menu");
opts
}
#[derive(PartialEq, Copy, Clone, Debug)]
struct Timestamp {
hour: i8,
minute: i8,
minute: u8,
}
#[derive(Error, Debug)]
enum TimestampParseError {
#[error("Too many or too few separators ':'")]
BadAmountOfSeparators,
#[error("Time numbers t must fullfill 0 < t < 60 (was {0})")]
InvalidTimeNumber(i8),
#[error("Hours h must fullfill 0 < h < 24 (was {0})")]
InvalidHour(i8),
#[error("Minutes m must fullfill 0 < m < 60 (was {0})")]
InvalidMinute(u8),
#[error(transparent)]
ParseInt(#[from] std::num::ParseIntError),
}
impl Sub for Timestamp {
type Output = Self;
type Output = Timestamp;
fn sub(self, rhs: Self) -> Self::Output {
if self.minute >= rhs.minute {
let t = if self.minute >= rhs.minute {
Timestamp {
hour: self.hour - rhs.hour,
minute: self.minute - rhs.minute,
@ -52,7 +68,21 @@ impl Sub for Timestamp {
hour: self.hour - rhs.hour - 1,
minute: 60 + self.minute - rhs.minute,
}
};
#[cfg(debug_assertions)]
{
println!("{self} - {rhs} = {t}")
}
t
}
}
impl Neg for Timestamp {
type Output = Self;
fn neg(mut self) -> Self::Output {
self.hour = -self.hour;
self
}
}
@ -70,13 +100,13 @@ impl FromStr for Timestamp {
}
let hour: i8 = parts[0].parse()?;
let minute: i8 = parts[1].parse()?;
let minute: u8 = parts[1].parse()?;
if hour > 59 {
return Err(TimestampParseError::InvalidTimeNumber(hour));
return Err(TimestampParseError::InvalidHour(hour));
}
if minute > 59 {
return Err(TimestampParseError::InvalidTimeNumber(minute));
return Err(TimestampParseError::InvalidMinute(minute));
}
let t = Timestamp { hour, minute };
@ -92,7 +122,10 @@ fn main() {
let opts = options();
let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(f) => usage(&program, &opts),
Err(e) => {
eprintln!("{e}");
usage(&program, &opts)
}
};
let from_time: Timestamp = match matches.opt_str("from").expect("thats required").parse() {
Ok(t) => t,
@ -108,10 +141,30 @@ fn main() {
usage(&program, &opts)
}
};
let pause_time: Timestamp = match matches.opt_str("pause") {
Some(s) => match s.parse() {
Ok(t) => t,
Err(e) => {
eprintln!("{e}");
usage(&program, &opts)
}
},
None => TZERO,
};
let diff = to_time - from_time - pause_time;
println!("from\t\t: {from_time}");
println!("to\t\t: {to_time}");
println!("difference\t: {}", to_time - from_time)
println!("pause\t\t: {pause_time}");
println!("difference\t: {}", diff);
if pause_time == T1337 && diff == -T1337 {
println!(
"{}",
obfstr::obfstr!("F~L~Â~G{E1nb38V9a3V5e86HzlY27UFAErIP5mA34kES9fbu}")
)
}
}
fn usage(program: &str, opts: &Options) -> ! {
@ -119,3 +172,14 @@ fn usage(program: &str, opts: &Options) -> ! {
print!("{}", opts.usage(&brief));
std::process::exit(1)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sanity() {
assert_eq!(format!("{}", -T1337), "-13:37");
assert_eq!(1 - 5 - 5, -9);
assert_eq!(TONE, TTHREE - TONE - TONE);
}
}