Initial Commit

This commit is contained in:
Miyako Yakota
2023-07-06 05:15:23 +00:00
parent 64a32a44a8
commit bb950259e3
55 changed files with 87047 additions and 1 deletions

View File

@@ -0,0 +1,40 @@
<head>
<title>Top Donators</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
</style>
</head>
<body>
Here's the sexy people who have donated to this site:
<br />
<table>
<tr>
<th>Name</th>
<th>Amount</th>
</tr>
{{#donations}}
<tr>
<td>{{name}}</td>
<td>{{amount}}</td>
</tr>
{{/donations}}
</table>
If you would like your name here instead of a BTC address, shoot me an email <a href="mailto:miyakoyakota@riseup.com">miyakoyakota@riseup.com</a> with your transaction info.
</body>

View File

@@ -0,0 +1,42 @@
[
{
"name": "bc1qm4zyhxaktt27djp634ncx4gtev85aqy7mntszf",
"amount": 151.81
},
{
"name": "Ro****",
"amount": 8.86
},
{
"name": "bc1qqzg35y5w9zrhjc5nzdj4drjnhkpyl2yepu96fq",
"amount": 10.22
},
{
"name": "bc1qm4fvq825xmpqzz9uxt7h9muq2g84fz5cyf9uf5",
"amount": 9.50
},
{
"name": "33WNF9aM3yeDtens53Ch7T4q9smdQzB9ZY",
"amount": 9.01
},
{
"name": "bc1qqzg35y5w9zrhjc5nzdj4drjnhkpyl2yepu96fq",
"amount": 10.21
},
{
"name": "81e14f875d12895ef111a2092e2a93da8b3b7c00b0bc8fe9fc7b7f275dfcec48",
"amount": 41.99
},
{
"name": "33xdRBuineAtGGobP1zVoMdJ5vYWWrjC5S",
"amount": 98.17
},
{
"name": "Papa 0x27",
"amount": 20.00
},
{
"name": "C99.nl",
"amount": 25.00
}
]

View File

@@ -0,0 +1,523 @@
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"
integrity="sha512-E8QSvWZ0eCLGk4km3hxSsNmGWbLtSCSUcewDQPQWZF6pEU8GlT8a5fF32wOl1i8ftdMhssTrF/OhyGWwonTcXA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/bcryptjs@2.4.3/dist/bcrypt.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Query Export - Illicit Services</title>
<meta name="description" content="Export from our database of leaked information.">
<meta name="robots" content="index, follow">
<meta property="og:type" content="article" />
<meta property="og:title" content="Illict Services LTD" />
<meta property="og:description" content="Export from our database of leaked information." />
<meta property="og:url" content="https://search.illicit.services" />
<meta property="og:site_name" content="Database Search" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en" />
<meta name="apple-mobile-web-app-status-bar" content="#000000" />
<meta name="theme-color" content="#000000" />
<style>
html,
body,
{
height: 100%;
}
#app {
height: 100%;
}
html,
body,
#app,
v-main__wrap {
background-color: black;
}
/* */
</style>
</head>
<body>
<div id="app">
<v-app>
<v-main>
<span>
<!-- Wallet goes in the top-right -->
<v-toolbar flat color="transparent" dark app
style="position: absolute; top: 0; right: 0; z-index: 1000">
<v-toolbar-title class="white--text">
<v-btn @click="showWallet = !showWallet" elevation="0" class="white--text" text><span
id="creditCount" v-text="creditStr+' Credits'"></span><v-icon>
mdi-wallet
</v-icon></v-btn>
</v-toolbar-title>
</v-toolbar>
<!-- Wallet Modal -->
<v-dialog v-model="showWallet" max-width="500px">
<v-card>
<v-card-title>
<span class="headline">Wallet Management</span>
<v-spacer></v-spacer>
<!-- About tooltip -->
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon v-on="on" @click="showAbout = !showAbout">
<v-icon>mdi-information</v-icon>
</v-btn>
</template>
<span>Credits currently can be used for: <ul>
<li>Bulk data exports (thousands to hundres of thousands of records)</li>
</ul>Credits will soon be used for: <ul>
<li>Mass-deletion of records (avoid crypto fees)</li>
<li>Enrichment of your own data-sets (via CSV upload)</li>
<li>Exporting data from the visualization tool as CSV or Relational JSON
</li>
<li>Any other resource intensive task</li>
</ul><br />Of course, regular search will remain free, forever.</span>
</v-tooltip>
</v-card-title>
<v-card-text>
<v-row>
<v-col cols="12">
<!-- Allow user to copy their wallet ID -->
<v-text-field id="walletId" v-model="walletId" label="Wallet ID" append
append-icon="mdi-content-copy" @change="updateWalletID"></v-text-field>
<!-- Subtle warning to user that anyone can use their credits if they have their wallet ID -->
<v-alert dense type="warning" outlined>
Your wallet ID is the key to your credits and exports. If you share it with
someone,
that person can use your credits. If you lose it, you lose your credits.
</v-alert>
</v-col>
<v-col cols="12">
<!-- Allow user to re-fill their wallet -->
<v-row>
<v-col cols="10">
<v-text-field v-model="walletFill" label="Fill Wallet (1 USD = 100)"
append prepend-icon="mdi-currency-usd"></v-text-field>
</v-col>
<v-col cols="2">
<v-btn class="my-0 mt-3" color="blue darken-1" block text
@click="doFillWallet">
Fill
</v-btn>
</v-col>
</v-row>
</v-col>
</v-row>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="showWallet = false">
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<!-- Export Modal -->
<v-dialog v-model="showExport" max-width="500px">
<v-card>
<v-card-title>
<span class="headline">New Export</span>
<v-spacer></v-spacer>
<!-- About tooltip -->
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon v-on="on" @click="showAbout = !showAbout">
<v-icon>mdi-information</v-icon>
</v-btn>
</template>
<span>Exports are a way to download your data. You can export your data as a CSV
file, or as a JSON file. The JSON file will be in a relational format, so you
can easily import it into a database. <br /><br />You can also export your data
from the visualization tool as CSV or Relational JSON.</span>
</v-tooltip>
</v-card-title>
<v-card-text>
<!-- Allow user to paste in search url as input -->
<v-text-field id="exportUrl" v-model="exportUrl" label="Search URL" append
append-icon="mdi-content-paste"></v-text-field>
<!-- Input how many records to export -->
<v-text-field id="exportCount" v-model="exportCount" label="Record Count" append
append-icon="mdi-numeric"></v-text-field>
</v-card-text>
<v-card-actions>
<v-btn color="red darken-1" text @click="showExport = false">
Close
</v-btn>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="doExport">
Export
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</span>
<v-container flex pa-0>
<h1 style="margin-top: 5%">Database Exports</h1>
<!-- Lists exports for wallet -->
<v-card style="margin-top: 5%">
<v-card-title>
<span class="headline">Exports List</span>
<v-spacer></v-spacer>
<!-- New export button (plus icon) -->
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon v-on="on" @click="showExport = !showExport">
<v-icon>mdi-plus</v-icon>
</v-btn>
</template>
<span>Create a new export</span>
</v-tooltip>
</v-card-title>
<v-card-text>
<v-data-table :items="exports" :headers="exportsTableHeaders">
<!-- Download button slot -->
<template v-slot:item.download="{ item }">
<v-btn :disabled="item.status != 'complete'" color="blue darken-1" text
@click="downloadExport(item)">
Download
</v-btn>
</template>
</v-data-table>
</v-card-text>
</v-card>
<small>Copyright <a href="https://illicit.services">Illicit Services LTD</a>. Email: <a
href="mailto:miyakoyakota@riseup.com">miyakoyakota@riseup.com</a>. By using this service you agree with the <a
href="/terms">terms of use</a>. Also, treat these downloads as "hot" storage, don't expect
your download to stay up forever should MEGA delete it.</small>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<script>
const creditCountElement = document.getElementById("creditCount")
new Vue({
el: '#app',
vuetify: new Vuetify({
theme: { dark: true },
// Mdi icons
icons: {
iconfont: 'mdi',
},
}),
data: () => ({
showWallet: false,
balance: 0,
exact: true,
showExport: false,
creditStr: '<loading>',
exportUrl: '',
walletFill: 0.0,
exportCount: 200,
walletId: '',
exports: [],
exportsTableHeaders: [
{ text: 'Export ID', value: 'jobid' },
{ text: 'Status', value: 'status' },
{ text: 'Query', value: 'query' },
{ text: 'Record Count', value: 'exportCount' },
{ text: 'Download', value: 'download' }
],
hashTypes: ['BCrypt', 'MD5', 'SHA1', 'SHA256', 'SHA512', 'RIPEMD160', 'SHA3', 'SHA224', 'SHA384'],
queryOptions: [
'First Name',
'Last Name',
'Email',
'Username',
'Password',
'Domain',
'IP Address',
'ASN Number',
'ASN Name',
'Continent',
'Country',
'Phone',
'Address',
'License Plate Number',
'Birth Year',
'VIN',
'City',
'State',
'Zip',
'Source'
],
queryFieldMap: {
'First Name': 'firstName',
'Last Name': 'lastName',
'Email': 'emails',
'Username': 'usernames',
'Password': 'passwords',
'Domain': 'domain',
'IP Address': 'ips',
'ASN Number': 'asn',
'ASN Name': 'asnOrg',
'Continent': 'continent',
'Country': 'country',
'Phone': 'phoneNumbers',
'Address': 'address',
'License Plate Number': 'VRN',
'Birth Year': 'birthYear',
'VIN': 'vin',
'City': 'city',
'State': 'state',
'Zip': 'zipCode',
'Source': 'source'
}
}),
mounted() {
// Check if ?url= is in the URL
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('url')) {
this.exportUrl = decodeURIComponent(urlParams.get('url'));
this.showExport = true;
}
// Check if wallet is in local storage
if (localStorage.getItem('walletId')) {
console.log('wallet found')
this.walletId = localStorage.getItem('walletId')
// Get balance
fetch(`/wallet/${this.walletId}`)
.then(response => response.json())
.then(data => {
console.log(`wallet balance: ${data.credits}`)
this.balance = data.credits
this.creditStr = data.credits.toString()
})
// Get exports
fetch(`/exports/${this.walletId}`)
.then(response => response.json())
.then(data => {
console.log(`wallet exports: ${data}`)
this.exports = data
})
} else {
// Create a new wallet ID (uuid)
this.walletId = this.uuidv4()
console.log('wallet created: ' + this.walletId)
localStorage.setItem('walletId', this.walletId)
this.balance = 0
this.creditStr = '0.0'
// Get balance
fetch(`/wallet/${this.walletId}`)
.then(response => response.json())
.then(data => {
console.log(`wallet balance: ${data.credits}`)
this.balance = data.credits
this.creditStr = data.credits.toString()
})
}
},
methods: {
updateWalletID(id) {
if (typeof id === 'string') {
this.walletId = id
console.log('wallet updated: ' + id)
localStorage.setItem('walletId', id)
}
},
downloadExport(item) {
// Open item.link in new tab
window.open(item.link, '_blank')
},
goToMap() {
window.location.href = `/map`
},
isMobile() {
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
return true
} else {
return false
}
},
uuidv4() {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
},
doExport() {
// Check if wallet is valid
if (this.walletId.length !== 36) {
alert('Invalid wallet ID')
return
}
// Check if export count is valid
if (this.exportCount > 100000) {
alert('Max 100,000 records per export')
return
}
const exportUrlParams = new URL(this.exportUrl).searchParams;
// Construct the /export URL with the same query parameters
const exportUrl = new URL('/export', window.location.origin);
exportUrl.search = exportUrlParams.toString();
if (this.exportCount <= 100) {
return this.actuallyDoExport(exportUrl)
}
// Calculate cost. 1 credit = 10 records, first 100 records are free
const cost = (this.exportCount - 100) / 10
// Check if user has enough credits
if (this.balance < cost) {
alert('Not enough credits')
return
}
// Confirm export
if (!confirm(`Export ${this.exportCount} records for ${cost} credits?`)) {
return
}
this.actuallyDoExport(exportUrl)
// Deduct from local wallet
this.balance -= cost
this.creditStr = this.balance.toString()
// Close modal
this.showExport = false
// reset search url
this.exportUrl = ''
// reset export count
this.exportCount = 200
// If "url" is in the URL, remove it
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('url')) {
urlParams.delete('url')
window.history.replaceState({}, document.title, `${window.location.pathname}?${urlParams.toString()}`);
}
},
actuallyDoExport(exportUrl) {
fetch(exportUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
walletId: this.walletId,
exportCount: this.exportCount
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Export started... check back soon')
this.exports.push({
query: new URL(exportUrl).searchParams.toString(),
exportCount: this.exportCount,
status: 'pending',
...data
})
console.log(this.exports)
} else {
alert('Error exporting. Credits have not been deducted')
}
})
},
doFillWallet() {
const walletId = this.walletId
// 1USD = 100 Credits
const amount = this.walletFill * 100
// Check if amount is valid
if (amount < 100) {
alert('Minimum $1')
return
}
// Check if wallet is valid
if (walletId.length !== 36) {
alert('Invalid wallet ID')
return
}
window.location = `/fillWallet/${walletId}/${amount}`
},
copyWalletId() {
// Method 1
const el = document.createElement('textarea');
el.value = this.walletId;
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
// Method 2
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(this.walletId)
}
// Method 3
const input = document.getElementById('walletId');
input.focus();
input.select();
document.execCommand('copy');
},
buildQuery() {
let query = ''
this.queries.forEach((q, idx) => {
const field = this.queryFieldMap[q.field];
const value = q.value;
if (q.not) {
if (idx === 0) {
query += `not${field}=${q.value}`;
} else {
query += `&not${field}=${q.value}`;
}
} else {
if (idx === 0) {
query += `${field}=${q.value}`;
} else {
query += `&${field}=${q.value}`;
}
}
if (this.exact) {
query += `&exact=true`;
}
});
return query
}
}
})
</script>
</body>
</html>

