mirror of
https://github.com/MiyakoYakota/search.0t.rocks.git
synced 2025-02-05 15:37:21 +00:00
524 lines
24 KiB
HTML
524 lines
24 KiB
HTML
|
<!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 += `¬${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>
|