Skip to content

Commit 5279522

Browse files
committed
Obfuscation
1 parent eb193f9 commit 5279522

File tree

1 file changed

+132
-19
lines changed

1 file changed

+132
-19
lines changed

randomize.ts

Lines changed: 132 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ interface FileMapping {
1111

1212
interface ObfuscatorConfig {
1313
enabled: boolean;
14+
preserveExtensions?: string[];
15+
directories?: string[];
1416
}
1517

1618
class BuildObfuscator {
@@ -21,7 +23,11 @@ class BuildObfuscator {
2123

2224
constructor(config: ObfuscatorConfig = { enabled: true }) {
2325
this.root = process.cwd();
24-
this.config = config;
26+
this.config = {
27+
preserveExtensions: [".json", ".css", ".scss"],
28+
directories: ["src/components", "src/layouts", "src/lib", "src/pages"],
29+
...config,
30+
};
2531
}
2632

2733
private generateName(extension: string, isRoute: boolean = false): string {
@@ -50,7 +56,7 @@ class BuildObfuscator {
5056
} while (this.usedNames.has(name));
5157

5258
this.usedNames.add(name);
53-
59+
5460
return `${name}${extension}`;
5561
}
5662

@@ -187,16 +193,18 @@ class BuildObfuscator {
187193
}
188194

189195
private processSourceFiles(): void {
190-
const directories = ["src/components", "src/layouts", "src/lib", "src/pages"];
196+
const directories = this.config.directories || ["src/components", "src/layouts", "src/lib", "src/pages"];
191197

192198
for (const dir of directories) {
193199
const dirPath = path.join(this.root, dir);
194200
if (!fs.existsSync(dirPath)) continue;
195201

196-
const files = this.findFiles(dirPath, [".astro", ".ts"]);
202+
const files = this.findFiles(dirPath, [".astro", ".ts", ".tsx", ".js", ".jsx"]);
197203

198204
for (const file of files) {
199-
if (path.basename(file) === "index.astro") continue;
205+
if (path.basename(file) === "index.astro" || this.config.preserveExtensions?.includes(path.extname(file))) {
206+
continue;
207+
}
200208

201209
const isRoute = file.includes("/pages/");
202210
const randomizedName = this.generateName(path.extname(file), isRoute);
@@ -214,7 +222,7 @@ class BuildObfuscator {
214222
}
215223

216224
private updateFileContents(): void {
217-
const filesToUpdate = this.findFiles(path.join(this.root, "src"), [".astro", ".ts"]);
225+
const filesToUpdate = this.findFiles(path.join(this.root, "src"), [".astro", ".ts", ".tsx", ".js", ".jsx"]);
218226

219227
for (const file of filesToUpdate) {
220228
let content = fs.readFileSync(file, "utf-8");
@@ -223,6 +231,8 @@ class BuildObfuscator {
223231
for (const [originalPath, mapping] of this.mappings) {
224232
const originalName = path.basename(mapping.original);
225233
const newName = path.basename(mapping.randomized);
234+
const originalNameNoExt = path.basename(mapping.original, path.extname(mapping.original));
235+
const newNameNoExt = path.basename(mapping.randomized, path.extname(mapping.randomized));
226236

227237
if (mapping.type === "favicon") {
228238
const faviconName = path.basename(originalPath);
@@ -235,31 +245,123 @@ class BuildObfuscator {
235245

236246
for (const { from, to } of patterns) {
237247
if (content.includes(from)) {
238-
content = content.replace(new RegExp(this.escapeRegex(from), "g"), to);
248+
content = content.replaceAll(from, to);
239249
modified = true;
240250
}
241251
}
242252
} else {
243253
const relDir = path.dirname(mapping.original).replace(path.join(this.root, "src"), "");
244-
const componentType = relDir.includes("/components") ? "components" : relDir.includes("/layouts") ? "layouts" : relDir.includes("/lib") ? "lib" : null;
254+
const componentType = relDir.includes("/components") ? "components" : relDir.includes("/layouts") ? "layouts" : relDir.includes("/lib") ? "lib" : relDir.includes("/pages") ? "pages" : null;
245255

246256
if (componentType) {
247-
const aliasPattern = `@/${componentType}/${this.escapeRegex(originalName)}`;
248-
const regex = new RegExp(`(['"\`])${aliasPattern}(['"\`])`, "g");
249-
const newContent = content.replace(regex, `$1@/${componentType}/${newName}$2`);
257+
const patterns = `@/${componentType}/${this.escapeRegex(originalName)}`;
258+
const regex = new RegExp(`(['"\`])${patterns}(['"\`])`, "g");
259+
const replacement = `$1@/${componentType}/${newName}$2`;
260+
let newContent = content.replace(regex, replacement);
261+
if (newContent !== content) {
262+
content = newContent;
263+
modified = true;
264+
}
265+
266+
const noExtPattern = `@/${componentType}/${this.escapeRegex(originalNameNoExt)}`;
267+
const noExtRegex = new RegExp(`(['"\`])${noExtPattern}(['"\`])`, "g");
268+
const noExtReplacement = `$1@/${componentType}/${newName}$2`;
269+
newContent = content.replace(noExtRegex, noExtReplacement);
270+
if (newContent !== content) {
271+
content = newContent;
272+
modified = true;
273+
}
274+
275+
const scriptSrcPattern = `src\\s*=\\s*(['"\`])@/${componentType}/${this.escapeRegex(originalName)}\\1`;
276+
const scriptSrcRegex = new RegExp(scriptSrcPattern, "g");
277+
const scriptSrcReplacement = `src=$1@/${componentType}/${newName}$1`;
278+
newContent = content.replace(scriptSrcRegex, scriptSrcReplacement);
279+
if (newContent !== content) {
280+
content = newContent;
281+
modified = true;
282+
}
283+
284+
const scriptSrcNoExtPattern = `src\\s*=\\s*(['"\`])@/${componentType}/${this.escapeRegex(originalNameNoExt)}\\1`;
285+
const scriptSrcNoExtRegex = new RegExp(scriptSrcNoExtPattern, "g");
286+
const scriptSrcNoExtReplacement = `src=$1@/${componentType}/${newName}$1`;
287+
newContent = content.replace(scriptSrcNoExtRegex, scriptSrcNoExtReplacement);
288+
if (newContent !== content) {
289+
content = newContent;
290+
modified = true;
291+
}
292+
293+
const absoluteSrcPattern = `(src\\s*=\\s*['"\`])/src/${componentType}/${this.escapeRegex(originalName)}(['"\`])`;
294+
const absoluteSrcRegex = new RegExp(absoluteSrcPattern, "g");
295+
const absoluteSrcReplacement = `$1/src/${componentType}/${newName}$2`;
296+
newContent = content.replace(absoluteSrcRegex, absoluteSrcReplacement);
297+
if (newContent !== content) {
298+
content = newContent;
299+
modified = true;
300+
}
301+
302+
const absoluteSrcNoExtPattern = `(src\\s*=\\s*['"\`])/src/${componentType}/${this.escapeRegex(originalNameNoExt)}(['"\`])`;
303+
const absoluteSrcNoExtRegex = new RegExp(absoluteSrcNoExtPattern, "g");
304+
const absoluteSrcNoExtReplacement = `$1/src/${componentType}/${newName}$2`;
305+
newContent = content.replace(absoluteSrcNoExtRegex, absoluteSrcNoExtReplacement);
250306
if (newContent !== content) {
251307
content = newContent;
252308
modified = true;
253309
}
254310
}
255311

256-
if (mapping.type === "route") {
257-
const originalFileName = path.basename(mapping.original, path.extname(mapping.original));
258-
const newFileName = path.basename(mapping.randomized, path.extname(mapping.randomized));
312+
const currentFileDir = path.dirname(file);
313+
let relativePath = path.relative(currentFileDir, mapping.original);
314+
relativePath = relativePath.replace(/\\/g, "/");
259315

316+
if (!relativePath.startsWith(".")) {
317+
relativePath = `./${relativePath}`;
318+
}
319+
320+
const regex = new RegExp(`(['"\`])${this.escapeRegex(relativePath)}(['"\`])`, "g");
321+
let newRelativePath = path.relative(currentFileDir, mapping.randomized);
322+
newRelativePath = newRelativePath.replace(/\\/g, "/");
323+
if (!newRelativePath.startsWith(".")) {
324+
newRelativePath = `./${newRelativePath}`;
325+
}
326+
327+
let newContent = content.replace(regex, `$1${newRelativePath}$2`);
328+
if (newContent !== content) {
329+
content = newContent;
330+
modified = true;
331+
}
332+
333+
const relativePathNoExt = relativePath.replace(path.extname(relativePath), "");
334+
const noExtRegex = new RegExp(`(['"\`])${this.escapeRegex(relativePathNoExt)}(['"\`])`, "g");
335+
const newRelativePathWithExt = newRelativePath;
336+
337+
newContent = content.replace(noExtRegex, `$1${newRelativePathWithExt}$2`);
338+
if (newContent !== content) {
339+
content = newContent;
340+
modified = true;
341+
}
342+
343+
const scriptRelativePattern = `src\\s*=\\s*(['"\`])${this.escapeRegex(relativePath)}\\1`;
344+
const scriptRelativeRegex = new RegExp(scriptRelativePattern, "g");
345+
newContent = content.replace(scriptRelativeRegex, `src=$1${newRelativePath}$1`);
346+
if (newContent !== content) {
347+
content = newContent;
348+
modified = true;
349+
}
350+
351+
const scriptRelativeNoExtPattern = `src\\s*=\\s*(['"\`])${this.escapeRegex(relativePathNoExt)}\\1`;
352+
const scriptRelativeNoExtRegex = new RegExp(scriptRelativeNoExtPattern, "g");
353+
newContent = content.replace(scriptRelativeNoExtRegex, `src=$1${newRelativePath}$1`);
354+
if (newContent !== content) {
355+
content = newContent;
356+
modified = true;
357+
}
358+
359+
if (mapping.type === "route") {
260360
const routeReplacements = [
261-
{ pattern: new RegExp(`(['"\`])/${this.escapeRegex(originalFileName)}(['"\`])`, "g"), replacement: `$1/${newFileName}$2` },
262-
{ pattern: new RegExp(`(href\\s*=\\s*['"\`])/${this.escapeRegex(originalFileName)}(['"\`])`, "g"), replacement: `$1/${newFileName}$2` },
361+
{ pattern: new RegExp(`(['"\`])/${this.escapeRegex(originalNameNoExt)}(['"\`])`, "g"), replacement: `$1/${newNameNoExt}$2` },
362+
{ pattern: new RegExp(`(href\\s*=\\s*['"\`])/${this.escapeRegex(originalNameNoExt)}(['"\`])`, "g"), replacement: `$1/${newNameNoExt}$2` },
363+
{ pattern: new RegExp(`===\\s*['"\`]/${this.escapeRegex(originalNameNoExt)}['"\`]`, "g"), replacement: `=== '/${newNameNoExt}'` },
364+
{ pattern: new RegExp(`['"\`]/${this.escapeRegex(originalNameNoExt)}['"\`]\\s*===`, "g"), replacement: `'/${newNameNoExt}' ===` },
263365
];
264366

265367
for (const { pattern, replacement } of routeReplacements) {
@@ -285,6 +387,7 @@ class BuildObfuscator {
285387
for (const mapping of sortedMappings) {
286388
if (fs.existsSync(mapping.original)) {
287389
fs.renameSync(mapping.original, mapping.randomized);
390+
console.log(`Renamed: ${path.relative(this.root, mapping.original)}${path.basename(mapping.randomized)}`);
288391
}
289392
}
290393
}
@@ -303,19 +406,29 @@ class BuildObfuscator {
303406

304407
this.processFavicons();
305408
this.processSourceFiles();
409+
410+
console.log(`Found ${this.mappings.size} files to obfuscate`);
411+
306412
this.updateFileContents();
307413
this.renameFiles();
308414

309415
const routeMappings: Record<string, string> = {};
310416
for (const [, mapping] of this.mappings) {
311417
if (mapping.type === "route") {
312-
const originalRoute = "/" + path.basename(mapping.original, path.extname(mapping.original));
313-
const newRoute = "/" + path.basename(mapping.randomized, path.extname(mapping.randomized));
418+
const originalRoute = `/${path.basename(mapping.original, path.extname(mapping.original))}`;
419+
const newRoute = `/${path.basename(mapping.randomized, path.extname(mapping.randomized))}`;
314420
routeMappings[originalRoute] = newRoute;
315421
}
316422
}
317423

318-
console.log("Routes updated:", routeMappings);
424+
if (Object.keys(routeMappings).length > 0) {
425+
console.log("Routes updated:");
426+
for (const [old, newRoute] of Object.entries(routeMappings)) {
427+
console.log(` ${old}${newRoute}`);
428+
}
429+
}
430+
431+
console.log("Obfuscation completed!");
319432
}
320433

321434
public async revert(): Promise<void> {

0 commit comments

Comments
 (0)