Compare commits

..

No commits in common. "b0dd58fa9cb7c0b9b72b0b68dd0de296ab51cd65" and "7527288d95ff55fcc1709c6a38d711ab72210def" have entirely different histories.

8 changed files with 92 additions and 175 deletions

View File

@ -303,8 +303,4 @@ export default class ExtendedRequest {
connection: "443", connection: "443",
}; };
} }
getMaxPriority() {
return Math.max(...this.stolenData.map((entry) => entry.getPriority()));
}
} }

View File

@ -1,10 +1,6 @@
import React from "react"; import React from "react";
import { RequestCluster } from "../request-cluster"; import { RequestCluster } from "../request-cluster";
import { import { Classifications, Sources } from "../stolen-data-entry";
Classifications,
Sources,
StolenDataEntry,
} from "../stolen-data-entry";
const emailClassifications: Record<keyof typeof Classifications, string> = { const emailClassifications: Record<keyof typeof Classifications, string> = {
id: "sztucznie nadane mi ID", id: "sztucznie nadane mi ID",
@ -29,10 +25,11 @@ export default function DomainSummary({
Właścicielowi domeny <strong>{cluster.id}</strong> zostały ujawnione:{" "} Właścicielowi domeny <strong>{cluster.id}</strong> zostały ujawnione:{" "}
<ul> <ul>
<li>Mój adres IP</li> <li>Mój adres IP</li>
{cluster.representativeStolenData {cluster
.getRepresentativeStolenData()
.filter((entry) => entry.isMarked) .filter((entry) => entry.isMarked)
.map((entry) => ( .map((entry) => (
<li key={entry.id}> <li>
{emailClassifications[entry.classification]}{" "} {emailClassifications[entry.classification]}{" "}
{emailSources[entry.source]} (nazwa: <code>{entry.name}</code>,{" "} {emailSources[entry.source]} (nazwa: <code>{entry.name}</code>,{" "}
wartość: <code>{entry.getValuePreview()}</code>) wartość: <code>{entry.getValuePreview()}</code>)

View File

@ -192,20 +192,18 @@ export default function EmailTemplate2({
. .
</> </>
) : ( ) : (
<> /* HTML */ `o ile po wejściu na stronę wcisnąłem w wyskakującym
o ile po wejściu na stronę wcisnąłem w wyskakującym okienku przycisk okienku przycisk ${config.popup_accept_all_text}, o tyle nie stanowi
{config.popup_accept_all_text}, o tyle nie stanowi to według mnie to według mnie ważnej w świetle RODO zgody, gdyż brakowało w tym
ważnej w świetle RODO zgody, gdyż brakowało w tym okienku równie okienku równie łatwo osiągalnego przycisku, którego kliknięcie
łatwo osiągalnego przycisku, którego kliknięcie skutkowałoby skutkowałoby zasygnalizowaniem braku mojej zgody na takie
zasygnalizowaniem braku mojej zgody na takie przetwarzanie moich przetwarzanie moich danych. Mówiąc wprost &mdash; wyrażenie zgody
danych. Mówiąc wprost &mdash; wyrażenie zgody było łatwiejsze niż było łatwiejsze niż jej niewyrażenie. Niewyrażenie zgody wiąże się z
jej niewyrażenie. Niewyrażenie zgody wiąże się z negatywną negatywną konsekwencją konieczności przechodzenia przez dodatkowe
konsekwencją konieczności przechodzenia przez dodatkowe kroki w kroki w wyskakującym okienku. Zatem tak otrzymana przez Państwo moja
wyskakującym okienku. Zatem tak otrzymana przez Państwo moja zgoda zgoda nie jest poprawną podstawą prawną do przetwarzania moich
nie jest poprawną podstawą prawną do przetwarzania moich danych danych osobowych, gdyż nie spełnia warunku dobrowolności wspomnianego
osobowych, gdyż nie spełnia warunku dobrowolności wspomnianego w w Art. 4. pkt 11. RODO.`
Art. 4. pkt 11. RODO.
</>
)}{" "} )}{" "}
Za zgodę nie można też uznać posiadania włączonej obsługi cookies w Za zgodę nie można też uznać posiadania włączonej obsługi cookies w
przeglądarce, jakichkolwiek innych ustawień przeglądarki, ani pasywnych przeglądarce, jakichkolwiek innych ustawień przeglądarki, ani pasywnych
@ -382,5 +380,4 @@ export default function EmailTemplate2({
</p> </p>
</> </>
); );
return result;
} }

View File

@ -22,36 +22,9 @@ function handleNewFile(
} }
function generateFakeHAR(entries: StolenDataEntry[]) { function generateFakeHAR(entries: StolenDataEntry[]) {
const requests = unique(entries.map((entry) => entry.request)) const requests = entries
.sort((request1, request2) => { .sort((entry1, entry2) => entry2.getPriority() - entry1.getPriority())
if (request1.shorthost < request2.shorthost) { .map((entry) => entry.request);
return -1;
} else if (request1.shorthost > request2.shorthost) {
return 1;
} else {
return request2.getMaxPriority() - request1.getMaxPriority();
}
})
.filter((_, index, array) => {
if (index !== 0 && array[index].shorthost == array[index - 1].shorthost) {
return false;
}
return true;
})
.sort(
(entry1, entry2) => entry2.getMaxPriority() - entry1.getMaxPriority()
);
console.log(
"GENERATEHAR! Got",
entries.length,
"entries, ",
unique(entries.map((e) => e.request)),
"requests. Filtered down to",
requests.length,
"requests"
);
return { return {
log: { log: {
version: "1.2", version: "1.2",
@ -74,7 +47,7 @@ function generateFakeHAR(entries: StolenDataEntry[]) {
}, },
}, },
], ],
entries: requests.map((r) => r.toHAR()), entries: unique(requests).map((r) => r.toHAR()),
}, },
}; };
} }

