Compare commits

..

No commits in common. "66272fa31824019e8915d04846167f9eb08015fb" and "eea9808d096e4116e707065a37bc20db200ecc28" have entirely different histories.

16 changed files with 134 additions and 141 deletions

1
.gitignore vendored
View File

@ -2,4 +2,3 @@
node_modules
sidebar.js
/web-ext-artifacts/
lib/*

View File

@ -1,5 +0,0 @@
import { init } from "./memory";
init();
alert("memory initialized!");

View File

@ -7,12 +7,9 @@
"sidebar_action": {
"default_title": "ICD Skaner",
"default_panel": "sidebar/sidebar.html",
"default_panel": "sidebar.html",
"default_icon": "sidebar_icon.png"
},
"background": {
"scripts": ["lib/background.js"]
},
"icons": {
"48": "icons/border-48.png"
},

View File

@ -3,7 +3,7 @@ import { getshorthost } from "./util";
import { EventEmitter } from "events";
import { RequestCluster } from "./request-cluster";
export default class Memory extends EventEmitter {
class Memory extends EventEmitter {
origin_to_history = {} as Record<string, Record<string, RequestCluster>>;
async register(request: ExtendedRequest) {
await request.init();
@ -64,8 +64,6 @@ export default class Memory extends EventEmitter {
}
}
export function init() {
const memory = new Memory();
(window as any).memory = memory;
}
export default memory;

View File

@ -4,7 +4,7 @@
"description": "",
"main": "email-template-harsh.js",
"scripts": {
"build": "npx esbuild sidebar/sidebar.tsx report-window/report-window.tsx --bundle background.ts --bundle --outdir=./lib",
"build": "npx esbuild sidebar.tsx --bundle --outfile=./lib/sidebar.js",
"watch": "npm run build -- --watch"
},
"repository": {

9
popup.html Normal file
View File

@ -0,0 +1,9 @@
<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 Normal file
View File

@ -0,0 +1,90 @@
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 }),
]);
};

View File

@ -1,11 +0,0 @@
<!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>

View File

@ -1,15 +0,0 @@
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"));

View File

@ -4,8 +4,7 @@ import ExtendedRequest from "./extended-request";
export type Sources = "cookie" | "pathname" | "queryparams" | "header";
import { TCString, TCModel } from "@iabtcf/core";
import { getMemory, isJSONObject, isURL, parseToObject } from "./util";
import memory from "./memory";
import { isJSONObject, isURL, parseToObject } from "./util";
const id = (function* id() {
let i = 0;
@ -78,33 +77,17 @@ export class StolenDataEntry {
getParsedValue(key_path: string): string | Record<string, unknown> {
let object = StolenDataEntry.parseValue(this.value);
console.log("key_path", key_path);
for (const key of key_path.split(".")) {
if (key === "") continue;
console.log(key, object[key]);
object = StolenDataEntry.parseValue(object[key]);
}
return object;
}
addMark(key: string) {
addMarkedValue(key: string) {
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);
}
}
}
@ -148,22 +131,8 @@ export class MergedStolenDataEntry {
);
}
addMark(key: string) {
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));
addMarkedValue(key: string) {
this.entries.forEach((entry) => entry.addMarkedValue(key));
}
}

View File

@ -39,7 +39,6 @@
</head>
<body>
<div id="app"></div>
<script src="/lib/sidebar/sidebar.js"></script>
<script src="./lib/sidebar.js"></script>
</body>
</html>

View File

@ -1,8 +1,9 @@
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import Options from "../options";
import memory from "./memory";
import Options from "./options";
import { StolenData } from "./stolen-data";
import { getMemory, useEmitter } from "../util";
import { useEmitter } from "./util";
async function getCurrentTab() {
const [tab] = await browser.tabs.query({
@ -16,7 +17,7 @@ const Sidebar = () => {
const [origin, setOrigin] = useState<string | null>(null);
const [minValueLength, setMinValueLength] = useState<number | null>(7);
const [cookiesOnly, setCookiesOnly] = useState<boolean>(false);
const [counter, setCounter] = useEmitter(getMemory());
const [counter, setCounter] = useEmitter(memory);
useEffect(() => {
const listener = async (data) => {

View File

@ -1,7 +1,7 @@
import React from "react";
import memory from "../memory";
import { MergedStolenDataEntry, Sources } from "../request-cluster";
import { getMemory, hyphenate } from "../util";
import memory from "./memory";
import { MergedStolenDataEntry, Sources } from "./request-cluster";
import { hyphenate } from "./util";
function StolenDataValueTable({
entry,
@ -15,14 +15,7 @@ function StolenDataValueTable({
<tbody>
{Object.keys(entry.getParsedValues(prefixKey)[0]).map((key) => (
<tr key={`${prefixKey}.${key}`}>
<th
onClick={(e) => {
entry.toggleMark(prefixKey);
e.stopPropagation();
}}
>
{hyphenate(key)}
</th>
<th>{hyphenate(key)}</th>
<td>
<StolenDataValue
entry={entry}
@ -44,29 +37,13 @@ function StolenDataValue({
prefixKey?: string;
}) {
const value = entry.getParsedValues(prefixKey)[0];
let body = null;
if (!value) {
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} />;
return <></>;
}
return (
<div
onClick={(e) => {
entry.toggleMark(prefixKey);
e.stopPropagation();
}}
data-marks={entry.getMarkedValues().join(", ")}
>
{body}
</div>
);
if (typeof value === "string") {
return <>{entry.getParsedValues(prefixKey)[0] as string}</>;
}
return <StolenDataValueTable entry={entry} prefixKey={prefixKey} />;
}
export default function StolenDataCluster({
@ -81,7 +58,7 @@ export default function StolenDataCluster({
minValueLength: number;
cookiesOnly: boolean;
}) {
const cluster = getMemory().getClustersForOrigin(origin)[shorthost];
const cluster = memory.getClustersForOrigin(origin)[shorthost];
const icons: Record<Sources, string> = {
cookie: "🍪",
pathname: "🛣",
@ -91,12 +68,12 @@ export default function StolenDataCluster({
return (
<div>
<h2>
<a href={"https://" + cluster.id}>{cluster.id}</a>{" "}
{cluster.hasCookies() ? "🍪" : ""} x{cluster.requests.length}{" "}
{cluster.id} {cluster.hasCookies() ? "🍪" : ""} x
{cluster.requests.length}{" "}
<a
href="#"
style={{ fontSize: "10px" }}
onClick={() => getMemory().removeCookiesFor(origin, shorthost)}
onClick={() => memory.removeCookiesFor(origin, shorthost)}
>
Wyczyść cookiesy
</a>

View File

@ -1,7 +1,8 @@
import React from "react";
import { RequestCluster } from "../request-cluster";
import memory from "./memory";
import { RequestCluster } from "./request-cluster";
import StolenDataCluster from "./stolen-data-cluster";
import { getMemory, getshorthost } from "../util";
import { getshorthost } from "./util";
export function StolenData({
origin,
@ -19,7 +20,7 @@ export function StolenData({
if (!origin) {
return <div></div>;
}
const clusters = Object.values(getMemory().getClustersForOrigin(origin)).sort(
const clusters = Object.values(memory.getClustersForOrigin(origin)).sort(
RequestCluster.sortCompare
);
return (
@ -31,7 +32,7 @@ export function StolenData({
<button
style={{ marginLeft: "1rem" }}
onClick={() =>
getMemory().removeCookiesFor(
memory.removeCookiesFor(
origin,
getshorthost(new URL(origin).host)
)
@ -42,23 +43,12 @@ export function StolenData({
<button
style={{ marginLeft: "1rem" }}
onClick={() => {
getMemory().removeRequestsFor(origin);
memory.removeRequestsFor(origin);
refresh();
}}
>
Wyczyść pamięć
</button>
<button
onClick={() =>
window.open(
"/report-window/report-window.html",
"new_window",
"width=800,height=600"
)
}
>
Generuj maila
</button>
</h1>
{clusters
.filter((cluster) => !cookiesOnly || cluster.hasCookies())

View File

@ -1,6 +1,5 @@
import { EventEmitter } from "events";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import Memory from "./memory";
export type Unpromisify<T> = T extends Promise<infer R> ? R : T;
export type Unarray<T> = T extends Array<infer R> ? R : T;
@ -77,7 +76,3 @@ export function isURL(str: unknown): str is string {
export function hyphenate(str: string): string {
return str.replace(/[_\[A-Z]/g, `${String.fromCharCode(173)}$&`);
}
export function getMemory(): Memory {
return (browser.extension.getBackgroundPage().window as any).memory as Memory;
}