roxify 1.8.2 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -1
- package/dist/utils/native.js +2 -9
- package/native/main.rs +9 -0
- package/native/png_utils.rs +45 -0
- package/package.json +1 -1
package/Cargo.toml
CHANGED
package/dist/utils/native.js
CHANGED
|
@@ -69,18 +69,11 @@ function getNativeModule() {
|
|
|
69
69
|
// --- 1. Platform-specific candidates (checked FIRST) ---
|
|
70
70
|
// These are the ONLY safe candidates — they match the current OS+arch.
|
|
71
71
|
const candidates = [];
|
|
72
|
+
candidates.push(resolve(root, 'roxify_native.node'), resolve(moduleDir, '..', 'roxify_native.node'));
|
|
72
73
|
for (const triple of triples) {
|
|
73
74
|
const name = `roxify_native-${triple}.node`;
|
|
74
75
|
const libName = `libroxify_native-${triple}.node`;
|
|
75
|
-
candidates.push(
|
|
76
|
-
// dist/ sibling (npm-installed package)
|
|
77
|
-
resolve(moduleDir, '..', name), resolve(moduleDir, '..', libName),
|
|
78
|
-
// package root
|
|
79
|
-
resolve(root, name), resolve(root, libName),
|
|
80
|
-
// node_modules/roxify/
|
|
81
|
-
resolve(root, 'node_modules', 'roxify', name), resolve(root, 'node_modules', 'roxify', libName),
|
|
82
|
-
// two levels up (global npm install)
|
|
83
|
-
resolve(moduleDir, '..', '..', name), resolve(moduleDir, '..', '..', libName));
|
|
76
|
+
candidates.push(resolve(moduleDir, '..', name), resolve(moduleDir, '..', libName), resolve(root, name), resolve(root, libName), resolve(root, 'node_modules', 'roxify', name), resolve(root, 'node_modules', 'roxify', libName), resolve(moduleDir, '..', '..', name), resolve(moduleDir, '..', '..', libName));
|
|
84
77
|
}
|
|
85
78
|
// --- 2. Build output candidates (local dev) ---
|
|
86
79
|
for (const triple of triples) {
|
package/native/main.rs
CHANGED
|
@@ -229,6 +229,15 @@ fn main() -> anyhow::Result<()> {
|
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
let png_data = std::fs::read(&input)?;
|
|
233
|
+
match png_utils::extract_file_list_from_pixels(&png_data) {
|
|
234
|
+
Ok(json) => {
|
|
235
|
+
println!("{}", json);
|
|
236
|
+
return Ok(());
|
|
237
|
+
}
|
|
238
|
+
Err(_) => {}
|
|
239
|
+
}
|
|
240
|
+
|
|
232
241
|
eprintln!("No file list found in PNG");
|
|
233
242
|
std::process::exit(1);
|
|
234
243
|
}
|
package/native/png_utils.rs
CHANGED
|
@@ -160,6 +160,14 @@ fn decode_to_rgb(png_data: &[u8]) -> Result<Vec<u8>, String> {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
pub fn extract_name_from_png(png_data: &[u8]) -> Option<String> {
|
|
163
|
+
if let Some(name) = extract_name_direct(png_data) {
|
|
164
|
+
return Some(name);
|
|
165
|
+
}
|
|
166
|
+
let reconst = crate::reconstitution::crop_and_reconstitute(png_data).ok()?;
|
|
167
|
+
extract_name_direct(&reconst)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
fn extract_name_direct(png_data: &[u8]) -> Option<String> {
|
|
163
171
|
let raw = decode_to_rgb(png_data).ok()?;
|
|
164
172
|
let pos = find_pixel_header(&raw).ok()?;
|
|
165
173
|
let mut idx = pos + 4;
|
|
@@ -190,3 +198,40 @@ fn extract_payload_direct(png_data: &[u8]) -> Result<Vec<u8>, String> {
|
|
|
190
198
|
let payload = raw[idx..end].to_vec();
|
|
191
199
|
Ok(payload)
|
|
192
200
|
}
|
|
201
|
+
|
|
202
|
+
pub fn extract_file_list_from_pixels(png_data: &[u8]) -> Result<String, String> {
|
|
203
|
+
if let Ok(result) = extract_file_list_direct(png_data) {
|
|
204
|
+
return Ok(result);
|
|
205
|
+
}
|
|
206
|
+
let reconst = crate::reconstitution::crop_and_reconstitute(png_data)?;
|
|
207
|
+
extract_file_list_direct(&reconst)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
fn extract_file_list_direct(png_data: &[u8]) -> Result<String, String> {
|
|
211
|
+
let raw = decode_to_rgb(png_data)?;
|
|
212
|
+
let pos = find_pixel_header(&raw)?;
|
|
213
|
+
let mut idx = pos + 4;
|
|
214
|
+
if idx + 2 > raw.len() { return Err("Truncated header".to_string()); }
|
|
215
|
+
idx += 1;
|
|
216
|
+
let name_len = raw[idx] as usize; idx += 1;
|
|
217
|
+
if idx + name_len > raw.len() { return Err("Truncated name".to_string()); }
|
|
218
|
+
idx += name_len;
|
|
219
|
+
if idx + 4 > raw.len() { return Err("Truncated payload length".to_string()); }
|
|
220
|
+
let payload_len = ((raw[idx] as u32) << 24)
|
|
221
|
+
| ((raw[idx+1] as u32) << 16)
|
|
222
|
+
| ((raw[idx+2] as u32) << 8)
|
|
223
|
+
| (raw[idx+3] as u32);
|
|
224
|
+
idx += 4;
|
|
225
|
+
idx += payload_len as usize;
|
|
226
|
+
if idx + 8 > raw.len() { return Err("No file list in pixel data".to_string()); }
|
|
227
|
+
if &raw[idx..idx + 4] != b"rXFL" { return Err("No rXFL marker in pixel data".to_string()); }
|
|
228
|
+
idx += 4;
|
|
229
|
+
let json_len = ((raw[idx] as u32) << 24)
|
|
230
|
+
| ((raw[idx+1] as u32) << 16)
|
|
231
|
+
| ((raw[idx+2] as u32) << 8)
|
|
232
|
+
| (raw[idx+3] as u32);
|
|
233
|
+
idx += 4;
|
|
234
|
+
let json_end = idx + json_len as usize;
|
|
235
|
+
if json_end > raw.len() { return Err("Truncated file list JSON".to_string()); }
|
|
236
|
+
String::from_utf8(raw[idx..json_end].to_vec()).map_err(|e| format!("Invalid UTF-8 in file list: {}", e))
|
|
237
|
+
}
|
package/package.json
CHANGED