Compare commits
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
ea70d26a38 | |||
1680026bc4 | |||
d5a8172759 | |||
039698264a | |||
7cf1b95461 | |||
799f17eac8 | |||
5c96a7f4cb | |||
32107f0ebc | |||
3910b5c67e | |||
b2487c0511 | |||
1106e86b41 | |||
c16e8f3d7c | |||
aae1a7e970 | |||
3a32456534 | |||
67544a4bff | |||
e3f4f8858d | |||
e3d6e6b83c | |||
cc713004b0 | |||
ea59a506f8 | |||
65e1ab2ecc | |||
5f29730613 | |||
8fe2083d8d | |||
|
45d87bc2a7 | ||
09dfe8d63a | |||
|
6ec2722e59 | ||
|
78f6dbb7a6 | ||
|
3d9711b605 | ||
|
2e136a7ad5 | ||
|
09cab7dee3 | ||
adf82b3dd6 | |||
520a26923e | |||
7c4de6fc5c | |||
4163bf3cf7 | |||
|
4f17c5164a | ||
|
1c773becf3 | ||
8dc9953818 | |||
0cebdd78f5 | |||
9d711ccdbb |
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
@ -1,9 +0,0 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"ECLI",
|
||||
"EROD",
|
||||
"targetowania",
|
||||
"targetowaniem",
|
||||
"TSUE"
|
||||
]
|
||||
}
|
112
README.md
112
README.md
@ -1,52 +1,5 @@
|
||||
<h1 style="display: flex; align-items: center;"><img src="./assets/icon-addon-2048.png" alt="Rentgen logo" style="margin-right: 1rem;" width="48"/> Rentgen</h1>
|
||||
|
||||
<strong>Rentgen</strong> to wtyczka dla przeglądarek opartych o Firefoxa, która automatycznie wizualizuje, jakie dane zostały ~~wykradzione~~ wysłane do podmiotów trzecich przez odwiedzane strony.
|
||||
|
||||
**Funkcje Rentgena:**
|
||||
|
||||
- analiza ruchu sieciowego generowanego przez stronę internetową;
|
||||
- wizualizacja danych przekazanych do podmiotów trzecich przez odwiedzaną stronę (historia przeglądania użytkownika oraz jego ciasteczka);
|
||||
- przygotowywanie zrzutów ekranów narzędzi deweloperskich będących dowodem przekazanych danych do podmiotów trzecich;
|
||||
- pomoc w oszacowaniu potencjalnych obszarów roboczych względem zgodności z RODO;
|
||||
- generowanie raportu lub treści maila, którą można wysłać do administratora oraz Urzędu Ochrony Danych Osobowych.
|
||||
|
||||
## Jak zbudować i uruchomić Rentgena ze źródeł
|
||||
|
||||
### Wymagania wstępne
|
||||
|
||||
- System operacyjny: Linux x86_64
|
||||
- Node.js: 16.x
|
||||
- npm: 7.x lub wyższy
|
||||
|
||||
### Proces budowy
|
||||
|
||||
1. Pobierz repozytorium przez `git pull https://git.internet-czas-dzialac.pl/icd/rentgen.git` lub pobierz archwium zip
|
||||
2. Przejdź do głównego katalogu pobranego repozytorium
|
||||
3. Uruchom komendę: `npm install`
|
||||
4. Uruchom komendę: `npm run build`
|
||||
5. Uruchom komendę: `npm run create-package`
|
||||
6. Przejdź do katalogu `web-ext-artifacts`
|
||||
7. Znajdziesz tam archiwum zip: `rentgen-x-x-x.zip` (`x-x-x` oznaczają wersję wtyczki)
|
||||
|
||||
### Kroki do uruchomienia
|
||||
|
||||
1. Uruchom Firefoxa i przejdź do strony `about:debugging`
|
||||
2. Kliknij zakładkę _This Firefox_
|
||||
3. Kliknij przycisk _Load Temporary Add-on..._
|
||||
4. Wybierz archiwum, które zbudowałeś w ostatnim kroku procesu budowy
|
||||
|
||||
## Zgłaszanie błędów
|
||||
|
||||
Link do issue trackera na naszej instancji Discourse: https://forum.internet-czas-dzialac.pl/c/rentgen-issue-tracker
|
||||
|
||||
Nie przyjmujemy zgłoszeń na platformie Microsoft Github.
|
||||
|
||||
Każdy problem zostanie sprawdzony i przeniesiony na wewnętrzną listę problemów na naszej instancji Gitea: https://git.internet-czas-dzialac.pl/icd/rentgen/issues. Korzystamy z Gitea i najprawdopodobniej w przyszłości dzięki federalizacji Gitea będziemy w stanie wpuścić użytkowników do zgłaszania błędów bezpośrednio ze strony Gitea.
|
||||
|
||||
---
|
||||
|
||||
## English description 🇬🇧
|
||||
|
||||
<strong>Rentgen</strong> is an add-on prepared for Firefox-based browsers. This extension will automatically visualize all the data that a given website ~~steals~~ sends to third parties.
|
||||
|
||||
Note: At the moment, we support Polish language because this extension generates mail content that is dedicated to Polish website owners. In further versions of this add-on, we will add other languages as well.
|
||||
@ -59,6 +12,10 @@ Note: At the moment, we support Polish language because this extension generates
|
||||
- assisting in the evaluation of potential work areas for compliance with GDPR;
|
||||
- generating a report or email content that can be sent to an administrator and Personal Data Protection Office in Poland.
|
||||
|
||||
## Installation
|
||||
|
||||
Firefox: https://addons.mozilla.org/en-US/firefox/addon/rentgen/
|
||||
|
||||
## How to build and run Rentgen on your own
|
||||
|
||||
### Pre-requirements
|
||||
@ -86,17 +43,72 @@ Note: At the moment, we support Polish language because this extension generates
|
||||
|
||||
## Issue tracker
|
||||
|
||||
Link to issue tracker on our Discourse instance: https://forum.internet-czas-dzialac.pl/c/rentgen-issue-tracker
|
||||
If you find a problem, please send us an email: kontakt@internet-czas-dzialac.pl
|
||||
|
||||
We don't receive issues on Microsoft Github.
|
||||
|
||||
Each issue will be reviewed and moved to an internal issues list of our Gitea instance: https://git.internet-czas-dzialac.pl/icd/rentgen/issues. We use Gitea and most likely in the future with the federalization of Gitea, we will be able to let users in to report issues directly from the Gitea site.
|
||||
|
||||
## Screenshots
|
||||
|
||||
<img src="./assets/screenshots/1.png" />
|
||||
<img src="./assets/screenshots/2.png" />
|
||||
<img src="./assets/screenshots/image-14.png" />
|
||||
<img src="./assets/screenshots/image-15.png" />
|
||||
<img src="./assets/screenshots/3a.png" />
|
||||
<img src="./assets/screenshots/3b.png" />
|
||||
<img src="./assets/screenshots/4a.png" />
|
||||
<img src="./assets/screenshots/4b.png" />
|
||||
<img src="./assets/screenshots/5a.png" />
|
||||
<img src="./assets/screenshots/5b.png" />
|
||||
<img src="./assets/screenshots/2022-07-14_21-04.png" />
|
||||
|
||||
---
|
||||
|
||||
<strong>Rentgen</strong> to wtyczka dla przeglądarek opartych o Firefoxa, która automatycznie wizualizuje, jakie dane zostały ~~wykradzione~~ wysłane do podmiotów trzecich przez odwiedzane strony. Wtyczka obrazuje ilość skryptów śledzących na stronie internetowej i pomaga w sformułowaniu maila do administratora strony, który może być podstawą do skargi RODO w Urzędzie Ochrony Danych Osobowych.
|
||||
|
||||
**Funkcje Rentgena:**
|
||||
|
||||
- analiza ruchu sieciowego generowanego przez stronę internetową;
|
||||
- wizualizacja danych przekazanych do podmiotów trzecich przez odwiedzaną stronę (historia przeglądania użytkownika oraz jego ciasteczka);
|
||||
- przygotowywanie zrzutów ekranów narzędzi deweloperskich będących dowodem przekazanych danych do podmiotów trzecich;
|
||||
- pomoc w oszacowaniu potencjalnych obszarów roboczych względem zgodności z RODO;
|
||||
- generowanie raportu lub treści maila, którą można wysłać do administratora oraz Urzędu Ochrony Danych Osobowych.
|
||||
|
||||
## Instalacja
|
||||
|
||||
Firefox: https://addons.mozilla.org/pl/firefox/addon/rentgen/
|
||||
|
||||
## Jak zbudować i uruchomić Rentgena ze źródeł
|
||||
|
||||
### Wymagania wstępne
|
||||
|
||||
- System operacyjny: Linux x86_64
|
||||
- Node.js: 16.x
|
||||
- npm: 7.x lub wyższy
|
||||
|
||||
### Proces budowy
|
||||
|
||||
1. Pobierz repozytorium przez `git pull https://git.internet-czas-dzialac.pl/icd/rentgen.git` lub pobierz archwium zip
|
||||
2. Przejdź do głównego katalogu pobranego repozytorium
|
||||
3. Uruchom komendę: `npm install`
|
||||
4. Uruchom komendę: `npm run build`
|
||||
5. Uruchom komendę: `npm run create-package`
|
||||
6. Przejdź do katalogu `web-ext-artifacts`
|
||||
7. Znajdziesz tam archiwum zip: `rentgen-x-x-x.zip` (`x-x-x` oznaczają wersję wtyczki)
|
||||
|
||||
### Kroki do uruchomienia
|
||||
|
||||
1. Uruchom Firefoxa i przejdź do strony `about:debugging`
|
||||
2. Kliknij zakładkę _This Firefox_
|
||||
3. Kliknij przycisk _Load Temporary Add-on..._
|
||||
4. Wybierz archiwum, które zbudowałeś w ostatnim kroku procesu budowy
|
||||
|
||||
## Zgłaszanie błędów
|
||||
|
||||
Jeżeli znajdziesz jakieś problem, napisz do nas maila: kontakt@internet-czas-dzialac.pl
|
||||
|
||||
Nie przyjmujemy zgłoszeń na platformie Microsoft Github.
|
||||
|
||||
Każdy problem zostanie sprawdzony i przeniesiony na wewnętrzną listę problemów na naszej instancji Gitea: https://git.internet-czas-dzialac.pl/icd/rentgen/issues. Korzystamy z Gitea i najprawdopodobniej w przyszłości dzięki federalizacji Gitea będziemy w stanie wpuścić użytkowników do zgłaszania błędów bezpośrednio ze strony Gitea.
|
||||
|
||||
---
|
||||
|
||||
|
BIN
assets/screenshots/2022-07-14_21-04.png
Normal file
BIN
assets/screenshots/2022-07-14_21-04.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 414 KiB |
BIN
assets/screenshots/image-14.png
Normal file
BIN
assets/screenshots/image-14.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 752 KiB |
BIN
assets/screenshots/image-15.png
Normal file
BIN
assets/screenshots/image-15.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 346 KiB |
@ -5,6 +5,7 @@ import { Problem } from './problems/problem';
|
||||
import { TransferOutsideEU } from './problems/transfer-outside-eu';
|
||||
import { UnknownIdentity } from './problems/unknown-identity';
|
||||
import { UnknownLegalBasis } from './problems/unknown-legal-basis';
|
||||
import { UnknownPurposes } from './problems/unknown-purpose';
|
||||
import { UnlawfulCookieAccess } from './problems/unlawful-cookies';
|
||||
|
||||
export default function deduceProblems(
|
||||
@ -13,6 +14,7 @@ export default function deduceProblems(
|
||||
): Problem[] {
|
||||
return [
|
||||
NoInformationAtAllProblem,
|
||||
UnknownPurposes,
|
||||
UnlawfulCookieAccess,
|
||||
UnknownLegalBasis,
|
||||
UnknownIdentity,
|
||||
|
@ -7,6 +7,8 @@ import './email-content.scss';
|
||||
import { Fragment, useState } from 'react';
|
||||
import emailIntro from './email-intro';
|
||||
import { reportIntro } from './report-intro';
|
||||
import { downloadText } from '../../util';
|
||||
import { getFakeClusterData } from './fake-clusters';
|
||||
|
||||
const SS_URL = 'http://65.108.60.135:3000';
|
||||
|
||||
@ -136,6 +138,23 @@ export default function EmailContent({
|
||||
</p>
|
||||
</section>
|
||||
) : null}
|
||||
<div className="diag-toolbox">
|
||||
<a
|
||||
href="#"
|
||||
onClick={() =>
|
||||
downloadText(
|
||||
'diag.json',
|
||||
JSON.stringify({
|
||||
answers,
|
||||
fake_clusters_data: getFakeClusterData(clusters),
|
||||
visited_url,
|
||||
})
|
||||
)
|
||||
}
|
||||
>
|
||||
Pobierz plik diagnostyczny
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -9,7 +9,49 @@ export const Explainers: Record<ExplainerKey, (zaimek_index: 0 | 1 | 2 | 3) => J
|
||||
<p>
|
||||
Sztucznie wygenerowane identyfikatory przechowywane w plikach Cookies stanowią dane
|
||||
osobowe. Wskazuje na to wprost Art. 4. pkt 1. RODO, wymieniając „identyfikator
|
||||
internetowy” i „numer identyfikacyjny” jako przykłady danych osobowych.
|
||||
internetowy” i „numer identyfikacyjny” jako przykłady danych osobowych. Losowe
|
||||
przypisane identyfikatory mogą nie zawierać imienia i nazwiska osoby, której
|
||||
dotyczą, ani nie prowadzić wprost do ich ustalenia, ale pozwalają odróżnić jedną,
|
||||
daną konkretną osobę, od innych.
|
||||
</p>
|
||||
<p>
|
||||
Por. komentarz z D. Lubasz [w:] Ochrona Danych Osobowych [red.] D. Lubasz, Warszawa
|
||||
2020 r., str. 81:
|
||||
</p>
|
||||
<p>
|
||||
<em>
|
||||
Zidentyfikowaną osobą fizyczną jest osoba, której tożsamość jest ustalona -
|
||||
bezpośrednio i natychmiast, czyli taka, którą bezpośrednio można wskazać,
|
||||
wyodrębnić lub wyróżnić z określonej zbiorowości.{' '}
|
||||
<strong>Nie musi to natomiast polegać na podaniu jej imienia nazwiska</strong>.
|
||||
Konstatacja ta jest zwłaszcza istotna w środowisku cyfrowym, w którym
|
||||
identyfikacja sprowadza się do oznaczenia danego użytkownika w celu wywierania
|
||||
na niego określonego wpływu. (...) Możliwą do zidentyfikowania jest osoba,
|
||||
której tożsamość dopiero administrator może ustalić -{' '}
|
||||
<strong>niezależnie od tego, czy to zrobi, czy nie</strong>.
|
||||
</em>
|
||||
</p>
|
||||
<p>
|
||||
Podobnie za{' '}
|
||||
<em>
|
||||
P. Litwiński [w:] Rozporządzenie UE w sprawie ochrony osób fizycznych w związku
|
||||
z przetwarzaniem danych osobowych i w sprawie swobodnego przepływu takich
|
||||
danych, Komentarz [red.] P. Litwiński, Warszawa 2018 r.
|
||||
</em>
|
||||
:
|
||||
</p>
|
||||
<p>
|
||||
<em>
|
||||
Jak zwrócono uwagę w nauce prawa, identyfikacja osoby powinna być rozumiana jako
|
||||
możliwość „fizycznego” wskazania tejże osoby, nie zaś jako ustalenie
|
||||
podstawowych danych tej osoby (...). Analogicznie,{' '}
|
||||
<em>identyfikacja osoby nie wymaga znajomości jej imienia lub nazwiska</em>,
|
||||
wymaga natomiast znajomości pewnych unikalnych cech tej osoby, które odróżniają
|
||||
ją od innych osób (...). W ten sam sposób należy więc rozumieć zwrot „można
|
||||
zidentyfikować” - nie tylko jako możliwość odniesienia konkretnej informacji do
|
||||
konkretnej osoby, lecz także jako możliwość wskazania tej osoby, rozumianego
|
||||
jako faktyczne wyodrębnienie jej spośród innych osób.
|
||||
</em>
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
|
56
components/report-window/fake-clusters.ts
Normal file
56
components/report-window/fake-clusters.ts
Normal file
@ -0,0 +1,56 @@
|
||||
// good for diagnostic purposes
|
||||
|
||||
import { RequestCluster } from '../../request-cluster';
|
||||
import { DataLocation } from '../../stolen-data-entry';
|
||||
|
||||
export type FakeRequestClusterData = {
|
||||
id: string;
|
||||
hasCookies: boolean;
|
||||
hasMarkedCookies: boolean;
|
||||
hasMarks: boolean;
|
||||
exposesOriginWhere: DataLocation[];
|
||||
exposesOrigin: boolean;
|
||||
};
|
||||
|
||||
export function getFakeClusterData(
|
||||
clusters: Record<string, RequestCluster>
|
||||
): Record<string, FakeRequestClusterData> {
|
||||
return Object.fromEntries(
|
||||
Object.entries(clusters).map(([key, cluster]) => [key, cluster.makeDataForFake()])
|
||||
);
|
||||
}
|
||||
|
||||
export function makeFakeClusters(
|
||||
fake_clusters_data: Record<string, FakeRequestClusterData>
|
||||
): Record<string, FakeCluster> {
|
||||
return Object.fromEntries(
|
||||
Object.entries(fake_clusters_data).map(([key, cluster_data]) => [
|
||||
key,
|
||||
new FakeCluster(cluster_data),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
export class FakeCluster extends RequestCluster {
|
||||
constructor(public data: FakeRequestClusterData) {
|
||||
super(data.id);
|
||||
|
||||
for (const key of [
|
||||
'hasCookies',
|
||||
'hasMarkedCookies',
|
||||
'hasMarks',
|
||||
'exposesOriginWhere',
|
||||
'exposesOrigin',
|
||||
]) {
|
||||
//@ts-ignore
|
||||
this[key] = () => {
|
||||
//@ts-ignore
|
||||
return this.data[key];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
hasCookies() {
|
||||
return this.data.hasCookies;
|
||||
}
|
||||
}
|
@ -150,7 +150,9 @@ function generateHostPage(
|
||||
...defaultValue('was_processing_necessary'),
|
||||
visibleIf: `{${f('legal_basis_type')}} = "legitimate_interest" or {${f(
|
||||
'present'
|
||||
)}} = "not_mentioned" or {popup_type} = "none"`,
|
||||
)}} = "not_mentioned" or {${f(
|
||||
'present'
|
||||
)}} = "not_before_making_a_choice" or {popup_type} = "none"`,
|
||||
choices: [
|
||||
{ value: 'yes', text: 'Tak, było konieczne' },
|
||||
{ value: 'no', text: 'Nie, nie było konieczne' },
|
||||
|
@ -44,7 +44,7 @@ export default class NoInformationAtAllProblem extends Problem {
|
||||
<li>Jaki jest cel takiego przetwarzania danych przez Państwa stronę?</li>
|
||||
<li>
|
||||
Jaka jest podstawa prawna takiego przetwarzania{' '}
|
||||
{mode == 'email' ? _('moich') : ''} danych osobowych $
|
||||
{mode == 'email' ? _('moich') : ''} danych osobowych
|
||||
{mode == 'report' ? 'użytkowników końcowych' : ''} przez Państwa stronę?
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -5,7 +5,8 @@ import { Problem } from './problem';
|
||||
|
||||
export class TransferOutsideEU extends Problem {
|
||||
getNecessaryExplainers(): ExplainerKey[] {
|
||||
return [];
|
||||
const has_cookies = this.getRelatedClusters().some((cluster) => cluster.hasCookies());
|
||||
return has_cookies ? ['cookies_are_pii'] : [];
|
||||
}
|
||||
|
||||
qualifies(): boolean {
|
||||
|
@ -18,15 +18,12 @@ export class UnknownIdentity extends Problem {
|
||||
<h2>Tożsamość administratora</h2>
|
||||
{mode == 'email' ? (
|
||||
<p>
|
||||
Na Państwa stronie nie {_('znalazłem')} informacji o tym, kto jest
|
||||
administratorem moich danych osobowych przetwarzanych przez Państwa stronę w
|
||||
trakcie {_('moich')} odwiedzin.
|
||||
Na Państwa stronie nie {_('znalazłem')} sposobu na poznanie tożsamości
|
||||
administratora strony <strong>przed</strong> podjęciem wyboru dotyczącego
|
||||
przetwarzania danych mnie dotyczących.
|
||||
</p>
|
||||
) : (
|
||||
<p>
|
||||
Na stronie brakuje informacji o tym, kto jest administratorem danych
|
||||
osobowych osób ją odwiedzających.
|
||||
</p>
|
||||
<p>Na stronie brakuje sposobu na poznanie tożsamości administratora strony.</p>
|
||||
)}
|
||||
<p>
|
||||
Zgodnie z treścią Art. 13 RODO, jeżeli dane osobowe osoby, której dane dotyczą,
|
||||
|
@ -21,7 +21,11 @@ const testCluster: (cluster: RequestCluster, answers: ParsedHostAnswers | undefi
|
||||
|
||||
export class UnknownLegalBasis extends Problem {
|
||||
getNecessaryExplainers(): ExplainerKey[] {
|
||||
return ['responsibility_for_third_parties'];
|
||||
const has_cookies = this.getRelatedClusters().some((cluster) => cluster.hasCookies());
|
||||
return [
|
||||
'responsibility_for_third_parties',
|
||||
...(has_cookies ? ['cookies_are_pii' as ExplainerKey] : []),
|
||||
];
|
||||
}
|
||||
|
||||
qualifies(): boolean {
|
||||
@ -70,8 +74,8 @@ export class UnknownLegalBasis extends Problem {
|
||||
Na stronie nie znajdują się informacje o tym, jaka jest podstawa prawna
|
||||
takiego przetwarzania danych osobowych, jakimi jest część historii
|
||||
przeglądania. Zgodnie z treścią Artykułu 13. p. 1 lit. c) RODO, aby
|
||||
przetwarzać dane osobowe, trzeba poinformować osobę, któ©ej dane dotyczą, o
|
||||
tym, jak ajest podstaw aprawna takiego przetwarzania danych.
|
||||
przetwarzać dane osobowe, trzeba poinformować osobę, której dane dotyczą, o
|
||||
tym, jaka jest podstawa prawna takiego przetwarzania danych.
|
||||
</p>
|
||||
)}
|
||||
{mode == 'email' ? (
|
||||
|
114
components/report-window/problems/unknown-purpose.tsx
Normal file
114
components/report-window/problems/unknown-purpose.tsx
Normal file
@ -0,0 +1,114 @@
|
||||
import { RequestCluster } from '../../../request-cluster';
|
||||
import { dataLocationToText, wordlist } from '../../../util';
|
||||
import { ExplainerKey } from '../explainers';
|
||||
import { v } from '../verbs';
|
||||
import { Problem } from './problem';
|
||||
|
||||
export class UnknownPurposes extends Problem {
|
||||
getNecessaryExplainers(): ExplainerKey[] {
|
||||
const has_cookies = this.getAffectedClusters().some((cluster) => cluster.hasCookies());
|
||||
if (has_cookies) {
|
||||
return ['cookies_are_pii'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
isHostAffected(host: string) {
|
||||
const answers = this.answers.hosts[host];
|
||||
if (!answers) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
['not_mentioned', 'not_before_making_a_choice'].includes(answers.present) &&
|
||||
['no', 'not_sure'].includes(answers.was_processing_necessary) &&
|
||||
(this.clusters[host].hasCookies() || this.clusters[host].exposesOrigin())
|
||||
);
|
||||
}
|
||||
|
||||
qualifies(): boolean {
|
||||
return Object.keys(this.answers.hosts).some((host) => this.isHostAffected(host));
|
||||
}
|
||||
|
||||
getAffectedClusters(): RequestCluster[] {
|
||||
return Object.keys(this.answers.hosts)
|
||||
.filter((host) => this.isHostAffected(host))
|
||||
.map((host) => this.clusters[host]);
|
||||
}
|
||||
|
||||
getEmailContent({ mode, tone }: { mode: 'email' | 'report'; tone: 'official' | 'polite' }) {
|
||||
const _ = (key: string) => v(key, this.answers.zaimek);
|
||||
const affected_clusters = this.getAffectedClusters();
|
||||
const has_history = affected_clusters.some((cluster) => cluster.exposesOrigin());
|
||||
const has_cookies = affected_clusters.some((cluster) => cluster.hasCookies());
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2>Cele przetwarzania danych</h2>
|
||||
<p>
|
||||
Państwa strona{' '}
|
||||
{mode == 'email'
|
||||
? `ujawniła dane ${_('mnie')} dotyczące`
|
||||
: 'ujawnia dane dotyczące użytkowników'}{' '}
|
||||
w zakresie{' '}
|
||||
{wordlist([
|
||||
...(has_cookies ? ['treści plików cookies'] : []),
|
||||
...(has_history
|
||||
? [
|
||||
mode === 'email'
|
||||
? `części ${_('mojej')} historii przeglądania`
|
||||
: `części historii przeglądania`,
|
||||
]
|
||||
: []),
|
||||
])}{' '}
|
||||
podmiotom, które są właścicielami nastepujących domen:
|
||||
</p>
|
||||
<ul>
|
||||
{affected_clusters.map((cluster, index) => {
|
||||
const locations = cluster.exposesOriginWhere();
|
||||
return (
|
||||
<li>
|
||||
<strong>{cluster.id}</strong>:{' '}
|
||||
{wordlist([
|
||||
...(cluster.hasCookies() ? ['treść plików cookies'] : []),
|
||||
...(cluster.exposesOrigin()
|
||||
? [
|
||||
(mode === 'email'
|
||||
? `część ${_('mojej')} historii przeglądania`
|
||||
: `część historii przeglądania użytkownika`) +
|
||||
' (' +
|
||||
wordlist(
|
||||
locations.map((l) => dataLocationToText(l))
|
||||
) +
|
||||
')',
|
||||
]
|
||||
: []),
|
||||
])}
|
||||
{index === affected_clusters.length - 1 ? '.' : ';'}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
{mode === 'email' ? (
|
||||
tone === 'official' ? (
|
||||
<p>
|
||||
Proszę o wskazanie, jakie są cele takiego przetwarzania danych, które
|
||||
mnie dotyczą.
|
||||
</p>
|
||||
) : (
|
||||
<p>
|
||||
Apeluję o umieszczenie informacji na temat na Państwa stronie, aby jej
|
||||
użytkownicy mogli podejmować w pełni świadome wybory dotyczące
|
||||
przetwarzania danych ich dotyczących.
|
||||
</p>
|
||||
)
|
||||
) : (
|
||||
<p>
|
||||
<strong>Zalecenie</strong>: warto dodać informacje o tym, jakie są cele
|
||||
ujawniania wyżej opisanych danych wyżej opisanym podmiotom trzecim.
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
@ -5,6 +5,17 @@
|
||||
font-family: 'OpenSans' !important;
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
#main-section {
|
||||
flex-grow: 1;
|
||||
margin-bottom: 20px; // to contain diag section
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 1rem;
|
||||
}
|
||||
@ -289,3 +300,9 @@ h1 {
|
||||
color: $ultra-black-color;
|
||||
}
|
||||
}
|
||||
|
||||
.diag-toolbox {
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ function Report() {
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
<section>{result}</section>
|
||||
<section id="main-section">{result}</section>
|
||||
</Fragment>
|
||||
);
|
||||
} catch (e) {
|
||||
|
@ -39,20 +39,34 @@ h2 {
|
||||
}
|
||||
|
||||
.browser {
|
||||
height: 8.667rem;
|
||||
height: 9.267rem;
|
||||
font-weight: 800 !important;
|
||||
color: $disabled-grey !important;
|
||||
border: 1px solid $disabled-grey;
|
||||
background-image: linear-gradient(to bottom, $icd-rentgen-color 20%, #fff 20%, #fff 100%);
|
||||
animation: xray 2s cubic-bezier(0, 1.43, 0.39, 1.43) infinite;
|
||||
background: linear-gradient(to bottom, $icd-rentgen-color 20%, #fff 20%, #fff 100%);
|
||||
background-size: 100%;
|
||||
background-position-y: 26.5px;
|
||||
|
||||
&--filled {
|
||||
background-size: 100%;
|
||||
background-position-y: 26.5px;
|
||||
animation: none;
|
||||
|
||||
.browser__header {
|
||||
background-color: #fff;
|
||||
&--address-bar {
|
||||
border: 1px solid #8a949f;
|
||||
height: 1rem;
|
||||
width: 10rem;
|
||||
font-size: 0.667rem;
|
||||
font-weight: 400;
|
||||
padding: 0 0.25rem;
|
||||
color: #000;
|
||||
overflow: hidden;
|
||||
word-break: normal;
|
||||
inline-size: 10rem;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
background: linear-gradient(to left, $icd-rentgen-color 20%, #fff 20%, #fff 100%);
|
||||
animation: xray-header 2s cubic-bezier(0, 1.43, 0.39, 1.43) infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,17 +76,30 @@ h2 {
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes xray-header {
|
||||
to {
|
||||
background-position-x: 11.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
height: 1.667rem;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
background-color: #fff;
|
||||
padding: 0 0.5rem;
|
||||
font-size: 1.25rem;
|
||||
border-bottom: 1px solid $disabled-grey;
|
||||
|
||||
&--in_progress {
|
||||
.browser__header--address-bar {
|
||||
background: linear-gradient(to left, $icd-rentgen-color 20%, #fff 20%, #fff 100%);
|
||||
animation: xray-header 2s cubic-bezier(0, 1.43, 0.39, 1.43) infinite;
|
||||
}
|
||||
}
|
||||
|
||||
&--address-bar {
|
||||
border: 1px solid #8a949f;
|
||||
height: 1rem;
|
||||
|
@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
||||
import { RequestCluster } from '../../request-cluster';
|
||||
import './screenshot-generator.scss';
|
||||
|
||||
const SS_URL = 'http://65.108.60.135:3000';
|
||||
const SS_URL = 'https://screenshot-service.internet-czas-dzialac.pl';
|
||||
|
||||
enum taskState {
|
||||
WAITING = 'waiting',
|
||||
@ -12,6 +12,7 @@ enum taskState {
|
||||
|
||||
type Screenshot = {
|
||||
url: string;
|
||||
thumb_url: string;
|
||||
domain: string;
|
||||
filename: string;
|
||||
found_headers: string[];
|
||||
@ -33,10 +34,11 @@ interface screenshotTask {
|
||||
url: string;
|
||||
waiting_took: number;
|
||||
zip_url: string;
|
||||
preview: string;
|
||||
}
|
||||
|
||||
function createTaskEndpoint(visited_url: string, domains: string[]) {
|
||||
return `${SS_URL}/api/requests?url=${visited_url}${domains.reduce(
|
||||
return `${SS_URL}/api/requests?url=${encodeURIComponent(visited_url)}${domains.reduce(
|
||||
(prev: string, curr: string) => prev + '&domains[]=' + curr,
|
||||
''
|
||||
)}`;
|
||||
@ -70,14 +72,20 @@ export default function ScreenshotGenerator({
|
||||
const [taskId, setTaskId] = React.useState<string | null>(null);
|
||||
const [output, setOutput] = React.useState<any>({});
|
||||
const [currentAction, setCurrentAction] = React.useState<string>('');
|
||||
const [preview, setPreview] = React.useState<string>('');
|
||||
const [lastPreview, setLastPreview] = React.useState<string>('');
|
||||
|
||||
async function subscribeTask(path: string): Promise<screenshotTask> {
|
||||
let response = { status: taskState.WAITING };
|
||||
let last_preview = '';
|
||||
while (response.status === taskState.WAITING || response.status === taskState.RUNNING) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
response = await (await pollTask(path)).json();
|
||||
setImages((response as screenshotTask)?.images);
|
||||
setCurrentAction((response as screenshotTask)?.current_action);
|
||||
setLastPreview(last_preview);
|
||||
setPreview((response as screenshotTask)?.preview);
|
||||
last_preview = (response as screenshotTask)?.preview;
|
||||
document.querySelector('.images')?.scrollTo({
|
||||
top: document.querySelector('.images')?.scrollHeight,
|
||||
behavior: 'smooth',
|
||||
@ -149,11 +157,18 @@ export default function ScreenshotGenerator({
|
||||
className="sv_next_btn"
|
||||
onClick={async () => {
|
||||
setMode('in_progress');
|
||||
const task = await createTask(visited_url, Object.keys(clusters));
|
||||
const task = await createTask(
|
||||
visited_url,
|
||||
Object.values(clusters)
|
||||
.filter((cluster) => cluster.hasMarks())
|
||||
.map((cluster) => cluster.id)
|
||||
);
|
||||
const urlArr = task.url.split('/');
|
||||
setTaskId(urlArr[urlArr.length - 1]);
|
||||
const response = await subscribeTask(task.url);
|
||||
setImages(response.images);
|
||||
setLastPreview(preview);
|
||||
setPreview(response.preview);
|
||||
setOutput(response);
|
||||
setRequestPath(response.zip_url);
|
||||
}}
|
||||
@ -186,13 +201,29 @@ export default function ScreenshotGenerator({
|
||||
) : null}
|
||||
|
||||
<div className="images">
|
||||
{mode === 'in_progress' ? (
|
||||
<div
|
||||
className="browser"
|
||||
style={{
|
||||
backgroundImage: `url(${SS_URL}${preview})${
|
||||
lastPreview ? `, url(${SS_URL}${lastPreview})` : ''
|
||||
}`,
|
||||
}}
|
||||
>
|
||||
<div className="browser__header browser__header--in_progress">
|
||||
<div className="browser__header--address-bar"></div>
|
||||
<div className="browser__header--controls">· · ·</div>
|
||||
</div>
|
||||
<div className="browser__content"></div>
|
||||
</div>
|
||||
) : null}
|
||||
{images.map((screenshot) => {
|
||||
return (
|
||||
<div
|
||||
key={`${taskId}_${screenshot.url}`}
|
||||
className="browser browser--filled"
|
||||
style={{
|
||||
backgroundImage: `url(${SS_URL}${screenshot.url})`,
|
||||
backgroundImage: `url(${SS_URL}${screenshot.thumb_url})`,
|
||||
}}
|
||||
>
|
||||
<div className="browser__header">
|
||||
@ -205,16 +236,6 @@ export default function ScreenshotGenerator({
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{mode === 'in_progress' ? (
|
||||
<div className="browser">
|
||||
<div className="browser__header">
|
||||
<div className="browser__header--address-bar"></div>
|
||||
<div className="browser__header--controls">· · ·</div>
|
||||
</div>
|
||||
<div className="browser__content"></div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="buttons-container">
|
||||
|
@ -9,7 +9,7 @@ const words = {
|
||||
mnie: ['mnie', 'mnie', 'mnie', 'nas'],
|
||||
moich: ['moich', 'moich', 'moich', 'naszych'],
|
||||
moje: ['moje', 'moje', 'moje', 'nasze'],
|
||||
mojego: ['mojefo', 'mojego', 'mojego', 'naszego'],
|
||||
mojego: ['mojego', 'mojego', 'mojego', 'naszego'],
|
||||
moja: ['moja', 'moja', 'moja', 'nasza'],
|
||||
mojej: ['mojej', 'mojej', 'mojej', 'naszej'],
|
||||
muszę: ['muszę', 'muszę', 'muszę', 'musimy'],
|
||||
|
@ -7,6 +7,15 @@
|
||||
flex-flow: column;
|
||||
border-bottom: none;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.icon.cookie-data {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.domain-checkbox {
|
||||
margin-right: 0.5rem;
|
||||
width: 0.875rem;
|
||||
|
@ -2,12 +2,10 @@ import React from 'react';
|
||||
import { getMemory } from '../../memory';
|
||||
import { StolenDataEntry } from '../../stolen-data-entry';
|
||||
|
||||
import { maskString, useEmitter } from '../../util';
|
||||
import { useEmitter } from '../../util';
|
||||
|
||||
import './stolen-data-cluster.scss';
|
||||
|
||||
const MAX_STRING_VALUE_LENGTH = 100;
|
||||
|
||||
function StolenDataValue({ entry }: { entry: StolenDataEntry; prefixKey?: string }) {
|
||||
const [version] = useEmitter(entry);
|
||||
let body = null;
|
||||
@ -43,13 +41,16 @@ function StolenDataRow({ entry }: { entry: StolenDataEntry }) {
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={entry.isMarked}
|
||||
id={entry.id.toString()}
|
||||
onChange={() => {
|
||||
entry.toggleMark();
|
||||
getMemory().emit('change', entry.request.shorthost);
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<th title={`Nazwa: ${entry.name}\nŹródło: ${entry.source}`}>{entry.name}</th>
|
||||
<th title={`Nazwa: ${entry.name}\nŹródło: ${entry.source}`}>
|
||||
<label htmlFor={entry.id.toString()}>{entry.name}</label>
|
||||
</th>
|
||||
<td className="icons">
|
||||
{entry.source === 'cookie' ? (
|
||||
<span title="Dane przechowywane w Cookies">
|
||||
@ -103,13 +104,11 @@ export default function StolenDataCluster({
|
||||
shorthost,
|
||||
minValueLength,
|
||||
cookiesOnly,
|
||||
refreshToken,
|
||||
cookiesOrOriginOnly,
|
||||
detailsVisibility,
|
||||
}: {
|
||||
origin: string;
|
||||
shorthost: string;
|
||||
refreshToken: number;
|
||||
minValueLength: number;
|
||||
cookiesOnly: boolean;
|
||||
cookiesOrOriginOnly: boolean;
|
||||
@ -122,20 +121,34 @@ export default function StolenDataCluster({
|
||||
return (
|
||||
<div className="stolen-data-cluster-container">
|
||||
<header className="domains-container">
|
||||
<div>
|
||||
<div className="domains-container__header">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="domain-checkbox"
|
||||
data-version={version}
|
||||
checked={cluster.hasMarks()}
|
||||
onChange={() => {
|
||||
console.log('Clicked checkbox!', {
|
||||
cluster_id: cluster.id,
|
||||
has_marks: cluster.hasMarks(),
|
||||
});
|
||||
cluster.hasMarks() ? cluster.undoMark() : cluster.autoMark();
|
||||
getMemory().emit('change', cluster.id);
|
||||
}}
|
||||
/>
|
||||
<a className="domain" href={'https://' + cluster.id} target="_blank">
|
||||
{cluster.id}
|
||||
</a>
|
||||
</a>{' '}
|
||||
{cluster.hasCookies() ? (
|
||||
<img
|
||||
src="/assets/icons/cookie.svg"
|
||||
height={16}
|
||||
width={16}
|
||||
className="icon cookie-data"
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
<div className="subdomains-container">
|
||||
{fullHosts.map((host, index) => (
|
||||
|
@ -14,6 +14,15 @@ async function getCurrentTab() {
|
||||
import './../../styles/global.scss';
|
||||
import './toolbar.scss';
|
||||
|
||||
function isDomainHighlySuspicious(domain: string): boolean {
|
||||
return (
|
||||
domain.includes('facebook') ||
|
||||
domain.includes('twitter') ||
|
||||
domain.includes('linkedin') ||
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
const Toolbar = () => {
|
||||
const [origin, setOrigin] = React.useState<string | null>(null);
|
||||
const [eventCounts] = useEmitter(getMemory());
|
||||
@ -53,6 +62,13 @@ const Toolbar = () => {
|
||||
if (!origin) return;
|
||||
const exposedOriginDomains = Object.values(getMemory().getClustersForOrigin(origin))
|
||||
.filter((cluster) => cluster.exposesOrigin())
|
||||
.sort((cluster1, cluster2) =>
|
||||
isDomainHighlySuspicious(cluster1.id)
|
||||
? -1
|
||||
: isDomainHighlySuspicious(cluster2.id)
|
||||
? 1
|
||||
: 0
|
||||
)
|
||||
.map((cluster) => cluster.id);
|
||||
setExposedOriginDomainCopy('');
|
||||
|
||||
@ -86,6 +102,13 @@ const Toolbar = () => {
|
||||
if (!origin) return;
|
||||
const cookieDomains = Object.values(getMemory().getClustersForOrigin(origin))
|
||||
.filter((cluster) => cluster.hasCookies())
|
||||
.sort((cluster1, cluster2) =>
|
||||
isDomainHighlySuspicious(cluster1.id)
|
||||
? -1
|
||||
: isDomainHighlySuspicious(cluster2.id)
|
||||
? 1
|
||||
: 0
|
||||
)
|
||||
.map((cluster) => cluster.id);
|
||||
setCookieDomainCopy('');
|
||||
|
||||
|
13
diag.html
Normal file
13
diag.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>RENTGEN DIAG</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="/node_modules/react/umd/react.production.min.js"></script>
|
||||
<script src="/node_modules/react-dom/umd/react-dom.production.min.js"></script>
|
||||
<script src="/node_modules/survey-react/survey.react.min.js"></script>
|
||||
<script src="./lib/diag.js"></script>
|
||||
</html>
|
65
diag.tsx
Normal file
65
diag.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import EmailContent from './components/report-window/email-content';
|
||||
|
||||
import { makeFakeClusters } from './components/report-window/fake-clusters';
|
||||
|
||||
class ErrorBoundary extends React.Component<any, { hasError: boolean; error: any }> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = { hasError: false, error: null };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: any) {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return <h1>Something went wrong.</h1>;
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
function Diag() {
|
||||
const [json, setjson] = React.useState(
|
||||
JSON.stringify({ answers: { hosts: {} }, visited_url: '', fake_clusters_data: {} })
|
||||
);
|
||||
const { answers, visited_url, fake_clusters_data } = JSON.parse(json);
|
||||
const fake_clusters = makeFakeClusters(fake_clusters_data);
|
||||
return (
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '50% 50%', minHeight: '100vh' }}>
|
||||
<div>
|
||||
<textarea
|
||||
style={{ width: 'calc(100% - 50px)', height: '100%' }}
|
||||
value={json}
|
||||
onChange={(e) => {
|
||||
setjson(e.target.value);
|
||||
}}
|
||||
></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<EmailContent
|
||||
{...{
|
||||
answers,
|
||||
visited_url,
|
||||
clusters: fake_clusters,
|
||||
scrRequestPath: '/screenshots',
|
||||
downloadFiles: () => {
|
||||
alert('download!');
|
||||
},
|
||||
user_role: 'user',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<ErrorBoundary>
|
||||
<Diag />
|
||||
</ErrorBoundary>,
|
||||
document.getElementById('app')
|
||||
);
|
@ -48,6 +48,7 @@ esbuild
|
||||
'components/sidebar/sidebar.tsx',
|
||||
'components/report-window/report-window.tsx',
|
||||
'background.ts',
|
||||
'diag.tsx',
|
||||
'styles/global.scss',
|
||||
'styles/fonts.scss',
|
||||
],
|
||||
|
@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
import { StolenDataEntry } from './stolen-data-entry';
|
||||
import { DataLocation, StolenDataEntry } from './stolen-data-entry';
|
||||
import {
|
||||
flattenObjectEntries,
|
||||
getshorthost,
|
||||
@ -164,12 +164,12 @@ export default class ExtendedRequest {
|
||||
);
|
||||
}
|
||||
|
||||
exposesOrigin() {
|
||||
exposesOriginWhere(): null | DataLocation {
|
||||
const host = this.originalHost;
|
||||
const path = this.originalPathname || '/';
|
||||
const shorthost = getshorthost(host);
|
||||
if (this.getReferer().includes(shorthost)) {
|
||||
return true;
|
||||
return { path: this.url, source: 'header', key: 'Referer' };
|
||||
}
|
||||
for (const entry of this.stolenData) {
|
||||
if (
|
||||
@ -177,10 +177,14 @@ export default class ExtendedRequest {
|
||||
entry.value.includes(path) ||
|
||||
entry.value.includes(shorthost)
|
||||
) {
|
||||
return true;
|
||||
return entry.toDataLocation();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
exposesOrigin() {
|
||||
return this.exposesOriginWhere() !== null;
|
||||
}
|
||||
|
||||
private getAllStolenData(): StolenDataEntry[] {
|
||||
@ -301,6 +305,10 @@ export default class ExtendedRequest {
|
||||
return this.stolenData.filter((data) => data.isMarked);
|
||||
}
|
||||
|
||||
unmarkAllEntries() {
|
||||
this.stolenData.forEach((entry) => entry.unmark());
|
||||
}
|
||||
|
||||
getHost() {
|
||||
return new URL(this.url).host;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"manifest_version": 2,
|
||||
"name": "Rentgen",
|
||||
"short_name": "Rentgen",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.10",
|
||||
"author": "Kuba Orlik, Arkadiusz Wieczorek (Internet. Czas działać!)",
|
||||
"homepage_url": "https://git.internet-czas-dzialac.pl/icd/rentgen",
|
||||
"background": {
|
||||
|
614
package-lock.json
generated
614
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "rentgen",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.10",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "rentgen",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.10",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@iabtcf/core": "^1.3.1",
|
||||
@ -287,9 +287,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@iabtcf/core": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@iabtcf/core/-/core-1.4.0.tgz",
|
||||
"integrity": "sha512-LfyscG/rNhw542MX4pNSBPzK3ddHDYB8cz7pNTOI6D664x7jJmVZjkRmw8X/h9yGQ2c0a/1AP9F8n5/UsxKjeA=="
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@iabtcf/core/-/core-1.5.3.tgz",
|
||||
"integrity": "sha512-DZsenDL6uz/jULc/PlWs9HA2eDHkAcL+JiZ5TtB1O5ZSwZ2BMyJc4I5qC+j/7BZFPXqaHRbGQ7QpbxmcHYLw1Q=="
|
||||
},
|
||||
"node_modules/@mdn/browser-compat-data": {
|
||||
"version": "4.1.13",
|
||||
@ -364,9 +364,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz",
|
||||
"integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==",
|
||||
"version": "18.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.4.tgz",
|
||||
"integrity": "sha512-M0+G6V0Y4YV8cqzHssZpaNCqvYwlCiulmm0PwpNLF55r/+cT8Ol42CHRU1SEaYFH2rTwiiE1aYg/2g2rrtGdPA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
@ -2033,9 +2033,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz",
|
||||
"integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==",
|
||||
"version": "0.14.49",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.49.tgz",
|
||||
"integrity": "sha512-/TlVHhOaq7Yz8N1OJrjqM3Auzo5wjvHFLk+T8pIue+fhnhIMpfAzsG6PLVMbFveVxqD2WOp3QHei+52IMUNmCw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
@ -2045,144 +2045,32 @@
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"esbuild-android-64": "0.14.48",
|
||||
"esbuild-android-arm64": "0.14.48",
|
||||
"esbuild-darwin-64": "0.14.48",
|
||||
"esbuild-darwin-arm64": "0.14.48",
|
||||
"esbuild-freebsd-64": "0.14.48",
|
||||
"esbuild-freebsd-arm64": "0.14.48",
|
||||
"esbuild-linux-32": "0.14.48",
|
||||
"esbuild-linux-64": "0.14.48",
|
||||
"esbuild-linux-arm": "0.14.48",
|
||||
"esbuild-linux-arm64": "0.14.48",
|
||||
"esbuild-linux-mips64le": "0.14.48",
|
||||
"esbuild-linux-ppc64le": "0.14.48",
|
||||
"esbuild-linux-riscv64": "0.14.48",
|
||||
"esbuild-linux-s390x": "0.14.48",
|
||||
"esbuild-netbsd-64": "0.14.48",
|
||||
"esbuild-openbsd-64": "0.14.48",
|
||||
"esbuild-sunos-64": "0.14.48",
|
||||
"esbuild-windows-32": "0.14.48",
|
||||
"esbuild-windows-64": "0.14.48",
|
||||
"esbuild-windows-arm64": "0.14.48"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-android-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz",
|
||||
"integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-android-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-darwin-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz",
|
||||
"integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-darwin-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-freebsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-freebsd-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-32": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz",
|
||||
"integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"esbuild-android-64": "0.14.49",
|
||||
"esbuild-android-arm64": "0.14.49",
|
||||
"esbuild-darwin-64": "0.14.49",
|
||||
"esbuild-darwin-arm64": "0.14.49",
|
||||
"esbuild-freebsd-64": "0.14.49",
|
||||
"esbuild-freebsd-arm64": "0.14.49",
|
||||
"esbuild-linux-32": "0.14.49",
|
||||
"esbuild-linux-64": "0.14.49",
|
||||
"esbuild-linux-arm": "0.14.49",
|
||||
"esbuild-linux-arm64": "0.14.49",
|
||||
"esbuild-linux-mips64le": "0.14.49",
|
||||
"esbuild-linux-ppc64le": "0.14.49",
|
||||
"esbuild-linux-riscv64": "0.14.49",
|
||||
"esbuild-linux-s390x": "0.14.49",
|
||||
"esbuild-netbsd-64": "0.14.49",
|
||||
"esbuild-openbsd-64": "0.14.49",
|
||||
"esbuild-sunos-64": "0.14.49",
|
||||
"esbuild-windows-32": "0.14.49",
|
||||
"esbuild-windows-64": "0.14.49",
|
||||
"esbuild-windows-arm64": "0.14.49"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz",
|
||||
"integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==",
|
||||
"version": "0.14.49",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.49.tgz",
|
||||
"integrity": "sha512-hYmzRIDzFfLrB5c1SknkxzM8LdEUOusp6M2TnuQZJLRtxTgyPnZZVtyMeCLki0wKgYPXkFsAVhi8vzo2mBNeTg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -2195,134 +2083,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-arm": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz",
|
||||
"integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-mips64le": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz",
|
||||
"integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-ppc64le": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz",
|
||||
"integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-riscv64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz",
|
||||
"integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-s390x": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz",
|
||||
"integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-netbsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-openbsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-plugin-sass": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-plugin-sass/-/esbuild-plugin-sass-1.0.1.tgz",
|
||||
@ -2338,70 +2098,6 @@
|
||||
"esbuild": ">=0.11.14"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-sunos-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz",
|
||||
"integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-32": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz",
|
||||
"integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz",
|
||||
"integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
@ -3083,20 +2779,6 @@
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@ -6366,14 +6048,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/survey-core": {
|
||||
"version": "1.9.39",
|
||||
"resolved": "https://registry.npmjs.org/survey-core/-/survey-core-1.9.39.tgz",
|
||||
"integrity": "sha512-nwnDUSc/Pdd5tZSwIfUJVfcayEHx4hpKwRK5y2T6Pjf4Hr9n/uOgxXUzx/ilKigh7KUwZjnfCXEtbegYwMhc5w=="
|
||||
"version": "1.9.40",
|
||||
"resolved": "https://registry.npmjs.org/survey-core/-/survey-core-1.9.40.tgz",
|
||||
"integrity": "sha512-oYKRDqeigleseDqF/za0ZtSqn+Tg5clxLyG0bXiAQ0K2l/J5JPRigMuI7VbW4+Er5lU04JfMpzcw9/U8pP3Niw=="
|
||||
},
|
||||
"node_modules/survey-react": {
|
||||
"version": "1.9.39",
|
||||
"resolved": "https://registry.npmjs.org/survey-react/-/survey-react-1.9.39.tgz",
|
||||
"integrity": "sha512-itOXq6FdSDoDp71p89d3wt25aBeQfBWT0fU43dxCZEkrmQvRYURWdoiLy/AkCISSyAIQm/KgvQY8hcTaLV+NQg==",
|
||||
"version": "1.9.40",
|
||||
"resolved": "https://registry.npmjs.org/survey-react/-/survey-react-1.9.40.tgz",
|
||||
"integrity": "sha512-ZDH2CCAOMSG0cyu8+Ahc56/TetGyicp4Oz2LO44YaptddRg2HSFQCQRWS3ockMJCO/aH69yPNhARwtJt3eROQA==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.5.0 || ^17.0.1 || ^18.1.0",
|
||||
"react-dom": "^16.5.0 || ^17.0.1 || ^18.1.0"
|
||||
@ -7682,9 +7364,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@iabtcf/core": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@iabtcf/core/-/core-1.4.0.tgz",
|
||||
"integrity": "sha512-LfyscG/rNhw542MX4pNSBPzK3ddHDYB8cz7pNTOI6D664x7jJmVZjkRmw8X/h9yGQ2c0a/1AP9F8n5/UsxKjeA=="
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@iabtcf/core/-/core-1.5.3.tgz",
|
||||
"integrity": "sha512-DZsenDL6uz/jULc/PlWs9HA2eDHkAcL+JiZ5TtB1O5ZSwZ2BMyJc4I5qC+j/7BZFPXqaHRbGQ7QpbxmcHYLw1Q=="
|
||||
},
|
||||
"@mdn/browser-compat-data": {
|
||||
"version": "4.1.13",
|
||||
@ -7753,9 +7435,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz",
|
||||
"integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==",
|
||||
"version": "18.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.4.tgz",
|
||||
"integrity": "sha512-M0+G6V0Y4YV8cqzHssZpaNCqvYwlCiulmm0PwpNLF55r/+cT8Ol42CHRU1SEaYFH2rTwiiE1aYg/2g2rrtGdPA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prop-types": {
|
||||
@ -9073,142 +8755,37 @@
|
||||
"dev": true
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz",
|
||||
"integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==",
|
||||
"version": "0.14.49",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.49.tgz",
|
||||
"integrity": "sha512-/TlVHhOaq7Yz8N1OJrjqM3Auzo5wjvHFLk+T8pIue+fhnhIMpfAzsG6PLVMbFveVxqD2WOp3QHei+52IMUNmCw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild-android-64": "0.14.48",
|
||||
"esbuild-android-arm64": "0.14.48",
|
||||
"esbuild-darwin-64": "0.14.48",
|
||||
"esbuild-darwin-arm64": "0.14.48",
|
||||
"esbuild-freebsd-64": "0.14.48",
|
||||
"esbuild-freebsd-arm64": "0.14.48",
|
||||
"esbuild-linux-32": "0.14.48",
|
||||
"esbuild-linux-64": "0.14.48",
|
||||
"esbuild-linux-arm": "0.14.48",
|
||||
"esbuild-linux-arm64": "0.14.48",
|
||||
"esbuild-linux-mips64le": "0.14.48",
|
||||
"esbuild-linux-ppc64le": "0.14.48",
|
||||
"esbuild-linux-riscv64": "0.14.48",
|
||||
"esbuild-linux-s390x": "0.14.48",
|
||||
"esbuild-netbsd-64": "0.14.48",
|
||||
"esbuild-openbsd-64": "0.14.48",
|
||||
"esbuild-sunos-64": "0.14.48",
|
||||
"esbuild-windows-32": "0.14.48",
|
||||
"esbuild-windows-64": "0.14.48",
|
||||
"esbuild-windows-arm64": "0.14.48"
|
||||
"esbuild-android-64": "0.14.49",
|
||||
"esbuild-android-arm64": "0.14.49",
|
||||
"esbuild-darwin-64": "0.14.49",
|
||||
"esbuild-darwin-arm64": "0.14.49",
|
||||
"esbuild-freebsd-64": "0.14.49",
|
||||
"esbuild-freebsd-arm64": "0.14.49",
|
||||
"esbuild-linux-32": "0.14.49",
|
||||
"esbuild-linux-64": "0.14.49",
|
||||
"esbuild-linux-arm": "0.14.49",
|
||||
"esbuild-linux-arm64": "0.14.49",
|
||||
"esbuild-linux-mips64le": "0.14.49",
|
||||
"esbuild-linux-ppc64le": "0.14.49",
|
||||
"esbuild-linux-riscv64": "0.14.49",
|
||||
"esbuild-linux-s390x": "0.14.49",
|
||||
"esbuild-netbsd-64": "0.14.49",
|
||||
"esbuild-openbsd-64": "0.14.49",
|
||||
"esbuild-sunos-64": "0.14.49",
|
||||
"esbuild-windows-32": "0.14.49",
|
||||
"esbuild-windows-64": "0.14.49",
|
||||
"esbuild-windows-arm64": "0.14.49"
|
||||
}
|
||||
},
|
||||
"esbuild-android-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz",
|
||||
"integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-android-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-darwin-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz",
|
||||
"integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-darwin-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-freebsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-freebsd-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-32": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz",
|
||||
"integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz",
|
||||
"integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-arm": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz",
|
||||
"integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-mips64le": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz",
|
||||
"integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-ppc64le": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz",
|
||||
"integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-riscv64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz",
|
||||
"integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-s390x": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz",
|
||||
"integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-netbsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-openbsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==",
|
||||
"version": "0.14.49",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.49.tgz",
|
||||
"integrity": "sha512-hYmzRIDzFfLrB5c1SknkxzM8LdEUOusp6M2TnuQZJLRtxTgyPnZZVtyMeCLki0wKgYPXkFsAVhi8vzo2mBNeTg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
@ -9224,34 +8801,6 @@
|
||||
"tmp": "0.2.1"
|
||||
}
|
||||
},
|
||||
"esbuild-sunos-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz",
|
||||
"integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-32": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz",
|
||||
"integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz",
|
||||
"integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
@ -9779,13 +9328,6 @@
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@ -12337,14 +11879,14 @@
|
||||
}
|
||||
},
|
||||
"survey-core": {
|
||||
"version": "1.9.39",
|
||||
"resolved": "https://registry.npmjs.org/survey-core/-/survey-core-1.9.39.tgz",
|
||||
"integrity": "sha512-nwnDUSc/Pdd5tZSwIfUJVfcayEHx4hpKwRK5y2T6Pjf4Hr9n/uOgxXUzx/ilKigh7KUwZjnfCXEtbegYwMhc5w=="
|
||||
"version": "1.9.40",
|
||||
"resolved": "https://registry.npmjs.org/survey-core/-/survey-core-1.9.40.tgz",
|
||||
"integrity": "sha512-oYKRDqeigleseDqF/za0ZtSqn+Tg5clxLyG0bXiAQ0K2l/J5JPRigMuI7VbW4+Er5lU04JfMpzcw9/U8pP3Niw=="
|
||||
},
|
||||
"survey-react": {
|
||||
"version": "1.9.39",
|
||||
"resolved": "https://registry.npmjs.org/survey-react/-/survey-react-1.9.39.tgz",
|
||||
"integrity": "sha512-itOXq6FdSDoDp71p89d3wt25aBeQfBWT0fU43dxCZEkrmQvRYURWdoiLy/AkCISSyAIQm/KgvQY8hcTaLV+NQg==",
|
||||
"version": "1.9.40",
|
||||
"resolved": "https://registry.npmjs.org/survey-react/-/survey-react-1.9.40.tgz",
|
||||
"integrity": "sha512-ZDH2CCAOMSG0cyu8+Ahc56/TetGyicp4Oz2LO44YaptddRg2HSFQCQRWS3ockMJCO/aH69yPNhARwtJt3eROQA==",
|
||||
"requires": {}
|
||||
},
|
||||
"tai-password-strength": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rentgen",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.10",
|
||||
"description": "Rentgen is an add-on prepared for Firefox-based browsers. This extension will automatically visualize all the data that a given website sends to third parties.",
|
||||
"main": "esbuild.config.js",
|
||||
"type": "module",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { FakeRequestClusterData } from './components/report-window/fake-clusters';
|
||||
import ExtendedRequest from './extended-request';
|
||||
import { SaferEmitter } from './safer-emitter';
|
||||
import { Sources, StolenDataEntry } from './stolen-data-entry';
|
||||
import { DataLocation, Sources, StolenDataEntry } from './stolen-data-entry';
|
||||
|
||||
import { allSubhosts, isSameURL, reduceConcat, unique } from './util';
|
||||
|
||||
@ -171,7 +172,13 @@ export class RequestCluster extends SaferEmitter {
|
||||
return this.requests.map((request) => request.getMarkedEntries()).reduce(reduceConcat, []);
|
||||
}
|
||||
|
||||
exposesOrigin() {
|
||||
exposesOriginWhere(): DataLocation[] {
|
||||
return this.requests
|
||||
.map((request) => request.exposesOriginWhere())
|
||||
.filter((l) => l !== null) as DataLocation[];
|
||||
}
|
||||
|
||||
exposesOrigin(): boolean {
|
||||
return this.requests.some((request) => request.exposesOrigin());
|
||||
}
|
||||
|
||||
@ -184,9 +191,7 @@ export class RequestCluster extends SaferEmitter {
|
||||
|
||||
undoMark() {
|
||||
this.calculateRepresentativeStolenData();
|
||||
this.representativeStolenData.forEach((entry) => {
|
||||
entry.unmark();
|
||||
});
|
||||
this.requests.forEach((request) => request.unmarkAllEntries());
|
||||
}
|
||||
|
||||
getDataTypeDescription(noun = 'Twojej') {
|
||||
@ -203,4 +208,15 @@ export class RequestCluster extends SaferEmitter {
|
||||
}
|
||||
return types_of_data.join(', ');
|
||||
}
|
||||
|
||||
makeDataForFake(): FakeRequestClusterData {
|
||||
return {
|
||||
id: this.id,
|
||||
hasCookies: this.hasCookies(),
|
||||
hasMarkedCookies: this.hasMarkedCookies(),
|
||||
hasMarks: this.hasMarks(),
|
||||
exposesOriginWhere: this.exposesOriginWhere(),
|
||||
exposesOrigin: this.exposesOrigin(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,12 @@ const id = (function* id() {
|
||||
|
||||
export type DecodingSchema = 'base64' | 'raw';
|
||||
|
||||
export type DataLocation = {
|
||||
path: string;
|
||||
source: Sources;
|
||||
key: string;
|
||||
};
|
||||
|
||||
export class StolenDataEntry extends SaferEmitter {
|
||||
public isIAB = false;
|
||||
public id: number;
|
||||
@ -253,4 +259,12 @@ export class StolenDataEntry extends SaferEmitter {
|
||||
haystack.includes(getshorthost(this.request.origin))
|
||||
);
|
||||
}
|
||||
|
||||
toDataLocation(): DataLocation {
|
||||
return {
|
||||
path: this.request.url,
|
||||
source: this.source,
|
||||
key: this.name,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
36
util.ts
36
util.ts
@ -1,5 +1,6 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import React from 'react';
|
||||
import { DataLocation, Sources } from './stolen-data-entry';
|
||||
|
||||
export type Unpromisify<T> = T extends Promise<infer R> ? R : T;
|
||||
export type Unarray<T> = T extends Array<infer R> ? R : T;
|
||||
@ -77,7 +78,7 @@ export function useEmitter(
|
||||
export function parseCookie(cookie: string): Record<string, string> {
|
||||
return cookie
|
||||
.split(';')
|
||||
.map((l) => l.split('='))
|
||||
.map((l) => [l.slice(0, l.indexOf('=')), l.slice(l.indexOf('=') + 1)])
|
||||
.reduce(
|
||||
(acc, [key, value]) => ({
|
||||
...acc,
|
||||
@ -283,8 +284,37 @@ export function normalizeForClassname(string: string) {
|
||||
}
|
||||
|
||||
export function wordlist(words: string[]) {
|
||||
return words.reduce(
|
||||
(acc, word, i) => `${acc}${i > 0 ? (i < words.length - 1 ? ',' : ' i') : ''} ${word}`,
|
||||
return Array.from(new Set(words)).reduce(
|
||||
(acc, word, i) =>
|
||||
`${acc}${
|
||||
i > 0 ? (i < words.length - 1 ? ', ' : Math.random() > 0.5 ? ' i ' : ' oraz ') : ''
|
||||
}${word}`,
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
const source_to_word: Record<Sources, string> = {
|
||||
cookie: 'plik cookie o nazwie',
|
||||
pathname: 'fragment ścieżki w URL',
|
||||
queryparams: 'query params w URL o nazwie',
|
||||
header: 'nagłówek HTTP',
|
||||
request_body: 'body zapytania HTTP, pod kluczem',
|
||||
};
|
||||
|
||||
export function dataLocationToText(l: DataLocation) {
|
||||
return `${source_to_word[l.source]} ${l.key}`;
|
||||
}
|
||||
|
||||
export function downloadText(filename: string, text: string) {
|
||||
// https://stackoverflow.com/questions/45831191/generate-and-download-file-from-js
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
|
||||
element.setAttribute('download', filename);
|
||||
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
|
||||
element.click();
|
||||
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user