physis/
execlookup.rs

1// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use std::fs;
5
6fn from_u16(from: &mut [u16]) -> &[u8] {
7    #[cfg(target_endian = "little")]
8    from.iter_mut().for_each(|word| *word = word.to_be());
9
10    let ptr: *const u8 = from.as_ptr().cast();
11    let len = from.len().checked_mul(2).unwrap();
12
13    unsafe { std::slice::from_raw_parts(ptr, len) }
14}
15
16fn find_needle(installer_file: &[u8], needle: &str) -> Option<String> {
17    let mut needle: Vec<u16> = needle.encode_utf16().collect();
18    let bytes = from_u16(&mut needle);
19
20    let mut position = installer_file
21        .windows(bytes.len())
22        .position(|window| window == bytes)?;
23
24    let parse_char_at_position = |position: usize| {
25        let upper = installer_file[position];
26        let lower = installer_file[position + 1];
27
28        let result = char::decode_utf16([((upper as u16) << 8) | lower as u16])
29            .map(|r| r.map_err(|e| e.unpaired_surrogate()))
30            .collect::<Vec<_>>();
31
32        result[0]
33    };
34
35    let mut string: String = String::new();
36
37    let mut last_char = parse_char_at_position(position);
38    while last_char.is_ok() && last_char.unwrap() != '\0' {
39        string.push(last_char.unwrap());
40
41        position += 2;
42        last_char = parse_char_at_position(position);
43    }
44
45    Some(string)
46}
47
48/// Extract the frontier URL from ffxivlauncher.exe
49pub fn extract_frontier_url(launcher_path: &str) -> Option<String> {
50    let installer_file = fs::read(launcher_path).unwrap();
51
52    // New Frontier URL format
53    if let Some(url) = find_needle(&installer_file, "https://launcher.finalfantasyxiv.com") {
54        return Some(url);
55    }
56
57    // Old Frontier URL format
58    if let Some(url) = find_needle(&installer_file, "https://frontier.ffxiv.com") {
59        return Some(url);
60    }
61
62    None
63}