@gxp-dev/tools 2.0.6 โ 2.0.7
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/browser-extensions/README.md +1 -0
- package/browser-extensions/chrome/background.js +857 -0
- package/browser-extensions/chrome/content.js +51 -0
- package/browser-extensions/chrome/devtools.html +9 -0
- package/browser-extensions/chrome/devtools.js +23 -0
- package/browser-extensions/chrome/icons/gx_off_128.png +0 -0
- package/browser-extensions/chrome/icons/gx_off_16.png +0 -0
- package/browser-extensions/chrome/icons/gx_off_32.png +0 -0
- package/browser-extensions/chrome/icons/gx_off_64.png +0 -0
- package/browser-extensions/chrome/icons/gx_on_128.png +0 -0
- package/browser-extensions/chrome/icons/gx_on_16.png +0 -0
- package/browser-extensions/chrome/icons/gx_on_32.png +0 -0
- package/browser-extensions/chrome/icons/gx_on_64.png +0 -0
- package/browser-extensions/chrome/inspector.js +1087 -0
- package/browser-extensions/chrome/manifest.json +70 -0
- package/browser-extensions/chrome/panel.html +638 -0
- package/browser-extensions/chrome/panel.js +862 -0
- package/browser-extensions/chrome/popup.html +399 -0
- package/browser-extensions/chrome/popup.js +515 -0
- package/browser-extensions/chrome/rules.json +1 -0
- package/browser-extensions/chrome/test-chrome.html +145 -0
- package/browser-extensions/chrome/test-mixed-content.html +190 -0
- package/browser-extensions/chrome/test-uri-pattern.html +199 -0
- package/browser-extensions/firefox/README.md +134 -0
- package/browser-extensions/firefox/background.js +804 -0
- package/browser-extensions/firefox/content.js +120 -0
- package/browser-extensions/firefox/debug-errors.html +229 -0
- package/browser-extensions/firefox/debug-https.html +113 -0
- package/browser-extensions/firefox/devtools.html +9 -0
- package/browser-extensions/firefox/devtools.js +24 -0
- package/browser-extensions/firefox/icons/gx_off_128.png +0 -0
- package/browser-extensions/firefox/icons/gx_off_16.png +0 -0
- package/browser-extensions/firefox/icons/gx_off_32.png +0 -0
- package/browser-extensions/firefox/icons/gx_off_64.png +0 -0
- package/browser-extensions/firefox/icons/gx_on_128.png +0 -0
- package/browser-extensions/firefox/icons/gx_on_16.png +0 -0
- package/browser-extensions/firefox/icons/gx_on_32.png +0 -0
- package/browser-extensions/firefox/icons/gx_on_64.png +0 -0
- package/browser-extensions/firefox/inspector.js +1087 -0
- package/browser-extensions/firefox/manifest.json +67 -0
- package/browser-extensions/firefox/panel.html +638 -0
- package/browser-extensions/firefox/panel.js +862 -0
- package/browser-extensions/firefox/popup.html +525 -0
- package/browser-extensions/firefox/popup.js +536 -0
- package/browser-extensions/firefox/test-gramercy.html +126 -0
- package/browser-extensions/firefox/test-imports.html +58 -0
- package/browser-extensions/firefox/test-masking.html +147 -0
- package/browser-extensions/firefox/test-uri-pattern.html +199 -0
- package/package.json +7 -2
- package/runtime/PortalContainer.vue +326 -0
- package/runtime/dev-tools/DevToolsModal.vue +217 -0
- package/runtime/dev-tools/LayoutSwitcher.vue +221 -0
- package/runtime/dev-tools/MockDataEditor.vue +621 -0
- package/runtime/dev-tools/SocketSimulator.vue +562 -0
- package/runtime/dev-tools/StoreInspector.vue +644 -0
- package/runtime/dev-tools/index.js +6 -0
- package/runtime/gxpStringsPlugin.js +428 -0
- package/runtime/index.html +22 -0
- package/runtime/main.js +32 -0
- package/runtime/mock-api/auth-middleware.js +97 -0
- package/runtime/mock-api/image-generator.js +221 -0
- package/runtime/mock-api/index.js +197 -0
- package/runtime/mock-api/response-generator.js +394 -0
- package/runtime/mock-api/route-generator.js +323 -0
- package/runtime/mock-api/socket-triggers.js +371 -0
- package/runtime/mock-api/spec-loader.js +300 -0
- package/runtime/server.js +180 -0
- package/runtime/stores/gxpPortalConfigStore.js +554 -0
- package/runtime/stores/index.js +6 -0
- package/runtime/vite-inspector-plugin.js +749 -0
- package/runtime/vite-source-tracker-plugin.js +232 -0
- package/runtime/vite.config.js +402 -0
- package/scripts/launch-chrome.js +90 -0
- package/scripts/pack-chrome.js +91 -0
- package/socket-events/AiSessionMessageCreated.json +18 -0
- package/socket-events/SocialStreamPostCreated.json +24 -0
- package/socket-events/SocialStreamPostVariantCompleted.json +23 -0
- package/template/README.md +332 -0
- package/template/app-manifest.json +32 -0
- package/template/dev-assets/images/avatar-placeholder.png +0 -0
- package/template/dev-assets/images/background-placeholder.jpg +0 -0
- package/template/dev-assets/images/banner-placeholder.jpg +0 -0
- package/template/dev-assets/images/icon-placeholder.png +0 -0
- package/template/dev-assets/images/logo-placeholder.png +0 -0
- package/template/dev-assets/images/product-placeholder.jpg +0 -0
- package/template/dev-assets/images/thumbnail-placeholder.jpg +0 -0
- package/template/env.example +51 -0
- package/template/gitignore +53 -0
- package/template/index.html +22 -0
- package/template/main.js +28 -0
- package/template/src/DemoPage.vue +459 -0
- package/template/src/Plugin.vue +38 -0
- package/template/src/stores/index.js +9 -0
- package/template/src/stores/test-data.json +173 -0
- package/template/theme-layouts/AdditionalStyling.css +0 -0
- package/template/theme-layouts/PrivateLayout.vue +39 -0
- package/template/theme-layouts/PublicLayout.vue +39 -0
- package/template/theme-layouts/SystemLayout.vue +39 -0
- package/template/vite.config.js +333 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
// Configuration defaults
|
|
2
|
+
const DEFAULT_CONFIG = {
|
|
3
|
+
enabled: false,
|
|
4
|
+
// Legacy fields for backward compatibility
|
|
5
|
+
redirectUrl: "https://localhost:3060/src/Plugin.vue",
|
|
6
|
+
urlPattern: "uploads\\/plugin-version\\/\\d+\\/file_name\\/.*\\.js(\\?.*)?",
|
|
7
|
+
useCustomPattern: false,
|
|
8
|
+
// New rules-based configuration
|
|
9
|
+
rules: {
|
|
10
|
+
js: {
|
|
11
|
+
enabled: true,
|
|
12
|
+
pattern: "uploads\\/plugin-version\\/\\d+\\/file_name\\/.*\\.js(\\?.*)?",
|
|
13
|
+
redirectUrl: "https://localhost:3060/src/Plugin.vue",
|
|
14
|
+
useCustomPattern: false,
|
|
15
|
+
},
|
|
16
|
+
css: {
|
|
17
|
+
enabled: true,
|
|
18
|
+
pattern:
|
|
19
|
+
"uploads\\/plugin-version\\/\\d+\\/style_file_name\\/.*\\.css(\\?.*)?",
|
|
20
|
+
redirectUrl: "",
|
|
21
|
+
returnBlank: true,
|
|
22
|
+
useCustomPattern: false,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
maskingMode: false,
|
|
26
|
+
clearCacheOnEnable: true,
|
|
27
|
+
disableCacheForRedirects: true,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Global state
|
|
31
|
+
let config = { ...DEFAULT_CONFIG };
|
|
32
|
+
let pendingChanges = false;
|
|
33
|
+
|
|
34
|
+
// DOM elements
|
|
35
|
+
const elements = {
|
|
36
|
+
// Status and main toggle
|
|
37
|
+
statusMessage: null,
|
|
38
|
+
masterToggle: null,
|
|
39
|
+
statusInfo: null,
|
|
40
|
+
|
|
41
|
+
// JavaScript rule elements
|
|
42
|
+
jsRuleContainer: null,
|
|
43
|
+
jsRuleToggle: null,
|
|
44
|
+
jsRedirectUrl: null,
|
|
45
|
+
jsUseCustomPattern: null,
|
|
46
|
+
jsPattern: null,
|
|
47
|
+
jsPatternGroup: null,
|
|
48
|
+
|
|
49
|
+
// CSS rule elements
|
|
50
|
+
cssRuleContainer: null,
|
|
51
|
+
cssRuleToggle: null,
|
|
52
|
+
cssRedirectUrl: null,
|
|
53
|
+
cssReturnBlank: null,
|
|
54
|
+
cssUseCustomPattern: null,
|
|
55
|
+
cssPattern: null,
|
|
56
|
+
cssPatternGroup: null,
|
|
57
|
+
cssRedirectGroup: null,
|
|
58
|
+
|
|
59
|
+
// Advanced settings
|
|
60
|
+
advancedHeader: null,
|
|
61
|
+
advancedContent: null,
|
|
62
|
+
advancedToggle: null,
|
|
63
|
+
maskingMode: null,
|
|
64
|
+
clearCacheOnEnable: null,
|
|
65
|
+
disableCacheForRedirects: null,
|
|
66
|
+
|
|
67
|
+
// Action buttons
|
|
68
|
+
saveBtn: null,
|
|
69
|
+
clearCacheBtn: null,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Initialize popup
|
|
73
|
+
document.addEventListener("DOMContentLoaded", async () => {
|
|
74
|
+
try {
|
|
75
|
+
initializeElements();
|
|
76
|
+
setupEventListeners();
|
|
77
|
+
await loadConfiguration();
|
|
78
|
+
updateUI();
|
|
79
|
+
console.log("[JavaScript Proxy] Popup initialized successfully");
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error("[JavaScript Proxy] Error initializing popup:", error);
|
|
82
|
+
showStatus("Error initializing popup: " + error.message, "error");
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Initialize DOM elements
|
|
87
|
+
function initializeElements() {
|
|
88
|
+
// Get all elements and store in global object
|
|
89
|
+
for (const key in elements) {
|
|
90
|
+
const element = document.getElementById(key);
|
|
91
|
+
if (!element) {
|
|
92
|
+
throw new Error(`Required element not found: ${key}`);
|
|
93
|
+
}
|
|
94
|
+
elements[key] = element;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Setup event listeners
|
|
99
|
+
function setupEventListeners() {
|
|
100
|
+
// Master toggle
|
|
101
|
+
elements.masterToggle.addEventListener("change", handleMasterToggle);
|
|
102
|
+
|
|
103
|
+
// Rule toggles
|
|
104
|
+
elements.jsRuleToggle.addEventListener("change", () =>
|
|
105
|
+
handleRuleToggle("js")
|
|
106
|
+
);
|
|
107
|
+
elements.cssRuleToggle.addEventListener("change", () =>
|
|
108
|
+
handleRuleToggle("css")
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// JavaScript rule events
|
|
112
|
+
elements.jsRedirectUrl.addEventListener("input", () =>
|
|
113
|
+
handleFieldChange("js", "redirectUrl")
|
|
114
|
+
);
|
|
115
|
+
elements.jsUseCustomPattern.addEventListener("change", () =>
|
|
116
|
+
handleCustomPatternToggle("js")
|
|
117
|
+
);
|
|
118
|
+
elements.jsPattern.addEventListener("input", () =>
|
|
119
|
+
handleFieldChange("js", "pattern")
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// CSS rule events
|
|
123
|
+
elements.cssRedirectUrl.addEventListener("input", () =>
|
|
124
|
+
handleFieldChange("css", "redirectUrl")
|
|
125
|
+
);
|
|
126
|
+
elements.cssReturnBlank.addEventListener("change", handleCssBlankToggle);
|
|
127
|
+
elements.cssUseCustomPattern.addEventListener("change", () =>
|
|
128
|
+
handleCustomPatternToggle("css")
|
|
129
|
+
);
|
|
130
|
+
elements.cssPattern.addEventListener("input", () =>
|
|
131
|
+
handleFieldChange("css", "pattern")
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// Advanced settings toggle
|
|
135
|
+
elements.advancedHeader.addEventListener("click", toggleAdvancedSettings);
|
|
136
|
+
|
|
137
|
+
// Advanced settings checkboxes
|
|
138
|
+
elements.maskingMode.addEventListener("change", () =>
|
|
139
|
+
handleAdvancedSettingChange("maskingMode")
|
|
140
|
+
);
|
|
141
|
+
elements.clearCacheOnEnable.addEventListener("change", () =>
|
|
142
|
+
handleAdvancedSettingChange("clearCacheOnEnable")
|
|
143
|
+
);
|
|
144
|
+
elements.disableCacheForRedirects.addEventListener("change", () =>
|
|
145
|
+
handleAdvancedSettingChange("disableCacheForRedirects")
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// Action buttons
|
|
149
|
+
elements.saveBtn.addEventListener("click", saveConfiguration);
|
|
150
|
+
elements.clearCacheBtn.addEventListener("click", clearCache);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Load configuration from storage
|
|
154
|
+
async function loadConfiguration() {
|
|
155
|
+
try {
|
|
156
|
+
const result = await browser.runtime.sendMessage({ action: "getConfig" });
|
|
157
|
+
if (result) {
|
|
158
|
+
config = { ...DEFAULT_CONFIG, ...result };
|
|
159
|
+
// Ensure rules exist and have proper structure
|
|
160
|
+
config = migrateConfig(config);
|
|
161
|
+
}
|
|
162
|
+
console.log("[JavaScript Proxy] Loaded configuration:", config);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.error("[JavaScript Proxy] Error loading configuration:", error);
|
|
165
|
+
showStatus("Error loading configuration: " + error.message, "error");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Migrate legacy configuration to new rules format
|
|
170
|
+
function migrateConfig(config) {
|
|
171
|
+
// If rules don't exist, create them from legacy config
|
|
172
|
+
if (!config.rules) {
|
|
173
|
+
config.rules = {
|
|
174
|
+
js: {
|
|
175
|
+
enabled: true,
|
|
176
|
+
pattern: config.urlPattern || DEFAULT_CONFIG.rules.js.pattern,
|
|
177
|
+
redirectUrl: config.redirectUrl || DEFAULT_CONFIG.rules.js.redirectUrl,
|
|
178
|
+
useCustomPattern: config.useCustomPattern || false,
|
|
179
|
+
},
|
|
180
|
+
css: {
|
|
181
|
+
enabled: true,
|
|
182
|
+
pattern: DEFAULT_CONFIG.rules.css.pattern,
|
|
183
|
+
redirectUrl: "",
|
|
184
|
+
returnBlank: true,
|
|
185
|
+
useCustomPattern: false,
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
} else {
|
|
189
|
+
// Ensure all required fields exist
|
|
190
|
+
if (!config.rules.js) {
|
|
191
|
+
config.rules.js = {
|
|
192
|
+
enabled: true,
|
|
193
|
+
pattern: config.urlPattern || DEFAULT_CONFIG.rules.js.pattern,
|
|
194
|
+
redirectUrl: config.redirectUrl || DEFAULT_CONFIG.rules.js.redirectUrl,
|
|
195
|
+
useCustomPattern: config.useCustomPattern || false,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (!config.rules.css) {
|
|
199
|
+
config.rules.css = {
|
|
200
|
+
enabled: true,
|
|
201
|
+
pattern: DEFAULT_CONFIG.rules.css.pattern,
|
|
202
|
+
redirectUrl: "",
|
|
203
|
+
returnBlank: true,
|
|
204
|
+
useCustomPattern: false,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return config;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Update UI based on current configuration
|
|
213
|
+
function updateUI() {
|
|
214
|
+
// Update master toggle
|
|
215
|
+
elements.masterToggle.checked = config.enabled;
|
|
216
|
+
updateStatusInfo();
|
|
217
|
+
|
|
218
|
+
// Update rule toggles
|
|
219
|
+
elements.jsRuleToggle.checked = config.rules.js.enabled;
|
|
220
|
+
elements.cssRuleToggle.checked = config.rules.css.enabled;
|
|
221
|
+
|
|
222
|
+
// Update JavaScript rule fields
|
|
223
|
+
elements.jsRedirectUrl.value = config.rules.js.redirectUrl || "";
|
|
224
|
+
elements.jsUseCustomPattern.checked = config.rules.js.useCustomPattern;
|
|
225
|
+
elements.jsPattern.value = config.rules.js.pattern || "";
|
|
226
|
+
|
|
227
|
+
// Update CSS rule fields
|
|
228
|
+
elements.cssRedirectUrl.value = config.rules.css.redirectUrl || "";
|
|
229
|
+
elements.cssReturnBlank.checked = config.rules.css.returnBlank;
|
|
230
|
+
elements.cssUseCustomPattern.checked = config.rules.css.useCustomPattern;
|
|
231
|
+
elements.cssPattern.value = config.rules.css.pattern || "";
|
|
232
|
+
|
|
233
|
+
// Update advanced settings
|
|
234
|
+
elements.maskingMode.checked = config.maskingMode;
|
|
235
|
+
elements.clearCacheOnEnable.checked = config.clearCacheOnEnable;
|
|
236
|
+
elements.disableCacheForRedirects.checked = config.disableCacheForRedirects;
|
|
237
|
+
|
|
238
|
+
// Update UI visibility and states
|
|
239
|
+
updateRuleContainerStates();
|
|
240
|
+
updatePatternVisibility("js");
|
|
241
|
+
updatePatternVisibility("css");
|
|
242
|
+
updateCssRedirectVisibility();
|
|
243
|
+
updateSaveButtonState();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Update status info text
|
|
247
|
+
function updateStatusInfo() {
|
|
248
|
+
const activeRules = [];
|
|
249
|
+
if (config.enabled) {
|
|
250
|
+
if (config.rules.js.enabled) activeRules.push("JS redirects");
|
|
251
|
+
if (config.rules.css.enabled) {
|
|
252
|
+
if (config.rules.css.returnBlank) {
|
|
253
|
+
activeRules.push("CSS blank returns");
|
|
254
|
+
} else {
|
|
255
|
+
activeRules.push("CSS redirects");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (config.enabled && activeRules.length > 0) {
|
|
261
|
+
elements.statusInfo.textContent = `Extension is active: ${activeRules.join(
|
|
262
|
+
", "
|
|
263
|
+
)}`;
|
|
264
|
+
} else if (config.enabled) {
|
|
265
|
+
elements.statusInfo.textContent =
|
|
266
|
+
"Extension is enabled but no rules are active";
|
|
267
|
+
} else {
|
|
268
|
+
elements.statusInfo.textContent = "Extension is currently disabled";
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Update rule container visual states
|
|
273
|
+
function updateRuleContainerStates() {
|
|
274
|
+
// Disable rule containers when master toggle is off
|
|
275
|
+
elements.jsRuleContainer.classList.toggle("disabled", !config.enabled);
|
|
276
|
+
elements.cssRuleContainer.classList.toggle("disabled", !config.enabled);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Update pattern field visibility for a rule
|
|
280
|
+
function updatePatternVisibility(ruleType) {
|
|
281
|
+
const rule = config.rules[ruleType];
|
|
282
|
+
const patternGroup = elements[`${ruleType}PatternGroup`];
|
|
283
|
+
|
|
284
|
+
if (rule.useCustomPattern) {
|
|
285
|
+
patternGroup.classList.remove("hidden");
|
|
286
|
+
} else {
|
|
287
|
+
patternGroup.classList.add("hidden");
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Update CSS redirect URL visibility based on blank return setting
|
|
292
|
+
function updateCssRedirectVisibility() {
|
|
293
|
+
if (config.rules.css.returnBlank) {
|
|
294
|
+
elements.cssRedirectGroup.classList.add("hidden");
|
|
295
|
+
} else {
|
|
296
|
+
elements.cssRedirectGroup.classList.remove("hidden");
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Update save button state
|
|
301
|
+
function updateSaveButtonState() {
|
|
302
|
+
elements.saveBtn.disabled = !pendingChanges;
|
|
303
|
+
elements.saveBtn.textContent = pendingChanges ? "Save Changes" : "No Changes";
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Handle master toggle change
|
|
307
|
+
async function handleMasterToggle() {
|
|
308
|
+
const enabled = elements.masterToggle.checked;
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
// Send toggle message to background script
|
|
312
|
+
const response = await browser.runtime.sendMessage({
|
|
313
|
+
action: "toggleProxy",
|
|
314
|
+
enabled: enabled,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
if (response && response.success) {
|
|
318
|
+
config.enabled = enabled;
|
|
319
|
+
updateUI();
|
|
320
|
+
showStatus(
|
|
321
|
+
enabled
|
|
322
|
+
? "Extension enabled successfully"
|
|
323
|
+
: "Extension disabled successfully",
|
|
324
|
+
"success"
|
|
325
|
+
);
|
|
326
|
+
} else {
|
|
327
|
+
throw new Error(response ? response.error : "Unknown error");
|
|
328
|
+
}
|
|
329
|
+
} catch (error) {
|
|
330
|
+
console.error("[JavaScript Proxy] Error toggling proxy:", error);
|
|
331
|
+
showStatus("Error toggling extension: " + error.message, "error");
|
|
332
|
+
// Revert the toggle
|
|
333
|
+
elements.masterToggle.checked = config.enabled;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Handle rule toggle change
|
|
338
|
+
function handleRuleToggle(ruleType) {
|
|
339
|
+
const toggle = elements[`${ruleType}RuleToggle`];
|
|
340
|
+
config.rules[ruleType].enabled = toggle.checked;
|
|
341
|
+
setPendingChanges(true);
|
|
342
|
+
updateUI();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Handle field changes
|
|
346
|
+
function handleFieldChange(ruleType, fieldName) {
|
|
347
|
+
const element =
|
|
348
|
+
elements[
|
|
349
|
+
`${ruleType}${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}`
|
|
350
|
+
];
|
|
351
|
+
config.rules[ruleType][fieldName] = element.value;
|
|
352
|
+
setPendingChanges(true);
|
|
353
|
+
updateUI();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Handle custom pattern toggle
|
|
357
|
+
function handleCustomPatternToggle(ruleType) {
|
|
358
|
+
const toggle = elements[`${ruleType}UseCustomPattern`];
|
|
359
|
+
config.rules[ruleType].useCustomPattern = toggle.checked;
|
|
360
|
+
setPendingChanges(true);
|
|
361
|
+
updatePatternVisibility(ruleType);
|
|
362
|
+
updateSaveButtonState();
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Handle CSS blank return toggle
|
|
366
|
+
function handleCssBlankToggle() {
|
|
367
|
+
config.rules.css.returnBlank = elements.cssReturnBlank.checked;
|
|
368
|
+
setPendingChanges(true);
|
|
369
|
+
updateCssRedirectVisibility();
|
|
370
|
+
updateUI();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Handle advanced setting changes
|
|
374
|
+
function handleAdvancedSettingChange(settingName) {
|
|
375
|
+
config[settingName] = elements[settingName].checked;
|
|
376
|
+
setPendingChanges(true);
|
|
377
|
+
updateSaveButtonState();
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Toggle advanced settings panel
|
|
381
|
+
function toggleAdvancedSettings() {
|
|
382
|
+
const isHidden = elements.advancedContent.classList.contains("hidden");
|
|
383
|
+
|
|
384
|
+
if (isHidden) {
|
|
385
|
+
elements.advancedContent.classList.remove("hidden");
|
|
386
|
+
elements.advancedToggle.textContent = "Hide โฒ";
|
|
387
|
+
} else {
|
|
388
|
+
elements.advancedContent.classList.add("hidden");
|
|
389
|
+
elements.advancedToggle.textContent = "Show โผ";
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Set pending changes state
|
|
394
|
+
function setPendingChanges(hasPendingChanges) {
|
|
395
|
+
pendingChanges = hasPendingChanges;
|
|
396
|
+
updateSaveButtonState();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Validate configuration
|
|
400
|
+
function validateConfig() {
|
|
401
|
+
const errors = [];
|
|
402
|
+
|
|
403
|
+
// Check JavaScript rule
|
|
404
|
+
if (config.rules.js.enabled) {
|
|
405
|
+
if (!config.rules.js.redirectUrl) {
|
|
406
|
+
errors.push(
|
|
407
|
+
"JavaScript redirect URL is required when JS rule is enabled"
|
|
408
|
+
);
|
|
409
|
+
} else {
|
|
410
|
+
try {
|
|
411
|
+
new URL(config.rules.js.redirectUrl);
|
|
412
|
+
} catch (e) {
|
|
413
|
+
errors.push("JavaScript redirect URL is not valid");
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (config.rules.js.useCustomPattern && !config.rules.js.pattern) {
|
|
418
|
+
errors.push(
|
|
419
|
+
"JavaScript custom pattern is required when custom pattern is enabled"
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (config.rules.js.pattern) {
|
|
424
|
+
try {
|
|
425
|
+
new RegExp(config.rules.js.pattern);
|
|
426
|
+
} catch (e) {
|
|
427
|
+
errors.push("JavaScript URL pattern is not a valid regular expression");
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Check CSS rule
|
|
433
|
+
if (config.rules.css.enabled) {
|
|
434
|
+
if (!config.rules.css.returnBlank && !config.rules.css.redirectUrl) {
|
|
435
|
+
errors.push(
|
|
436
|
+
"CSS redirect URL is required when CSS rule is enabled and not returning blank"
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (config.rules.css.redirectUrl) {
|
|
441
|
+
try {
|
|
442
|
+
new URL(config.rules.css.redirectUrl);
|
|
443
|
+
} catch (e) {
|
|
444
|
+
errors.push("CSS redirect URL is not valid");
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (config.rules.css.useCustomPattern && !config.rules.css.pattern) {
|
|
449
|
+
errors.push(
|
|
450
|
+
"CSS custom pattern is required when custom pattern is enabled"
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (config.rules.css.pattern) {
|
|
455
|
+
try {
|
|
456
|
+
new RegExp(config.rules.css.pattern);
|
|
457
|
+
} catch (e) {
|
|
458
|
+
errors.push("CSS URL pattern is not a valid regular expression");
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return errors;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Save configuration
|
|
467
|
+
async function saveConfiguration() {
|
|
468
|
+
if (!pendingChanges) return;
|
|
469
|
+
|
|
470
|
+
try {
|
|
471
|
+
// Validate configuration
|
|
472
|
+
const errors = validateConfig();
|
|
473
|
+
if (errors.length > 0) {
|
|
474
|
+
showStatus("Validation errors: " + errors.join(", "), "error");
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Disable save button during save
|
|
479
|
+
elements.saveBtn.disabled = true;
|
|
480
|
+
elements.saveBtn.textContent = "Saving...";
|
|
481
|
+
|
|
482
|
+
// Send configuration to background script
|
|
483
|
+
const response = await browser.runtime.sendMessage({
|
|
484
|
+
action: "updateConfig",
|
|
485
|
+
config: config,
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
if (response && response.success) {
|
|
489
|
+
setPendingChanges(false);
|
|
490
|
+
showStatus("Configuration saved successfully", "success");
|
|
491
|
+
} else {
|
|
492
|
+
throw new Error(response ? response.error : "Unknown error");
|
|
493
|
+
}
|
|
494
|
+
} catch (error) {
|
|
495
|
+
console.error("[JavaScript Proxy] Error saving configuration:", error);
|
|
496
|
+
showStatus("Error saving configuration: " + error.message, "error");
|
|
497
|
+
} finally {
|
|
498
|
+
updateSaveButtonState();
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Clear cache
|
|
503
|
+
async function clearCache() {
|
|
504
|
+
try {
|
|
505
|
+
elements.clearCacheBtn.disabled = true;
|
|
506
|
+
elements.clearCacheBtn.textContent = "Clearing...";
|
|
507
|
+
|
|
508
|
+
const response = await browser.runtime.sendMessage({
|
|
509
|
+
action: "clearCache",
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
if (response && response.success) {
|
|
513
|
+
showStatus("Cache cleared successfully", "success");
|
|
514
|
+
} else {
|
|
515
|
+
throw new Error(response ? response.error : "Unknown error");
|
|
516
|
+
}
|
|
517
|
+
} catch (error) {
|
|
518
|
+
console.error("[JavaScript Proxy] Error clearing cache:", error);
|
|
519
|
+
showStatus("Error clearing cache: " + error.message, "error");
|
|
520
|
+
} finally {
|
|
521
|
+
elements.clearCacheBtn.disabled = false;
|
|
522
|
+
elements.clearCacheBtn.textContent = "Clear Cache";
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Show status message
|
|
527
|
+
function showStatus(message, type = "success") {
|
|
528
|
+
elements.statusMessage.textContent = message;
|
|
529
|
+
elements.statusMessage.className = `status-message status-${type}`;
|
|
530
|
+
elements.statusMessage.classList.remove("hidden");
|
|
531
|
+
|
|
532
|
+
// Auto-hide after 5 seconds
|
|
533
|
+
setTimeout(() => {
|
|
534
|
+
elements.statusMessage.classList.add("hidden");
|
|
535
|
+
}, 5000);
|
|
536
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Test Gramercy.cloud Regex Pattern</title>
|
|
5
|
+
<style>
|
|
6
|
+
body { font-family: Arial, sans-serif; padding: 20px; max-width: 800px; }
|
|
7
|
+
.test-section { margin: 20px 0; padding: 20px; border: 2px solid #ddd; border-radius: 8px; }
|
|
8
|
+
.success { border-color: #28a745; background: #f8fff8; }
|
|
9
|
+
.warning { border-color: #ffc107; background: #fffbf0; }
|
|
10
|
+
.code { background: #e9ecef; padding: 8px; font-family: monospace; margin: 8px 0; word-break: break-all; }
|
|
11
|
+
.results { background: #f5f5f5; padding: 10px; margin: 10px 0; border-radius: 4px; }
|
|
12
|
+
button { padding: 10px 15px; margin: 5px; cursor: pointer; background: #007bff; color: white; border: none; border-radius: 4px; }
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<h1>Gramercy.cloud Regex Test</h1>
|
|
17
|
+
|
|
18
|
+
<div class="test-section success">
|
|
19
|
+
<h2>โ
Your Regex Pattern</h2>
|
|
20
|
+
<div class="code">([a-zA-Z0-9-]+\.)gramercy\.cloud\/uploads</div>
|
|
21
|
+
<p><strong>Target URL:</strong></p>
|
|
22
|
+
<div class="code">https://hilton-pop-art-cytz-dani-martin-hueg.gramercy.cloud/uploads/assets/5233/file_name/nU01Ln1738011172.png?URLPrefix=...</div>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div class="test-section">
|
|
26
|
+
<h2>๐งช Regex Testing</h2>
|
|
27
|
+
<button onclick="testRegex()">Test Regex Match</button>
|
|
28
|
+
<button onclick="testActualRequest()">Test Actual XHR Request</button>
|
|
29
|
+
<div id="testResults" class="results"></div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div class="test-section warning">
|
|
33
|
+
<h2>โ๏ธ Extension Setup Required</h2>
|
|
34
|
+
<ol>
|
|
35
|
+
<li>Open the Traffic Proxy extension popup</li>
|
|
36
|
+
<li>Add a new rule:</li>
|
|
37
|
+
<ul>
|
|
38
|
+
<li><strong>Pattern:</strong> <code>([a-zA-Z0-9-]+\.)gramercy\.cloud\/uploads</code></li>
|
|
39
|
+
<li><strong>Redirect To:</strong> <code>your-proxy-server.com</code></li>
|
|
40
|
+
</ul>
|
|
41
|
+
<li>Enable the proxy (green button)</li>
|
|
42
|
+
<li>Click "Test Actual XHR Request" below</li>
|
|
43
|
+
</ol>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<script>
|
|
47
|
+
function log(message) {
|
|
48
|
+
const results = document.getElementById('testResults');
|
|
49
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
50
|
+
results.innerHTML += `<div>${timestamp}: ${message}</div>`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function testRegex() {
|
|
54
|
+
const results = document.getElementById('testResults');
|
|
55
|
+
results.innerHTML = '';
|
|
56
|
+
|
|
57
|
+
const pattern = /([a-zA-Z0-9-]+\.)gramercy\.cloud\/uploads/i;
|
|
58
|
+
const testUrls = [
|
|
59
|
+
'https://hilton-pop-art-cytz-dani-martin-hueg.gramercy.cloud/uploads/assets/5233/file_name/nU01Ln1738011172.png',
|
|
60
|
+
'hilton-pop-art-cytz-dani-martin-hueg.gramercy.cloud', // hostname only
|
|
61
|
+
'hilton-pop-art-cytz-dani-martin-hueg.gramercy.cloud/uploads', // hostname + path
|
|
62
|
+
'other-subdomain.gramercy.cloud/uploads/test.jpg',
|
|
63
|
+
'gramercy.cloud/uploads', // should NOT match (no subdomain)
|
|
64
|
+
'hilton-pop-art-cytz-dani-martin-hueg.gramercy.cloud/downloads' // should NOT match (wrong path)
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
log('๐งช Testing regex pattern against various URLs:');
|
|
68
|
+
|
|
69
|
+
testUrls.forEach(url => {
|
|
70
|
+
const matches = pattern.test(url);
|
|
71
|
+
const icon = matches ? 'โ
' : 'โ';
|
|
72
|
+
log(`${icon} ${url} - ${matches ? 'MATCHES' : 'NO MATCH'}`);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
log('');
|
|
76
|
+
log('๐ Summary: Your regex will match URLs with:');
|
|
77
|
+
log(' โข Any subdomain of gramercy.cloud');
|
|
78
|
+
log(' โข Path starting with /uploads');
|
|
79
|
+
log(' โข Case insensitive matching');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function testActualRequest() {
|
|
83
|
+
const results = document.getElementById('testResults');
|
|
84
|
+
results.innerHTML = '';
|
|
85
|
+
|
|
86
|
+
log('๐ Testing actual XHR request to gramercy.cloud...');
|
|
87
|
+
|
|
88
|
+
// The exact URL from your example
|
|
89
|
+
const testUrl = 'https://hilton-pop-art-cytz-dani-martin-hueg.gramercy.cloud/uploads/assets/5233/file_name/nU01Ln1738011172.png?URLPrefix=aHR0cHM6Ly9oaWx0b24tcG9wLWFydC1jeXR6LWRhbmktbWFydGluLWh1ZWcuZ3JhbWVyY3kuY2xvdWQvdXBsb2Fkcy9hc3NldHMvNTIzMy9maWxlX25hbWU=&Expires=1749745178&KeyName=uploads-backend-key&Signature=s1rfbFVLZWNdagigcQxbRacOa4k=';
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
log('๐ก Making XHR request...');
|
|
93
|
+
|
|
94
|
+
const xhr = new XMLHttpRequest();
|
|
95
|
+
xhr.onload = function() {
|
|
96
|
+
log(`โ
XHR Success: ${xhr.status} ${xhr.statusText}`);
|
|
97
|
+
log(`๐ Response size: ${xhr.responseText.length} bytes`);
|
|
98
|
+
log('๐ Check browser Network tab to see if request was intercepted');
|
|
99
|
+
log('๐ You should see a proxy notification if extension is working');
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
xhr.onerror = function() {
|
|
103
|
+
log('โ XHR failed - this might be expected if proxy redirected');
|
|
104
|
+
log('๐ Check browser Network tab to see actual destination');
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
xhr.ontimeout = function() {
|
|
108
|
+
log('โฐ XHR timed out');
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
xhr.open('GET', testUrl);
|
|
112
|
+
xhr.timeout = 10000; // 10 second timeout
|
|
113
|
+
xhr.send();
|
|
114
|
+
|
|
115
|
+
} catch (error) {
|
|
116
|
+
log(`โ Error making request: ${error.message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Auto-run regex test on page load
|
|
121
|
+
window.addEventListener('load', function() {
|
|
122
|
+
testRegex();
|
|
123
|
+
});
|
|
124
|
+
</script>
|
|
125
|
+
</body>
|
|
126
|
+
</html>
|