From 9ff5d4b44fd9fe81581dae94d54c4f52c5a1b434 Mon Sep 17 00:00:00 2001 From: "Aviv \"RustyStriker\" Romem" Date: Fri, 10 Jun 2022 19:47:54 +0300 Subject: [PATCH] its working, gonna try bashing the commands --- .gitignore | 1 + Cargo.lock | 7 +++ Cargo.toml | 8 +++ src/main.rs | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ca8a9ac --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "injector" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a8619a0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "injector" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8eeb6b7 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,178 @@ +use std::str::from_utf8_unchecked; +use std::{str::from_utf8, process::Command}; +use std::fs::{self, File, OpenOptions}; +use std::io::{Read, Write, Seek, SeekFrom}; +use std::ffi::OsString; +use std::path::Path; +#[derive(Debug)] +struct Ops { + folder: Option, + output: Option, + recursive: bool, + +} + +// Father please forgive me for the sins im about to commit +static mut HOME_DIR: String = String::new(); + +fn main() { + let ops = read_ops(); + println!("{:?}", ops); + if ops.folder.is_none() || ops.output.is_none() { + panic!("missing folder/output!"); + } + unsafe { HOME_DIR = ops.folder.clone().unwrap(); } + inject_folder(&ops.folder.unwrap(), &ops.output.unwrap(), ops.recursive); +} + +fn inject_folder(folder: &str, output: &str, rec: bool) { + // Create the directory just in case + let _ = fs::create_dir_all(output); + + let f = fs::read_dir(folder).expect(&format!("Couldn't open folder {}", folder)); + for i in f.filter(|x| x.is_ok()).map(|x| x.unwrap()) { + if i.file_name().to_str().unwrap().starts_with('.') { + continue; // Invis folder/file, we dont want to copy them + } + let pbuf = i.path(); + let p = pbuf.as_path(); + if p.is_file() { + let op = String::from_iter([output, "/", i.file_name().to_str().unwrap()]); + inject_file(&p, &Path::new(&op)); + } + else if rec && p.is_dir() { + let fol = p.as_os_str().to_str().unwrap(); + let out = String::from_iter([output, "/", i.file_name().to_str().unwrap()]); + inject_folder(fol, &out, rec); + } + } +} + +fn inject_file(file: &Path, output: &Path) { + println!("injecting {:?} to {:?}", file, output); + let mut inp = OpenOptions::new().read(true).open(file).expect(&format!("Cannot open {:?}", file.as_os_str())); + let mut out = File::create(output).expect(&format!("Cannot create file {:?}", output.as_os_str())); + let mut buf: [u8; 2048] = [0; 2048]; + + + if file.extension().unwrap_or(&OsString::new()) == "html" { + // Copy while also reading and searching for ... + while let Ok(len) = inp.read(&mut buf) { + if len == 0 { + // EOF + break; + } + match from_utf8(&buf[..len]) { + Ok(s) => { + write_injection(s, &mut out, &mut inp, file.parent().unwrap().as_os_str().to_str().unwrap()); + }, + Err(e) => { + if e.valid_up_to() == 0 { + panic!("File is not valid UTF8"); + } + // Safety: we know all bytes are valid from the error... + let s = unsafe { from_utf8_unchecked(&buf[..e.valid_up_to()]) }; + inp.seek(SeekFrom::Current(-1 * (len - e.valid_up_to()) as i64)).unwrap(); + + write_injection(s, &mut out, &mut inp, file.parent().unwrap().as_os_str().to_str().unwrap()); + }, + } + + } + } + else { + // Just copy the file! + while let Ok(len) = inp.read(&mut buf) { + if len == 0 { + // EOF + break; + } + let res = out.write(&buf[..len]); + if res.is_err() { + panic!("Cannot write to {:?}", output.as_os_str()); + } + else if res.unwrap() != len { + panic!("cannot continue writing to {:?}", output.as_os_str()); + } + } + } + out.flush().expect(&format!("Cannot flush file {:?}", output.as_os_str())); +} + +fn write_injection(s: &str, out: &mut File, inp: &mut File, cfolder: &str) { + let tag : &str = ""; + let ctag : &str = ""; + + if s.contains(tag) && s.contains(ctag) { + let (pre,post) = s.split_once(tag).unwrap(); + let (com, post) = post.split_once(ctag).unwrap(); + + out.write(pre.as_bytes()).unwrap(); + + let mut com_iter = com.split(' '); + let com = Command::new(com_iter.next().unwrap()) + .args( + com_iter.map(|x| x + .replace("$HOME", unsafe { &HOME_DIR }) + .replace("$CURRENT", cfolder) + ) + ) + .output(); + + let com = match com { + Ok(o) => String::from_utf8(o.stdout).unwrap_or(String::from("UTF8 conversion error")), + Err(_) => String::from("Failed running command :("), + }; + + out.write(com.as_bytes()).unwrap(); + write_injection(post, out, inp, cfolder); + } + else if s.contains(tag) { + // We have the first tag but not the second, so we want to go back in the input file.. + let (copy, keep) = s.split_once(tag).unwrap(); + + out.write(copy.as_bytes()).unwrap(); + // Return the length of whatever we just read and the tag length + inp.seek(SeekFrom::Current(-1 * (keep.as_bytes().len() + tag.as_bytes().len()) as i64)).unwrap(); + } + else { + // Make sure we are not just cutting it in the middle + let chars = tag.chars().collect::>(); + let mut wrote = false; + for i in 1..chars.len() { + if s.ends_with(&chars[..i]) { + let back: usize = chars[..i].iter().map(|x| x.len_utf8()).sum(); + let to_write = s.replace(&chars[..i], ""); + out.write(to_write.as_bytes()).unwrap(); + + inp.seek(SeekFrom::Current(-1 * back as i64)).unwrap(); + wrote = true; + break; + } + } + if !wrote { + out.write(s.as_bytes()).unwrap(); + } + } +} + +fn read_ops() -> Ops { + let args = std::env::args(); + let mut ops = Ops { folder: None, output: None, recursive: false }; + + for a in args.skip(1) { + if a.starts_with('-') { + if a.trim() == "-r" || a.trim() == "--recursive" { + ops.recursive = true; + } + } + else if ops.folder.is_none() { + ops.folder = Some(a); + } + else if ops.output.is_none() { + ops.output = Some(a); + } + } + + ops +} \ No newline at end of file