/ xa24tb.php
xa24tb.php
  1  <?php
  2  /*
  3  define('DEV_MODE', $_SERVER['REMOTE_ADDR'] === '51.159.28.165');
  4  
  5  if (!DEV_MODE) {
  6    http_response_code(404);
  7    echo('File not found.');
  8    die();
  9  }
 10  else {
 11    ini_set('display_errors', 1);
 12    error_reporting(E_ALL & ~E_NOTICE);
 13    $mysql_suppress_err = false;
 14  }
 15  */
 16  require_once 'lib/db.php';
 17  require_once 'lib/userpwd.php';
 18  
 19  define('CURRENCY_CODE', '_');
 20  define('STARTING_AMOUNT', 1000);
 21  define('MAX_BUY_SELL_SIZE', 1000);
 22  
 23  const STOCK_LIST = [
 24    'PEPE', 'WOJK', 'ANIME', 'CHAD', 'CLOWN', 'LOL', 'SICP', 'AUTSM', 'BANE',
 25    'CIA', 'BOOB', 'RDDT', 'DESU', 'JANNY', 'GME', 'CHUCK', 'YTSB', 'GACHI'
 26  ];
 27  
 28  function output_json($data) {
 29    header('Content-Type: application/json');
 30    echo json_encode($data);
 31  }
 32  
 33  function output_error($msg) {
 34    output_json(['error' => $msg]);
 35    die();
 36  }
 37  
 38  function create_account() {
 39    $user_ip = $_SERVER['REMOTE_ADDR'];
 40    
 41    if (isset($_COOKIE['4chan_pass'])) {
 42      $userpwd = new UserPwd($user_ip, '4chan.org', $_COOKIE['4chan_pass']);
 43    }
 44    else {
 45      $userpwd = new UserPwd($user_ip, '4chan.org');
 46    }
 47    
 48    $user_id = $userpwd->getPwd();
 49    
 50    $sql = "SELECT id FROM april_stock_users WHERE user_id = '%s' LIMIT 1";
 51    
 52    $res = mysql_global_call($sql, $user_id);
 53    
 54    if (!$res) {
 55      output_error('Internal Server Error (frac1)');
 56    }
 57    
 58    if (mysql_num_rows($res)) {
 59      $account = get_account_balance($user_id);
 60      output_json($account);
 61      die();
 62    }
 63    
 64    $cur_code = CURRENCY_CODE;
 65    $cur_amount = (int)STARTING_AMOUNT;
 66    
 67    $sql =<<<SQL
 68  INSERT INTO april_stock_users (user_id, stock, amount)
 69  VALUES ('%s', '$cur_code', $cur_amount)
 70  SQL;
 71  
 72    $res = mysql_global_call($sql, $user_id);
 73    
 74    if (!$res) {
 75      output_error('Internal Server Error (frac0)');
 76    }
 77    
 78    $userpwd->setCookie('.4chan.org');
 79    
 80    output_json([
 81      'balance' => $cur_amount
 82    ]);
 83  }
 84  
 85  function get_account_balance($user_id) {
 86    $sql = "SELECT stock, SUM(amount) as amount FROM april_stock_users WHERE user_id = '%s' GROUP BY stock";
 87    
 88    $res = mysql_global_call($sql, $user_id);
 89    
 90    $data = [];
 91    
 92    while ($row = mysql_fetch_assoc($res)) {
 93      if ($row['stock'] == CURRENCY_CODE) {
 94        $amount = (int)$row['amount'];
 95        
 96        if ($amount < 0) {
 97          $amount = 0;
 98        }
 99        
100        $data['balance'] = $amount;
101      }
102      else if (in_array($row['stock'], STOCK_LIST)) {
103        $amount = (int)$row['amount'];
104        
105        if ($amount <= 0) {
106          continue;
107        }
108        
109        $data[$row['stock']] = $amount;
110      }
111    }
112    
113    return $data;
114  }
115  
116  function get_account() {
117    $user_ip = $_SERVER['REMOTE_ADDR'];
118    
119    if (!isset($_COOKIE['4chan_pass'])) {
120      output_error('Account not found');
121    }
122    
123    $userpwd = new UserPwd($user_ip, '4chan.org', $_COOKIE['4chan_pass']);
124    
125    if ($userpwd->isNew()) {
126      output_error('Account not found');
127    }
128    
129    $user_id = $userpwd->getPwd();
130    
131    $data = get_account_balance($user_id);
132    
133    return [$user_id, $data];
134  }
135  
136  function get_stock_price($stock) {
137    if ($stock == CURRENCY_CODE) {
138      output_error('Stock not found');
139    }
140    
141    $sql = "SELECT price FROM april_stock_prices WHERE stock = '%s' ORDER BY id DESC LIMIT 1";
142    
143    $res = mysql_global_call($sql, $stock);
144    
145    if (!$res) {
146      return false;
147    }
148    
149    $price = (int)mysql_fetch_row($res)[0];
150    
151    if ($price <= 0) {
152      return false;
153    }
154    
155    return $price;
156  }
157  
158  function get_stock_http_param() {
159    if (!isset($_POST['stock']) || !$_POST['stock'] || $_POST['stock'] == CURRENCY_CODE) {
160      return false;
161    }
162    
163    return $_POST['stock'];
164  }
165  
166  function get_amount_http_param() {
167    if (!isset($_POST['amount']) || !$_POST['amount']) {
168      return false;
169    }
170    
171    $amount = (int)$_POST['amount'];
172    
173    if ($amount < 1 || $amount > MAX_BUY_SELL_SIZE) {
174      return false;
175    }
176    
177    return $amount;
178  }
179  
180  function get_price_http_param() {
181    if (!isset($_POST['price']) || !$_POST['price']) {
182      return false;
183    }
184    
185    $price = (int)$_POST['price'];
186    
187    if ($price < 1) {
188      return false;
189    }
190    
191    return $price;
192  }
193  
194  function enforce_cooldown($user_id) {
195    $sql =<<<SQL
196  SELECT id FROM april_stock_users WHERE user_id = '%s'
197  AND created_on > DATE_SUB(NOW(), INTERVAL 10 SECOND)
198  SQL;
199    
200    $res = mysql_global_call($sql, $user_id);
201    
202    if (!$res) {
203      return true;
204    }
205    
206    if (mysql_num_rows($res)) {
207      output_error('You can only make an order once every 10 seconds');
208    }
209    
210    return false;
211  }
212  
213  /**
214   * BUY
215   */
216  
217  function buy_stock() {
218    $stock = get_stock_http_param();
219    
220    if (!$stock) {
221      output_error('Stock not found');
222    }
223    
224    $amount = get_amount_http_param();
225    
226    if (!$amount) {
227      output_error('Invalid amount');
228    }
229    
230    $user_price = get_price_http_param();
231    
232    if (!$user_price) {
233      output_error('Invalid price');
234    }
235    
236    $price = get_stock_price($stock);
237    
238    if (!$price) {
239      output_error('Invalid price');
240    }
241    
242    if ($user_price != $price) {
243      output_error('The price has changed.');
244    }
245    
246    $total_price = $amount * $price;
247    
248    list($user_id, $account) = get_account();
249    
250    if ($total_price > $account['balance']) {
251      output_error('Your account balance is too low');
252    }
253    
254    enforce_cooldown($user_id);
255    
256    // Decrement balance
257    $cur_code = CURRENCY_CODE;
258    
259    $sql =<<<SQL
260  INSERT INTO april_stock_users (user_id, stock, amount)
261  VALUES ('%s', '$cur_code', -$total_price)
262  SQL;
263    
264    $res = mysql_global_call($sql, $user_id);
265    
266    if (!$res) {
267      output_error('Internal Server Error (bi05-2)');
268    }
269    
270    // Increment the stock amount
271    $sql =<<<SQL
272  INSERT INTO april_stock_users (user_id, stock, amount)
273  VALUES ('%s', '%s', $amount)
274  SQL;
275    
276    $res = mysql_global_call($sql, $user_id, $stock);
277    
278    if (!$res) {
279      output_error('Internal Server Error (bi05-2)');
280    }
281    
282    $account = get_account_balance($user_id);
283    
284    output_json($account);
285  }
286  
287  /**
288   * SELL
289   */
290  function sell_stock() {
291    $stock = get_stock_http_param();
292    
293    if (!$stock) {
294      output_error('Stock not found');
295    }
296    
297    $amount = get_amount_http_param();
298    
299    if (!$amount) {
300      output_error('Invalid amount');
301    }
302    
303    $user_price = get_price_http_param();
304    
305    if (!$user_price) {
306      output_error('Invalid price');
307    }
308    
309    $price = get_stock_price($stock);
310    
311    if (!$price) {
312      output_error('Invalid price');
313    }
314    
315    if ($user_price != $price) {
316      output_error('The price has changed.');
317    }
318    
319    $total_price = $amount * $price;
320    
321    list($user_id, $account) = get_account();
322    
323    if ($amount > $account[$stock]) {
324      output_error('Your account balance is too low');
325    }
326    
327    // Cooldown
328    enforce_cooldown($user_id);
329    
330    // Decrement the stock amount
331    $sql =<<<SQL
332  INSERT INTO april_stock_users (user_id, stock, amount)
333  VALUES ('%s', '%s', -$amount)
334  SQL;
335    
336    $res = mysql_global_call($sql, $user_id, $stock);
337    
338    if (!$res) {
339      output_error('Internal Server Error (bi05-2)');
340    }
341    
342    // Increment balance
343    $cur_code = CURRENCY_CODE;
344    
345    $sql =<<<SQL
346  INSERT INTO april_stock_users (user_id, stock, amount)
347  VALUES ('%s', '$cur_code', $total_price)
348  SQL;
349    
350    $res = mysql_global_call($sql, $user_id);
351    
352    if (!$res) {
353      output_error('Internal Server Error (bi05-2)');
354    }
355    
356    $account_balance = get_account_balance($user_id);
357    
358    output_json($account_balance);
359  }
360  
361  output_error('The market is closed');
362  
363  if (isset($_POST['create'])) {
364    create_account();
365  }
366  else if (isset($_POST['mode'])) {
367    if ($_POST['mode'] === 'buy') {
368      buy_stock();
369    }
370    else if ($_POST['mode'] === 'sell') {
371      sell_stock();
372    }
373    else {
374      output_error('Bad request');
375    }
376  }
377  else {
378    output_error('Bad request');
379  }