Track quota usage and allow upgrading quotas

This commit is contained in:
Daniel Winzen
2019-12-14 20:59:04 +01:00
parent fee1c135c2
commit 0e0fb54eae
11 changed files with 300 additions and 40 deletions

View File

@ -5,7 +5,7 @@ const DBUSER='hosting'; // Database user
const DBPASS='MY_PASSWORD'; // Database password const DBPASS='MY_PASSWORD'; // Database password
const DBNAME='hosting'; // Database const DBNAME='hosting'; // Database
const PERSISTENT=true; // Use persistent database conection true/false const PERSISTENT=true; // Use persistent database conection true/false
const DBVERSION=16; //database layout version const DBVERSION=17; //database layout version
const CAPTCHA=1; // Captcha difficulty (0=off, 1=simple, 2=moderate, 3=extreme) const CAPTCHA=1; // Captcha difficulty (0=off, 1=simple, 2=moderate, 3=extreme)
const ADDRESS='dhosting4xxoydyaivckq7tsmtgi4wfs3flpeyitekkmqwu4v4r46syd.onion'; // our own address const ADDRESS='dhosting4xxoydyaivckq7tsmtgi4wfs3flpeyitekkmqwu4v4r46syd.onion'; // our own address
const CANONICAL_URL='https://hosting.danwin1210.me'; // our preferred domain for search engines const CANONICAL_URL='https://hosting.danwin1210.me'; // our preferred domain for search engines
@ -24,7 +24,7 @@ const INDEX_MD5S=[ //MD5 sums of index.hosting.html files that should be considd
const REQUIRE_APPROVAL=false; //require admin approval of new sites? true/false const REQUIRE_APPROVAL=false; //require admin approval of new sites? true/false
const ENABLE_SHELL_ACCESS=true; //allows users to login via ssh, when disabled only (s)ftp is allowed - run setup.php to migrate existing accounts const ENABLE_SHELL_ACCESS=true; //allows users to login via ssh, when disabled only (s)ftp is allowed - run setup.php to migrate existing accounts
const ADMIN_PASSWORD='MY_PASSWORD'; //password for admin interface const ADMIN_PASSWORD='MY_PASSWORD'; //password for admin interface
const SERVICE_INSTANCES=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's']; //one character per instance - run multiple tor+php-fpm instances for load balancing, remove all but one instance if you expect less than 200 accounts. - run setup.php after change const SERVICE_INSTANCES=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's']; //one character per instance - run multiple tor+php-fpm instances for load balancing, remove all but one instance if you expect less than 200 accounts. If tor starts using 100% cpu and failing circuits every few hours after a restart, add more instances. In my experience this happens around 250 hidden services per instance - run setup.php after change
const DISABLED_PHP_VERSIONS=[]; //php versions still installed on the system but no longer offered for new accounts const DISABLED_PHP_VERSIONS=[]; //php versions still installed on the system but no longer offered for new accounts
const PHP_VERSIONS=[3 => '7.2', 4 => '7.3', 5 => '7.4']; //currently active php versions const PHP_VERSIONS=[3 => '7.2', 4 => '7.3', 5 => '7.4']; //currently active php versions
const DEFAULT_PHP_VERSION='7.3'; //default php version const DEFAULT_PHP_VERSION='7.3'; //default php version
@ -116,9 +116,20 @@ const MAX_NUM_USER_DBS = 5; //maximum number of databases a user may have
const MAX_NUM_USER_ONIONS = 3; //maximum number of onion domains a user may have const MAX_NUM_USER_ONIONS = 3; //maximum number of onion domains a user may have
const MAX_NUM_USER_DOMAINS = 3; //maximum number of clearnet domains a user may have const MAX_NUM_USER_DOMAINS = 3; //maximum number of clearnet domains a user may have
const SKIP_USER_CHROOT_UPDATE = true; //skips updating user chroots when running setup.php const SKIP_USER_CHROOT_UPDATE = true; //skips updating user chroots when running setup.php
const DEFAULT_QUOTA_SIZE = 10 * 1024 * 1024; //per user disk quota in kb - Defaults to 10 GB const DEFAULT_QUOTA_SIZE = 1024 * 1024; //per user disk quota in kb - Defaults to 1 GB
const DEFAULT_QUOTA_FILES = 100000; //per user file quota - by default allow no more than 100000 files const DEFAULT_QUOTA_FILES = 100000; //per user file quota - by default allow no more than 100000 files
const NUM_GUARDS = 50; //number of tor guard relays to distribute the load on const NUM_GUARDS = 50; //number of tor guard relays to distribute the load on
//Optional paid upgrades in format of 'identifier' => ['name', 'usd_price']
const ACCOUNT_UPGRADES = [
'1g_quota' => ['name' => '+1GB disk Quota', 'usd_price' => 10],
'5g_quota' => ['name' => '+5GB disk Quota', 'usd_price' => 20],
'10g_quota' => ['name' => '+10GB disk Quota', 'usd_price' => 30],
'20g_quota' => ['name' => '+20GB disk Quota', 'usd_price' => 40],
];
const COINPAYMENTS_PRIVATE = 'COINPAYMENTS_PRIVATE_API_KEY';
const COINPAYMENTS_PUBLIC = 'COINPAYMENTS_PUBLIC_API_KEY';
const COINPAYMENTS_MERCHANT_ID = 'COINPAYMENTS_MERCHANT_ID';
const COINPAYMENTS_IPN_SECRET = 'COINPAYMENTS_IPN_SECRET';
function get_onion_v2($pkey) : string { function get_onion_v2($pkey) : string {
$keyData = openssl_pkey_get_details($pkey); $keyData = openssl_pkey_get_details($pkey);
@ -751,3 +762,103 @@ function get_db_instance(){
} }
return $db; return $db;
} }
function coinpayments_create_transaction(string $currency, int $price, string $payment_for, $user_id = null){
$query=[];
$query['currency1'] = 'USD';
$query['currency2'] = $currency;
$query['amount'] = $price;
$query['buyer_email'] = 'daniel@danwin1210.me';
$query['version'] = '1';
$query['cmd'] = 'create_transaction';
$query['key'] = COINPAYMENTS_PUBLIC;
$query['format'] = 'json';
$query_string = http_build_query( $query );
$hmac = hash_hmac( 'sha512', $query_string, COINPAYMENTS_PRIVATE );
$ch = curl_init();
curl_setopt( $ch, CURLOPT_POSTFIELDS, $query_string );
curl_setopt( $ch, CURLOPT_HTTPHEADER, ["HMAC: $hmac", 'Content-type: application/x-www-form-urlencoded'] );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_URL, 'https://www.coinpayments.net/api.php' );
$result = curl_exec( $ch );
if( !$result ) {
return false;
}
$json = json_decode( $result, true );
if( !$json ){
return false;
}
if( $json['error'] !== 'ok' ) {
return false;
}
$db = get_db_instance();
$stmt = $db->prepare('INSERT INTO payments (user_id, payment_for, txn_id, status) VALUES (?, ?, ?, 0);');
$stmt->execute([$user_id, $payment_for, $json['result']['txn_id']]);
return $json['result'];
}
function coinpayments_get_rates(){
$query=[];
$query['accepted'] = '1';
$query['short'] = '0';
$query['version'] = '1';
$query['cmd'] = 'rates';
$query['key'] = COINPAYMENTS_PUBLIC;
$query['format'] = 'json';
$query_string = http_build_query( $query );
$hmac = hash_hmac( 'sha512', $query_string, COINPAYMENTS_PRIVATE );
$ch = curl_init();
curl_setopt( $ch, CURLOPT_POSTFIELDS, $query_string );
curl_setopt( $ch, CURLOPT_HTTPHEADER, ["HMAC: $hmac", 'Content-type: application/x-www-form-urlencoded'] );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_URL, 'https://www.coinpayments.net/api.php' );
$result = curl_exec( $ch );
if( !$result ) {
return false;
}
$json = json_decode( $result, true );
if( !$json ){
return false;
}
if( $json['error'] !== 'ok' ) {
return false;
}
return $json['result'];
}
function payment_status_update(string $txid){
$db = get_db_instance();
$stmt = $db->prepare('SELECT * FROM payments WHERE txn_id = ?;');
$stmt->execute([$txid]);
while($tmp = $stmt->fetch(PDO::FETCH_ASSOC)){
if($tmp['status'] == '2'){
switch($tmp['payment_for']){
case '1g_quota':
add_disk_quota($tmp['user_id'], 1024 * 1024);
break;
case '5g_quota':
add_disk_quota($tmp['user_id'], 5 * 1024 * 1024);
break;
case '10g_quota':
add_disk_quota($tmp['user_id'], 10 * 1024 * 1024);
break;
case '20g_quota':
add_disk_quota($tmp['user_id'], 20 * 1024 * 1024);
break;
default:
break;
}
}
}
}
function add_disk_quota(int $user_id, int $kb){
$db = get_db_instance();
$stmt = $db->prepare('SELECT quota_size FROM disk_quota WHERE user_id = ?;');
$stmt->execute([$user_id]);
$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt = $db->prepare('UPDATE disk_quota SET quota_size = ?, updated = 1 WHERE user_id = ?;');
$stmt->execute([$tmp['quota_size'] + $kb, $user_id]);
}

