Dark background for QR files
[stouyapi.git] / www / push-to-my-ouya.php
1 <?php
2 /**
3  * Click "push to my OUYA" in the browser, and the OUYA will install
4  * the game a few minutes later.
5  *
6  * Works without registration.
7  * We simply use the IP address as user identification.
8  * Pushed games are deleted after 24 hours.
9  * Maximal 30 games per IP to prevent flooding.
10  *
11  * @author Christian Weiske <cweiske@cweiske.de>
12  * @see    api/v1/queued_downloads.php
13  * @see    api/v1/queued_downloads_delete.php
14  */
15 $dbFile     = __DIR__ . '/../data/push-to-my-ouya.sqlite3';
16 $apiGameDir = __DIR__ . '/api/v1/details-data/';
17
18 require_once __DIR__ . '/../src/push-to-my-ouya-helpers.php';
19
20 //support different ipv4-only domain
21 header('Access-Control-Allow-Origin: *');
22
23 if ($_SERVER['REQUEST_METHOD'] != 'POST') {
24     header('HTTP/1.0 400 Bad Request');
25     header('Content-type: text/plain');
26     echo 'POST only, please' . "\n";
27     exit(1);
28 }
29
30 if (!isset($_GET['game'])) {
31     header('HTTP/1.0 400 Bad Request');
32     header('Content-type: text/plain');
33     echo '"game" parameter missing' . "\n";
34     exit(1);
35 }
36
37 $game = $_GET['game'];
38 $cleanGame = preg_replace('#[^a-zA-Z0-9._]#', '', $game);
39 if ($game != $cleanGame) {
40     header('HTTP/1.0 400 Bad Request');
41     header('Content-type: text/plain');
42     echo 'Invalid game' . "\n";
43     exit(1);
44 }
45
46 $apiGameFile = $apiGameDir . $game . '.json';
47 if (!file_exists($apiGameFile)) {
48     header('HTTP/1.0 404 Not Found');
49     header('Content-type: text/plain');
50     echo 'Game does not exist' . "\n";
51     exit(1);
52 }
53
54 $ip = $_SERVER['REMOTE_ADDR'];
55 if ($ip == '') {
56     header('HTTP/1.0 400 Bad Request');
57     header('Content-type: text/plain');
58     echo 'Cannot detect your IP address' . "\n";
59     exit(1);
60 }
61 $ip = mapIp($ip);
62
63 try {
64     $db = new SQLite3($dbFile, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
65 } catch (Exception $e) {
66     header('HTTP/1.0 500 Internal server error');
67     header('Content-type: text/plain');
68     echo 'Cannot open database' . "\n";
69     echo $e->getMessage() . "\n";
70     exit(2);
71 }
72
73 $res = $db->querySingle(
74     'SELECT name FROM sqlite_master WHERE type = "table" AND name = "pushes"'
75 );
76 if ($res === null) {
77     //table does not exist yet
78     $db->exec(
79         <<<SQL
80         CREATE TABLE pushes (
81             id INTEGER PRIMARY KEY AUTOINCREMENT,
82             game TEXT NOT NULL,
83             ip TEXT NOT NULL,
84             created_at TEXT DEFAULT CURRENT_TIMESTAMP
85         )
86 SQL
87     );
88 }
89
90 //clean up old pushes
91 $db->exec(
92     'DELETE FROM pushes'
93     . ' WHERE created_at < \'' . gmdate('Y-m-d H:i:s', time() - 86400) . '\''
94 );
95
96 //check if this IP already pushed this game
97 $numThisGame = $db->querySingle(
98     'SELECT COUNT(*) FROM pushes'
99     . ' WHERE ip = \'' . SQLite3::escapeString($ip) . '\''
100     . ' AND game = \'' . SQLite3::escapeString($game) . '\''
101 );
102 if ($numThisGame >= 1) {
103     header('HTTP/1.0 400 Bad Request');
104     header('Content-type: text/plain');
105     echo 'Already pushed.' . "\n";
106     exit(1);
107 }
108
109 //check number of pushes for this IP
110 $numPushes = $db->querySingle(
111     'SELECT COUNT(*) FROM pushes'
112     . ' WHERE ip = \'' . SQLite3::escapeString($ip) . '\''
113 );
114 if ($numPushes >= 30) {
115     header('HTTP/1.0 400 Bad Request');
116     header('Content-type: text/plain');
117     echo 'Too many pushes. Come back tomorrow.' . "\n";
118     exit(1);
119 }
120
121 //store the push
122 $stmt = $db->prepare('INSERT INTO pushes (game, ip) VALUES(:game, :ip)');
123 $stmt->bindValue(':game', $game);
124 $stmt->bindValue(':ip', $ip);
125 $res = $stmt->execute();
126 if ($res === false) {
127     header('HTTP/1.0 500 Internal server error');
128     header('Content-type: text/plain');
129     echo 'Cannot store push' . "\n";
130     exit(3);
131 }
132 $res->finalize();
133
134 header('HTTP/1.0 200 OK');
135 header('Content-type: text/plain');
136 echo 'Push accepted' . "\n";
137 exit(3);
138 ?>