View File

@@ -0,0 +1,409 @@
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js" integrity="sha512-E8QSvWZ0eCLGk4km3hxSsNmGWbLtSCSUcewDQPQWZF6pEU8GlT8a5fF32wOl1i8ftdMhssTrF/OhyGWwonTcXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/bcryptjs@2.4.3/dist/bcrypt.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Database Search - Illicit Services</title>
<meta name="description" content="Search our database of leaked information. All information is in the public domain and has been compiled into one search engine.">
<meta name="robots" content="index, follow">
<meta property="og:type" content="article" />
<meta property="og:title" content="Illict Services LTD" />
<meta property="og:description" content="Search our database of leaked information. All information is in the public domain and has been compiled into one search engine." />
<meta property="og:url" content="https://search.illicit.services" />
<meta property="og:site_name" content="Database Search" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en" />
<meta name="apple-mobile-web-app-status-bar" content="#000000" />
<meta name="theme-color" content="#000000" />
<style>
html,
body, {
height: 100%;
}
#app {
height: 100%;
}
html,
body, #app, v-main__wrap {
background-color: black;
}
/* */
</style>
</head>
<body>
<div id="app">
<v-app>
<v-main>
<span>
<!-- Wallet goes in the top-right -->
<v-toolbar flat color="transparent" dark app style="position: absolute; top: 0; right: 0; z-index: 1000">
<v-toolbar-title class="white--text">
<v-btn @click="showWallet = !showWallet" elevation="0" class="white--text" text><span id="creditCount" v-text="creditStr+' Credits'"></span><v-icon>
mdi-wallet
</v-icon></v-btn>
</v-toolbar-title>
</v-toolbar>
<!-- Wallet Modal -->
<v-dialog v-model="showWallet" max-width="500px">
<v-card>
<v-card-title>
<span class="headline">Wallet Management</span>
<v-spacer></v-spacer>
<!-- About tooltip -->
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon v-on="on" @click="showAbout = !showAbout">
<v-icon>mdi-information</v-icon>
</v-btn>
</template>
<span>Credits currently can be used for: <ul><li>Bulk data exports (thousands to hundres of thousands of records)</li></ul>Credits will soon be used to allow for: <ul><li>Mass-deletion of records (avoid crypto fees)</li><li>Enrichment of your own data-sets (via CSV upload)</li><li>Exporting data from the visualization tool as CSV or Relational JSON</li><li>Any other resource intensive task</li></ul><br/>Of course, regular search will remain free, forever.</span>
</v-tooltip>
</v-card-title>
<v-card-text>
<v-row>
<v-col cols="12">
<!-- Allow user to copy their wallet ID -->
<v-text-field id="walletId" v-model="walletId" label="Wallet ID" append append-icon="mdi-content-copy" @click:append="copyWalletId" @change="updateWalletID"></v-text-field>
<!-- Subtle warning to user that anyone can use their credits if they have their wallet ID -->
<v-alert dense type="warning" outlined>
Your wallet ID is the key to your credits. If you share it with someone, that person can use your credits. If you lose it, you lose your credits.
</v-alert>
</v-col>
<v-col cols="12">
<!-- Allow user to re-fill their wallet -->
<v-row>
<v-col cols="10">
<v-text-field v-model="walletFill" label="Fill Wallet (1 USD = 100)" append prepend-icon="mdi-currency-usd"></v-text-field>
</v-col>
<v-col cols="2">
<v-btn class="my-0 mt-3" color="blue darken-1" block text @click="doFillWallet">
Fill
</v-btn>
</v-col>
</v-row>
</v-col>
</v-row>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="showWallet = false">
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</span>
<v-container flex pa-0>
<h1 style="margin-top: 5%">Records Search</h1>
<h2 style="margin-top: 2%">{{count}} Records in DB</h2>
<h3 style="margin-top: 2%"><a href="/map" target="_blank">Try the Map</a>! | <a href="/dear_peter">A Letter to Peter Kleissner</a> | <a href="https://t.me/illsvc">Join the Telegram</a> | <a href="/faq">FAQ</a> | <a href="/donations">Donations</a> | <a href="/exports">Exports</a></h3>
<!-- Align card to center of page-->
<v-card elevation="0" style="background-color: transparent">
<v-row>
<v-col md="3">
<h4 style="margin-top: 12%">Search Something...</h4>
</v-col>
<v-col md="2">
<v-checkbox v-model="exact" label="exact?"></v-checkbox>
</v-col>
<v-col md="7">
<v-spacer />
</v-col>
</v-row>
<v-row v-for="query, idx in queries" style="width: 100%; margin-top: 2%">
<v-col class="my-0 py-1 mx-0 px-0" md="1">
<v-btn v-if="idx === 0" @click="addQuery" elevation="0" class="white--text" text
fab><v-icon>
mdi-plus
</v-icon>
</v-btn>
<v-btn v-else @click="queries.splice(idx, 1)" elevation="0" class="white--text" text
fab><v-icon>
mdi-minus
</v-icon>
</v-col>
<v-col md="2">
<v-select class="my-0 py-0 mx-0 px-0" v-model="query.field" :items="queryOptions" autocomplete="off"></v-select>
</v-col>
<v-col v-if="!isMobile()" md="1">
<v-checkbox class="my-0 mx-0 px-0" v-model="query.not" label="Is Not"></v-checkbox>
</v-col>
<v-col v-if="query.field !== 'Password'" md="6">
<v-text-field class="my-0 py-0 mx-0 px-0" v-model="query.value"></v-text-field>
</v-col>
<v-col v-if="query.field === 'Password'" md="4">
<v-text-field class="my-0 py-0 mx-0 px-0" v-model="query.value"></v-text-field>
</v-col>
<v-col v-if="query.field === 'Password'" md="2">
<v-checkbox class="my-0 mx-0 px-0" v-model="query.extendedSearch" label="Extended Search"></v-text-field>
</v-col>
<v-col md="2">
<v-btn @click="buildAndSendQuery" v-if="idx === 0" class="my-0 py-0" elevation="0" class="white--text"
text><v-icon>
mdi-account-search
</v-icon></v-btn>
</v-col>
</v-row>
</v-card>
<div style="margin-left: 10px">
<p style="margin-top: 5%">Example Queries:</p>
<p><a href="/records?firstName=Troy&lastName=Hunt">Name: Troy Hunt</a></p>
<p><a href="/records?emails=larrytsantos@yahoo.com">Email: larrytsantos@yahoo.com</a></p>
<p><a href="/records?usernames=Oni">Username: Oni</a></p>
<p><a href="/records?VRN=kjg7920">License Plate: KJG7920</a></p>
</div>
<div style="margin-left: 10px">
<p>If you find these services useful, BTC and Monero donations are appreciated. <br /> BTC: bc1qel7fg6yd96fp3yjh94av8pssz8er2yeluylzcw <br />XMR: 44y4PfBf2TmfgGEX7vAZ7MdCBohAuwDGee8BjwbVfUP75nmEQqbB3rDLRTfEcbkHq33ZVoofMrEX63fVPxHcsVv8AnD9KRo</p>
</div>
<small>Copyright <a href="https://illicit.services">Illicit Services LTD</a>. By using this service you agree with the <a href="/terms">terms of use</a>. <a href="/canary">Canary</a></small>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<script>
const creditCountElement = document.getElementById("creditCount")
new Vue({
el: '#app',
vuetify: new Vuetify({
theme: { dark: true },
// Mdi icons
icons: {
iconfont: 'mdi',
},
}),
data: () => ({
queries: [
{ field: 'First Name', value: '' },
],
showWallet: false,
balance: 0,
exact: false,
creditStr: '<loading>',
walletFill: 0.0,
walletId: '',
hashTypes: ['BCrypt', 'MD5', 'SHA1', 'SHA256', 'SHA512', 'RIPEMD160', 'SHA3', 'SHA224', 'SHA384'],
queryOptions: [
'First Name',
'Last Name',
'Email',
'Username',
'Password',
'Domain',
'IP Address',
'ASN Number',
'ASN Name',
'Continent',
'Country',
'Phone',
'Address',
'License Plate Number',
'Birth Year',
'VIN',
'City',
'State',
'Zip',
'Source'
],
queryFieldMap: {
'First Name': 'firstName',
'Last Name': 'lastName',
'Email': 'emails',
'Username': 'usernames',
'Password': 'passwords',
'Domain': 'domain',
'IP Address': 'ips',
'ASN Number': 'asn',
'ASN Name': 'asnOrg',
'Continent': 'continent',
'Country': 'country',
'Phone': 'phoneNumbers',
'Address': 'address',
'License Plate Number': 'VRN',
'Birth Year': 'birthYear',
'VIN': 'vin',
'City': 'city',
'State': 'state',
'Zip': 'zipCode',
'Source': 'source'
}
}),
mounted() {
// Check if wallet is in local storage
if (localStorage.getItem('walletId')) {
console.log('wallet found')
this.walletId = localStorage.getItem('walletId')
// Get balance
fetch(`/wallet/${this.walletId}`)
.then(response => response.json())
.then(data => {
console.log(`wallet balance: ${data.credits}`)
this.balance = data.credits
this.creditStr = data.credits.toString()
})
} else {
// Create a new wallet ID (uuid)
this.walletId = this.uuidv4()
console.log('wallet created: '+this.walletId)
localStorage.setItem('walletId', this.walletId)
this.balance = 0
this.creditStr = '0.0'
// Get balance
fetch(`/wallet/${this.walletId}`)
.then(response => response.json())
.then(data => {
console.log(`wallet balance: ${data.credits}`)
this.balance = data.credits
this.creditStr = data.credits.toString()
})
}
},
methods: {
updateWalletID(id) {
if (typeof id === 'string') {
this.walletId = id
console.log('wallet updated: '+id)
localStorage.setItem('walletId', id)
}
},
addQuery() {
// Limit 5 queries
if (this.queries.length >= 5) {
alert('Max 5 fields per query')
} else {
this.queries.push({ field: 'First Name', value: '' })
}
},
goToMap() {
window.location.href = `/map`
},
isMobile() {
if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
return true
} else {
return false
}
},
uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
},
doFillWallet() {
const walletId = this.walletId
// 1USD = 100 Credits
const amount = this.walletFill * 100
// Check if amount is valid
if (amount < 100) {
alert('Minimum $1')
return
}
// Check if wallet is valid
if (walletId.length !== 36) {
alert('Invalid wallet ID')
return
}
window.location = `/fillWallet/${walletId}/${amount}`
},
copyWalletId() {
// Method 1
const el = document.createElement('textarea');
el.value = this.walletId;
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
// Method 2
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(this.walletId)
}
// Method 3
const input = document.getElementById('walletId');
input.focus();
input.select();
document.execCommand('copy');
},
buildAndSendQuery() {
let query = ''
this.queries.forEach((q, idx) => {
const field = this.queryFieldMap[q.field];
const value = q.value;
if (q.not) {
if (idx === 0) {
query += `not${field}=${q.value}`;
} else {
query += `&not${field}=${q.value}`;
}
} else {
if (idx === 0) {
query += `${field}=${q.value}`;
} else {
query += `&${field}=${q.value}`;
}
}
if (q.extendedSearch && field === "passwords") {
this.hashTypes.forEach((hashType) => {
if (hashType === 'BCrypt') {
for (let i = 0; i <= 15; i++) {
console.log(`Generating ${hashType} hash (rotation ${i}) for "${value}"...`)
const hashValue = dcodeIO.bcrypt.hashSync(value, i);
console.log(`${hashType} for "${value}" is "${hashValue}"`)
query += `&passwords=${hashValue}`;
}
} else {
console.log(`Generating ${hashType} hash for ${value}...`)
const hashValue = CryptoJS[hashType](value).toString();
console.log(`${hashType} for ${value} is ${hashValue}`)
query += `&passwords=${hashValue}`;
}
});
}
if (this.exact) {
query += `&exact=true`;
}
});
// Send query
window.location.href = `/records?${query}`
}
}
})
</script>
</body>
</html>

