2023-07-06 05:15:23 +00:00

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 += `&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>