View File

@ -1,5 +1,6 @@
{ {
"require": { "require": {
"paragonie/sodium_compat": "^1.11" "paragonie/sodium_compat": "^1.11",
"chillerlan/php-qrcode": "^3.1"
} }
} }

View File

@ -2,6 +2,19 @@
include('common.php'); include('common.php');
$db = get_db_instance(); $db = get_db_instance();
//update quota usage
$stmt=$db->query('SELECT id, system_account FROM users WHERE id NOT IN (SELECT user_id FROM new_account) AND todelete!=1;');
$update=$db->prepare('UPDATE disk_quota SET quota_size_used = ?, quota_files_used = ? WHERE user_id = ?;');
while($tmp=$stmt->fetch(PDO::FETCH_NUM)){
$quota = shell_exec('quota -pu ' . escapeshellarg($tmp[1]));
$quota_array = explode("\n", $quota);
if(!empty($quota_array[2])){
$quota_size=(int) preg_replace('~^\s+[^\s]+\s+([^\s]+).*~', '$1', $quota_array[2]);
$quota_files=(int) preg_replace('~^\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+([^\s]+).*~', '$1', $quota_array[2]);
$update->execute([$quota_size, $quota_files, $tmp[0]]);
}
}
//delete tmp files older than 24 hours //delete tmp files older than 24 hours
$stmt=$db->query('SELECT system_account FROM users;'); $stmt=$db->query('SELECT system_account FROM users;');
$all=$stmt->fetchAll(PDO::FETCH_NUM); $all=$stmt->fetchAll(PDO::FETCH_NUM);

