Egre

Fauzan

May 24th, 2016
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 112.80 KB | None | 0 0
  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.  
  29. if (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.  
  45. if(stripos($_SERVER['REQUEST_URI'], '@') !== FALSE ||
  46. stripos(urldecode($_SERVER['REQUEST_URI']), '@') !== FALSE) {
  47. header("Location: ."); die('Please wait...');
  48. }
  49.  
  50. session_start();
  51. header('Content-Type: text/html; charset=utf-8');
  52. ini_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;
  61. require_once("config.php");
  62. if(!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.  
  71. if(!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. }
  79. if(!isset($connection_options['verify_peer'])) {
  80. $connection_options['verify_peer'] = $verify_peer;
  81. }
  82.  
  83. if (!isset($display_errors)) $display_errors = false;
  84. ini_set('display_errors', $display_errors);
  85. if($display_errors)
  86. error_reporting(-1);
  87.  
  88.  
  89. if(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);
  96. if($_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.  
  107. require_once('libs/faucetbox.php');
  108.  
  109. try {
  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>&lt;head&gt;</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
  149. create table if not exists Faucetinabox_Settings (
  150. `name` varchar(64) not null,
  151. `value` text not null,
  152. primary key(`name`)
  153. );
  154. create table if not exists Faucetinabox_IPs (
  155. `ip` varchar(20) not null,
  156. `last_used` timestamp not null,
  157. primary key(`ip`)
  158. );
  159. create 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. );
  165. create 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. );
  171. create 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.  
  179. INSERT 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. ;
  225. QUERY;
  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>
  306. TEMPLATE;
  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:
  560. 127.0.0.0/8
  561. 172.16.0.1
  562. 192.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:
  567. proxy
  568. compute.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:
  573. 1HmUrGAf4Bz9KMX6Pg67RA2VZgWVPnpyvS
  574. 13q29zfcesTiZoed1BNFr3VYr4zBGfuwW4"><:: 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.  
  888. var 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>
  1155. TEMPLATE;
  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">&times;</span><span class="sr-only">Close</span></button>
  1169. Don't remember? <a href="?p=password-reset">Reset your password</a>.
  1170. </div>
  1171. TEMPLATE;
  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>
  1177. TEMPLATE;
  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>
  1184. TEMPLATE;
  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>
  1190. TEMPLATE;
  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>
  1203. TEMPLATE;
  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>
  1209. TEMPLATE;
  1210.  
  1211. $oneclick_update_button_template = <<<TEMPLATE
  1212. or
  1213. <input type="hidden" name="task" value="oneclick-update">
  1214. <input type="submit" class="btn btn-primary" value="Update automatically">
  1215. TEMPLATE;
  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">&times;</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>
  1239. TEMPLATE;
  1240.  
  1241. $page_nav_template = <<<TEMPLATE
  1242. <li><a href="#page-wrap-<:: i ::>" role="tab" data-toggle="tab">Page <:: i ::></a></li>
  1243. TEMPLATE;
  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>
  1257. TEMPLATE;
  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>
  1264. TEMPLATE;
  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>
  1271. TEMPLATE;
  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>
  1278. TEMPLATE;
  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>
  1285. TEMPLATE;
  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>
  1295. TEMPLATE;
  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>
  1299. TEMPLATE;
  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>
  1303. TEMPLATE;
  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>
  1307. TEMPLATE;
  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>
  1311. TEMPLATE;
  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>
  1316. TEMPLATE;
  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>
  1321. TEMPLATE;
  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>
  1329. TEMPLATE;
  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>
  1338. TEMPLATE;
  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>
  1346. TEMPLATE;
  1347.  
  1348. $template_update_template = <<<TEMPLATE
  1349. <hr>
  1350. <ul>
  1351. <li><:: message ::></li>
  1352. </ul>
  1353. TEMPLATE;
  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>
  1381. TEMPLATE;
  1382.  
  1383. function 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.  
  1401. function 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.  
  1412. function 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
  1422. try {
  1423. $pass = $sql->query("SELECT `value` FROM `Faucetinabox_Settings` WHERE `name` = 'password'")->fetch();
  1424. } catch(PDOException $e) {
  1425. $pass = null;
  1426. }
  1427.  
  1428. function 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.  
  1433. function 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.  
  1443. function 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.  
  1471. function 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.  
  1488. function 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.  
  1506. function banned() {
  1507. trigger_error("Banned: ".getIP());
  1508. http_response_code(500);
  1509. die();
  1510. }
  1511.  
  1512. function suspicious($server, $comment) {
  1513. if($server) {
  1514. @file_get_contents($server."report/1/".urlencode(getIP())."/".urlencode($comment));
  1515. }
  1516. }
  1517.  
  1518.  
  1519. if($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. }
Add Comment
Please, Sign In to add comment