diff --git a/Cargo.lock b/Cargo.lock index 9b2d2844..5d35a3f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1295,6 +1295,7 @@ dependencies = [ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1815,6 +1816,14 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -2042,6 +2051,7 @@ dependencies = [ "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" +"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/Cargo.toml b/Cargo.toml index 3b29c352..7191172e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,9 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } +[target.'cfg(windows)'.dependencies] +winreg = "0.6.2" + [dev-dependencies] lazy_static = "1.2" paste = "0.1" diff --git a/src/auth_cookie.rs b/src/auth_cookie.rs new file mode 100644 index 00000000..5942994e --- /dev/null +++ b/src/auth_cookie.rs @@ -0,0 +1,30 @@ +//! Implementation of automatically fetching authentication cookie from a Roblox +//! Studio installation. + +#[cfg(windows)] +pub fn get_auth_cookie() -> Option { + use winreg::{enums::HKEY_CURRENT_USER, RegKey}; + + let hkcu = RegKey::predef(HKEY_CURRENT_USER); + let cookies = hkcu + .open_subkey("Software\\Roblox\\RobloxStudioBrowser\\roblox.com") + .ok()?; + + let entry: String = cookies.get_value(".ROBLOSECURITY").ok()?; + let mut cookie = None; + + for kv_pair in entry.split(",") { + let mut pieces = kv_pair.split("::"); + + if let Some("COOK") = pieces.next() { + cookie = pieces.next(); + } + } + + cookie.map(Into::into) +} + +#[cfg(not(windows))] +pub fn get_auth_cookie() -> Option { + None +} diff --git a/src/bin.rs b/src/bin.rs index f4d69fdc..7ed3c83f 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -54,7 +54,7 @@ fn main() { (about: "Generates a place or model file out of the project and uploads it to Roblox.") (@arg PROJECT: "Path to the project to upload. Defaults to the current directory.") (@arg kind: --kind +takes_value "The kind of asset to generate, 'place', or 'model'. Defaults to place.") - (@arg cookie: --cookie +takes_value "Security cookie to authenticate with. If not specified, Rojo will attempt to find one from the system automatically.") + (@arg cookie: --cookie +takes_value "Authenication cookie to authenticate with. If not specified, Rojo will attempt to find one from the system automatically.") (@arg asset_id: --asset_id +takes_value +required "Asset ID to upload to.") ) ); @@ -172,7 +172,7 @@ fn start_upload(sub_matches: &ArgMatches) { }; let kind = sub_matches.value_of("kind"); - let security_cookie = sub_matches.value_of("cookie").map(Into::into); + let auth_cookie = sub_matches.value_of("cookie").map(Into::into); let asset_id: u64 = { let arg = sub_matches.value_of("asset_id").unwrap(); @@ -188,12 +188,12 @@ fn start_upload(sub_matches: &ArgMatches) { let options = commands::UploadOptions { fuzzy_project_path, - security_cookie: security_cookie, + auth_cookie, asset_id, kind, }; - match commands::upload(&options) { + match commands::upload(options) { Ok(_) => {} Err(e) => { error!("{}", e); diff --git a/src/commands/upload.rs b/src/commands/upload.rs index b7fced34..6f8c0dbe 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -2,20 +2,27 @@ use std::path::PathBuf; use failure::Fail; +use crate::auth_cookie::get_auth_cookie; + #[derive(Debug, Fail)] pub enum UploadError { - #[fail(display = "This error cannot happen")] - StubError, + #[fail(display = "Rojo could not find your Roblox auth cookie. Please pass one via --cookie.")] + NeedAuthCookie, } #[derive(Debug)] pub struct UploadOptions<'a> { pub fuzzy_project_path: PathBuf, - pub security_cookie: Option, + pub auth_cookie: Option, pub asset_id: u64, pub kind: Option<&'a str>, } -pub fn upload(_options: &UploadOptions) -> Result<(), UploadError> { +pub fn upload(options: UploadOptions) -> Result<(), UploadError> { + let cookie = options + .auth_cookie + .or_else(get_auth_cookie) + .ok_or(UploadError::NeedAuthCookie)?; + unimplemented!("TODO: Reimplement upload command"); } diff --git a/src/lib.rs b/src/lib.rs index ed140a1d..a99f9114 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub mod commands; #[doc(hidden)] pub mod project; +mod auth_cookie; mod imfs; mod message_queue; mod path_map;