use based::request::api::{FallibleApiResponse, api_error}; use pacco::pkg::package::read_file_tar_raw; use rocket::tokio::io::AsyncReadExt; use rocket::{FromForm, State, post}; use serde_json::json; use pacco::pkg::Package; use pacco::pkg::arch::Architecture; // /pkg/// // /pkg/// use rocket::form::Form; use rocket::fs::TempFile; use crate::config::Config; #[derive(FromForm)] pub struct PkgUpload<'r> { pkg: TempFile<'r>, sig: Option>, } pub async fn tmp_file_to_vec<'r>(tmp: &TempFile<'r>) -> Vec { let mut buf = Vec::with_capacity(tmp.len() as usize); tmp.open() .await .unwrap() .read_to_end(&mut buf) .await .unwrap(); buf } #[post("/pkg//upload", data = "")] pub async fn upload_pkg( repo: &str, upload: Form>, user: based::auth::APIUser, config: &State, ) -> FallibleApiResponse { // TODO : Permission System if !user.0.is_admin() { return Err(api_error("Forbidden")); } if config.is_mirrored_repo(repo) { return Err(api_error("This repository is a mirror.")); } let pkg_file = tmp_file_to_vec(&upload.pkg).await; let content = read_file_tar_raw(&pkg_file, ".PKGINFO") .ok_or_else(|| api_error("Unable to read package file"))?; let pkg_info = Package::pkginfo_from_str(&content); let pkg_name = pkg_info .iter() .find(|x| x.0 == "pkgname") .ok_or_else(|| api_error("Package has no pkgname"))? .1 .as_str(); let (version, rel) = Package::version( &pkg_info .iter() .find(|x| x.0 == "pkgver") .ok_or_else(|| api_error("Package has no pkgver"))? .1, ); let arch = pkg_info .iter() .find(|x| x.0 == "arch") .ok_or_else(|| api_error("Package has no arch"))? .1 .as_str(); let arch = Architecture::parse(&arch).ok_or_else(|| api_error("Invalid architecture"))?; let (_, _, _, _, compression) = Package::extract_pkg_name(upload.pkg.name().unwrap()) .ok_or_else(|| api_error("Package has weird filename"))?; let pkg = Package::new(repo, arch, pkg_name, &version, rel, compression); pkg.save( pkg_file, if let Some(sig) = &upload.sig { Some(tmp_file_to_vec(sig).await) } else { None }, ); Ok(json!({"ok": format!("Added '{}' to '{}'", pkg.file_name(), repo)})) }