Compare commits
2 Commits
eea9808d09
...
66272fa318
Author | SHA1 | Date | |
---|---|---|---|
66272fa318 | |||
52b3ae39ea |
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
sidebar.js
|
sidebar.js
|
||||||
/web-ext-artifacts/
|
/web-ext-artifacts/
|
||||||
|
lib/*
|
||||||
|
5
background.ts
Normal file
5
background.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { init } from "./memory";
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
alert("memory initialized!");
|
@ -7,9 +7,12 @@
|
|||||||
|
|
||||||
"sidebar_action": {
|
"sidebar_action": {
|
||||||
"default_title": "ICD Skaner",
|
"default_title": "ICD Skaner",
|
||||||
"default_panel": "sidebar.html",
|
"default_panel": "sidebar/sidebar.html",
|
||||||
"default_icon": "sidebar_icon.png"
|
"default_icon": "sidebar_icon.png"
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"scripts": ["lib/background.js"]
|
||||||
|
},
|
||||||
"icons": {
|
"icons": {
|
||||||
"48": "icons/border-48.png"
|
"48": "icons/border-48.png"
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@ import { getshorthost } from "./util";
|
|||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { RequestCluster } from "./request-cluster";
|
import { RequestCluster } from "./request-cluster";
|
||||||
|
|
||||||
class Memory extends EventEmitter {
|
export default class Memory extends EventEmitter {
|
||||||
origin_to_history = {} as Record<string, Record<string, RequestCluster>>;
|
origin_to_history = {} as Record<string, Record<string, RequestCluster>>;
|
||||||
async register(request: ExtendedRequest) {
|
async register(request: ExtendedRequest) {
|
||||||
await request.init();
|
await request.init();
|
||||||
@ -64,6 +64,8 @@ class Memory extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const memory = new Memory();
|
export function init() {
|
||||||
|
const memory = new Memory();
|
||||||
|
|
||||||
export default memory;
|
(window as any).memory = memory;
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "email-template-harsh.js",
|
"main": "email-template-harsh.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npx esbuild sidebar.tsx --bundle --outfile=./lib/sidebar.js",
|
"build": "npx esbuild sidebar/sidebar.tsx report-window/report-window.tsx --bundle background.ts --bundle --outdir=./lib",
|
||||||
"watch": "npm run build -- --watch"
|
"watch": "npm run build -- --watch"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
<meta charset="utf-8">
|
|
||||||
<button id="clean">clean memory</button>
|
|
||||||
<button id="copy_harsh">copy harsh email template</button>
|
|
||||||
<button id="copy_polite">copy polite email template</button>
|
|
||||||
<div id="output"></div>
|
|
||||||
<script src="popup.js"></script>
|
|
||||||
<script src="render-data-list.js"></script>
|
|
||||||
<script src="email-template-harsh.js"></script>
|
|
||||||
<script src="email-template-polite.js"></script>
|
|
90
popup.js
90
popup.js
@ -1,90 +0,0 @@
|
|||||||
output.innerHTML = "loading...";
|
|
||||||
let tabid = null;
|
|
||||||
let tab = null;
|
|
||||||
let memory = null;
|
|
||||||
|
|
||||||
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
|
|
||||||
var currTab = tabs[0];
|
|
||||||
if (currTab) {
|
|
||||||
// Sanity check
|
|
||||||
/* document.write(JSON.stringify(currTab)); */
|
|
||||||
tabid = currTab.id;
|
|
||||||
tab = currTab;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function atLeastOneCookiedRequest(requests) {
|
|
||||||
return requests.some((request) => request.has_cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortByShorthost(tabdata) {
|
|
||||||
return Object.entries(tabdata).sort(([shorthost1], [shorthost2]) => {
|
|
||||||
return shorthost1 > shorthost2;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractAllCookies(requests) {
|
|
||||||
return Array.from(new Set(requests.map((request) => request.cookie))).filter(
|
|
||||||
(cookie) => cookie !== undefined
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function render(memory = {}) {
|
|
||||||
let output_txt = "";
|
|
||||||
if (!memory?.[tabid]) {
|
|
||||||
output_txt = "No data for this tab";
|
|
||||||
output.innerHTML = output_txt;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
output_txt = /* HTML */ `<h2>
|
|
||||||
Część Twojej historii przeglądania została wysłana przez stronę ${tab.url}
|
|
||||||
do:
|
|
||||||
</h2>
|
|
||||||
<ul></ul>`;
|
|
||||||
sortByShorthost(memory[tabid]).forEach(([shorthost, requests]) => {
|
|
||||||
output_txt += /* HTML */ `
|
|
||||||
<li>
|
|
||||||
${shorthost}
|
|
||||||
${atLeastOneCookiedRequest(requests)
|
|
||||||
? /* HTML */ `🍪 <ul>
|
|
||||||
${extractAllCookies(requests)
|
|
||||||
.map((cookie) => `<li><code>${cookie}</code></li>`)
|
|
||||||
.join("\n")}
|
|
||||||
</ul>`
|
|
||||||
: ""}
|
|
||||||
</li>
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
output_txt += "</ul>";
|
|
||||||
output.innerHTML = output_txt;
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.runtime.sendMessage({ msg: "get_memory" }, (_memory) => {
|
|
||||||
memory = _memory;
|
|
||||||
render(memory);
|
|
||||||
});
|
|
||||||
|
|
||||||
clean.onclick = () => {
|
|
||||||
chrome.runtime.sendMessage({ msg: "clear_memory" }, (memory_) => {
|
|
||||||
memory = memory_;
|
|
||||||
render(memory);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function getDate() {
|
|
||||||
return new Date().toISOString().split("T")[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_harsh.onclick = () => {
|
|
||||||
const text_html = harsh_email_template();
|
|
||||||
navigator.clipboard.write([
|
|
||||||
new ClipboardItem({ "text/plain": text_html, "text/html": text_html }),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
copy_polite.onclick = () => {
|
|
||||||
const text_html = polite_email_template();
|
|
||||||
navigator.clipboard.write([
|
|
||||||
new ClipboardItem({ "text/plain": text_html, "text/html": text_html }),
|
|
||||||
]);
|
|
||||||
};
|
|
11
report-window/report-window.html
Normal file
11
report-window/report-window.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Wygeneruj maila co zgłoszenia</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script src="/lib/report-window/report-window.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
15
report-window/report-window.tsx
Normal file
15
report-window/report-window.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom";
|
||||||
|
import { Memory } from "../memory";
|
||||||
|
|
||||||
|
const memory = (window as any).memory as Memory;
|
||||||
|
|
||||||
|
function Report() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Raport</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(<Report />, document.getElementById("app"));
|
@ -4,7 +4,8 @@ import ExtendedRequest from "./extended-request";
|
|||||||
export type Sources = "cookie" | "pathname" | "queryparams" | "header";
|
export type Sources = "cookie" | "pathname" | "queryparams" | "header";
|
||||||
|
|
||||||
import { TCString, TCModel } from "@iabtcf/core";
|
import { TCString, TCModel } from "@iabtcf/core";
|
||||||
import { isJSONObject, isURL, parseToObject } from "./util";
|
import { getMemory, isJSONObject, isURL, parseToObject } from "./util";
|
||||||
|
import memory from "./memory";
|
||||||
|
|
||||||
const id = (function* id() {
|
const id = (function* id() {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
@ -77,17 +78,33 @@ export class StolenDataEntry {
|
|||||||
|
|
||||||
getParsedValue(key_path: string): string | Record<string, unknown> {
|
getParsedValue(key_path: string): string | Record<string, unknown> {
|
||||||
let object = StolenDataEntry.parseValue(this.value);
|
let object = StolenDataEntry.parseValue(this.value);
|
||||||
console.log("key_path", key_path);
|
|
||||||
for (const key of key_path.split(".")) {
|
for (const key of key_path.split(".")) {
|
||||||
if (key === "") continue;
|
if (key === "") continue;
|
||||||
console.log(key, object[key]);
|
|
||||||
object = StolenDataEntry.parseValue(object[key]);
|
object = StolenDataEntry.parseValue(object[key]);
|
||||||
}
|
}
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
addMarkedValue(key: string) {
|
addMark(key: string) {
|
||||||
this.markedKeys.push(key);
|
this.markedKeys.push(key);
|
||||||
|
getMemory().emit("change"); // to trigger rerender
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMark(key: string) {
|
||||||
|
return this.markedKeys.some((k) => k == key);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeMark(key: string) {
|
||||||
|
this.markedKeys = this.markedKeys.filter((e) => e != key);
|
||||||
|
getMemory().emit("change"); // to trigger rerender
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMark(key: string) {
|
||||||
|
if (this.hasMark(key)) {
|
||||||
|
this.removeMark(key);
|
||||||
|
} else {
|
||||||
|
this.addMark(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,8 +148,22 @@ export class MergedStolenDataEntry {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addMarkedValue(key: string) {
|
addMark(key: string) {
|
||||||
this.entries.forEach((entry) => entry.addMarkedValue(key));
|
this.entries.forEach((entry) => entry.addMark(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
getMarkedValues() {
|
||||||
|
return this.entries
|
||||||
|
.map((entry) => entry.markedKeys)
|
||||||
|
.reduce((a, b) => a.concat(b), []);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMark(key: string): boolean {
|
||||||
|
return this.entries.some((entry) => entry.hasMark(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMark(key: string): void {
|
||||||
|
this.entries.forEach((entry) => entry.toggleMark(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script src="./lib/sidebar.js"></script>
|
<script src="/lib/sidebar/sidebar.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,9 +1,8 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import memory from "./memory";
|
import Options from "../options";
|
||||||
import Options from "./options";
|
|
||||||
import { StolenData } from "./stolen-data";
|
import { StolenData } from "./stolen-data";
|
||||||
import { useEmitter } from "./util";
|
import { getMemory, useEmitter } from "../util";
|
||||||
|
|
||||||
async function getCurrentTab() {
|
async function getCurrentTab() {
|
||||||
const [tab] = await browser.tabs.query({
|
const [tab] = await browser.tabs.query({
|
||||||
@ -17,7 +16,7 @@ const Sidebar = () => {
|
|||||||
const [origin, setOrigin] = useState<string | null>(null);
|
const [origin, setOrigin] = useState<string | null>(null);
|
||||||
const [minValueLength, setMinValueLength] = useState<number | null>(7);
|
const [minValueLength, setMinValueLength] = useState<number | null>(7);
|
||||||
const [cookiesOnly, setCookiesOnly] = useState<boolean>(false);
|
const [cookiesOnly, setCookiesOnly] = useState<boolean>(false);
|
||||||
const [counter, setCounter] = useEmitter(memory);
|
const [counter, setCounter] = useEmitter(getMemory());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const listener = async (data) => {
|
const listener = async (data) => {
|
@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import memory from "./memory";
|
import memory from "../memory";
|
||||||
import { MergedStolenDataEntry, Sources } from "./request-cluster";
|
import { MergedStolenDataEntry, Sources } from "../request-cluster";
|
||||||
import { hyphenate } from "./util";
|
import { getMemory, hyphenate } from "../util";
|
||||||
|
|
||||||
function StolenDataValueTable({
|
function StolenDataValueTable({
|
||||||
entry,
|
entry,
|
||||||
@ -15,7 +15,14 @@ function StolenDataValueTable({
|
|||||||
<tbody>
|
<tbody>
|
||||||
{Object.keys(entry.getParsedValues(prefixKey)[0]).map((key) => (
|
{Object.keys(entry.getParsedValues(prefixKey)[0]).map((key) => (
|
||||||
<tr key={`${prefixKey}.${key}`}>
|
<tr key={`${prefixKey}.${key}`}>
|
||||||
<th>{hyphenate(key)}</th>
|
<th
|
||||||
|
onClick={(e) => {
|
||||||
|
entry.toggleMark(prefixKey);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{hyphenate(key)}
|
||||||
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<StolenDataValue
|
<StolenDataValue
|
||||||
entry={entry}
|
entry={entry}
|
||||||
@ -37,13 +44,29 @@ function StolenDataValue({
|
|||||||
prefixKey?: string;
|
prefixKey?: string;
|
||||||
}) {
|
}) {
|
||||||
const value = entry.getParsedValues(prefixKey)[0];
|
const value = entry.getParsedValues(prefixKey)[0];
|
||||||
|
let body = null;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return <></>;
|
body = <></>;
|
||||||
|
} else if (typeof value === "string") {
|
||||||
|
body = (
|
||||||
|
<div style={{ border: entry.hasMark(prefixKey) ? "2px solid red" : "" }}>
|
||||||
|
{entry.getParsedValues(prefixKey)[0] as string}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
body = <StolenDataValueTable entry={entry} prefixKey={prefixKey} />;
|
||||||
}
|
}
|
||||||
if (typeof value === "string") {
|
return (
|
||||||
return <>{entry.getParsedValues(prefixKey)[0] as string}</>;
|
<div
|
||||||
}
|
onClick={(e) => {
|
||||||
return <StolenDataValueTable entry={entry} prefixKey={prefixKey} />;
|
entry.toggleMark(prefixKey);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
data-marks={entry.getMarkedValues().join(", ")}
|
||||||
|
>
|
||||||
|
{body}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function StolenDataCluster({
|
export default function StolenDataCluster({
|
||||||
@ -58,7 +81,7 @@ export default function StolenDataCluster({
|
|||||||
minValueLength: number;
|
minValueLength: number;
|
||||||
cookiesOnly: boolean;
|
cookiesOnly: boolean;
|
||||||
}) {
|
}) {
|
||||||
const cluster = memory.getClustersForOrigin(origin)[shorthost];
|
const cluster = getMemory().getClustersForOrigin(origin)[shorthost];
|
||||||
const icons: Record<Sources, string> = {
|
const icons: Record<Sources, string> = {
|
||||||
cookie: "🍪",
|
cookie: "🍪",
|
||||||
pathname: "🛣",
|
pathname: "🛣",
|
||||||
@ -68,12 +91,12 @@ export default function StolenDataCluster({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2>
|
<h2>
|
||||||
{cluster.id} {cluster.hasCookies() ? "🍪" : ""} x
|
<a href={"https://" + cluster.id}>{cluster.id}</a>{" "}
|
||||||
{cluster.requests.length}{" "}
|
{cluster.hasCookies() ? "🍪" : ""} x{cluster.requests.length}{" "}
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
style={{ fontSize: "10px" }}
|
style={{ fontSize: "10px" }}
|
||||||
onClick={() => memory.removeCookiesFor(origin, shorthost)}
|
onClick={() => getMemory().removeCookiesFor(origin, shorthost)}
|
||||||
>
|
>
|
||||||
Wyczyść cookiesy
|
Wyczyść cookiesy
|
||||||
</a>
|
</a>
|
@ -1,8 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import memory from "./memory";
|
import { RequestCluster } from "../request-cluster";
|
||||||
import { RequestCluster } from "./request-cluster";
|
|
||||||
import StolenDataCluster from "./stolen-data-cluster";
|
import StolenDataCluster from "./stolen-data-cluster";
|
||||||
import { getshorthost } from "./util";
|
import { getMemory, getshorthost } from "../util";
|
||||||
|
|
||||||
export function StolenData({
|
export function StolenData({
|
||||||
origin,
|
origin,
|
||||||
@ -20,7 +19,7 @@ export function StolenData({
|
|||||||
if (!origin) {
|
if (!origin) {
|
||||||
return <div></div>;
|
return <div></div>;
|
||||||
}
|
}
|
||||||
const clusters = Object.values(memory.getClustersForOrigin(origin)).sort(
|
const clusters = Object.values(getMemory().getClustersForOrigin(origin)).sort(
|
||||||
RequestCluster.sortCompare
|
RequestCluster.sortCompare
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
@ -32,7 +31,7 @@ export function StolenData({
|
|||||||
<button
|
<button
|
||||||
style={{ marginLeft: "1rem" }}
|
style={{ marginLeft: "1rem" }}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
memory.removeCookiesFor(
|
getMemory().removeCookiesFor(
|
||||||
origin,
|
origin,
|
||||||
getshorthost(new URL(origin).host)
|
getshorthost(new URL(origin).host)
|
||||||
)
|
)
|
||||||
@ -43,12 +42,23 @@ export function StolenData({
|
|||||||
<button
|
<button
|
||||||
style={{ marginLeft: "1rem" }}
|
style={{ marginLeft: "1rem" }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
memory.removeRequestsFor(origin);
|
getMemory().removeRequestsFor(origin);
|
||||||
refresh();
|
refresh();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Wyczyść pamięć
|
Wyczyść pamięć
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
window.open(
|
||||||
|
"/report-window/report-window.html",
|
||||||
|
"new_window",
|
||||||
|
"width=800,height=600"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Generuj maila
|
||||||
|
</button>
|
||||||
</h1>
|
</h1>
|
||||||
{clusters
|
{clusters
|
||||||
.filter((cluster) => !cookiesOnly || cluster.hasCookies())
|
.filter((cluster) => !cookiesOnly || cluster.hasCookies())
|
5
util.ts
5
util.ts
@ -1,5 +1,6 @@
|
|||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||||
|
import Memory from "./memory";
|
||||||
|
|
||||||
export type Unpromisify<T> = T extends Promise<infer R> ? R : T;
|
export type Unpromisify<T> = T extends Promise<infer R> ? R : T;
|
||||||
export type Unarray<T> = T extends Array<infer R> ? R : T;
|
export type Unarray<T> = T extends Array<infer R> ? R : T;
|
||||||
@ -76,3 +77,7 @@ export function isURL(str: unknown): str is string {
|
|||||||
export function hyphenate(str: string): string {
|
export function hyphenate(str: string): string {
|
||||||
return str.replace(/[_\[A-Z]/g, `${String.fromCharCode(173)}$&`);
|
return str.replace(/[_\[A-Z]/g, `${String.fromCharCode(173)}$&`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMemory(): Memory {
|
||||||
|
return (browser.extension.getBackgroundPage().window as any).memory as Memory;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user