null, 'name' => null, 'mail' => null, 'type' => null, 'key' => null, ), $_REQUEST ); $database = new PDO('sqlite:' . __DIR__ . '/../newsletter.db'); $database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); switch ($_REQUEST['action']) { case 'subscribe': if (isset($_REQUEST['url']) && !empty($_REQUEST['url'])) { goto failure; } $model->name = $_REQUEST['name']; $model->mail = $_REQUEST['mail']; $model->type = $_REQUEST['type']; $model->state = 'new'; $model->key = md5(microtime()); $model->changed = time(); file_put_contents( __DIR__ . '/../newsletter.log', sprintf( '[%s] %s registered %s (%s) (book)' . PHP_EOL, date('r'), $_SERVER['REMOTE_ADDR'], $model->mail, $model->type ), FILE_APPEND ); $insertStatement = $database->prepare( 'INSERT INTO newsletter (name, mail, type, state, key, changed) VALUES (:name, :mail, :type, :state, :key, :changed);' ); $insertStatement->bindValue(':name', $model->name); $insertStatement->bindValue(':mail', $model->mail); $insertStatement->bindValue(':type', $model->type); $insertStatement->bindValue(':state', $model->state); $insertStatement->bindValue(':key', $model->key); $insertStatement->bindValue(':changed', $model->changed); try { $insertStatement->execute(); } catch (\Exception $e) { // Ignore if already subscribed to newsletter } $insertStatement = $database->prepare( 'INSERT INTO book (name, mail, downloads, key, changed) VALUES (:name, :mail, :downloads, :key, :changed);' ); $insertStatement->bindValue(':name', $model->name); $insertStatement->bindValue(':mail', $model->mail); $insertStatement->bindValue(':downloads', $model->downloads); $insertStatement->bindValue(':key', $model->key); $insertStatement->bindValue(':changed', $model->changed); try { $insertStatement->execute(); } catch (\Exception $e) { goto failure; } header('Location: /book/registered.html'); $encodedMail = urlencode($model->mail); mail( $model->mail, "Download the book now", "Hi {$model->name}, You can now download \"Crafting Quality Software\" here: https://qafoo.com/book.php?action=confirm&mail={$encodedMail}&key={$model->key} Cheers, Qafoo", "From: Qafoo \r\n" ); exit(); case 'confirm': $model->mail = $_REQUEST['mail']; $model->state = 'confirmed'; $model->key = $_REQUEST['key']; $model->changed = time(); $selectStatement = $database->prepare( 'SELECT state FROM newsletter WHERE mail = :mail' ); $selectStatement->bindValue(':mail', $model->mail); $selectStatement->execute(); if (!count($rows = $selectStatement->fetchAll(PDO::FETCH_ASSOC))) { goto failure; } elseif ($rows[0]['state'] === 'new') { $updateStatement = $database->prepare( 'UPDATE newsletter SET state = :state, changed = :changed WHERE mail = :mail' ); $updateStatement->bindValue(':mail', $model->mail); $updateStatement->bindValue(':state', $model->state); $updateStatement->bindValue(':changed', $model->changed); $updateStatement->execute(); sendToCow(sprintf( " \x0314[book] %s confirmed their newsletter registration through book registration.\x03", $model->mail )); } header('Location: /book/download.html?key=' . $model->key); exit(); case 'download': $model->key = $_REQUEST['key']; $model->changed = time(); $selectStatement = $database->prepare( 'SELECT name, mail, downloads FROM book WHERE key = :key' ); $selectStatement->bindValue(':key', $_REQUEST['key']); $selectStatement->execute(); if (!count($rows = $selectStatement->fetchAll(PDO::FETCH_ASSOC))) { header('Location: /book/invalid.html'); exit(); } $row = reset($rows); $model->name = $row['name']; $model->mail = $row['mail']; $model->downloads = $row['downloads']; if ($model->downloads > 6) { header('Location: /book/exceeded.html'); sendToCow(sprintf( " [book] \x02Warning:\x02 %s <%s> exceeded their download limit.", $model->name, $model->mail )); exit(); } $updateStatement = $database->prepare( 'UPDATE book SET downloads = :downloads, changed = :changed WHERE mail = :mail' ); $updateStatement->bindValue(':mail', $model->mail); $updateStatement->bindValue(':downloads', $model->downloads + 1); $updateStatement->bindValue(':changed', $model->changed); $updateStatement->execute(); if ($_REQUEST['type'] === 'epub') { header('Content-Type: application/epub+zip'); header('Content-Disposition: attachment; filename=crafting_quality_software.epub'); readfile(__DIR__ . '/../content/book-download.epub'); } else { header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename=crafting_quality_software.pdf'); readfile(__DIR__ . '/../content/book-download.pdf'); } sendToCow(sprintf( " \x0314[book] %s <%s> downloaded the {$_REQUEST['type']} version of the book.\x03", $model->name, $model->mail )); exit(); } failure: header('Location: /book/register.html');