Skip to content

Commit

Permalink
Update download.rs
Browse files Browse the repository at this point in the history
Signed-off-by: ArchBlood <35392110+ArchBlood@users.noreply.github.com>
  • Loading branch information
ArchBlood authored Dec 22, 2024
1 parent 82db022 commit f55c17e
Showing 1 changed file with 75 additions and 26 deletions.
101 changes: 75 additions & 26 deletions src/download.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::io::{self, Write};
use std::fs::File;
use std::path::Path;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use serde::Deserialize;
use reqwest::blocking;
use zip;
Expand All @@ -13,51 +13,100 @@ struct Config {

// Function to encapsulate download functionality
pub fn download() -> io::Result<()> {
// Read JSON file and deserialize into Config struct
let config_file = File::open("config.json")?;
let config: Config = serde_json::from_reader(config_file)?;
// Load configuration
let config = load_config("config.json")?;

// URL to download HumHub
let humhub_download_url = "https://download.humhub.com/downloads/install/humhub-1.16.2.zip";
// Download and extract HumHub
let humhub_version = "1.16.2";
let humhub_download_url = format!(
"https://download.humhub.com/downloads/install/humhub-{}.zip",
humhub_version
);
let humhub_zip_path = Path::new(&format!("humhub-{}.zip", humhub_version));
let humhub_extract_dir = Path::new("/var/www/html");

// File path to save the downloaded HumHub ZIP file
let humhub_zip_path = "humhub-1.16.2.zip";
download_file(&humhub_download_url, humhub_zip_path)?;
extract_zip(humhub_zip_path, humhub_extract_dir)?;

// Directory to extract HumHub ZIP file (root directory)
let humhub_extract_dir = "/var/www/html";
println!(
"HumHub version {} downloaded and extracted successfully to {}",
humhub_version,
humhub_extract_dir.display()
);

Ok(())
}

// Function to load configuration from a JSON file
fn load_config(path: &str) -> io::Result<Config> {
let config_file = File::open(path)?;
serde_json::from_reader(config_file).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}

// Function to download a file from a URL
fn download_file(url: &str, output_path: &Path) -> io::Result<()> {
println!("Downloading file from: {}", url);

// Initialize HTTP client
let client = blocking::Client::new();
let mut response = client
.get(url)
.send()
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

// Download HumHub
let mut response = client.get(humhub_download_url).send()?;
let mut zip_file = File::create(humhub_zip_path)?;
io::copy(&mut response, &mut zip_file)?;
if !response.status().is_success() {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("Failed to download file: HTTP {}", response.status())
));
}

// Extract HumHub ZIP file to the root directory
let extract_dir = Path::new(humhub_extract_dir);
let zip_file = File::open(humhub_zip_path)?;
let mut archive = zip::ZipArchive::new(zip_file)?;
let mut file = File::create(output_path)?;
io::copy(&mut response, &mut file)?;

println!("File downloaded to: {}", output_path.display());
Ok(())
}

// Function to extract a ZIP file to a target directory
fn extract_zip(zip_path: &Path, extract_dir: &Path) -> io::Result<()> {
println!("Extracting ZIP file: {}", zip_path.display());

let zip_file = File::open(zip_path)?;
let mut archive = zip::ZipArchive::new(zip_file)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

for i in 0..archive.len() {
let mut file = archive.by_index(i)?;
let outpath = extract_dir.join(file.sanitized_name());
let outpath = extract_dir.join(sanitize_path(&file.sanitized_name(), extract_dir)?);

if let Some(parent) = outpath.parent() {
if !parent.exists() {
std::fs::create_dir_all(parent)?;
fs::create_dir_all(parent)?;
}
}

if (&*file.name()).ends_with('/') {
std::fs::create_dir_all(&outpath)?;
if file.name().ends_with('/') {
fs::create_dir_all(&outpath)?;
} else {
let mut outfile = File::create(&outpath)?;
io::copy(&mut file, &mut outfile)?;
}
}

println!("HumHub downloaded and extracted successfully to {}", humhub_extract_dir);

println!("Extraction completed to: {}", extract_dir.display());
Ok(())
}

// Function to sanitize file paths and ensure they are within the target directory
fn sanitize_path(path: &Path, base_dir: &Path) -> io::Result<PathBuf> {
let sanitized = path
.strip_prefix("/")
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "Invalid file path"))?;

let full_path = base_dir.join(sanitized);
if full_path.starts_with(base_dir) {
Ok(full_path)
} else {
Err(io::Error::new(io::ErrorKind::InvalidInput, "Path traversal detected"))
}
}

0 comments on commit f55c17e

Please sign in to comment.