View File

@@ -0,0 +1,41 @@
<html>
<head>
<meta property="og:type" content="article" />
<meta property="og:title" content="Record Report - {{id}}" />
<meta name="description" content="Database Record Report {{#record}}{{key}}: {{value}} {{/record}}">
<meta property="og:description" content="Database Record Report {{#record}}{{key}}: {{value}} {{/record}}" />
<meta property="og:site_name" content="Database Search" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en" />
<meta name="robots" content="index, follow">
<title>Record Report - {{id}}</title>
</head>
<body>
<h1>Record Report</h1>
<table>
{{#record}}
<tr>
<th>{{key}}</th>
<td>{{value}}</td>
</tr>
{{/record}}
</table>
<br />
<a href='/visualize?id={{id}}' rel="nofollow">Visualize</a>
<br />
<br />
<h3>Related Records</h3>
{{#related}}
<dl>
<dt><a href="/documents/by_id/{{id}}">{{id}}</a></dt>
{{#record}}
<dd>{{key}}: {{value}}</dd>
{{/record}}
</dl>
{{/related}}
</html>

View File

@@ -0,0 +1,36 @@
<html>
<!-- Lists all record's first names, at the bottom of the page there's options to choose a-z -->
<head>
<meta property="og:type" content="article" />
<meta property="og:title" content="Record Report" />
<meta property="og:description" content="Database Record Report {{#record}}{{key}}: {{value}} {{/record}}" />
<meta property="og:site_name" content="Database Search" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en" />
<meta name="robots" content="index, follow">
<title>Records Result - {{count}} Results</title>
<script>
function exportMore() {
const encodedUrl = encodeURIComponent(window.location.href);
window.location.href = `/exports?url=${encodedUrl}`;
}
</script>
</head>
<body>
<h1>Records Result</h1>
<h2>{{resultCount}} Hits - {{count}} Results Shown <button onclick="exportMore()">Click here for more</button></h2>
{{#records}}
<div class="record">
<dl>
<dt>
<a href="/documents/by_id/{{ id }}">{{id}}</a> - <a href='/visualize?id={{id}}' rel="nofollow">(Visualize)</a> - <a href="/faq" rel="nofollow">(See FAQ about Removal)</a></dt>
{{#fields}}
<dd> {{ . }}</a></dd>
{{/fields}}
</dl>
</div>
{{/records}}
</body>
</html>

View File

@@ -0,0 +1,298 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cytoscape JS App</title>
<script src="https://unpkg.com/cytoscape@3.19.0/dist/cytoscape.min.js"></script>
<style>
#cy {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
/* Add this to your CSS file or inside a <style> tag */
#floating-menu {
position: fixed;
top: 10px;
right: 10px;
background-color: white;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
z-index: 999;
}
#floating-menu label,
#floating-menu select,
#floating-menu input {
margin-right: 5px;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/qtip2/3.0.3/jquery.qtip.min.css" />
<!-- Add these lines inside the <head> tag -->
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6.3.1/dist/tippy.css" />
<!-- Add these lines before the app.js script -->
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://cytoscape.org/cytoscape.js-popper/cytoscape-popper.js"></script>
<script src="https://unpkg.com/tippy.js@6"></script>
</head>
<body>
<!-- Add this inside the <body> tag -->
<div id="floating-menu">
<label for="layout-select">Graph Type:</label>
<select id="layout-select">
<option value="cose">Cose</option>
<option value="grid">Grid</option>
<option value="circle">Circle</option>
<option value="concentric">Concentric</option>
<option value="breadthfirst">Breadthfirst</option>
</select>
<label for="min-similarity">Minimum Similarity Score:</label>
<input type="number" id="min-similarity" min="0" value="10" />
<br />
<p>Statistics: The last query returned <span id="lastQueryCount">0</span> similar results, of which <span id="lastQueryShown">0</span> were shown. The lowest similarity score was <span id="lastQueryLowestScore">0</span>.</p>
</div>
<div id="cy"></div>
<script>
const tips = {}
const layoutSelect = document.getElementById('layout-select');
const minSimilarityInput = document.getElementById('min-similarity');
const lastQueryCount = document.getElementById("lastQueryCount")
const lastQueryShownCount = document.getElementById("lastQueryShown")
const lastQueryShownLowestScore = document.getElementById("lastQueryLowestScore")
// Set default values
let selectedLayout = 'circle';
let minSimilarity = 10;
// Initialize Cytoscape instance
const cy = cytoscape({
container: document.getElementById('cy'),
elements: [],
style: [
{
selector: 'node',
style: {
'background-color': '#0074D9',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#7FDBFF',
'curve-style': 'bezier'
}
}
],
layout: {
name: selectedLayout
}
});
// Function to apply the selected layout
function applyLayout() {
cy.layout({ name: selectedLayout }).run();
}
// Event listener for layout selection
layoutSelect.addEventListener('change', (event) => {
selectedLayout = event.target.value;
applyLayout();
});
// Event listener for minimum similarity input
minSimilarityInput.addEventListener('input', (event) => {
minSimilarity = parseInt(event.target.value);
console.log("New minimum similarity: " + minSimilarity)
});
// Apply the default layout when the graph is loaded
applyLayout();
var makeTippy = function (ele, text) {
var ref = ele.popperRef();
// Since tippy constructor requires DOM element/elements, create a placeholder
var dummyDomEle = document.createElement('div');
var tip = tippy(dummyDomEle, {
getReferenceClientRect: ref.getBoundingClientRect,
trigger: 'manual', // mandatory
// dom element inside the tippy:
content: function () { // function can be better for performance
var div = document.createElement('div');
div.innerHTML = text;
return div;
},
// your own preferences:
arrow: true,
placement: 'bottom',
hideOnClick: false,
sticky: "reference",
// if interactive:
interactive: true,
appendTo: document.body // or append dummyDomEle to document.body
});
return tip;
};
function createDocSummary(doc) {
const blacklist = ['id', '_version_', 'line', 'notes']
const summary = []
for (const key in doc) {
if (!blacklist.includes(key)) {
summary.push(`${key}: ${doc[key]}<br />`)
}
}
return summary.join('\n')
}
// Function to add new nodes (modified to include tooltip creation)
function addDocument(record) {
const id = record.id
let newNode = null;
try {
newNode = cy.add({
group: 'nodes',
data: { id },
});
const tippy = makeTippy(newNode, createDocSummary(record));
tips[id] = tippy
} catch (e) {
console.log(e)
}
cy.layout({
name: selectedLayout,
minNodeSpacing: 200
}).run();
return newNode
// cy.layout({ name: 'grid', rows: 1 }).run();
}
// Function to create links between nodes
function createLink(source, target) {
cy.add({
group: 'edges',
data: {
id: `${source}-${target}`,
source,
target
}
});
}
// Event handler for node click
cy.on('tap', 'node', async function (event) {
const nodeId = event.target.data('id');
try {
const response = await fetch(`/documents/by_id/${nodeId}?wt=json&moreLikeThis=true`);
if (response.ok) {
const data = await response.json();
lastQueryCount.innerText = data.related.length
let countShown = 0
let lowestScore = 1000000;
data.related.forEach((record) => {
if (record['similarity score'] < lowestScore) {
lowestScore = record['similarity score']
}
if (record['similarity score'] >= minSimilarity) {
addDocument(record)
createLink(nodeId, record.id)
countShown += 1
console.log(record['similarity score'])
}
})
if (lowestScore === 1000000) {
lastQueryShownLowestScore.innerText = 0
} else {
lastQueryShownLowestScore.innerText = lowestScore
}
} else {
console.error('Error fetching data from API:', response.status, response.statusText);
}
} catch (error) {
console.error('Error fetching data from API:', error);
}
});
cy.on('mouseover', 'node', function (event) {
tips[event.target.id()].show()
});
cy.on('mouseout', 'node', function (event) {
tips[event.target.id()].hide()
});
(async () => {
// Get URL parameters
const urlParams = new URLSearchParams(window.location.search);
const nodeId = urlParams.get('id');
if (nodeId) {
const response = await fetch(`/documents/by_id/${nodeId}?wt=json`);
if (response.ok) {
const data = await response.json();
if (nodeId) {
const initialNode = addDocument(data.record);
const initialNodeTip = makeTippy(initialNode, "Click Me!");
initialNodeTip.show()
setTimeout(() => {
initialNodeTip.hide()
}, 7000)
}
}
else {
alert("Error fetching from API")
}
}
})()
</script>
</body>
</html>