View File

@ -1,20 +1,27 @@
import React, { useEffect, useState } from "react"; import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { getMemory } from "../memory"; import { getMemory } from "../memory";
import { Classifications, StolenDataEntry } from "../stolen-data-entry"; import { Classifications } from "../stolen-data-entry";
import { reduceConcat, useEmitter } from "../util"; import { reduceConcat, useEmitter } from "../util";
import EmailTemplate from "./email-template"; import EmailTemplate from "./email-template";
import HARConverter from "./har-converter"; import HARConverter from "./har-converter";
function DataPreview({ function Report() {
entries, const origin = new URL(document.location.toString()).searchParams.get(
refresh, "origin"
}: { );
entries: StolenDataEntry[]; const [counter, setCounter] = useEmitter(getMemory());
refresh: () => void; function refresh() {
}) { setCounter((c) => c + 1);
// currently not used, maybe scraped entirely in the future }
const clusters = getMemory().getClustersForOrigin(origin);
const entries = Object.values(clusters)
.map((cluster) => cluster.getRepresentativeStolenData())
.reduce(reduceConcat, [])
.filter((entry) => entry.isMarked);
return ( return (
<div {...{ "data-version": counter }}>
<h1>Generuj treść maila dla {origin}</h1>
<table> <table>
<thead> <thead>
<tr> <tr>
@ -41,7 +48,9 @@ function DataPreview({
style={{ style={{
width: "400px", width: "400px",
overflowWrap: "anywhere", overflowWrap: "anywhere",
backgroundColor: entry.isRelatedToID() ? "#ffff0054" : "white", backgroundColor: entry.isRelatedToID()
? "#ffff0054"
: "white",
}} }}
> >
{entry.getValuePreview()} {entry.getValuePreview()}
@ -72,52 +81,10 @@ function DataPreview({
))} ))}
</tbody> </tbody>
</table> </table>
);
}
function Report() {
console.time("getOrigin");
const origin = new URL(document.location.toString()).searchParams.get(
"origin"
);
console.timeEnd("getOrigin");
console.time("useMemory");
const [counter, setCounter] = useEmitter(getMemory());
console.timeEnd("useMemory");
function refresh() {
setCounter((c) => c + 1);
}
console.time("getClustersForOrigin");
const clusters = getMemory().getClustersForOrigin(origin);
console.timeEnd("getClustersForOrigin");
const [entries, setEntries] = useState<StolenDataEntry[]>([]);
console.time("useEffect report-window");
useEffect(() => {
setEntries(
Object.values(clusters)
.map((cluster) => {
cluster.calculatetRepresentativeStolenData();
return cluster.representativeStolenData;
})
.reduce(reduceConcat, [])
.filter((entry) => entry.isMarked)
);
}, []);
console.timeEnd("useEffect report-window");
if (entries.length == 0) {
return <>Wczytywanie...</>;
}
console.time("rendering template");
const result = (
<div {...{ "data-version": counter }}>
{/*<DataPreview {...{entries, refresh}} */}
<h1>Generuj treść maila dla {origin}</h1>
<EmailTemplate {...{ entries, clusters, version: counter }} /> <EmailTemplate {...{ entries, clusters, version: counter }} />
<HARConverter {...{ entries }} /> <HARConverter {...{ entries }} />
</div> </div>
); );
console.timeEnd("rendering template");
return result;
} }
ReactDOM.render(<Report />, document.getElementById("app")); ReactDOM.render(<Report />, document.getElementById("app"));

