· 10 years ago · May 24, 2016, 01:18 PM
1<?php
2
3/*
4 * Faucet in a BOX
5 * https://faucetinabox.com/
6 *
7 * Copyright (c) 2014-2016 LiveHome Sp. z o. o.
8 *
9 * This file is part of Faucet in a BOX.
10 *
11 * Faucet in a BOX is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Faucet in a BOX is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Faucet in a BOX. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25
26$version = '63';
27
28
29if (get_magic_quotes_gpc()) {
30 $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
31 while (list($key, $val) = each($process)) {
32 foreach ($val as $k => $v) {
33 unset($process[$key][$k]);
34 if (is_array($v)) {
35 $process[$key][stripslashes($k)] = $v;
36 $process[] = &$process[$key][stripslashes($k)];
37 } else {
38 $process[$key][stripslashes($k)] = stripslashes($v);
39 }
40 }
41 }
42 unset($process);
43}
44
45if(stripos($_SERVER['REQUEST_URI'], '@') !== FALSE ||
46 stripos(urldecode($_SERVER['REQUEST_URI']), '@') !== FALSE) {
47 header("Location: ."); die('Please wait...');
48}
49
50session_start();
51header('Content-Type: text/html; charset=utf-8');
52ini_set('display_errors', false);
53
54$missing_configs = array();
55
56$session_prefix = crc32(__FILE__);
57
58$disable_curl = false;
59$verify_peer = true;
60$local_cafile = false;
61require_once("config.php");
62if(!isset($disable_admin_panel)) {
63 $disable_admin_panel = false;
64 $missing_configs[] = array(
65 "name" => "disable_admin_panel",
66 "default" => "false",
67 "desc" => "Allows to disable Admin Panel for increased security"
68 );
69}
70
71if(!isset($connection_options)) {
72 $connection_options = array(
73 'disable_curl' => $disable_curl,
74 'local_cafile' => $local_cafile,
75 'verify_peer' => $verify_peer,
76 'force_ipv4' => false
77 );
78}
79if(!isset($connection_options['verify_peer'])) {
80 $connection_options['verify_peer'] = $verify_peer;
81}
82
83if (!isset($display_errors)) $display_errors = false;
84ini_set('display_errors', $display_errors);
85if($display_errors)
86 error_reporting(-1);
87
88
89if(array_key_exists('HTTP_REFERER', $_SERVER)) {
90 $referer = $_SERVER['HTTP_REFERER'];
91} else {
92 $referer = "";
93}
94
95$host = parse_url($referer, PHP_URL_HOST);
96if($_SERVER['HTTP_HOST'] != $host) {
97 if (
98 array_key_exists("address_input_name", $_SESSION) &&
99 array_key_exists($_SESSION["address_input_name"], $_POST)
100 ) {
101 $_POST[$_SESSION['address_input_name']] = "";
102 if ($display_errors) trigger_error("REFERER CHECK FAILED, ASSUMING CSRF!");
103 }
104}
105
106
107require_once('libs/faucetbox.php');
108
109try {
110 $sql = new PDO($dbdsn, $dbuser, $dbpass, array(PDO::ATTR_PERSISTENT => true,
111 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
112} catch(PDOException $e) {
113 if ($display_errors) die("Can't connect to database. Check your config.php. Details: ".$e->getMessage());
114 else die("Can't connect to database. Check your config.php or set \$display_errors = true; to see details.");
115}
116
117
118$template_updates = array(
119 array(
120 "test" => "/address_input_name/",
121 "message" => "Name of the address field has to be updated. Please follow <a href='https://bitcointalk.org/index.php?topic=1094930.msg12231246#msg12231246'>these instructions</a>"
122 ),
123 array(
124 "test" => "/libs\/mmc\.js/",
125 "message" => "Add <code>".htmlspecialchars('<script type="text/javascript" src="libs/mmc.js"></script>')."</code> after jQuery in <code><head></code> section."
126 ),
127 array(
128 "test" => "/honeypot/",
129 "message" => "Add <code><pre>".htmlspecialchars('<input type="text" name="address" class="form-control" style="position: absolute; position: fixed; left: -99999px; top: -99999px; opacity: 0; width: 1px; height: 1px">')."<br>".htmlspecialchars('<input type="checkbox" name="honeypot" style="position: absolute; position: fixed; left: -99999px; top: -99999px; opacity: 0; width: 1px; height: 1px">')."</pre></code> near the input with name <code>".htmlspecialchars('<?php echo $data["address_input_name"]; ?>')."</code>."
130 )
131);
132
133$db_updates = array(
134 15 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('version', '15');"),
135 17 => array("ALTER TABLE `Faucetinabox_Settings` CHANGE `value` `value` TEXT NOT NULL;", "INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('balance', 'N/A');"),
136 33 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('ayah_publisher_key', ''), ('ayah_scoring_key', '');"),
137 34 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('custom_admin_link_default', 'true')"),
138 38 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('reverse_proxy', 'none')", "INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('default_captcha', 'recaptcha')"),
139 41 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('captchme_public_key', ''), ('captchme_private_key', ''), ('captchme_authentication_key', ''), ('reklamper_enabled', '')"),
140 46 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('last_balance_check', '0')"),
141 54 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('funcaptcha_public_key', ''), ('funcaptcha_private_key', '')"),
142 55 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('block_adblock', ''), ('button_timer', '0')"),
143 56 => array("INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('ip_check_server', ''),('ip_ban_list', ''),('hostname_ban_list', ''),('address_ban_list', '')"),
144 58 => ["DELETE FROM `Faucetinabox_Settings` WHERE `name` IN ('captchme_public_key', 'captchme_private_key', 'captchme_authentication_key', 'reklamper_enabled')"],
145 63 => ["INSERT IGNORE INTO `Faucetinabox_Settings` (`name`, `value`) VALUES ('safety_limits_end_time', '')"],
146);
147
148$default_data_query = <<<QUERY
149create table if not exists Faucetinabox_Settings (
150 `name` varchar(64) not null,
151 `value` text not null,
152 primary key(`name`)
153);
154create table if not exists Faucetinabox_IPs (
155 `ip` varchar(20) not null,
156 `last_used` timestamp not null,
157 primary key(`ip`)
158);
159create table if not exists Faucetinabox_Addresses (
160 `address` varchar(60) not null,
161 `ref_id` int null,
162 `last_used` timestamp not null,
163 primary key(`address`)
164);
165create table if not exists Faucetinabox_Refs (
166 `id` int auto_increment not null,
167 `address` varchar(60) not null unique,
168 `balance` bigint unsigned default 0,
169 primary key(`id`)
170);
171create table if not exists Faucetinabox_Pages (
172 `id` int auto_increment not null,
173 `url_name` varchar(50) not null unique,
174 `name` varchar(255) not null,
175 `html` text not null,
176 primary key(`id`)
177);
178
179INSERT IGNORE INTO Faucetinabox_Settings (name, value) VALUES
180('apikey', ''),
181('timer', '180'),
182('rewards', '90*100, 10*500'),
183('referral', '15'),
184('solvemedia_challenge_key', ''),
185('solvemedia_verification_key', ''),
186('solvemedia_auth_key', ''),
187('recaptcha_private_key', ''),
188('recaptcha_public_key', ''),
189('ayah_publisher_key', ''),
190('ayah_scoring_key', ''),
191('funcaptcha_private_key', ''),
192('funcaptcha_public_key', ''),
193('name', 'Faucet in a Box'),
194('short', 'Just another Faucet in a Box :)'),
195('template', 'default'),
196('custom_body_cl_default', ''),
197('custom_box_bottom_cl_default', ''),
198('custom_box_bottom_default', ''),
199('custom_box_top_cl_default', ''),
200('custom_box_top_default', ''),
201('custom_box_left_cl_default', ''),
202('custom_box_left_default', ''),
203('custom_box_right_cl_default', ''),
204('custom_box_right_default', ''),
205('custom_css_default', '/* custom_css */\\n/* center everything! */\\n.row {\\n text-align: center;\\n}\\n#recaptcha_widget_div, #recaptcha_area {\\n margin: 0 auto;\\n}\\n/* do not center lists */\\nul, ol {\\n text-align: left;\\n}'),
206('custom_footer_cl_default', ''),
207('custom_footer_default', ''),
208('custom_main_box_cl_default', ''),
209('custom_palette_default', ''),
210('custom_admin_link_default', 'true'),
211('version', '$version'),
212('currency', 'BTC'),
213('balance', 'N/A'),
214('reverse_proxy', 'none'),
215('last_balance_check', '0'),
216('default_captcha', 'recaptcha'),
217('ip_check_server', ''),
218('ip_ban_list', ''),
219('hostname_ban_list', ''),
220('address_ban_list', ''),
221('block_adblock', ''),
222('button_timer', '0'),
223('safety_limits_end_time', '')
224;
225QUERY;
226
227// ****************** START ADMIN TEMPLATES
228$master_template = <<<TEMPLATE
229<!DOCTYPE html>
230<html>
231 <head>
232 <title>Faucet in a Box</title>
233 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/css/bootstrap.min.css">
234 <link rel="stylesheet" id="palette-css" href="data:text/css;base64,IA==">
235 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.6.2/css/bootstrap-select.min.css">
236 <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
237 <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/js/bootstrap.min.js"></script>
238 <script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.6.2/js/bootstrap-select.min.js"></script>
239 <style type="text/css">
240 a, .btn, tr, td, .glyphicon{
241 transition: all 0.2s ease-in;
242 -o-transition: all 0.2s ease-in;
243 -webkit-transition: all 0.2s ease-in;
244 -moz-transition: all 0.2s ease-in;
245 }
246 .form-group {
247 margin: 15px !important;
248 }
249 textarea.form-control {
250 min-height: 120px;
251 }
252 .tab-content > .active {
253 border-radius: 0px 0px 4px 6px;
254 margin-top: -1px;
255 }
256 .prev-box {
257 border-radius: 4px;
258 }
259 .prev-box > .btn {
260 min-width: 45px;
261 height: 33px;
262 font-weight: bold;
263 }
264 .prev-box > .text-white {
265 text-shadow: 0 0 2px black;
266 }
267 .prev-box > .active {
268 margin-top: -2px;
269 height: 36px;
270 font-weight: bold;
271 font-size: 130%;
272 border-radius: 3px !important;
273 box-shadow: 0px 1px 2px #333;
274 }
275 .prev-box > .transparent {
276 border: 1px dotted #FF0000;
277 box-shadow: inset 0px 0px 5px #FFF;
278 }
279 .prev-box > .transparent.active {
280 box-shadow: 0px 1px 2px #333, inset 0px 0px 5px #FFF;
281 }
282 .picker-label {
283 padding-top: 11px;
284 }
285 .bg-black{
286 background: #000;
287 }
288 .bg-white{
289 background: #fff;
290 }
291 .text-black{
292 color: #000;
293 }
294 .text-white{
295 color: #fff;
296 }
297 </style>
298 </head>
299 <body>
300 <div class="container">
301 <h1>Welcome to your Faucet in a Box Admin Page!</h1><hr>
302 <:: content ::>
303 </div>
304 </body>
305</html>
306TEMPLATE;
307
308$admin_template = <<<TEMPLATE
309<noscript>
310 <div class="alert alert-danger text-center" role="alert">
311 <p class="lead">
312 You have disabled Javascript. Javascript is required for the admin panel to work!
313 </p>
314 </div>
315 <style>
316 #admin-content{ display: none !important; }
317 </style>
318</noscript>
319
320<:: oneclick_update_alert ::>
321<:: version_check ::>
322<:: changes_saved ::>
323<:: new_files ::>
324<:: connection_error ::>
325<:: curl_warning ::>
326<:: send_coins_message ::>
327<:: missing_configs ::>
328<:: template_updates ::>
329<:: nastyhosts_not_allowed ::>
330<:: reverse_proxy_changed_alert ::>
331<:: reverse_proxy_misconfigured_alert ::>
332
333<form method="POST" id="admin-form" class="form-horizontal" role="form">
334
335 <div id="admin-content" role="tabpanel">
336
337 <!-- Nav tabs -->
338 <ul class="nav nav-tabs" role="tablist">
339 <li role="presentation" class="active"><a href="#basic" aria-controls="basic" role="tab" data-toggle="tab">Basic</a></li>
340 <li role="presentation"><a href="#captcha" aria-controls="captcha" role="tab" data-toggle="tab">Captcha</a></li>
341 <li role="presentation"><a href="#templates" aria-controls="templates" role="tab" data-toggle="tab">Templates</a></li>
342 <li role="presentation"><a href="#pages" aria-controls="pages" role="tab" data-toggle="tab">Pages</a></li>
343 <li role="presentation"><a href="#security" aria-controls="security" role="tab" data-toggle="tab">Security</a></li>
344 <li role="presentation"><a href="#advanced" aria-controls="advanced" role="tab" data-toggle="tab">Advanced</a></li>
345 <li role="presentation"><a href="#referrals" aria-controls="referrals" role="tab" data-toggle="tab">Referrals</a></li>
346 <li role="presentation"><a href="#send-coins" aria-controls="send-coins" role="tab" data-toggle="tab">Manually send coins</a></li>
347 <li role="presentation"><a href="#reset" aria-controls="reset" role="tab" data-toggle="tab">Factory reset</a></li>
348 </ul>
349
350 <div class="tab-content">
351 <div role="tabpanel" class="tab-pane active" id="basic">
352 <h2>Basic</h2>
353 <h3>Faucet Info</h3>
354 <div class="form-group">
355 <label for="name" class="control-label">Faucet name</label>
356 <input type="text" class="form-control" name="name" value="<:: name ::>">
357 </div>
358 <div class="form-group">
359 <label for="short" class="control-label">Short description</label>
360 <input type="text" class="form-control" name="short" value="<:: short ::>">
361 </div>
362
363 <h3>Access</h3>
364 <div class="row">
365 <div class="col-md-6">
366 <div class="form-group">
367 <:: invalid_key ::>
368 <label for="apikey" class="control-label">FaucetBOX.com API key</label>
369 <p>You can get it from <a href="https://faucetbox.com/">FaucetBOX.com dashboard</a> (you have to register and log in)</p>
370 <input type="text" class="form-control" name="apikey" value="<:: apikey ::>">
371 </div>
372 </div>
373 <div class="col-md-6">
374 <div class="form-group">
375 <label for="currency" class="control-label">Currency</label>
376 <p>Select currency you want to use.</p>
377 <select id="currency" class="form-control selectpicker" name="currency" id="currency">
378 <:: currencies ::>
379 </select>
380 </div>
381 </div>
382 </div>
383 <div class="row">
384 <div class="col-md-6">
385 <div class="form-group">
386 <label for="timer" class="control-label">Timer (in minutes)</label>
387 <p>How often users can get coins from you?</p>
388 <input type="text" class="form-control" name="timer" value="<:: timer ::>">
389 </div>
390 </div>
391 <div class="col-md-6">
392 <div class="form-group">
393 <label for="referral" class="control-label">Referral earnings:</label>
394 <p>in percents (0 to disable)</p>
395 <input type="text" class="form-control" name="referral" value="<:: referral ::>">
396 </div>
397 </div>
398 </div>
399 <div class="row">
400 <div class="col-md-6">
401 <div class="form-group">
402 <label for="button-timer" class="control-label">Enable <i>Get reward</i> button after some time</label>
403 <p>Enter number of seconds for which the <i>Get reward</i> button should be disabled</p>
404 <input type="text" class="form-control" name="button_timer" value="<:: button_timer ::>">
405 </div>
406 </div>
407 <div class="col-md-6">
408 <div class="form-group">
409 <label for="block-adblock" class="control-label"><input type="checkbox" name="block_adblock" <:: block_adblock ::> > Detect and block users with ad blocking software</label>
410 <p><i>Get reward</i> button will be disabled if AdBlock, uBlock or something similar is detected</p>
411 </div>
412 </div>
413 </div>
414 <h3>Rewards</h3>
415 <div class="form-group">
416 <p id="rewards-desc-nojs">How much users can get from you? You can set multiple rewards (separate them with a comma) and set weights for them, to define how plausible each reward will be. <br>Examples: <code>100</code>, <code>50, 150, 300</code>, <code>10*50, 2*100</code>. The last example means 50 satoshi or DOGE 10 out of 12 times, 100 satoshi or DOGE 2 out of 12 times.</p>
417 <p class="hidden" id="rewards-desc-js">
418 How much coins users can get from you? You can set multiple rewards using "Add reward" button. Amount can be either a number (ex. <code>100</code>) or a range (ex. <code>100-500</code>). Chance must be in percentage between 1 and 100. Sum of all chances must be equal 100%.
419 </p>
420 <p>Enter values in satoshi (1 satoshi of xCOIN = 0.00000001 xCOIN) for everything except DOGE. For DOGE it's in whole coins.</p>
421 <input id="rewards-raw" type="text" class="form-control" name="rewards" value="<:: rewards ::>">
422 <div id="rewards-box" class="hidden">
423 <div class="alert alert-info">
424 <b>PREVIEW:</b> Possible rewards: <span id="rewards-preview">loading...</span>
425 </div>
426 <table class="table">
427 <thead>
428 <tr>
429 <th>Amount</th>
430 <th>Chance (in %)</th>
431 <th class="text-center">Options</th>
432 </tr>
433 </thead>
434 <tbody>
435 </tbody>
436 </table>
437 <div class="alert alert-warning hidden rewards-warning">
438 Some incorrect fields were discarded. Amount can be either a number (eg. "100") or a range (eg. "100-200"). If amount is a range, the second number must be greater than the first one (eg. "200-100" is incorrect). Chance must be greater than 0 and lower than 100.
439 </div>
440 <div class="alert alert-danger hidden rewards-alert">
441 Sum of rewards' chances is not equal to 100 (%).
442 (<i class="math"></i>)
443 <a href="#" id="rewards-auto-fix" class="pull-right">Auto fix (this will remove all invalid rows)</a>
444 </div>
445 <button id="add-reward" class="btn btn-primary">Add reward</button>
446 </div>
447 </div>
448 </div>
449 <div role="tabpanel" class="tab-pane" id="captcha">
450 <h2>Captcha</h2>
451 <div class="row">
452 <div class="form-group">
453 <p class="alert alert-info">Some captcha systems may be unsafe and fail to stop bots. You should always read opinions about your chosen Captcha system first.</p>
454 <label for="default_captcha" class="control-label">Default captcha:</label>
455 <select class="form-control selectpicker" name="default_captcha" id="default_captcha">
456 <option value="SolveMedia">SolveMedia</option>
457 <option value="reCaptcha">reCaptcha</option>
458 <option value="AreYouAHuman">Are You A Human</option>
459 <option value="FunCaptcha">FunCaptcha</option>
460 </select>
461 </div>
462 </div>
463 <div class="row">
464 <div class="col-lg-6 col-md-6">
465 <div class="well">
466 <h4>reCaptcha</h4>
467 <div class="form-group" id="recaptcha">
468 <p>Get your keys <a href="https://www.google.com/recaptcha/admin#list">here</a>.</p>
469 <label for="recaptcha_public_key" class="control-label">reCaptcha public key:</label>
470 <input type="text" class="form-control" name="recaptcha_public_key" value="<:: recaptcha_public_key ::>">
471 <label for="recaptcha_private_key" class="control-label">reCaptcha private key:</label>
472 <input type="text" class="form-control" name="recaptcha_private_key" value="<:: recaptcha_private_key ::>">
473 <label><input type="checkbox" class="captcha-disable-checkbox"> Turn on this captcha system</label>
474 </div>
475 </div>
476 </div>
477 <div class="col-lg-6 col-md-6">
478 <div class="well">
479 <h4>Are You A Human</h4>
480 <div class="form-group" id="ayah">
481 <p>Get your keys <a href="https://portal.areyouahuman.com/dashboard">here</a>.</p>
482 <label for="ayah_publisher_key" class="control-label">Are You A Human publisher key:</label>
483 <input type="text" class="form-control" name="ayah_publisher_key" value="<:: ayah_publisher_key ::>">
484 <label for="ayah_scoring_key" class="control-label">Are You A Human scoring key:</label>
485 <input type="text" class="form-control" name="ayah_scoring_key" value="<:: ayah_scoring_key ::>">
486 <label><input type="checkbox" class="captcha-disable-checkbox"> Turn on this captcha system</label>
487 </div>
488 </div>
489 </div>
490 </div>
491 <div class="row">
492 <div class="col-lg-6 col-md-6">
493 <div class="well">
494 <h4>SolveMedia</h4>
495 <div class="form-group" id="solvemedia">
496 <p>Get your keys <a href="https://portal.solvemedia.com/portal/">here</a> (select <em>Sites</em> from the menu after logging in).</p>
497 <label for="solvemedia_challenge_key" class="control-label">SolveMedia challenge key:</label>
498 <input type="text" class="form-control" name="solvemedia_challenge_key" value="<:: solvemedia_challenge_key ::>">
499 <label for="solvemedia_verification_key" class="control-label">SolveMedia verification key:</label>
500 <input type="text" class="form-control" name="solvemedia_verification_key" value="<:: solvemedia_verification_key ::>">
501 <label for="solvemedia_auth_key" class="control-label">SolveMedia authentication key:</label>
502 <input type="text" class="form-control" name="solvemedia_auth_key" value="<:: solvemedia_auth_key ::>">
503 <label><input type="checkbox" class="captcha-disable-checkbox"> Turn on this captcha system</label>
504 </div>
505 </div>
506 </div>
507 <div class="col-lg-6 col-md-6">
508 <div class="well">
509 <h4>FunCaptcha</h4>
510 <div class="form-group" id="funcaptcha">
511 <p>Get your keys <a href="https://www.funcaptcha.com/domain-settings">here</a>.</p>
512 <label for="funcaptcha_public_key" class="control-label">FunCaptcha public key:</label>
513 <input type="text" class="form-control" name="funcaptcha_public_key" value="<:: funcaptcha_public_key ::>">
514 <label for="funcaptcha_private_key" class="control-label">FunCaptcha private key:</label>
515 <input type="text" class="form-control" name="funcaptcha_private_key" value="<:: funcaptcha_private_key ::>">
516 <label><input type="checkbox" class="captcha-disable-checkbox"> Turn on this captcha system</label>
517 </div>
518 </div>
519 </div>
520 </div>
521 </div>
522 <div role="tabpanel" class="tab-pane" id="templates">
523 <h2>Template options</h2>
524 <div class="form-group">
525 <div class="col-xs-12 col-sm-2 col-lg-1">
526 <label for="template" class="control-label">Template:</label>
527 </div>
528 <div class="col-xs-3">
529 <select id="template-select" name="template" class="selectpicker"><:: templates ::></select>
530 </div>
531 </div>
532 <div id="template-options">
533 <:: template_options ::>
534 </div>
535 </div>
536 <div role="tabpanel" class="tab-pane" id="pages">
537 <h2>Pages</h2>
538 <p>Here you can create, delete and edit custom static pages.</p>
539 <ul class="nav nav-tabs pages-nav" role="tablist">
540 <li class="pull-right"><button type="button" id="pageAddButton" class="btn btn-info"><span class="glyphicon">+</span> Add new page</button></li>
541 <:: pages_nav ::>
542 </ul>
543 <div id="pages-inner" class="tab-content">
544 <:: pages ::>
545 </div>
546 </div>
547 <div role="tabpanel" class="tab-pane" id="security">
548 <h2>Security</h2>
549 <h3>Bot protection</h3>
550 <div class="form-group">
551 <label for="ip_check_server" class="control-label">Use external IP address check service (it'll also report suspicious addresses to this service):</label>
552 <select id="ip_check_server" name="ip_check_server" class="form-control selectpicker">
553 <option value="http://v1.nastyhosts.com/">NastyHosts.com</option>
554 <option value="">Disabled</option>
555 </select>
556 </div>
557 <div class="form-group">
558 <label for="ip_ban_list" class="control-label">List of IP addresses or IP networks in CIDR notation to ban (one value per line)</label>
559 <textarea class="form-control" name="ip_ban_list" id="ip_ban_list" placeholder="Example value:
560127.0.0.0/8
561172.16.0.1
562192.168.0.0/24"><:: ip_ban_list ::></textarea>
563 </div>
564 <div class="form-group">
565 <label for="hostname_ban_list" class="control-label">List of hostnames to ban. Partial match is enough. Requires external IP address check service enabled. (one value per line)</label>
566 <textarea class="form-control" name="hostname_ban_list" id="hostname_ban_list" placeholder="Example value:
567proxy
568compute.amazonaws.com"><:: hostname_ban_list ::></textarea>
569 </div>
570 <div class="form-group">
571 <label for="address_ban_list" class="control-label">List of cryptocurrency addresses to ban (one address per line)</label>
572 <textarea class="form-control" name="address_ban_list" id="address_ban_list" placeholder="Example value:
5731HmUrGAf4Bz9KMX6Pg67RA2VZgWVPnpyvS
57413q29zfcesTiZoed1BNFr3VYr4zBGfuwW4"><:: address_ban_list ::></textarea>
575 </div>
576 </div>
577 <div role="tabpanel" class="tab-pane" id="advanced">
578 <h2>Advanced</h2>
579 <h3>Reverse Proxy</h3>
580 <div class="form-group">
581 <p class="alert alert-danger"><b>Be careful! This is an advanced feature. Don't use it unless you know what you're doing. If you set it wrong or you don't properly configure your proxy AND your server YOU MAY LOSE YOUR COINS!</b></p>
582 <p class="alert alert-info">This feature is experimental! It may not work properly and may lead you to losing coins. You have been warned.</p>
583 <p>This setting allows you to change the method of identifying users. By default Faucet in a Box will use the connecting IP address. Hovewer if you're using a reverse proxy, like CloudFlare or Incapsula, the connecting IP address will always be the address of the proxy. That results in all faucet users sharing the same timer. If you set this option to a correct proxy, then Faucet in a Box will use a corresponding HTTP Header instead of IP address.</p>
584 <p>However you MUST prevent anyone from bypassing the proxy. HTTP Headers can be spoofed, so if someone can access your page directly, then he can send his own headers, effectively ignoring the timer you've set and stealing all your coins!</p>
585 <p>Faucet in a Box has a security feature that will disable Reverse Proxy support if it detects any connection that has bypassed the proxy. Hovewer the detection is not perfect, so you shouldn't rely on it. Instead make proper precautions, for example by configuring your firewall to only allow connections from your proxy IP addresses.</p>
586 <p>If you're using a Reverse Proxy (CloudFlare or Incapsula) choose it from the list below. If your provider is not listed below contact us at support@faucetbox.com</p>
587 <p><em>None</em> is always a safe setting, but - as explained above - the timer may be shared between all your users if you're using a proxy.</p>
588 <label for="reverse_proxy" class="control-label">Reverse Proxy provider:</label>
589 <select id="reverse_proxy" name="reverse_proxy" class="form-control selectpicker">
590 <option value="cloudflare">CloudFlare (CF-Connecting-IP)</option>
591 <option value="incapsula">Incapsula (Incap-Client-IP)</option>
592 <option value="none">None (Connecting IP address)</option>
593 </select>
594 </div>
595 </div>
596 <div role="tabpanel" class="tab-pane" id="referrals">
597 <h2>Referrals</h2>
598 <div class="alert alert-info">
599 On this tab you can check all addresses which have referral.
600 </div>
601 <div class="row" style="padding: 15px 0 30px;">
602 <div class="col-md-10">
603 <input type="text" class="form-control" id="referral_address" value="" placeholder="Referral address">
604 </div>
605 <div class="col-md-2">
606 <button class="btn btn-primary" id="check_referral" style="width: 100%;">Check</button>
607 </div>
608 </div>
609 <div class="alert alert-danger hidden" id="referral-ajax-error">
610 An error occurred while receiving addresses with this referral. Please try again later or contact <a href="http://faucetbox.com/support" target="_blank">support team</a>.
611 </div>
612 <table class="table hidden" id="referral_list">
613 <thead>
614 <tr>
615 <th>#</th>
616 <th>Address</th>
617 <th>Referral</th>
618 </tr>
619 </thead>
620 <tbody>
621
622 </tbody>
623 </table>
624
625 <div style="height: 30px;"></div>
626
627 </div>
628 <div role="tabpanel" class="tab-pane" id="send-coins">
629 <h2>Manually send coins</h2>
630 <div class="form-group">
631 <p class="alert alert-info">You can use the form below to send coins to given address manaully</p>
632 <label for="" class="control-label">Amount in satoshi:</label>
633 <input type="text" class="form-control" name="send_coins_amount" value="1" id="input_send_coins_amount">
634 <label for="" class="control-label">Currency:</label>
635 <input type="text" class="form-control" name="send_coins_currency" value="<:: currency ::>" disabled>
636 <label for="" class="control-label">Receiver address:</label>
637 <input type="text" class="form-control" name="send_coins_address" value=""id="input_send_coins_address">
638 </div>
639 <div class="form-group">
640 <div class="alert alert-info">
641 Are you sure you would like to send <span id="send_coins_satoshi">0</span> satoshi (<span id="send_coins_bitcoins">0.00000000</span> <:: currency ::>) to <span id="send_coins_address">address</span>?
642 <input class="btn btn-primary pull-right" style="margin-top: -7px;" type="submit" name="send_coins" value="Yes, send coins">
643 </div>
644 </div>
645 </div>
646 <div role="tabpanel" class="tab-pane" id="reset">
647 <h2>Factory reset</h2>
648 <div class="alert alert-danger">
649 This will reset all settings except: API key, captcha keys, admin password and pages. Deleted data can't be recovered!<br>
650 Please select the checkbox to confirm and click button below.
651 </div>
652 <div class="text-center">
653 <label>
654 <input type="checkbox" name="factory_reset_confirm">
655 Yes, I want to reset back to factory settings
656 </label>
657 </div>
658 <div class="text-center">
659 <input type="submit" name="reset" class="btn btn-warning btn-lg" style="" value="Reset settings to defaults">
660 </div>
661 </div>
662 </div>
663
664 </div>
665
666 <hr>
667
668 <div class="form-group">
669 <button type="submit" name="save_settings" class="btn btn-success btn-lg">
670 <span class="glyphicon glyphicon-ok"></span>
671 Save changes
672 </button>
673 <a href="?p=logout" class="btn btn-default btn-lg pull-right">
674 <span class="glyphicon glyphicon-log-out"></span>
675 Logout
676 </a>
677 </div>
678 <script type="text/javascript">
679
680 if (typeof btoa == "undefined") {
681 // discuss at: http://phpjs.org/functions/base64_encode/
682 // original by: Tyler Akins (http://rumkin.com)
683 // improved by: Bayron Guevara
684 // improved by: Thunder.m
685 // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
686 // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
687 // improved by: Rafał Kukawski (http://kukawski.pl)
688 // bugfixed by: Pellentesque Malesuada
689 function btoa(e){var t,r,c,a,n,h,o,A,i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",d=0,l=0,u="",C=[];if(!e)return e;e=unescape(encodeURIComponent(e));do t=e.charCodeAt(d++),r=e.charCodeAt(d++),c=e.charCodeAt(d++),A=t<<16|r<<8|c,a=A>>18&63,n=A>>12&63,h=A>>6&63,o=63&A,C[l++]=i.charAt(a)+i.charAt(n)+i.charAt(h)+i.charAt(o);while(d<e.length);u=C.join("");var s=e.length%3;return(s?u.slice(0,s-3):u)+"===".slice(s||3)}
690 }
691
692
693 function renumberPages(){
694 $(".pages-nav > li").each(function(index){
695 if(index != 0){
696 $(this).children().first().attr("href", "#page-wrap-" + index);
697 $(this).children().first().text("Page " + index);
698 }
699 });
700 $("#pages-inner > div.tab-pane").each(function(index){
701 var i = index+1;
702 $(this).attr("id", "page-wrap-" + i);
703 $(this).children().each(function(i2){
704 var ending = "html";
705 var item = "textarea";
706 if(i2 == 0){
707 ending = "name";
708 item = "input";
709 }
710
711 $(this).children('label').attr("for", "pages." + i + "." + ending);
712 $(this).children(item).attr("id", "pages." + i + "." + ending).attr("name", "pages[" + i + "][" + ending + "]");
713 });
714 });
715 }
716
717 function deletePage(btn) {
718 $(btn).parent().remove();
719 $(".pages-nav > .active").remove();
720 $(".pages-nav > li:nth-child(2) > a").tab('show');
721 renumberPages();
722 }
723
724 function reloadSendCoinsConfirmation() {
725
726 var satoshi = $("#input_send_coins_amount").val();
727 var bitcoin = satoshi / 100000000;
728 var address = $("#input_send_coins_address").val();
729
730 $("#send_coins_satoshi").text(satoshi);
731 $("#send_coins_bitcoins").text(bitcoin.toFixed(8));
732 $("#send_coins_address").text(address);
733
734 }
735
736 var tmp = [];
737
738 $(function() {
739
740 $("#check_referral").click(function (e) {
741
742 $(this).attr("disabled", true).text("Checking...");
743
744 $.ajax(document.location.href, {method: "POST", data: {action: "check_referrals", referral: $("#referral_address").val()}})
745 .done(function (data) {
746
747 $("#check_referral").attr("disabled", false).text("Check");
748
749 if (data.status == 200) {
750
751 $("#referral-ajax-error").addClass("hidden");
752
753 $("#referral_list").removeClass("hidden").find("tbody").html("");
754
755 for (i in data.addresses) {
756 var el = data.addresses[i];
757
758 $("#referral_list tbody").append(
759 $("<tr>").append(
760 $("<td>").html( (i+1) + "." )
761 ).append(
762 $("<td>").text(el.address).append(
763 $("<span>").addClass("glyphicon glyphicon-chevron-right pull-right")
764 )
765 ).append(
766 $("<td>").text(el.referral)
767 )
768 );
769
770 }
771
772 if (data.addresses.length == 0) {
773 $("#referral_list tbody").append(
774 $("<tr>").append(
775 $("<td>").attr("colspan", 5).append(
776 $("<p>").addClass("lead text-center text-muted").text("No addresses found")
777 )
778 )
779 );
780 }
781
782 } else {
783 $("#referral-ajax-error").removeClass("hidden");
784 $("#referral_list").addClass("hidden");
785 }
786
787 }).fail(function () {
788 $("#referral-ajax-error").removeClass("hidden");
789 $("#referral_list").addClass("hidden");
790 });
791
792 });
793
794 $("#admin-form").submit(function (e) {
795 e.preventDefault();
796 });
797
798 $("#admin-form input[type=submit], #admin-form button[type=submit]").click(function (e) {
799 e.preventDefault();
800 var data = btoa($("#admin-form").serialize());
801 $("<form>").attr("method", "POST").append(
802 $("<input>")
803 .attr("type", "hidden")
804 .attr("name", "encoded_data")
805 .val(data)
806 ).append(
807 $("<input>")
808 .attr("type", "hidden")
809 .attr("name", $(this).attr("name"))
810 .val( $(this).val().length > 0 ? $(this).val() : $(this).text() )
811 ).hide().appendTo('body').submit();
812 });
813
814 $("#input_send_coins_amount, #input_send_coins_address").change(reloadSendCoinsConfirmation).keydown(reloadSendCoinsConfirmation).keyup(reloadSendCoinsConfirmation).keypress(reloadSendCoinsConfirmation);
815
816 $("#pageAddButton").click(function() {
817 var i = $("#pages-inner").children("div").length.toString();
818 var j = parseInt(i)+1;
819 var newpage = <:: page_form_template ::>
820 .replace(/<:: i ::>/g, i)
821 .replace("<:: html ::>", '')
822 .replace("<:: page_name ::>", '');
823 $("#pages-inner").append(newpage);
824 var newtab = <:: page_nav_template ::>
825 .replace(/<:: i ::>/g, i);
826 $('.pages-nav').append(newtab);
827 renumberPages();
828 $(".pages-nav > li").last().children().first().tab('show');
829 });
830 $(".pages-nav > li:nth-child(2)").addClass('active');
831 $('#pages-inner').children().first().addClass('active');
832
833 $('.pages-nav a').click(function (e) {
834 e.preventDefault();
835 $(this).tab('show');
836 });
837 $("#template-select").change(function() {
838 var t = $(this).val();
839 $.post("", { "get_options": t }, function(data) { $("#template-options").html(data); $('.selectpicker').selectpicker(); });
840 });
841 $("#reverse_proxy").val("<:: reverse_proxy ::>"); //must be before selectpicker render
842 $("#default_captcha").val("<:: default_captcha ::>"); //must be before selectpicker render
843 $("#ip_check_server").val("<:: ip_check_server ::>"); //must be before selectpicker render
844 $('.selectpicker').selectpicker(); //render selectpicker on page load
845
846 $('.nav-tabs a').click(function (e) {
847 e.preventDefault()
848 $(this).tab('show');
849 if (typeof localStorage !== "undefined") {
850 localStorage["current_tab"] = $(this).attr('href');
851 }
852 });
853
854 if (typeof localStorage !== "undefined" && typeof localStorage["current_tab"] !== "undefined") {
855 $('a[href=' + localStorage["current_tab"] + ']').tab('show');
856 }
857
858 $(".captcha-disable-checkbox").each(function(){
859 $(this).parent().parent().find("input[type=text]").each(function(){
860 if ($(this).val() == '') {
861 $(this).parent().find(".captcha-disable-checkbox").attr("checked", false);
862 $(this).parent().find("input[type=text]").attr("readonly", true);
863 } else {
864 $(this).parent().find(".captcha-disable-checkbox").attr("checked", true);
865 $(this).parent().find("input[type=text]").attr("readonly", false);
866 }
867 });
868 }).change(function(){
869 if ($(this).prop("checked")) {
870 $(this).parent().parent().find("input[type=text]").each(function(){
871 $(this).val(tmp[$(this).attr("name")]);
872 $(this).attr("readonly", false);
873 });
874 } else {
875 $(this).parent().parent().find("input[type=text]").each(function(){
876 tmp[$(this).attr("name")] = $(this).val();
877 $(this).val("");
878 $(this).attr("readonly", true);
879 });
880 }
881 });
882
883 RewardsSystem.init();
884 });
885
886
887
888var RewardsSystem = {
889
890 init: function() {
891
892 $('#rewards-raw').addClass('hidden');
893 $('#rewards-box').removeClass('hidden');
894
895 $('#rewards-desc-nojs').addClass('hidden');
896 $('#rewards-desc-js').removeClass('hidden');
897
898 $('#add-reward').click(function (e) {
899 e.preventDefault();
900 RewardsSystem.addRow();
901 });
902
903 $('#rewards-auto-fix').click(function (e) {
904 e.preventDefault();
905 RewardsSystem.autoFix();
906 RewardsSystem.autoFix();
907 });
908
909 $('#currency').change(RewardsSystem.rewardsUpdate);
910
911 RewardsSystem.fromRawData();
912
913 },
914
915 fromRawData: function() {
916 var rewards = [];
917
918 var raw = $('#rewards-raw').val().trim().split(' ');
919 for (i in raw) {
920 var reward = raw[i];
921 if (reward.trim() == '') continue;
922 reward = reward.split('*');
923 if (typeof reward[1] == 'undefined') {
924 rewards[rewards.length] = {
925 amount: RewardsSystem.parseAmount(reward[0]),
926 chance: 1
927 };
928 } else {
929 rewards[rewards.length] = {
930 amount: RewardsSystem.parseAmount(reward[1]),
931 chance: parseFloat(parseFloat(reward[0]).toFixed(2))
932 };
933 }
934 }
935
936 var chance_sum = 0;
937
938 for (i in rewards) {
939 chance_sum += rewards[i].chance;
940 }
941
942 rewards.sort(function (a,b) {
943 return b.chance - a.chance;
944 });
945
946 RewardsSystem.updateCurrentRewrads(rewards, chance_sum);
947 RewardsSystem.rewardsUpdate();
948 },
949
950 addRow: function () {
951 var tr = $('<tr>')
952 .append(
953 $('<td>').addClass('form-group').append(
954 $('<input>').addClass('form-control reward-amount').attr({
955 type: 'text'
956 })
957 )
958 )
959 .append(
960 $('<td>').addClass('form-group').append(
961 $('<input>').addClass('form-control reward-chance').attr({
962 type: 'number',
963 min: '1',
964 step: '0.01'
965 })
966 )
967 )
968 .append(
969 $('<td>').addClass('text-center').append(
970 $('<span>').addClass('btn btn-warning').text('Delete')
971 )
972 );
973 tr.find('span').click(RewardsSystem.delete);
974 tr.find('input').on('change click blur keypress keydown keyup', RewardsSystem.rewardsUpdate);
975
976 $('#rewards-box table tbody').append(tr);
977 },
978
979 getCurrentRewards: function () {
980 var rewards = [];
981 var sum_chance = 0;
982 $('#rewards-box table tbody tr').each(function (i, t) {
983 var amount = $(t).find('.reward-amount').val().trim();
984 var chance = parseFloat($(t).find('.reward-chance').val().trim());
985 if (isNaN(chance)) chance = 0;
986 if (RewardsSystem.validateAmount(amount) && !isNaN(chance) && chance > 0) {
987 chance = parseFloat(chance.toFixed(2));
988 sum_chance += chance;
989 rewards[rewards.length] = {
990 amount: amount,
991 chance: chance
992 };
993 }
994 });
995 return {
996 'rewards': rewards,
997 'sum': sum_chance
998 };
999 },
1000
1001 updateCurrentRewrads: function (rewards, sum) {
1002 if (typeof sum == 'undefined') sum = 100;
1003 $('#rewards-box table tbody').html('');
1004 for (i in rewards) {
1005 var reward = rewards[i];
1006 RewardsSystem.addRow();
1007 $('#rewards-box table tr').last().find('.reward-amount').val(reward.amount);
1008 $('#rewards-box table tr').last().find('.reward-chance').val(parseFloat((reward.chance / sum * 100.0).toFixed(2)));
1009 }
1010 },
1011
1012 delete: function () {
1013 $(this).parent().parent().remove();
1014 RewardsSystem.rewardsUpdate();
1015 },
1016
1017 autoFix: function() {
1018 var rewards = RewardsSystem.getCurrentRewards();
1019 var diff = rewards.sum / 100;
1020
1021 rewards.sum = 0;
1022 rewards.count = 0;
1023 rewards.omit = 0;
1024 for (i in rewards.rewards) {
1025 if (rewards.rewards[i].chance / diff >= 1) {
1026 rewards.sum += rewards.rewards[i].chance;
1027 rewards.count++;
1028 } else {
1029 rewards.omit += rewards.rewards[i].chance;
1030 }
1031 }
1032
1033 var diff = rewards.sum / (100-rewards.omit);
1034
1035 for (i in rewards.rewards) {
1036 if (rewards.rewards[i].chance / diff >= 1) {
1037 rewards.rewards[i].chance = rewards.rewards[i].chance / diff;
1038 }
1039 }
1040
1041 RewardsSystem.updateCurrentRewrads(rewards.rewards);
1042 RewardsSystem.rewardsUpdate();
1043 },
1044
1045 parseAmount: function (amount) {
1046
1047 var new_amount = '';
1048
1049 for (i = 0; i < amount.length; i++) {
1050
1051 var char = amount[i];
1052
1053 if (char == ',') char = '.';
1054
1055 if (char == '.' && i == 0) {
1056 new_amount += '0.';
1057 } else if (!isNaN(parseInt(char)) || ((char == '-' || char == '.') && i > 0 && i < amount.length-1)) {
1058 new_amount += char;
1059 }
1060
1061 }
1062
1063 return new_amount;
1064
1065 },
1066
1067 validateAmount: function(amount) {
1068 if (amount.indexOf('-') != -1) {
1069 var from = parseFloat(amount.substring(0, amount.indexOf('-')));
1070 var to = parseFloat(amount.substring(amount.indexOf('-')+1));
1071 return (!isNaN(from) && !isNaN(to) && to > from && from > 0);
1072 } else {
1073 var num = parseFloat(amount);
1074 return (!isNaN(num) && num > 0);
1075 }
1076 },
1077
1078 rewardsUpdate: function (e) {
1079
1080 if (typeof e == 'undefined' || typeof e.type == 'undefined') {
1081 e = {
1082 type: ''
1083 };
1084 }
1085
1086 var raw = '';
1087 var preview = '';
1088
1089 var new_chance_sum = 0.0;
1090 var chance_math = '';
1091
1092
1093 $('.rewards-warning').addClass('hidden');
1094
1095 $('#rewards-box table tbody tr').each(function (i, t) {
1096
1097
1098 var amount = RewardsSystem.parseAmount($(t).find('.reward-amount').val().trim());
1099 var chance = parseFloat($(t).find('.reward-chance').val().trim());
1100
1101 if (isNaN(chance)) chance = 0;
1102
1103 $(t).find('.reward-amount').parent().removeClass('has-warning');
1104 $(t).find('.reward-chance').parent().removeClass('has-warning');
1105
1106 var validAmount = RewardsSystem.validateAmount(amount);
1107 var validChance = (!isNaN(chance) && chance > 0);
1108
1109 if (validAmount && validChance) {
1110
1111 chance = parseFloat(chance.toFixed(2));
1112
1113 if ($(t).find('.reward-amount').val() != amount && e.type == 'blur') {
1114 $(t).find('.reward-amount').val(amount);
1115 }
1116 if ($(t).find('.reward-chance').val() != chance) {
1117 $(t).find('.reward-chance').val(chance);
1118 }
1119
1120 new_chance_sum += chance;
1121 chance_math += (i > 0 ? ' + ' : '') + chance + '%';
1122
1123 raw += (i > 0 ? ', ' : '') + chance + '*' + amount;
1124 preview += (i > 0 ? ', ' : '') + amount + ' (' + chance + '%)';
1125
1126 } else if ((!validAmount && validChance) || (validAmount && !validChance)) {
1127 $('.rewards-warning').removeClass('hidden');
1128 if (!validAmount) {
1129 $(t).find('.reward-amount').parent().addClass('has-warning');
1130 }
1131 if (!validChance) {
1132 $(t).find('.reward-chance').parent().addClass('has-warning');
1133 }
1134 }
1135
1136 });
1137
1138 $('#rewards-raw').val(raw);
1139 $('#rewards-preview').text(preview + ' ' + ($('#currency').val() == 'DOGE' ? 'DOGE' : 'satoshi'));
1140
1141 if (parseFloat(new_chance_sum.toFixed(2)) != '100') {
1142 $('.rewards-alert').removeClass('hidden');
1143 $('.rewards-alert .math').text(chance_math + ' = ' + new_chance_sum.toFixed(2) + '%');
1144 } else {
1145 $('.rewards-alert').addClass('hidden');
1146 }
1147
1148 },
1149
1150};
1151
1152
1153 </script>
1154</form>
1155TEMPLATE;
1156
1157$admin_login_template = <<<TEMPLATE
1158<form method="POST" class="form-horizontal" role="form">
1159 <div class="form-group">
1160 <label for="password" class="control-label">Password:</label>
1161 <input type="password" class="form-control" name="password">
1162 </div>
1163 <div class="form-group">
1164 <input type="submit" class="btn btn-primary btn-lg" value="Login">
1165 </div>
1166</form>
1167<div class="alert alert-warning alert-dismissible" role="alert">
1168 <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
1169Don't remember? <a href="?p=password-reset">Reset your password</a>.
1170</div>
1171TEMPLATE;
1172
1173$session_error_template = <<<TEMPLATE
1174<div class="alert alert-danger" role="alert">
1175 There was a problem with accessing your session data on the server. Check your server logs and contact your hosting provider for further help.
1176</div>
1177TEMPLATE;
1178
1179$login_error_template = <<<TEMPLATE
1180<div class="alert alert-danger" role="alert">
1181 <span class="glyphicon glyphicon-remove"></span>
1182 Incorrect password.
1183</div>
1184TEMPLATE;
1185
1186$pass_template = <<<TEMPLATE
1187<div class="alert alert-info" role="alert">
1188 Your password: <:: password ::>. Make sure to save it. <a class="alert-link" href="?p=admin">Click here to continue</a>.
1189</div>
1190TEMPLATE;
1191
1192$pass_reset_template = <<<TEMPLATE
1193<form method="POST">
1194 <div class="form-group">
1195 <label for="dbpass" class="control-label">To reset your Admin Password, enter your database password here:</label>
1196 <input type="password" class="form-control" name="dbpass">
1197 </div>
1198 <p class="form-group alert alert-info" role="alert">
1199 You must enter the same password you've entered in your config.php file.
1200 </p>
1201 <input type="submit" class="form-group pull-right btn btn-warning" value="Reset password">
1202</form>
1203TEMPLATE;
1204
1205$invalid_key_error_template = <<<TEMPLATE
1206<div class="alert alert-danger" role="alert">
1207 You've entered an invalid API key!
1208</div>
1209TEMPLATE;
1210
1211$oneclick_update_button_template = <<<TEMPLATE
1212or
1213<input type="hidden" name="task" value="oneclick-update">
1214<input type="submit" class="btn btn-primary" value="Update automatically">
1215TEMPLATE;
1216
1217$new_version_template = <<<TEMPLATE
1218<form method="POST">
1219 <div class="alert alert-info alert-dismissible" role="alert">
1220 <button type="button" class="close" data-dismiss="alert">
1221 <span aria-hidden="true">×</span>
1222 <span class="sr-only">Close</span>
1223 </button>
1224 <span style="line-height: 34px">
1225 There's a new version of Faucet in a Box available!
1226 Your version: $version; new version: <b><:: version ::></b>
1227 </span>
1228 <span class="pull-right text-right">
1229 <a class="btn btn-primary" href="<:: url ::>" target="_blank">Download version <:: version ::></a>
1230 <:: oneclick_update_button ::>
1231 <br><br>
1232 <a href="https://faucetinabox.com/#update" target="_blank">
1233 Manual update instructions
1234 </a>
1235 </span>
1236 <:: changelog ::>
1237 </div>
1238</form>
1239TEMPLATE;
1240
1241$page_nav_template = <<<TEMPLATE
1242 <li><a href="#page-wrap-<:: i ::>" role="tab" data-toggle="tab">Page <:: i ::></a></li>
1243TEMPLATE;
1244
1245$page_form_template = <<<TEMPLATE
1246<div class="page-wrap panel panel-default tab-pane" id="page-wrap-<:: i ::>">
1247 <div class="form-group">
1248 <label class="control-label" for="pages.<:: i ::>.name">Page name:</label>
1249 <input class="form-control" type="text" id="pages.<:: i ::>.name" name="pages[<:: i ::>][name]" value="<:: page_name ::>">
1250 </div>
1251 <div class="form-group">
1252 <label class="control-label" for="pages.<:: i ::>.html">HTML content:</label>
1253 <textarea class="form-control" id="pages.<:: i ::>.html" name="pages[<:: i ::>][html]"><:: html ::></textarea>
1254 </div>
1255 <button type="button" class="btn btn-sm pageDeleteButton" onclick="deletePage(this);">Delete this page</button>
1256</div>
1257TEMPLATE;
1258
1259$changes_saved_template = <<<TEMPLATE
1260<p class="alert alert-success">
1261 <span class="glyphicon glyphicon-ok"></span>
1262 Changes successfully saved!
1263</p>
1264TEMPLATE;
1265
1266$oneclick_update_success_template = <<<TEMPLATE
1267<p class="alert alert-success">
1268 <span class="glyphicon glyphicon-ok"></span>
1269 Faucet in a BOX script was successfully updated to the newest version!
1270</p>
1271TEMPLATE;
1272
1273$nastyhosts_not_allowed_template = <<<TEMPLATE
1274<p class="alert alert-danger">
1275 <span class="glyphicon glyphicon-remove"></span>
1276 You can't enable NastyHosts.com, because your IP address is marked as suspicious and you won't be able to access Admin Panel.
1277</p>
1278TEMPLATE;
1279
1280$oneclick_update_fail_template = <<<TEMPLATE
1281<p class="alert alert-danger">
1282 <span class="glyphicon glyphicon-remove"></span>
1283 An error occurred while updating Faucet in a BOX script. Please install new version manually.
1284</p>
1285TEMPLATE;
1286
1287$new_files_template = <<<TEMPLATE
1288<div class="alert alert-danger">
1289 Some of your template files need to be updated manually. Please compare original and new files and merge the changes:
1290 <ul>
1291 <:: new_files ::>
1292 </ul>
1293 Remember to remove <code>.new</code> files when you're done.
1294</div>
1295TEMPLATE;
1296
1297$connection_error_template = <<<TEMPLATE
1298<p class="alert alert-danger">Error connecting to <a href="https://faucetbox.com">FaucetBOX.com API</a>. Either your hosting provider doesn't support external connections or FaucetBOX.com API is down. Send an email to <a href="mailto:support@faucetbox.com">support@faucetbox.com</a> if you need help.</p>
1299TEMPLATE;
1300
1301$reverse_proxy_changed_alert_template = <<<TEMPLATE
1302<p class="alert alert-danger"><b><em>Reverse Proxy</em> provider setting automatically changed back to None, because people viewing your faucet without reverse proxy were detected</b>.<br>Make sure your reverse proxy is configured correctly!</p>
1303TEMPLATE;
1304
1305$reverse_proxy_misconfigured_alert_template = <<<TEMPLATE
1306<p class="alert alert-warning">It seems that you're using <:: reverse_proxy_provider ::> as your Reverse Proxy provider. You should configure it in <em>Advanced</em> tab or timer won't work correctly.</p>
1307TEMPLATE;
1308
1309$curl_warning_template = <<<TEMPLATE
1310<p class="alert alert-danger">cURL based connection failed, using legacy method. Please set <code>'disable_curl' => true,</code> in <code>config.php</code> file.</p>
1311TEMPLATE;
1312
1313$send_coins_success_template = <<<TEMPLATE
1314<p class="alert alert-success">You sent {{amount}} satoshi to <a href="https://faucetbox.com/check/{{address}}" target="_blank">{{address}}</a>.</p>
1315<script> $(document).ready(function(){ $('.nav-tabs a[href="#send-coins"]').tab('show'); }); </script>
1316TEMPLATE;
1317
1318$send_coins_error_template = <<<TEMPLATE
1319<p class="alert alert-danger">There was an error while sending {{amount}} satoshi to "{{address}}": <u>{{error}}</u></p>
1320<script> $(document).ready(function(){ $('.nav-tabs a[href="#send-coins"]').tab('show'); }); </script>
1321TEMPLATE;
1322
1323$missing_configs_template = <<<TEMPLATE
1324<div class="alert alert-warning">
1325<b>There are missing settings in your config.php file. That's probably because they were added in recent update.</b>
1326<:: missing_configs ::>
1327<hr>
1328</div>
1329TEMPLATE;
1330
1331$missing_config_template = <<<TEMPLATE
1332<hr>
1333 <ul>
1334 <li>Name: <:: config_name ::></li>
1335 <li>Default: <code>$<:: config_name ::> = <:: config_default ::>;</code></li>
1336 <li><:: config_description ::></li>
1337 </ul>
1338TEMPLATE;
1339
1340$template_updates_template = <<<TEMPLATE
1341<div class="alert alert-warning">
1342 <b>Your template file is out of date and won't work with this version of Faucet in a BOX. Here's what you have to do to fix that:</b>
1343 <:: template_updates ::>
1344<hr>
1345</div>
1346TEMPLATE;
1347
1348$template_update_template = <<<TEMPLATE
1349<hr>
1350 <ul>
1351 <li><:: message ::></li>
1352 </ul>
1353TEMPLATE;
1354
1355// ****************** END ADMIN TEMPLATES
1356
1357#reCaptcha template
1358$recaptcha_template = <<<TEMPLATE
1359<script src="https://www.google.com/recaptcha/api.js" async defer></script>
1360<div class="g-recaptcha" data-sitekey="<:: your_site_key ::>"></div>
1361<noscript>
1362 <div style="width: 302px; height: 352px;">
1363 <div style="width: 302px; height: 352px; position: relative;">
1364 <div style="width: 302px; height: 352px; position: absolute;">
1365 <iframe src="https://www.google.com/recaptcha/api/fallback?k=<:: your_site_key ::>"
1366 frameborder="0" scrolling="no"
1367 style="width: 302px; height:352px; border-style: none;">
1368 </iframe>
1369 </div>
1370 <div style="width: 250px; height: 80px; position: absolute; border-style: none;
1371 bottom: 21px; left: 25px; margin: 0px; padding: 0px; right: 25px;">
1372 <textarea id="g-recaptcha-response" name="g-recaptcha-response"
1373 class="g-recaptcha-response"
1374 style="width: 250px; height: 80px; border: 1px solid #c1c1c1;
1375 margin: 0px; padding: 0px; resize: none;" value="">
1376 </textarea>
1377 </div>
1378 </div>
1379 </div>
1380</noscript>
1381TEMPLATE;
1382
1383function checkOneclickUpdatePossible($response) {
1384 global $version;
1385
1386 $oneclick_update_possible = false;
1387 if(!empty($response['changelog'][$version]['hashes'])) {
1388 $hashes = $response['changelog'][$version]['hashes'];
1389 $oneclick_update_possible = class_exists("ZipArchive");
1390 foreach($hashes as $file => $hash) {
1391 if(strpos($file, 'templates/') === 0)
1392 continue;
1393 $oneclick_update_possible &=
1394 is_writable($file) &&
1395 sha1_file($file) === $hash;
1396 }
1397 }
1398 return $oneclick_update_possible;
1399}
1400
1401function setNewPass() {
1402 global $sql;
1403 $alphabet = str_split('qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890');
1404 $password = '';
1405 for($i = 0; $i < 15; $i++)
1406 $password .= $alphabet[array_rand($alphabet)];
1407 $hash = crypt($password);
1408 $sql->query("REPLACE INTO Faucetinabox_Settings VALUES ('password', '$hash')");
1409 return $password;
1410}
1411
1412function randHash($length) {
1413 $alphabet = str_split('qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890');
1414 $hash = '';
1415 for($i = 0; $i < $length; $i++) {
1416 $hash .= $alphabet[array_rand($alphabet)];
1417 }
1418 return $hash;
1419}
1420
1421// check if configured
1422try {
1423 $pass = $sql->query("SELECT `value` FROM `Faucetinabox_Settings` WHERE `name` = 'password'")->fetch();
1424} catch(PDOException $e) {
1425 $pass = null;
1426}
1427
1428function checkRevProxyIp($file) {
1429 require_once("libs/http-foundation/IpUtils.php");
1430 return IpUtils::checkIp($_SERVER['REMOTE_ADDR'], array_map(function($v) { return trim($v); }, file($file)));
1431}
1432
1433function detectRevProxyProvider() {
1434 if(checkRevProxyIp("libs/ips/cloudflare.txt")) {
1435 return "cloudflare";
1436 } elseif(checkRevProxyIp("libs/ips/incapsula.txt")) {
1437 return "incapsula";
1438 }
1439
1440 return "none";
1441}
1442
1443function getIP() {
1444 global $sql;
1445 static $cache_ip;
1446 if($cache_ip) return $cache_ip;
1447 $type = $sql->query("SELECT `value` FROM `Faucetinabox_Settings` WHERE `name` = 'reverse_proxy'")->fetch();
1448 if (!$type) $type = array('none');
1449 $ip = null;
1450 switch ($type[0]) {
1451 case 'cloudflare':
1452 if(checkRevProxyIp("libs/ips/cloudflare.txt"))
1453 $ip = array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : null;
1454 break;
1455 case 'incapsula':
1456 if(checkRevProxyIp("libs/ips/incapsula.txt"))
1457 $ip = array_key_exists('HTTP_INCAP_CLIENT_IP', $_SERVER) ? $_SERVER['HTTP_INCAP_CLIENT_IP'] : null;
1458 break;
1459 default:
1460 $ip = $_SERVER['REMOTE_ADDR'];
1461 }
1462 if (empty($ip)) {
1463 $sql->query("UPDATE `Faucetinabox_Settings` SET `value` = 'none-auto' WHERE `name` = 'reverse_proxy' AND `value` <> 'none' LIMIT 1");
1464 $cache_ip = $_SERVER['REMOTE_ADDR'];
1465 return $_SERVER['REMOTE_ADDR'];
1466 }
1467 $cache_ip = $ip;
1468 return $ip;
1469}
1470
1471function is_ssl(){
1472 if(isset($_SERVER['HTTPS'])){
1473 if('on' == strtolower($_SERVER['HTTPS']))
1474 return true;
1475 if('1' == $_SERVER['HTTPS'])
1476 return true;
1477 if(true == $_SERVER['HTTPS'])
1478 return true;
1479 }elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])){
1480 return true;
1481 }
1482 if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') {
1483 return true;
1484 }
1485 return false;
1486}
1487
1488function ipSubnetCheck ($ip, $network) {
1489 $network = explode("/", $network);
1490 $net = $network[0];
1491
1492 if(count($network) > 1) {
1493 $mask = $network[1];
1494 } else {
1495 $mask = 32;
1496 }
1497
1498 $net = ip2long ($net);
1499 $mask = ~((1 << (32 - $mask)) - 1);
1500
1501 $ip_net = $ip & $mask;
1502
1503 return ($ip_net == $net);
1504}
1505
1506function banned() {
1507 trigger_error("Banned: ".getIP());
1508 http_response_code(500);
1509 die();
1510}
1511
1512function suspicious($server, $comment) {
1513 if($server) {
1514 @file_get_contents($server."report/1/".urlencode(getIP())."/".urlencode($comment));
1515 }
1516}
1517
1518
1519if($pass) {
1520 if(array_key_exists('p', $_GET) && $_GET['p'] == 'logout')
1521 $_SESSION = array();
1522
1523 // check db updates
1524 $dbversion = $sql->query("SELECT `value` FROM `Faucetinabox_Settings` WHERE `name` = 'version'")->fetch();
1525 if($dbversion) {
1526 $dbversion = intval($dbversion[0]);
1527 } else {
1528 $dbversion = -1;
1529 }
1530 foreach($db_updates as $v => $update) {
1531 if($v > $dbversion) {
1532 foreach($update as $query) {
1533 $sql->exec($query);
1534 }
1535 }
1536 }
1537 if($dbversion < 17) {
1538 // dogecoin changed from satoshi to doge
1539 // better clear rewards...
1540 $c = $sql->query("SELECT `value` FROM `Faucetinabox_Settings` WHERE `name` = 'currency'")->fetch();
1541 if($c[0] == 'DOGE')
1542 $sql->exec("UPDATE `Faucetinabox_Settings` SET `value` = '' WHERE name = 'rewards'");
1543 }
1544 if(intval($version) > intval($dbversion)) {
1545 $q = $sql->prepare("UPDATE `Faucetinabox_Settings` SET `value` = ? WHERE `name` = 'version'");
1546 $q->execute(array($version));
1547 }
1548
1549 $security_settings = array();
1550 $q = $sql->query("SELECT `name`, `value` FROM `Faucetinabox_Settings` WHERE `name` in ('ip_check_server', 'ip_ban_list', 'hostname_ban_list', 'address_ban_list')");
1551 while($row = $q->fetch()) {
1552 if(stripos($row["name"], "_list") !== false) {
1553 $security_settings[$row["name"]] = array();
1554 if(preg_match_all("/[^,;\s]+/", $row["value"], $matches)) {
1555 foreach($matches[0] as $m) {
1556 $security_settings[$row["name"]][] = $m;
1557 }
1558 }
1559 } else {
1560 $security_settings[$row["name"]] = $row["value"];
1561 }
1562 }
1563
1564 if(!empty($_POST["mmc"])) {
1565 $_SESSION["mouse_movement_detected"] = true;
1566 die();
1567 }
1568
1569 if($_SERVER["REQUEST_METHOD"] == "POST") {
1570 if($security_settings["ip_check_server"]) {
1571 if(!preg_match("#/$#", $security_settings["ip_check_server"])) {
1572 $security_settings["ip_check_server"] .= "/";
1573 }
1574 }
1575
1576 // banning
1577 $ip = ip2long(getIP());
1578 if($ip) { // only ipv4 supported here
1579 foreach($security_settings["ip_ban_list"] as $ban) {
1580 if(ipSubnetCheck($ip, $ban)) {
1581 banned();
1582 }
1583 }
1584 }
1585
1586 if($security_settings["ip_check_server"]) {
1587
1588 $hostnames = @file_get_contents($security_settings["ip_check_server"].getIP());
1589 $hostnames = json_decode($hostnames);
1590
1591 if($hostnames && property_exists($hostnames, "status") && $hostnames->status == 200) {
1592 if(property_exists($hostnames, 'suggestion') && $hostnames->suggestion == "deny") {
1593 banned();
1594 }
1595
1596 if(property_exists($hostnames, 'hostnames')) {
1597 foreach($security_settings["hostname_ban_list"] as $ban) {
1598 foreach($hostnames->hostnames as $hostname) {
1599 if(stripos($hostname, $ban) !== false) {
1600 banned();
1601 }
1602 }
1603 }
1604 }
1605
1606 }
1607 }
1608 $fake_address_input_used = false;
1609 if(!empty($_POST["address"])) {
1610 $fake_address_input_used = true;
1611 }
1612 }
1613
1614
1615 if(!$disable_admin_panel && array_key_exists('p', $_GET) && $_GET['p'] == 'admin') {
1616 $invalid_key = false;
1617 if (array_key_exists('password', $_POST)) {
1618 if ($pass[0] == crypt($_POST['password'], $pass[0])) {
1619 $_SESSION["$session_prefix-logged_in"] = true;
1620 header("Location: ?p=admin&session_check=0");
1621 die();
1622 } else {
1623 $admin_login_template = $login_error_template.$admin_login_template;
1624 }
1625 }
1626 if (array_key_exists("session_check", $_GET)) {
1627 if (array_key_exists("$session_prefix-logged_in", $_SESSION)) {
1628 header("Location: ?p=admin");
1629 die();
1630 } else {
1631 //show alert on login screen
1632 $admin_login_template = $session_error_template.$admin_login_template;
1633 }
1634 }
1635
1636 if(array_key_exists("$session_prefix-logged_in", $_SESSION)) { // logged in to admin page
1637
1638 //ajax
1639 if (array_key_exists("action", $_POST)) {
1640
1641 header("Content-type: application/json");
1642
1643 $response = ["status" => 404];
1644
1645 switch ($_POST["action"]) {
1646 case "check_referrals":
1647
1648 $referral = array_key_exists("referral", $_POST) ? trim($_POST["referral"]) : "";
1649
1650 $response["status"] = 200;
1651 $response["addresses"] = [];
1652
1653 if (strlen($referral) > 0) {
1654
1655 $q = $sql->prepare("SELECT `a`.`address`, `r`.`address` FROM `Faucetinabox_Refs` `r` LEFT JOIN `Faucetinabox_Addresses` `a` ON `r`.`id` = `a`.`ref_id` WHERE `r`.`address` LIKE ? ORDER BY `a`.`last_used` DESC");
1656 $q->execute(["%".$referral."%"]);
1657 while ($row = $q->fetch()) {
1658 $response["addresses"][] = [
1659 "address" => $row[0],
1660 "referral" => $row[1],
1661 ];
1662 }
1663
1664 }
1665
1666 break;
1667 }
1668
1669 die(json_encode($response));
1670
1671 }
1672
1673 if (array_key_exists('task', $_POST) && $_POST['task'] == 'oneclick-update') {
1674 function recurse_copy($copy_as_new,$src,$dst) {
1675 $dir = opendir($src);
1676 @mkdir($dst);
1677 while(false !== ( $file = readdir($dir)) ) {
1678 if (( $file != '.' ) && ( $file != '..' )) {
1679 if ( is_dir($src . '/' . $file) ) {
1680 recurse_copy($copy_as_new, $src . '/' . $file,$dst . '/' . $file);
1681 }
1682 else {
1683 $dstfile = $dst.'/'.$file;
1684 if(in_array(realpath($dstfile), $copy_as_new))
1685 $dstfile .= ".new";
1686 if(!copy($src . '/' . $file,$dstfile)) {
1687 return false;
1688 }
1689 }
1690 }
1691 }
1692 closedir($dir);
1693 return true;
1694 }
1695 function rrmdir($dir) {
1696 if (is_dir($dir)) {
1697 $objects = scandir($dir);
1698 foreach ($objects as $object) {
1699 if ($object != "." && $object != "..") {
1700 if (filetype($dir."/".$object) == "dir") rrmdir($dir."/".$object); else unlink($dir."/".$object);
1701 }
1702 }
1703 reset($objects);
1704 rmdir($dir);
1705 }
1706 }
1707
1708 ini_set('display_errors', true);
1709 error_reporting(-1);
1710 $fb = new FaucetBOX(null, null, $connection_options);
1711 $response = $fb->fiabVersionCheck();
1712 if(empty($response['version']) || $response['version'] == $version || !checkOneclickUpdatePossible($response)) {
1713 header("Location: ?p=admin&update_status=fail");
1714 die();
1715 }
1716
1717 $url = $response["url"];
1718 if($url[0] == '/') $url = "https:$url";
1719 $url .= "?update=auto";
1720
1721 if(!file_put_contents('update.zip', fopen($url, 'rb'))) {
1722 header("Location: ?p=admin&update_status=fail");
1723 die();
1724 }
1725
1726 $zip = new ZipArchive();
1727 if(!$zip->open('update.zip')) {
1728 unlink('update.zip');
1729 header("Location: ?p=admin&update_status=fail");
1730 die();
1731 }
1732
1733 if(!$zip->extractTo('./')) {
1734 unlink('update.zip');
1735 header("Location: ?p=admin&update_status=fail");
1736 die();
1737 }
1738
1739 $dir = trim($zip->getNameIndex(0), '/');
1740 $zip->close();
1741 unlink('update.zip');
1742 unlink("$dir/config.php");
1743
1744 $modified_files = [];
1745 foreach($response['changelog'][$version]['hashes'] as $file => $hash) {
1746 if(strpos($file, 'templates/') === 0 &&
1747 sha1_file($file) !== $hash
1748 ) {
1749 $modified_files[] = realpath($file);
1750 }
1751 }
1752 if(!recurse_copy($modified_files, $dir, '.')) {
1753 header("Location: ?p=admin&update_status=fail");
1754 die();
1755 }
1756 rrmdir($dir);
1757 header("Location: ?p=admin&update_status=success&new_files=".count($modified_files));
1758 die();
1759 }
1760
1761 if (
1762 array_key_exists("update_status", $_GET) &&
1763 in_array($_GET["update_status"], ["success", "fail"])
1764 ) {
1765 if ($_GET["update_status"] == "success") {
1766 $oneclick_update_alert = $oneclick_update_success_template;
1767 } else {
1768 $oneclick_update_alert = $oneclick_update_fail_template;
1769 }
1770 } else {
1771 $oneclick_update_alert = "";
1772 }
1773
1774 if (array_key_exists("encoded_data", $_POST)) {
1775 $data = base64_decode($_POST["encoded_data"]);
1776 if ($data) {
1777 parse_str($data, $tmp);
1778 $_POST = array_merge($_POST, $tmp);
1779 }
1780 }
1781
1782 if(array_key_exists('get_options', $_POST)) {
1783 if(file_exists("templates/{$_POST["get_options"]}/setup.php")) {
1784 require_once("templates/{$_POST["get_options"]}/setup.php");
1785 die(getTemplateOptions($sql, $_POST['get_options']));
1786 } else {
1787 die('<p>No template defined options available.</p>');
1788 }
1789 } else if(
1790 array_key_exists("reset", $_POST) &&
1791 array_key_exists("factory_reset_confirm", $_POST) &&
1792 $_POST["factory_reset_confirm"] == "on"
1793 ) {
1794 $sql->exec("DELETE FROM Faucetinabox_Settings WHERE name NOT LIKE '%key%' AND name != 'password'");
1795 $sql->exec($default_data_query);
1796 }
1797 $q = $sql->prepare("SELECT value FROM Faucetinabox_Settings WHERE name = ?");
1798 $q->execute(array('apikey'));
1799 $apikey = $q->fetch();
1800 $apikey = $apikey[0];
1801 $q->execute(array('currency'));
1802 $currency = $q->fetch();
1803 $currency = $currency[0];
1804 $fb = new FaucetBOX($apikey, $currency, $connection_options);
1805 $currencies = $fb->getCurrencies();
1806 $connection_error = '';
1807 $curl_warning = '';
1808 $missing_configs_info = '';
1809 if(!empty($missing_configs)) {
1810 $list = '';
1811 foreach($missing_configs as $missing_config) {
1812 $list .= str_replace(array("<:: config_name ::>", "<:: config_default ::>", "<:: config_description ::>"), array($missing_config['name'], $missing_config['default'], $missing_config['desc']), $missing_config_template);
1813 }
1814 $missing_configs_info = str_replace("<:: missing_configs ::>", $list, $missing_configs_template);
1815 }
1816 if($fb->curl_warning) {
1817 $curl_warning = $curl_warning_template;
1818 }
1819 if(!$currencies) {
1820 $currencies = array('BTC', 'LTC', 'DOGE', 'PPC', 'XPM', 'DASH');
1821 if($fb->communication_error) {
1822 $connection_error = $connection_error_template;
1823 }
1824 }
1825 $send_coins_message = '';
1826 if(array_key_exists('send_coins', $_POST)) {
1827
1828 $amount = array_key_exists('send_coins_amount', $_POST) ? intval($_POST['send_coins_amount']) : 0;
1829 $address = array_key_exists('send_coins_address', $_POST) ? trim($_POST['send_coins_address']) : '';
1830
1831 $fb = new FaucetBOX($apikey, $currency, $connection_options);
1832 $ret = $fb->send($address, $amount);
1833
1834 if ($ret['success']) {
1835 $send_coins_message = str_replace(array('{{amount}}','{{address}}'), array($amount,$address), $send_coins_success_template);
1836 } else {
1837 $send_coins_message = str_replace(array('{{amount}}','{{address}}','{{error}}'), array($amount,$address,$ret['message']), $send_coins_error_template);
1838 }
1839
1840 }
1841 $changes_saved = "";
1842 $nastyhosts_not_allowed_alert = "";
1843 if(array_key_exists('save_settings', $_POST)) {
1844 $currency = $_POST['currency'];
1845 $fb = new FaucetBOX($_POST['apikey'], $currency, $connection_options);
1846 $ret = $fb->getBalance();
1847
1848 if($ret['status'] == 403) {
1849 $invalid_key = true;
1850 } elseif($ret['status'] == 405) {
1851 $sql->query("UPDATE Faucetinabox_Settings SET `value` = 0 WHERE name = 'balance'");
1852 } elseif(array_key_exists('balance', $ret)) {
1853 $q = $sql->prepare("UPDATE Faucetinabox_Settings SET `value` = ? WHERE name = 'balance'");
1854 if($currency != 'DOGE')
1855 $q->execute(array($ret['balance']));
1856 else
1857 $q->execute(array($ret['balance_bitcoin']));
1858 }
1859
1860 $q = $sql->prepare("INSERT IGNORE INTO Faucetinabox_Settings (`name`, `value`) VALUES (?, ?)");
1861 $template = $_POST["template"];
1862 preg_match_all('/\$data\[([\'"])(custom_(?:(?!\1).)*)\1\]/', file_get_contents("templates/$template/index.php"), $matches);
1863 foreach($matches[2] as $box)
1864 $q->execute(array("{$box}_$template", ''));
1865
1866
1867 if (array_key_exists("ip_check_server", $_POST) && !empty($_POST["ip_check_server"])) {
1868
1869 $hostnames = @file_get_contents($_POST["ip_check_server"].getIP());
1870 $hostnames = json_decode($hostnames);
1871
1872 if ($hostnames && property_exists($hostnames, "status") && $hostnames->status == 200) {
1873 if (property_exists($hostnames, 'suggestion') && $hostnames->suggestion == "deny") {
1874 $nastyhosts_not_allowed_alert = $nastyhosts_not_allowed_template;
1875 $_POST["ip_check_server"] = "";
1876 }
1877 }
1878
1879 }
1880
1881
1882 $q = $sql->prepare("UPDATE Faucetinabox_Settings SET value = ? WHERE name = ?");
1883 $ipq = $sql->prepare("INSERT INTO Faucetinabox_Pages (url_name, name, html) VALUES (?, ?, ?)");
1884 $sql->exec("DELETE FROM Faucetinabox_Pages");
1885 foreach($_POST as $k => $v) {
1886 if($k == 'apikey' && $invalid_key)
1887 continue;
1888 if($k == 'pages') {
1889 foreach($_POST['pages'] as $p) {
1890 $url_name = strtolower(preg_replace("/[^A-Za-z0-9_\-]/", '', $p["name"]));
1891 $i = 0;
1892 $success = false;
1893 while(!$success) {
1894 try {
1895 if($i)
1896 $ipq->execute(array($url_name.'-'.$i, $p['name'], $p['html']));
1897 else
1898 $ipq->execute(array($url_name, $p['name'], $p['html']));
1899 $success = true;
1900 } catch(PDOException $e) {
1901 $i++;
1902 }
1903 }
1904 }
1905 continue;
1906 }
1907 $q->execute(array($v, $k));
1908 }
1909 if (!array_key_exists('block_adblock', $_POST)) $q->execute(array('', 'block_adblock'));
1910
1911 $changes_saved = $changes_saved_template;
1912 }
1913 $page = str_replace('<:: content ::>', $admin_template, $master_template);
1914 $query = $sql->query("SELECT name, value FROM Faucetinabox_Settings");
1915 while($row = $query->fetch()) {
1916 if($row[0] == 'template') {
1917 if(file_exists("templates/{$row[1]}/index.php")) {
1918 $current_template = $row[1];
1919 } else {
1920 $templates = glob("templates/*");
1921 if($templates)
1922 $current_template = substr($templates[0], strlen('templates/'));
1923 else
1924 die(str_replace("<:: content ::>", "<div class='alert alert-danger' role='alert'>No templates found! Please reinstall your faucet.</div>", $master_template));
1925 }
1926 } else {
1927 if ($row[0] == 'reverse_proxy') {
1928 if ($row[1] == 'none-auto') {
1929 $reverse_proxy_changed_alert = $reverse_proxy_changed_alert_template;
1930 $row[1] = 'none';
1931 } else {
1932 $reverse_proxy_changed_alert = '';
1933 }
1934 $provider = detectRevProxyProvider();
1935 if ($row[1] == 'none' && $provider !== $row[1]) {
1936 $reverse_proxy_misconfigured_alert = str_replace("<:: reverse_proxy_provider ::>", ucfirst($provider), $reverse_proxy_misconfigured_alert_template);
1937 } else {
1938 $reverse_proxy_misconfigured_alert = '';
1939 }
1940 $page = str_replace('<:: reverse_proxy_changed_alert ::>', $reverse_proxy_changed_alert, $page);
1941 $page = str_replace('<:: reverse_proxy_misconfigured_alert ::>', $reverse_proxy_misconfigured_alert, $page);
1942 }
1943 if($row[0] == 'block_adblock') {
1944 $row[1] = $row[1] == 'on' ? 'checked' : '';
1945 }
1946 $page = str_replace("<:: {$row[0]} ::>", $row[1], $page);
1947 }
1948 }
1949
1950
1951 $templates = '';
1952 foreach(glob("templates/*") as $template) {
1953 $template = basename($template);
1954 if($template == $current_template) {
1955 $templates .= "<option selected>$template</option>";
1956 } else {
1957 $templates .= "<option>$template</option>";
1958 }
1959 }
1960 $page = str_replace('<:: templates ::>', $templates, $page);
1961 $page = str_replace('<:: current_template ::>', $current_template, $page);
1962
1963
1964 if(file_exists("templates/{$current_template}/setup.php")) {
1965 require_once("templates/{$current_template}/setup.php");
1966 $page = str_replace('<:: template_options ::>', getTemplateOptions($sql, $current_template), $page);
1967 } else {
1968 $page = str_replace('<:: template_options ::>', '<p>No template defined options available.</p>', $page);
1969 }
1970
1971 $template_string = file_get_contents("templates/{$current_template}/index.php");
1972 $template_updates_info = '';
1973 foreach($template_updates as $update) {
1974 if(!preg_match($update["test"], $template_string)) {
1975 $template_updates_info .= str_replace("<:: message ::>", $update["message"], $template_update_template);
1976 }
1977 }
1978 if(!empty($template_updates_info)) {
1979 $template_updates_info = str_replace("<:: template_updates ::>", $template_updates_info, $template_updates_template);
1980 }
1981
1982 $q = $sql->query("SELECT name, html FROM Faucetinabox_Pages ORDER BY id");
1983 $pages = '';
1984 $pages_nav = '';
1985 $i = 1;
1986 while($userpage = $q->fetch()) {
1987 $html = htmlspecialchars($userpage['html']);
1988 $name = htmlspecialchars($userpage['name']);
1989 $pages .= str_replace(array('<:: i ::>', '<:: page_name ::>', '<:: html ::>'),
1990 array($i, $name, $html), $page_form_template);
1991 $pages_nav .= str_replace('<:: i ::>', $i, $page_nav_template);
1992 ++$i;
1993 }
1994 $page = str_replace('<:: pages ::>', $pages, $page);
1995 $page = str_replace('<:: pages_nav ::>', $pages_nav, $page);
1996 $currencies_select = "";
1997 foreach($currencies as $c) {
1998 if($currency == $c)
1999 $currencies_select .= "<option value='$c' selected>$c</option>";
2000 else
2001 $currencies_select .= "<option value='$c'>$c</option>";
2002 }
2003 $page = str_replace('<:: currency ::>', $currency, $page);
2004 $page = str_replace('<:: currencies ::>', $currencies_select, $page);
2005
2006
2007 if($invalid_key)
2008 $page = str_replace('<:: invalid_key ::>', $invalid_key_error_template, $page);
2009 else
2010 $page = str_replace('<:: invalid_key ::>', '', $page);
2011
2012 $page = str_replace('<:: page_form_template ::>',
2013 json_encode($page_form_template),
2014 $page);
2015 $page = str_replace('<:: page_nav_template ::>',
2016 json_encode($page_nav_template),
2017 $page);
2018
2019 $new_files = [];
2020 foreach (new RecursiveIteratorIterator (new RecursiveDirectoryIterator ('templates')) as $file) {
2021 $file = $file->getPathname();
2022 if(substr($file, -4) == ".new") {
2023 $new_files[] = $file;
2024 }
2025 }
2026
2027 if($new_files) {
2028 $new_files = implode("\n", array_map(function($v) { return "<li>$v</li>"; }, $new_files));
2029 $new_files = str_replace("<:: new_files ::>", $new_files, $new_files_template);
2030 } else {
2031 $new_files = "";
2032 }
2033 $page = str_replace("<:: new_files ::>", $new_files, $page);
2034
2035 $response = $fb->fiabVersionCheck();
2036 $oneclick_update_possible = checkOneclickUpdatePossible($response);
2037 if(!$connection_error && $response['version'] && $version < intval($response["version"])) {
2038 $page = str_replace('<:: version_check ::>', $new_version_template, $page);
2039 $changelog = '';
2040 foreach($response['changelog'] as $v => $changes) {
2041 $changelog_entries = array_map(function($entry) {
2042 return "<li>$entry</li>";
2043 }, $changes['changelog']);
2044 $changelog_entries = implode("", $changelog_entries);
2045 if(intval($v) > $version) {
2046 $changelog .= "<p>Changes in r$v (${changes['released']}): <ul>${changelog_entries}</ul></p>";
2047 }
2048 }
2049 $page = str_replace(array('<:: url ::>', '<:: version ::>', '<:: changelog ::>'), array($response['url'], $response['version'], $changelog), $page);
2050 if($oneclick_update_possible) {
2051 $page = str_replace('<:: oneclick_update_button ::>', $oneclick_update_button_template, $page);
2052 } else {
2053 $page = str_replace('<:: oneclick_update_button ::>', '', $page);
2054 }
2055 } else {
2056 $page = str_replace('<:: version_check ::>', '', $page);
2057 }
2058 $page = str_replace('<:: connection_error ::>', $connection_error, $page);
2059 $page = str_replace('<:: curl_warning ::>', $curl_warning, $page);
2060 $page = str_replace('<:: send_coins_message ::>', $send_coins_message, $page);
2061 $page = str_replace('<:: missing_configs ::>', $missing_configs_info, $page);
2062 $page = str_replace('<:: template_updates ::>', $template_updates_info, $page);
2063 $page = str_replace('<:: changes_saved ::>', $changes_saved, $page);
2064 $page = str_replace('<:: oneclick_update_alert ::>', $oneclick_update_alert, $page);
2065 $page = str_replace('<:: nastyhosts_not_allowed ::>', $nastyhosts_not_allowed_alert, $page);
2066 die($page);
2067 } else {
2068 // requested admin page without session
2069 $page = str_replace('<:: content ::>', $admin_login_template, $master_template);
2070 die($page);
2071 }
2072 } elseif(!$disable_admin_panel && array_key_exists('p', $_GET) && $_GET['p'] == 'password-reset') {
2073 $error = "";
2074 if(array_key_exists('dbpass', $_POST)) {
2075 if($_POST['dbpass'] == $dbpass) {
2076 $password = setNewPass();
2077 $page = str_replace('<:: content ::>', $pass_template, $master_template);
2078 $page = str_replace('<:: password ::>', $password, $page);
2079 die($page);
2080 } else {
2081 $error = "<p class='alert alert-danger' role='alert'>Wrong database password</p>";
2082 }
2083 }
2084 $page = str_replace('<:: content ::>', $error.$pass_reset_template, $master_template);
2085 die($page);
2086 } else {
2087 // show main page
2088 $q = $sql->query("SELECT value FROM Faucetinabox_Settings WHERE name = 'template'");
2089 $template = $q->fetch();
2090 $template = $template[0];
2091 if(!file_exists("templates/{$template}/index.php")) {
2092 $templates = glob("templates/*");
2093 if($templates)
2094 $template = substr($templates[0], strlen("templates/"));
2095 else
2096 die(str_replace('<:: content ::>', "<div class='alert alert-danger' role='alert'>No templates found!</div>", $master_template));
2097 }
2098
2099 if(array_key_exists("HTTPS", $_SERVER) && $_SERVER["HTTPS"])
2100 $protocol = "https://";
2101 else
2102 $protocol = "http://";
2103
2104 if (array_key_exists('address_input_name', $_SESSION) && array_key_exists($_SESSION['address_input_name'], $_POST)) {
2105 $_POST['address'] = $_POST[$_SESSION['address_input_name']];
2106 } else {
2107 if($display_errors && $_SERVER['REQUEST_METHOD'] == "POST") {
2108 if(array_key_exists('address_input_name', $_SESSION)) {
2109 trigger_error("Post request, but session is invalid.");
2110 } else {
2111 trigger_error("Post request, but invalid address input name.");
2112 }
2113 }
2114 unset($_POST['address']);
2115 }
2116
2117
2118 $data = array(
2119 "paid" => false,
2120 "disable_admin_panel" => $disable_admin_panel,
2121 "address" => "",
2122 "captcha_valid" => !array_key_exists('address', $_POST),
2123 "captcha" => false,
2124 "enabled" => false,
2125 "error" => false,
2126 "reflink" => $protocol.$_SERVER['HTTP_HOST'].strtok($_SERVER['REQUEST_URI'], '?').'?r='
2127 );
2128 if(array_key_exists('address', $_POST)) {
2129 $data["reflink"] .= $_POST['address'];
2130 } else if (array_key_exists('address', $_COOKIE)) {
2131 $data["reflink"] .= $_COOKIE['address'];
2132 $data["address"] = $_COOKIE['address'];
2133 } else {
2134 $data["reflink"] .= 'Your_Address';
2135 }
2136
2137
2138 $q = $sql->query("SELECT name, value FROM Faucetinabox_Settings WHERE name <> 'password'");
2139
2140 while($row = $q->fetch()) {
2141 if ($row[0] == "safety_limits_end_time") {
2142 $time = strtotime($row[1]);
2143 if ($time !== false && $time < time()) {
2144 $row[1] = "";
2145 }
2146 }
2147 $data[$row[0]] = $row[1];
2148 }
2149
2150 if(time() - $data['last_balance_check'] > 60*10) {
2151 $fb = new FaucetBOX($data['apikey'], $data['currency'], $connection_options);
2152 $ret = $fb->getBalance();
2153 if(array_key_exists('balance', $ret)) {
2154 if($data['currency'] != 'DOGE')
2155 $balance = $ret['balance'];
2156 else
2157 $balance = $ret['balance_bitcoin'];
2158 $q = $sql->prepare("UPDATE Faucetinabox_Settings SET value = ? WHERE name = ?");
2159 $q->execute(array(time(), 'last_balance_check'));
2160 $q->execute(array($balance, 'balance'));
2161 $data['balance'] = $balance;
2162 $data['last_balance_check'] = time();
2163 }
2164 }
2165
2166 $data['unit'] = 'satoshi';
2167 if($data["currency"] == 'DOGE')
2168 $data["unit"] = 'DOGE';
2169
2170
2171 #MuliCaptcha: Firstly check chosen captcha system
2172 $captcha = array('available' => array(), 'selected' => null);
2173 if ($data['solvemedia_challenge_key'] && $data['solvemedia_verification_key'] && $data['solvemedia_auth_key']) {
2174 $captcha['available'][] = 'SolveMedia';
2175 }
2176 if ($data['recaptcha_public_key'] && $data['recaptcha_private_key']) {
2177 $captcha['available'][] = 'reCaptcha';
2178 }
2179 if ($data['ayah_publisher_key'] && $data['ayah_scoring_key']) {
2180 $captcha['available'][] = 'AreYouAHuman';
2181 }
2182 if ($data['funcaptcha_public_key'] && $data['funcaptcha_private_key']) {
2183 $captcha['available'][] = 'FunCaptcha';
2184 }
2185
2186 #MuliCaptcha: Secondly check if user switched captcha or choose default
2187 if (array_key_exists('cc', $_GET) && in_array($_GET['cc'], $captcha['available'])) {
2188 $captcha['selected'] = $captcha['available'][array_search($_GET['cc'], $captcha['available'])];
2189 $_SESSION["$session_prefix-selected_captcha"] = $captcha['selected'];
2190 } elseif (array_key_exists("$session_prefix-selected_captcha", $_SESSION) && in_array($_SESSION["$session_prefix-selected_captcha"], $captcha['available'])) {
2191 $captcha['selected'] = $_SESSION["$session_prefix-selected_captcha"];
2192 } else {
2193 if($captcha['available'])
2194 $captcha['selected'] = $captcha['available'][0];
2195 if (in_array($data['default_captcha'], $captcha['available'])) {
2196 $captcha['selected'] = $data['default_captcha'];
2197 } else if($captcha['available']) {
2198 $captcha['selected'] = $captcha['available'][0];
2199 }
2200 }
2201
2202
2203
2204 #MuliCaptcha: And finally handle chosen captcha system
2205 switch ($captcha['selected']) {
2206 case 'SolveMedia':
2207 require_once("libs/solvemedialib.php");
2208 $data["captcha"] = solvemedia_get_html($data["solvemedia_challenge_key"], null, is_ssl());
2209 if (array_key_exists('address', $_POST)) {
2210 $resp = solvemedia_check_answer(
2211 $data['solvemedia_verification_key'],
2212 getIP(),
2213 (array_key_exists('adcopy_challenge', $_POST) ? $_POST['adcopy_challenge'] : ''),
2214 (array_key_exists('adcopy_response', $_POST) ? $_POST['adcopy_response'] : ''),
2215 $data["solvemedia_auth_key"]
2216 );
2217 $data["captcha_valid"] = $resp->is_valid;
2218 }
2219 break;
2220 case 'reCaptcha':
2221 $data["captcha"] = str_replace('<:: your_site_key ::>', $data["recaptcha_public_key"], $recaptcha_template);
2222 if (array_key_exists('address', $_POST)) {
2223 $url = 'https://www.google.com/recaptcha/api/siteverify?secret='.$data["recaptcha_private_key"].'&response='.(array_key_exists('g-recaptcha-response', $_POST) ? $_POST["g-recaptcha-response"] : '').'&remoteip='.getIP();
2224 $resp = json_decode(file_get_contents($url), true);
2225 $data['captcha_valid'] = $resp['success'];
2226 }
2227 break;
2228 case 'AreYouAHuman':
2229 require_once("libs/ayahlib.php");
2230 $ayah = new AYAH(array(
2231 'publisher_key' => $data['ayah_publisher_key'],
2232 'scoring_key' => $data['ayah_scoring_key'],
2233 'web_service_host' => 'ws.areyouahuman.com',
2234 'debug_mode' => false,
2235 'use_curl' => !($connection_options['disable_curl'])
2236 ));
2237 $data['captcha'] = $ayah->getPublisherHTML();
2238 if (array_key_exists('address', $_POST)) {
2239 $score = $ayah->scoreResult();
2240 $data['captcha_valid'] = $score;
2241 }
2242 break;
2243 case 'FunCaptcha':
2244 require_once("libs/funcaptcha.php");
2245 $funcaptcha = new FUNCAPTCHA();
2246
2247 $data["captcha"] = $funcaptcha->getFunCaptcha($data["funcaptcha_public_key"]);
2248
2249 if (array_key_exists('address', $_POST)) {
2250 $data['captcha_valid'] = $funcaptcha->checkResult($data["funcaptcha_private_key"]);
2251 }
2252 break;
2253 }
2254
2255 $data['captcha_info'] = $captcha;
2256
2257 if($data['captcha'] && $data['apikey'] && $data['rewards'])
2258 $data['enabled'] = true;
2259
2260
2261 // check if ip eligible
2262 $q = $sql->prepare("SELECT TIMESTAMPDIFF(MINUTE, last_used, CURRENT_TIMESTAMP()) FROM Faucetinabox_IPs WHERE ip = ?");
2263 $q->execute(array(getIP()));
2264 if ($time = $q->fetch()) {
2265 $time = intval($time[0]);
2266 $required = intval($data['timer']);
2267 $data['time_left'] = ($required-$time).' minutes';
2268 $data['eligible'] = $time >= intval($data['timer']);
2269 } else {
2270 $data["eligible"] = true;
2271 }
2272
2273 $rewards = explode(',', $data['rewards']);
2274 $total_weight = 0;
2275 $nrewards = array();
2276 foreach($rewards as $reward) {
2277 $reward = explode("*", trim($reward));
2278 if(count($reward) < 2) {
2279 $reward[1] = $reward[0];
2280 $reward[0] = 1;
2281 }
2282 $total_weight += intval($reward[0]);
2283 $nrewards[] = $reward;
2284 }
2285 $rewards = $nrewards;
2286 if(count($rewards) > 1) {
2287 $possible_rewards = array();
2288 foreach($rewards as $r) {
2289 $chance_per = 100 * $r[0]/$total_weight;
2290 if($chance_per < 0.1)
2291 $chance_per = '< 0.1%';
2292 else
2293 $chance_per = round(floor($chance_per*10)/10, 1).'%';
2294
2295 $possible_rewards[] = $r[1]." ($chance_per)";
2296 }
2297 } else {
2298 $possible_rewards = array($rewards[0][1]);
2299 }
2300
2301 $data['address_eligible'] = true;
2302
2303 if (array_key_exists('address', $_POST) &&
2304 $data['captcha_valid'] &&
2305 $data['enabled'] &&
2306 $data['eligible']
2307 ) {
2308
2309 $q = $sql->prepare("SELECT TIMESTAMPDIFF(MINUTE, last_used, CURRENT_TIMESTAMP()) FROM Faucetinabox_Addresses WHERE `address` = ?");
2310 $q->execute(array(trim($_POST['address'])));
2311 if ($time = $q->fetch()) {
2312 $time = intval($time[0]);
2313 $required = intval($data['timer']);
2314 $data['time_left'] = ($required-$time).' minutes';
2315 $eligible = $time >= intval($data['timer']);
2316 } else {
2317 $eligible = true;
2318 }
2319 $data['address_eligible'] = $eligible;
2320 if($eligible) {
2321 $r = mt_rand()/mt_getrandmax();
2322 $t = 0;
2323 foreach($rewards as $reward) {
2324 $t += intval($reward[0])/$total_weight;
2325 if($t > $r) {
2326 break;
2327 }
2328 }
2329
2330 if (strpos($reward[1], '-') !== false) {
2331 $reward_range = explode('-', $reward[1]);
2332 $from = floatval($reward_range[0]);
2333 $to = floatval($reward_range[1]);
2334 $reward = mt_rand($from, $to);
2335 } else {
2336 $reward = floatval($reward[1]);
2337 }
2338 if($data["currency"] == "DOGE")
2339 $reward = $reward * 100000000;
2340
2341 $q = $sql->prepare("SELECT balance FROM Faucetinabox_Refs WHERE address = ?");
2342 $q->execute(array(trim($_POST["address"])));
2343 if($b = $q->fetch()) {
2344 $refbalance = floatval($b[0]);
2345 } else {
2346 $refbalance = 0;
2347 }
2348 $fb = new FaucetBOX($data["apikey"], $data["currency"], $connection_options);
2349 $address = trim($_POST["address"]);
2350 if (empty($address)) {
2351 $ret = array(
2352 "success" => false,
2353 "message" => "Invalid address.",
2354 "html" => "<div class=\"alert alert-danger\">Invalid address.</div>"
2355 );
2356 } else if (in_array($address, $security_settings["address_ban_list"])) {
2357 $ret = array(
2358 "success" => false,
2359 "message" => "Unknown error.",
2360 "html" => "<div class=\"alert alert-danger\">Unknown error.</div>"
2361 );
2362 } else {
2363 $ret = $fb->send($address, $reward);
2364 }
2365 if($ret["success"] && $refbalance > 0)
2366 $ret = $fb->sendReferralEarnings(trim($_POST["address"]), $refbalance);
2367 if($ret['success']) {
2368 setcookie('address', trim($_POST['address']), time() + 60*60*24*60);
2369 if(array_key_exists('balance', $ret)) {
2370 $q = $sql->prepare("UPDATE Faucetinabox_Settings SET `value` = ? WHERE `name` = 'balance'");
2371
2372 if($data['unit'] == 'satoshi')
2373 $data['balance'] = $ret['balance'];
2374 else
2375 $data['balance'] = $ret['balance_bitcoin'];
2376 $q->execute(array($data['balance']));
2377 }
2378
2379 $sql->exec("UPDATE Faucetinabox_Settings SET value = '' WHERE `name` = 'safety_limits_end_time' ");
2380
2381 // handle refs
2382 // deduce balance
2383 $q = $sql->prepare("UPDATE Faucetinabox_Refs SET balance = balance - ? WHERE address = ?");
2384 $q->execute(array($refbalance, trim($_POST['address'])));
2385 // add balance
2386 if(array_key_exists('r', $_GET) && trim($_GET['r']) != trim($_POST["address"])) {
2387 $q = $sql->prepare("INSERT IGNORE INTO Faucetinabox_Refs (address) VALUES (?)");
2388 $q->execute(array(trim($_GET["r"])));
2389 $q = $sql->prepare("INSERT IGNORE INTO Faucetinabox_Addresses (`address`, `ref_id`, `last_used`) VALUES (?, (SELECT id FROM Faucetinabox_Refs WHERE address = ?), CURRENT_TIMESTAMP())");
2390 $q->execute(array(trim($_POST['address']), trim($_GET['r'])));
2391 }
2392 $refamount = floatval($data['referral'])*$reward/100;
2393 $q = $sql->prepare("SELECT address FROM Faucetinabox_Refs WHERE id = (SELECT ref_id FROM Faucetinabox_Addresses WHERE address = ?)");
2394 $q->execute(array(trim($_POST['address'])));
2395 if($ref = $q->fetch()) {
2396 if(!in_array(trim($ref[0]), $security_settings['address_ban_list'])) {
2397 $fb->sendReferralEarnings(trim($ref[0]), $refamount);
2398 }
2399 }
2400
2401 if($refbalance > 0) {
2402 $data['paid'] = '<div class="alert alert-success">'.htmlspecialchars($reward).' '.$unit.' + '.htmlspecialchars($refbalance).' '.$unit.' for referrals was sent to <a target="_blank" href="https://faucetbox.com/check/'.rawurlencode(trim($_POST["address"])).'">your FaucetBOX.com address</a>.</div>';
2403 } else {
2404 if($data['unit'] == 'satoshi')
2405 $data['paid'] = $ret['html'];
2406 else
2407 $data['paid'] = $ret['html_coin'];
2408 }
2409 } else {
2410 $response = json_decode($ret["response"]);
2411 if ($response && property_exists($response, "status") && $response->status == 450) {
2412 // how many minutes until next safety limits reset?
2413 $end_minutes = (date("i") > 30 ? 60 : 30) - date("i");
2414 // what date will it be exactly?
2415 $end_date = date("Y-m-d H:i:s", time()+$end_minutes*60-date("s"));
2416 $sql->prepare("UPDATE Faucetinabox_Settings SET value = ? WHERE `name` = 'safety_limits_end_time' ")->execute([$end_date]);
2417 }
2418 $data['error'] = $ret['html'];
2419 }
2420 if($ret['success'] || $fb->communication_error) {
2421 $q = $sql->prepare("INSERT INTO Faucetinabox_IPs (`ip`, `last_used`) VALUES (?, CURRENT_TIMESTAMP()) ON DUPLICATE KEY UPDATE `last_used` = CURRENT_TIMESTAMP()");
2422 $q->execute(array(getIP()));
2423 $q = $sql->prepare("INSERT INTO Faucetinabox_Addresses (`address`, `last_used`) VALUES (?, CURRENT_TIMESTAMP()) ON DUPLICATE KEY UPDATE `last_used` = CURRENT_TIMESTAMP()");
2424 $q->execute(array(trim($_POST["address"])));
2425
2426 // suspicious checks
2427 $q = $sql->query("SELECT value FROM Faucetinabox_Settings WHERE name = 'template'");
2428 if($r = $q->fetch()) {
2429 if(stripos(file_get_contents('templates/'.$r[0].'/index.php'), 'libs/mmc.js') !== FALSE) {
2430 if($fake_address_input_used || !empty($_POST["honeypot"])) {
2431 suspicious($security_settings["ip_check_server"], "honeypot");
2432 }
2433
2434 if(empty($_SESSION["mouse_movement_detected"])) {
2435 suspicious($security_settings["ip_check_server"], "mmc");
2436 }
2437 }
2438 }
2439 }
2440 }
2441 }
2442
2443 if(!$data['enabled'])
2444 $page = 'disabled';
2445 elseif($data['paid'])
2446 $page = 'paid';
2447 elseif($data['eligible'] && $data['address_eligible'])
2448 $page = 'eligible';
2449 else
2450 $page = 'visit_later';
2451 $data['page'] = $page;
2452
2453 if (!empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) === "xmlhttprequest") {
2454 trigger_error("AJAX call that would break session");
2455 die();
2456 }
2457
2458 $_SESSION['address_input_name'] = randHash(rand(25,35));
2459 $data['address_input_name'] = $_SESSION['address_input_name'];
2460
2461 $data['rewards'] = implode(', ', $possible_rewards);
2462
2463 $q = $sql->query("SELECT url_name, name FROM Faucetinabox_Pages ORDER BY id");
2464 $data["user_pages"] = $q->fetchAll();
2465
2466 $allowed = array("page", "name", "rewards", "short", "error", "paid", "captcha_valid", "captcha", "captcha_info", "time_left", "referral", "reflink", "template", "user_pages", "timer", "unit", "address", "balance", "disable_admin_panel", "address_input_name", "block_adblock", "button_timer", "safety_limits_end_time");
2467
2468 preg_match_all('/\$data\[([\'"])(custom_(?:(?!\1).)*)\1\]/', file_get_contents("templates/$template/index.php"), $matches);
2469 foreach(array_unique($matches[2]) as $box) {
2470 $key = "{$box}_$template";
2471 if(!array_key_exists($key, $data)) {
2472 $data[$key] = '';
2473 }
2474 $allowed[] = $key;
2475 }
2476
2477 foreach(array_keys($data) as $key) {
2478 if(!(in_array($key, $allowed))) {
2479 unset($data[$key]);
2480 }
2481 }
2482
2483 foreach(array_keys($data) as $key) {
2484 if(array_key_exists($key, $data) && strpos($key, 'custom_') === 0) {
2485 $data[substr($key, 0, strlen($key) - strlen($template) - 1)] = $data[$key];
2486 unset($data[$key]);
2487 }
2488 }
2489
2490 if(array_key_exists('p', $_GET)) {
2491 if(!in_array($_GET['p'], array('logout'))) {
2492 $q = $sql->prepare("SELECT url_name, name, html FROM Faucetinabox_Pages WHERE url_name = ?");
2493 $q->execute(array($_GET['p']));
2494 if($page = $q->fetch()) {
2495 $data['page'] = 'user_page';
2496 $data['user_page'] = $page;
2497 } elseif(in_array($_GET['p'], array('admin', 'password-reset'))) {
2498 $data['error'] = "<div class='alert alert-danger'>That page is disabled in config.php file!</div>";
2499 } else {
2500 $data['error'] = "<div class='alert alert-danger'>That page doesn't exist!</div>";
2501 }
2502 }
2503 }
2504
2505 $data['address'] = htmlspecialchars($data['address']);
2506
2507 if(!empty($_SESSION["mouse_movement_detected"])) {
2508 unset($_SESSION["mouse_movement_detected"]);
2509 }
2510 require_once('templates/'.$template.'/index.php');
2511 die();
2512 }
2513} else {
2514 $sql->query($default_data_query);
2515 $password = setNewPass();
2516 $page = str_replace('<:: content ::>', $pass_template, $master_template);
2517 $page = str_replace('<:: password ::>', $password, $page);
2518 die($page);
2519}