View File

@ -0,0 +1,44 @@
<?php
require('../common.php');
if(empty($_SERVER['HTTP_HMAC'])){
die("No HMAC signature sent");
}
$merchant = $_POST['merchant'] ?? '';
if(empty($merchant)){
die("No Merchant ID passed");
}
if($merchant !== COINPAYMENTS_MERCHANT_ID){
die("Invalid Merchant ID");
}
$request = file_get_contents('php://input');
if(empty($request)){
die("Error reading POST data");
}
$hmac = hash_hmac("sha512", $request, COINPAYMENTS_IPN_SECRET);
if($hmac !== $_SERVER['HTTP_HMAC']){
die("HMAC signature does not match");
}
$db = get_db_instance();
$status = 0;
if($_POST['status'] < 0){
$status = -1;
}elseif($_POST['status'] > 0 && $_POST['status'] < 100){
$status = 1;
}elseif($_POST['status'] >= 100){
$status = 2;
}
$stmt = $db->prepare('SELECT status FROM payments WHERE txn_id = ?;');
$stmt->execute([$_POST['txn_id']]);
if($tmp = $stmt->fetch(PDO::FETCH_ASSOC)){
if($status != $tmp['status']){
$stmt = $db->prepare('UPDATE payments SET status = ? WHERE txn_id = ?;');
$stmt->execute([$status, $_POST['txn_id']]);
payment_status_update($_POST['txn_id']);
}
}

View File