View File

@ -13,7 +13,6 @@ const source_priority: Array<Sources> = [
export class RequestCluster extends EventEmitter { export class RequestCluster extends EventEmitter {
public requests: ExtendedRequest[] = []; public requests: ExtendedRequest[] = [];
public representativeStolenData: StolenDataEntry[] = [];
constructor(public id: string) { constructor(public id: string) {
super(); super();
} }
@ -31,14 +30,14 @@ export class RequestCluster extends EventEmitter {
return false; return false;
} }
calculatetRepresentativeStolenData( getRepresentativeStolenData(
filter: { filter: {
minValueLength: number; minValueLength: number;
cookiesOnly: boolean; cookiesOnly: boolean;
cookiesOrOriginOnly: boolean; cookiesOrOriginOnly: boolean;
} = { minValueLength: 0, cookiesOnly: false, cookiesOrOriginOnly: false } } = { minValueLength: 0, cookiesOnly: false, cookiesOrOriginOnly: false }
): StolenDataEntry[] { ): StolenDataEntry[] {
this.representativeStolenData = this.requests return this.requests
.map((request) => request.stolenData) .map((request) => request.stolenData)
.reduce((a, b) => a.concat(b), []) .reduce((a, b) => a.concat(b), [])
@ -121,7 +120,6 @@ export class RequestCluster extends EventEmitter {
.sort((entry1, entry2) => .sort((entry1, entry2) =>
entry1.getPriority() > entry2.getPriority() ? -1 : 1 entry1.getPriority() > entry2.getPriority() ? -1 : 1
); );
return this.representativeStolenData;
} }
static sortCompare(a: RequestCluster, b: RequestCluster) { static sortCompare(a: RequestCluster, b: RequestCluster) {
@ -167,8 +165,7 @@ export class RequestCluster extends EventEmitter {
} }
autoMark() { autoMark() {
this.calculatetRepresentativeStolenData(); this.getRepresentativeStolenData().forEach((entry) => {
this.representativeStolenData.forEach((entry) => {
entry.autoMark(); entry.autoMark();
}); });
} }

View File

@ -125,15 +125,13 @@ export default function StolenDataCluster({
</h2> </h2>
<div> <div>
{cluster.getFullHosts().map((host) => ( {cluster.getFullHosts().map((host) => (
<a key={host} href={`https://${host}`}> <a href={`https://${host}`}>{host}, </a>
{host},{" "}
</a>
))} ))}
</div> </div>
<table> <table>
<tbody> <tbody>
{cluster {cluster
.calculatetRepresentativeStolenData({ .getRepresentativeStolenData({
minValueLength, minValueLength,
cookiesOnly, cookiesOnly,
cookiesOrOriginOnly, cookiesOrOriginOnly,

10
util.ts
View File

@ -1,11 +1,5 @@
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { import { Dispatch, SetStateAction, useEffect, useState } from "react";
Dispatch,
ReactChildren,
SetStateAction,
useEffect,
useState,
} from "react";
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;
@ -45,8 +39,6 @@ export function getshorthost(host: string) {
let lookback = parts.at(-2).length > 3 ? -2 : -3; let lookback = parts.at(-2).length > 3 ? -2 : -3;
if (parts.at(-2) == "doubleclick") { if (parts.at(-2) == "doubleclick") {
lookback = -4; // to distinguish between google ads and stats lookback = -4; // to distinguish between google ads and stats
} else if (parts.at(-2) == "google") {
lookback = -3; // to distinguish various google services
} }
return parts.slice(lookback).join("."); return parts.slice(lookback).join(".");
} }