@ -3,6 +3,7 @@ include('../common.php');
$db = get_db_instance(); $db = get_db_instance();
session_start(); session_start();
$user=check_login(); $user=check_login();
header('Content-Type: text/html; charset=UTF-8');
if(isset($_POST['action']) && $_POST['action']==='add_db'){ if(isset($_POST['action']) && $_POST['action']==='add_db'){
if($error=check_csrf_error()){ if($error=check_csrf_error()){
die($error); die($error);
@ -186,17 +187,18 @@ if(isset($_REQUEST['action']) && isset($_POST['domain']) && $_POST['action']==='
enqueue_instance_reload(); enqueue_instance_reload();
} }
} }
?>
header('Content-Type: text/html; charset=UTF-8'); <!DOCTYPE html><html><head>
echo '<!DOCTYPE html><html><head>'; <title>Daniel's Hosting - Dashboard</title>
echo '<title>Daniel\'s Hosting - Dashboard</title>'; <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'; <meta name="author" content="Daniel Winzen">
echo '<meta name="author" content="Daniel Winzen">'; <meta name="viewport" content="width=device-width, initial-scale=1">
echo '<meta name="viewport" content="width=device-width, initial-scale=1">'; <link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
echo '<link rel="canonical" href="' . CANONICAL_URL . $_SERVER['SCRIPT_NAME'] . '">'; <style type="text/css">#custom_onion:not(checked)+#private_key{display:none;}#custom_onion:checked+#private_key{display:block;}</style>
echo '<style type="text/css">#custom_onion:not(checked)+#private_key{display:none;}#custom_onion:checked+#private_key{display:block;}</style>'; <style>td{padding:5px}meter{width:200px}</style>
echo '</head><body>'; </head><body>
echo "<p>Logged in as $user[username] <a href=\"logout.php\">Logout</a> | <a href=\"password.php\">Change passwords</a> | <a target=\"_blank\" href=\"files.php\">FileManager</a> | <a href=\"delete.php\">Delete account</a></p>"; <p>Logged in as <?php echo htmlspecialchars($user['username']); ?> <a href="logout.php">Logout</a> | <a href="password.php">Change passwords</a> | <a target="_blank" href="files.php">FileManager</a> | <a href="delete.php">Delete account</a></p>
<?php
if(!empty($msg)){ if(!empty($msg)){
echo $msg; echo $msg;
} }
@ -300,21 +302,31 @@ echo '</table>';
if($count_dbs<MAX_NUM_USER_DBS){ if($count_dbs<MAX_NUM_USER_DBS){
echo '<p><form action="home.php" method="post"><input type="hidden" name="csrf_token" value="'.$_SESSION['csrf_token'].'"><button type="submit" name="action" value="add_db">Add new database</button></form></p>'; echo '<p><form action="home.php" method="post"><input type="hidden" name="csrf_token" value="'.$_SESSION['csrf_token'].'"><button type="submit" name="action" value="add_db">Add new database</button></form></p>';
} }
echo '<p><a href="password.php?type=sql">Change MySQL password</a></p>'; ?>
echo '<p>You can use <a href="/phpmyadmin/" target="_blank">PHPMyAdmin</a> and <a href="/adminer/?username='.htmlspecialchars($user['mysql_user']).'" target="_blank">Adminer</a> for web based database administration.</p>'; <p><a href="password.php?type=sql">Change MySQL password</a></p>
echo '<h3>System Account</h3>'; <p>You can use <a href="/phpmyadmin/" target="_blank">PHPMyAdmin</a> and <a href="/adminer/?username=<?php echo rawurlencode($user['mysql_user']); ?>" target="_blank">Adminer</a> for web based database administration.</p>
echo '<table border="1">'; <h3>System Account</h3>
echo '<tr><th>Username</th><th>Host</th><th>FTP Port</th><th>SFTP Port</th><th>POP3 Port</th><th>IMAP Port</th><th>SMTP port</th></tr>'; <table border="1">
<tr><th>Username</th><th>Host</th><th>FTP Port</th><th>SFTP Port</th><th>POP3 Port</th><th>IMAP Port</th><th>SMTP port</th></tr>
<?php
foreach(SERVERS as $server=>$tmp){ foreach(SERVERS as $server=>$tmp){
echo "<tr><td>$user[system_account]</td><td>$server</td><td>$tmp[ftp]</td><td>$tmp[sftp]</td><td>$tmp[pop3]</td><td>$tmp[imap]</td><td>$tmp[smtp]</td></tr>"; echo "<tr><td>$user[system_account]</td><td>$server</td><td>$tmp[ftp]</td><td>$tmp[sftp]</td><td>$tmp[pop3]</td><td>$tmp[imap]</td><td>$tmp[smtp]</td></tr>";
} }
echo '</table>'; ?>
echo '<p><a href="password.php?type=sys">Change system account password</a></p>'; </table>
echo '<p>You can use the <a target="_blank" href="files.php">FileManager</a> for web based file management.</p>'; <p><a href="password.php?type=sys">Change system account password</a></p>
echo '<h3>Logs</h3>'; <p>You can use the <a target="_blank" href="files.php">FileManager</a> for web based file management.</p>
echo '<table border="1">'; <?php
echo '<tr><th>Date</th><th>access.log</th><th>error.log</th></tr>'; $stmt = $db->prepare('SELECT quota_size, quota_size_used FROM disk_quota WHERE user_id = ?;');
echo '<tr><td>Today</td><td><a href="log.php?type=access&amp;old=0" target="_blank">access.log</log></td><td><a href="log.php?type=error&amp;old=0" target="_blank">error.log</a></td></tr>'; $stmt->execute([$user['id']]);
echo '<tr><td>Yesterday</td><td><a href="log.php?type=access&amp;old=1" target="_blank">access.log</log></td><td><a href="log.php?type=error&amp;old=1" target="_blank">error.log</a></td></tr>'; $quota = $stmt->fetch(PDO::FETCH_ASSOC);
echo '</table>'; $quota_usage = $quota['quota_size_used'] / $quota['quota_size'];
echo '</body></html>'; ?>
<p>Your disk usage: <meter value="<?php echo round($quota_usage, 2); ?>"><?php echo round($quota_usage * 100); ?>%</meter> - <?php echo round($quota_usage * 100, 2); ?>% (updated hourly) <a href="upgrade.php">Upgrade</a></p>
<h3>Logs</h3>
<table border="1">
<tr><th>Date</th><th>access.log</th><th>error.log</th></tr>
<tr><td>Today</td><td><a href="log.php?type=access&amp;old=0" target="_blank">access.log</log></td><td><a href="log.php?type=error&amp;old=0" target="_blank">error.log</a></td></tr>
<tr><td>Yesterday</td><td><a href="log.php?type=access&amp;old=1" target="_blank">access.log</log></td><td><a href="log.php?type=error&amp;old=1" target="_blank">error.log</a></td></tr>
</table>
</body></html>

View File

@ -22,9 +22,9 @@ header('X-Accel-Expires: 60');
<li>MariaDB (MySQL) database support</li> <li>MariaDB (MySQL) database support</li>
<li><a href="/phpmyadmin/" target="_blank">PHPMyAdmin</a> and <a href="/adminer/" target="_blank">Adminer</a> for web based database administration</li> <li><a href="/phpmyadmin/" target="_blank">PHPMyAdmin</a> and <a href="/adminer/" target="_blank">Adminer</a> for web based database administration</li>
<li>Web-based file manager</li> <li>Web-based file manager</li>
<li>FTP access</li> <li>FTP and SFTP access</li>
<li>SFTP access</li> <li>command line access to shell via SSH</li>
<li>10GB disk quota and a maximum of 100.000 files. If you need more, just <a href="https://danwin1210.me/contact.php">contact me</a></li> <li>1GB disk quota and a maximum of 100.000 files. - upgradable</li>
<li>mail() can send e-mails from your.onion@<?php echo ADDRESS; ?> (your.onion@hosting.danwin1210.me for clearnet) - not yet working but will return in future, use <a href="https://github.com/PHPMailer/PHPMailer" target="_blank">https://github.com/PHPMailer/PHPMailer</a> or similar for now</li> <li>mail() can send e-mails from your.onion@<?php echo ADDRESS; ?> (your.onion@hosting.danwin1210.me for clearnet) - not yet working but will return in future, use <a href="https://github.com/PHPMailer/PHPMailer" target="_blank">https://github.com/PHPMailer/PHPMailer</a> or similar for now</li>
<li>Webmail and IMAP, POP3 and SMTP access to your mail account</li> <li>Webmail and IMAP, POP3 and SMTP access to your mail account</li>
<li>Mail sent to anything@your.onion gets automatically redirected to your inbox</li> <li>Mail sent to anything@your.onion gets automatically redirected to your inbox</li>

View File

@ -73,7 +73,8 @@ if(isset($_POST['username'])){
echo '" required autofocus></td></tr>'; echo '" required autofocus></td></tr>';
echo '<tr><td>Password</td><td><input type="password" name="pass" required></td></tr>'; echo '<tr><td>Password</td><td><input type="password" name="pass" required></td></tr>';
send_captcha(); send_captcha();
echo '<tr><td colspan="2"><input type="submit" value="Login"></td></tr>'; ?>
echo '</table></form>'; <tr><td colspan="2"><input type="submit" value="Login"></td></tr>
echo '<p>If you disabled cookies, please re-enable them. You can\'t log in without!</p>'; </table></form>
echo '</body></html>'; <p>If you disabled cookies, please re-enable them. You can't log in without!</p>
</body></html>

3
var/www/html/robots.txt Normal file
View File

@ -0,0 +1,3 @@
User-agent: *
Allow: /

70
var/www/html/upgrade.php Normal file
View File

@ -0,0 +1,70 @@
<?php
require('../common.php');
session_start();
$user=check_login();
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
header('Content-Type: text/html; charset=UTF-8');
?>
<!DOCTYPE html><html><head>
<title>Daniel's Hosting - Upgrade account</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
<style>td{padding:5px;}</style>
</head><body>
<h1>Hosting - Upgrade account</h1>
<?php
$rates = coinpayments_get_rates();
if($rates === false){
echo '<p>An error occured talking to coinpayments</p>';
}else{
?>
<form action="upgrade.php" method="post">
<table border="1">
<tr><td>Desired upgrade</td><td>
<select name="upgrade">
<?php
foreach(ACCOUNT_UPGRADES as $name => $upgrade){
echo '<option value="'.htmlspecialchars($name).'">'.htmlspecialchars($upgrade['name']).' ($'.$upgrade['usd_price'].')</option>';
}
?>
</td></tr>
<tr><td>Desired payment currency</td><td>
<select name="currency">
<?php
$i=0;
foreach($rates as $symbol => $rate){
if($rate['accepted']===1 && in_array('payments', $rate['capabilities'])){
echo '<option value="'.htmlspecialchars($symbol).'">'.htmlspecialchars($rate['name']).' ('.htmlspecialchars($symbol).')</option>';
}
}
?>
</select></td></tr>
<tr><td colspan="2" style="text-align:center;"><button type="submit">Pay now</button></td></tr>
</table>
</form>
<?php
}
if(isset($_POST['currency']) && isset($_POST['upgrade'])){
if(!isset(ACCOUNT_UPGRADES[$_POST['upgrade']])){
echo "<p>Sorry, looks like you didn't select a valid upgrade.</p>";
}elseif(!isset($rates[$_POST['currency']]) || $rates[$_POST['currency']]['accepted'] !== 1 || !in_array('payments', $rates[$_POST['currency']]['capabilities'])){
echo "<p>Sorry, looks like you didn't select a valid payment currency.</p>";
}else{
$db = get_db_instance();
$transaction = coinpayments_create_transaction($_POST['currency'], ACCOUNT_UPGRADES[$_POST['upgrade']]['usd_price'], $_POST['upgrade'], $user['id']);
if($transaction === false){
echo "<p>An error occured creating the transaction, please try again</p>";
}else{
echo "<p>Please pay $transaction[amount] $_POST[currency] to $transaction[address]</p>";
echo '<img src="'.(new QRCode(new QROptions(['outputType' => QRCode::OUTPUT_IMAGE_PNG, 'eccLevel' => QRCode::ECC_H])))->render($transaction['address']).'" alt="QR Code">';
echo '<p>Once paid, it can take a while until the upgrade is applied to your account. Usually within an hour.</p>';
}
}
}
?>
<p><a href="home.php">Go back to dashboard.</a></p>
</body>
</html>

View File

@ -29,8 +29,9 @@ if(!@$version=$db->query("SELECT value FROM settings WHERE setting='version';"))
$db->exec('CREATE TABLE mysql_databases (user_id int(11) NOT NULL, mysql_database varchar(64) COLLATE latin1_bin NOT NULL, KEY user_id (user_id), CONSTRAINT mysql_database_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;'); $db->exec('CREATE TABLE mysql_databases (user_id int(11) NOT NULL, mysql_database varchar(64) COLLATE latin1_bin NOT NULL, KEY user_id (user_id), CONSTRAINT mysql_database_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;');
$db->exec("CREATE TABLE onions (user_id int(11) NULL, onion varchar(56) COLLATE latin1_bin NOT NULL PRIMARY KEY, private_key varchar(1000) COLLATE latin1_bin NOT NULL, version tinyint(1) NOT NULL, enabled tinyint(1) NOT NULL DEFAULT '1', num_intros tinyint(3) NOT NULL DEFAULT '3', enable_smtp tinyint(1) NOT NULL DEFAULT '1', max_streams tinyint(3) unsigned NOT NULL DEFAULT '20', instance char(1) NOT NULL DEFAULT '2', KEY user_id (user_id), KEY enabled (enabled), KEY instance(instance), CONSTRAINT onions_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE, CONSTRAINT instance_ibfk_1 FOREIGN KEY (instance) REFERENCES service_instances (id) ON DELETE RESTRICT ON UPDATE RESTRICT) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;"); $db->exec("CREATE TABLE onions (user_id int(11) NULL, onion varchar(56) COLLATE latin1_bin NOT NULL PRIMARY KEY, private_key varchar(1000) COLLATE latin1_bin NOT NULL, version tinyint(1) NOT NULL, enabled tinyint(1) NOT NULL DEFAULT '1', num_intros tinyint(3) NOT NULL DEFAULT '3', enable_smtp tinyint(1) NOT NULL DEFAULT '1', max_streams tinyint(3) unsigned NOT NULL DEFAULT '20', instance char(1) NOT NULL DEFAULT '2', KEY user_id (user_id), KEY enabled (enabled), KEY instance(instance), CONSTRAINT onions_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE, CONSTRAINT instance_ibfk_1 FOREIGN KEY (instance) REFERENCES service_instances (id) ON DELETE RESTRICT ON UPDATE RESTRICT) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;");
$db->exec("CREATE TABLE domains (user_id int(11) NULL, domain varchar(255) COLLATE latin1_bin NOT NULL PRIMARY KEY, enabled tinyint(1) NOT NULL DEFAULT '1', KEY user_id (user_id), KEY enabled (enabled), CONSTRAINT domains_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;"); $db->exec("CREATE TABLE domains (user_id int(11) NULL, domain varchar(255) COLLATE latin1_bin NOT NULL PRIMARY KEY, enabled tinyint(1) NOT NULL DEFAULT '1', KEY user_id (user_id), KEY enabled (enabled), CONSTRAINT domains_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;");
$db->exec('CREATE TABLE disk_quota (user_id int(11) NOT NULL, quota_size int(10) unsigned NOT NULL, quota_files int(10) unsigned NOT NULL, updated tinyint(1) NOT NULL DEFAULT 1, KEY user_id (user_id), KEY updated (updated), CONSTRAINT disk_quota_ibfk_2 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;'); $db->exec("CREATE TABLE disk_quota (user_id int(11) NOT NULL, quota_size int(10) unsigned NOT NULL, quota_files int(10) unsigned NOT NULL, updated tinyint(1) NOT NULL DEFAULT 1, quota_size_used int(10) unsigned NOT NULL DEFAULT '0', quota_files_used int(10) unsigned NOT NULL DEFAULT '0', KEY user_id (user_id), KEY updated (updated), CONSTRAINT disk_quota_ibfk_2 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;");
$db->exec('CREATE TABLE nginx_rewrites (id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id int(11) NOT NULL, `regex` varchar(255) NOT NULL, replacement varchar(255) NOT NULL, `flag` varchar(9) NOT NULL, ifnotexists tinyint(1) NOT NULL, CONSTRAINT nginx_rewrites_ibfk_2 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;'); $db->exec('CREATE TABLE nginx_rewrites (id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id int(11) NOT NULL, `regex` varchar(255) NOT NULL, replacement varchar(255) NOT NULL, `flag` varchar(9) NOT NULL, ifnotexists tinyint(1) NOT NULL, CONSTRAINT nginx_rewrites_ibfk_2 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;');
$db->exec('CREATE TABLE payments (id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id int(11) NULL, payment_for varchar(255) COLLATE latin1_bin NOT NULL, txn_id varchar(255) COLLATE utf8mb4_bin NOT NULL, status tinyint NOT NULL, CONSTRAINT payments_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;');
$db->exec('CREATE TABLE settings (setting varchar(50) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL PRIMARY KEY, value text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;'); $db->exec('CREATE TABLE settings (setting varchar(50) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL PRIMARY KEY, value text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;');
$stmt=$db->prepare("INSERT INTO settings (setting, value) VALUES ('version', ?);"); $stmt=$db->prepare("INSERT INTO settings (setting, value) VALUES ('version', ?);");
$stmt->execute([DBVERSION]); $stmt->execute([DBVERSION]);
@ -155,6 +156,10 @@ if(!@$version=$db->query("SELECT value FROM settings WHERE setting='version';"))
$db->exec('UPDATE onions SET enabled=1 WHERE enabled=2;'); $db->exec('UPDATE onions SET enabled=1 WHERE enabled=2;');
$db->exec('CREATE TABLE nginx_rewrites (id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id int(11) NOT NULL, `regex` varchar(255) NOT NULL, replacement varchar(255) NOT NULL, `flag` varchar(9) NOT NULL, ifnotexists tinyint(1) NOT NULL, CONSTRAINT nginx_rewrites_ibfk_2 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;'); $db->exec('CREATE TABLE nginx_rewrites (id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id int(11) NOT NULL, `regex` varchar(255) NOT NULL, replacement varchar(255) NOT NULL, `flag` varchar(9) NOT NULL, ifnotexists tinyint(1) NOT NULL, CONSTRAINT nginx_rewrites_ibfk_2 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;');
} }
if($version<17){
$db->exec("ALTER TABLE disk_quota ADD quota_size_used int(10) unsigned NOT NULL DEFAULT '0', ADD quota_files_used int(10) unsigned NOT NULL DEFAULT '0';");
$db->exec('CREATE TABLE payments (id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id int(11) NULL, payment_for varchar(255) COLLATE latin1_bin NOT NULL, txn_id varchar(255) COLLATE utf8mb4_bin NOT NULL, status tinyint NOT NULL, CONSTRAINT payments_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;');
}
$stmt=$db->prepare("UPDATE settings SET value=? WHERE setting='version';"); $stmt=$db->prepare("UPDATE settings SET value=? WHERE setting='version';");
$stmt->execute([DBVERSION]); $stmt->execute([DBVERSION]);
} }
@ -302,7 +307,7 @@ foreach(SERVICE_INSTANCES as $instance){
exec("systemctl start ".escapeshellarg("php$version-fpm@$instance")); exec("systemctl start ".escapeshellarg("php$version-fpm@$instance"));
} }
$stmt->execute([$instance]); $stmt->execute([$instance]);
echo "Successfully added new instance $instance. Don't forget to add _tor-$instance as allowed user to your firewall rules in /etc/rc.local"; echo "Successfully added new instance $instance. Don't forget to add _tor-$instance as allowed user to your firewall rules in /etc/rc.local\n";
} }
} }
// remove no longer enabled php/tor instances // remove no longer enabled php/tor instances

View File

@ -237,4 +237,4 @@ done
for BINARY in /usr/lib/php/*/*.so; do for BINARY in /usr/lib/php/*/*.so; do
CHROOT_BINARY $BINARY CHROOT_BINARY $BINARY
done done
ln $CHROOT_DIRECTORY/usr/bin/php7.4 $CHROOT_DIRECTORY/usr/bin/php ln -f $CHROOT_DIRECTORY/usr/bin/php7.4 $CHROOT_DIRECTORY/usr/bin/php