function do_order () { global $scanner, $dep, $db; # Get context position. $table = $scanner->context_table; $id = $scanner->context['id']; $scanner->push_context (); # Send order. $from =& cms_fetch_object ('d_order_address'); if (!$from) panic ('No order address specified.'); $template =& cms_fetch_object ('l_order_email'); if (!$template) panic ('No order template specified.'); $tree =& $scanner->scan ($template); $body = $scanner->exec ($tree, $table, $id); mail ($from, $_SERVER['SERVER_NAME'] . " - e-shop", htmllig2latin ($body)); # TODO subject attribute # Send confirmation. $subject =& cms_fetch_object ('d_order_email_subject'); if (!$subject) panic ('No order email subject.'); $to = dirtag_order_shipto (array ('field' => 'email')); $template =& cms_fetch_object ('l_order_confirm'); if (!$template) panic ('No order confirmation template.'); $tree =& $scanner->scan ($template); $body = $scanner->exec ($tree, $table, $id); mail ($to, $subject, htmllig2latin ($body), "From: $from\nReply-To: $from"); $scanner->pop_context (); }
function requirePostNonEmptyOrPanic($vars) { global $_POST; for ($i = 0; $i < count($vars); $i++) { if (!isset($_POST[$vars[$i]]) || strlen($_POST[$vars[$i]]) == 0) { panic("(POST) Empty arguments, {$vars[$i]}"); } } }
function play_card($col) { global $bot; global $req; global $row; // Remove the card that the bot just played from its hand. $res = pg_query_params('UPDATE bots SET cards=array_remove(cards, $1) WHERE id=$2;', [$req["card"], $bot["id"]]); if ($res === FALSE || pg_affected_rows($res) !== 1) { panic("Failed to remove the card '{$req['card']}' from the bot's hand which consists of '{$bot['cards']}'."); } pg_free_result($res); // Play the card in the round. $res = pg_query_params('UPDATE rounds SET ' . $col . '=$1 WHERE game=$2 AND round=$3;', [$req["card"], $bot["game"], $row["round"]]); if ($res === FALSE || pg_affected_rows($res) !== 1) { panic("Failed to play the card '{$req['card']}' in game '{$bot['game']}' round '{$row['round']}'."); } pg_free_result($res); // Add the card to our local copy of the row. $row[$col] = $req["card"]; }
<?php require "lib.php"; $username = g('usernameReg'); $password = g("passReg"); $email = g("email"); if (g("passReg", "") != g("repassReg", "")) { panic("Some var is emtpy or pass != repass after javascript test"); } if (strlen($password) < 5) { panic("Pass is shorter than 5 chars after javascript test"); } $r = redisLink(); if ($r->get("username:{$username}:id")) { panic("Username already in use"); } # Everything is ok, Register the user! $userid = $r->incr("global:nextUserId"); $r->set("username:{$username}:id", $userid); $r->set("uid:{$userid}:username", $username); $r->set("uid:{$userid}:hashpass", bcrypt_hash($password)); $r->set("uid:{$userid}:email", $email); $r->set("uid:{$userid}:regtime", time()); $r->set("uid:{$userid}:excludemyvisits", '0'); $authsecret = getrand(); $r->set("uid:{$userid}:auth", $authsecret); $r->set("auth:{$authsecret}", $userid); # Manage a Set with all the users, may be userful in the future $r->sadd("global:users", $userid); # User registered! Login this guy $now = time() + 3600 * 24 * 365;
function wiki($wiki, $article) { global $dataSource; global $_CONFIG; global $_EXTRAS; $out = ''; //if ($_CONFIG['oneWiki']){ $base = $_CONFIG['base']; $url = $_CONFIG['base'] . "/{$article}"; //} else { // $base = $_CONFIG['base']."/".$wiki; // $url = $_CONFIG['base']."/$wiki/$article"; //} $content = array($wiki, $article, "", "aqWiki (Admin)", date("r")); if (!isset($_GET['action'])) { $_GET['action'] = false; } switch ($_GET['action']) { case "viewrev": if (!$_GET['id']) { panic("View Revision", "Parameters incorrect"); } $id = $_GET['id']; $pages = $dataSource->getPage($article); debug("Found " . count($pages) . " pages"); $row = $pages[$id]; $content[2] = '<div class="info"><b>Note:</b> This is a <i>specific revision</i> of this page, and may be outdated, The current version is ((here|' . $article . ')). You can see the differences between this and the current revision <a href="' . $url . '?action=diff&from=' . $id . '">here</a></div>'; if (in_array($_EXTRAS['me'], $_EXTRAS['admins'])) { $content[2] .= '<div class="adminFunctions">Admin Actions: <a href="' . $url . '?action=revert&id=' . $id . '">Revert back to this version</a> </div>'; } $content[2] .= $row['content']; #."\n\n [ \"Edit This Page\":$url?action=edit | \"View Source\":$url?action=src ]"; $content[3] = $row['creator']; $content[4] = date("r", $row['created']); $limit = 3; $current = 0; $_EXTRAS['versions'] = ''; foreach ($pages as $row) { $line = date("r", $row['created']) . " - \"" . $row['creator'] . "\":{$base}/~" . $row['creator']; if ($row['comment']) { $line .= " : " . $row['comment']; } if ($row['revision'] == $id) { $_EXTRAS['versions'] .= "# " . $line . " [ Current ]\n"; } else { $_EXTRAS['versions'] .= "# " . $line . " [ <a href=\"" . $url . "?action=viewrev&id=" . $row['revision'] . "\" title=\"View this revision\">View</a> |" . " <a href=\"" . $url . "?action=diff&from=" . $id . "&to=" . $row['revision'] . "\"\" title=\"View differences between this and the current revision\">Diff</a> ]\n"; } $current++; if ($id < $row['revision']) { // Nothing happens } elseif ($current >= $limit && $_GET['action'] != "allrev") { if ($id == $row['revision']) { $limit += 6; } else { $_EXTRAS['versions'] .= "# \"Show rest of revisions\":" . $url . "?action=allrev\n"; break; } } } $content[2] .= $out; break; case "diff": $content[2] = "These are the differences between two versions of (({$article})). Lines styled <span class=\"added\">" . "like this</span> have been added to the entry, lines <span class=\"removed\">like this</span> have been removed.\n\n"; $from = isset($_GET['from']) ? $_GET['from'] : false; $to = isset($_GET['to']) ? $_GET['to'] : false; $_EXTRAS['textarea'] = $dataSource->diff($article, $from, $to); $content[2] .= "[[TEXTAREA]]"; break; case "newUser": /*mysql> describe users; +---------------+------------------+-------------------+ | Field | Type | Collation | +---------------+------------------+-------------------+ | id | int(10) unsigned | binary | | username | varchar(64) | latin1_swedish_ci | | real_name | tinytext | latin1_swedish_ci | | email | tinytext | latin1_swedish_ci | | birthday | date | latin1_swedish_ci | | password | tinytext | latin1_swedish_ci | | location | int(11) | binary | | last_access | timestamp | latin1_swedish_ci | | date_creation | timestamp | latin1_swedish_ci | | access_level | int(11) | binary | +---------------+------------------+-------------------+ 10 rows in set (0.05 sec) */ $form = '<form class="shiny" method=post action="' . $_SERVER['REQUEST_URI'] . '"><h2>New User</h2>' . "\n\n" . '|Username|<input type="text" name="username" value="' . $_POST['username'] . '">|(Must not be blank)|' . "\n" . '|Display Name|<input type="text" name="name" value="' . $_POST['name'] . '">|(Must not be blank)<br>|' . "\n" . '|e-Mail|<input type="text" name="email" value="' . $_POST['email'] . '">|(Must not be blank)<br>|' . "\n" . '|Password|<input type="password" name="password">|(Must not be blank)<br>|' . "\n" . '|Repeat Password |<input type="password" name="password2">| (Must match above) |' . "\n\n"; if (isset($_CONFIG['recaptcha_public_key'])) { require_once 'recaptchalib.php'; $public_key = $_CONFIG['recaptcha_public_key']; $form .= '<aqWikiNoProcess>' . recaptcha_get_html($public_key) . "</aqWikiNoProcess>\n\n"; } $form .= '<input type="submit" name="submit" value="Create User">' . "\n\n" . '</form>'; #print_r($_POST); if ($_POST['submit']) { $errors = array(); if ($_POST['username'] == "") { $errors[] = "Username cannot be blank"; } elseif (strstr($_POST['username'], ",")) { $errors[] = "Username cannot contain commas"; } elseif (isset($_EXTRAS['reservedUsers']) && in_array($_POST['username'], $_EXTRAS['reservedUsers'])) { $errors[] = "Username invalid"; } elseif (!$dataSource->unique("users", "username", $_POST['username'])) { $errors[] = "Username must be unique"; } if ($_POST['email'] == "") { $errors[] = "email cannot be blank"; } elseif (!$dataSource->unique("users", "email", $_POST['email'])) { $errors[] = "email must be unique"; } if ($_POST['name'] == "") { $errors[] = "Display Name cannot be blank"; } elseif (!$dataSource->unique("users", "real_name", $_POST['name'])) { $errors[] = "Display Name must be unique"; } if ($_POST['password'] == "") { $errors[] = "password cannot be blank"; } elseif ($_POST['password'] != $_POST['password2']) { $errors[] = "passwords must match"; } if (isset($_CONFIG['recaptcha_private_key'])) { $privatekey = $_CONFIG['recaptcha_private_key']; $resp = recaptcha_check_answer($privatekey, $_SERVER["REMOTE_ADDR"], $_POST["recaptcha_challenge_field"], $_POST["recaptcha_response_field"]); if (!$resp->is_valid) { $errors[] = "Captcha invalid"; } } if (count($errors) == 0) { $dataSource->newUser($_POST['username'], $_POST['name'], $_POST['password'], $_POST['email']); sendAdminEmail('New User Created', $_POST); $out = "h2. New user created\n\n"; $out .= "Hi, " . $_POST['name'] . ", Welcome to this aqWiki install.\n\n"; $url = parse_url($_SERVER['REQUEST_URI']); $out .= "You should now \"login\":" . $url['path'] . "?action=login"; } else { $out = "h2. Error in user creation\n\n"; foreach ($errors as $error) { $out .= "* " . $error . "\n"; } $out .= "\n\n" . $form; } } else { $out = "h2. New user\n\n"; $out .= $form; } $content[2] = $out; break; case "edit": if ($_EXTRAS['reqEdit']) { doAuth($_EXTRAS['reqEdit'], "edit a page"); } if ($_EXTRAS['restrictNewPages']) { doAuth($_EXTRAS['restrictNewPages'], "create a new page"); } $form = true; $text = false; switch ($_POST['submit']) { case "Preview": $out = $_POST['content']; $text = stripslashes($_POST['content']); break; case "Spell Check": $checker = new Spellchecker(); $text = strip_tags(textile($_POST['content'])); $num_errors = $checker->check($text); if ($num_errors > 0) { $out .= "h3. Spell Check\n\n"; #$out .= "Items <span class=\"spellCorrect\">like this</span> could be errors, hover over for suggestions. Items <span class=\"spellNoSuggest\">like this</span> arn't in the dictionary, and the spell checker has no idea.\n\n"; $errors = $checker->getErrors(); $oldtext = $text; foreach ($errors as $word => $suggestions) { /*$title = trim(implode(', ', $suggestions)); if ($title == ""){ $span = '<|-|'.$title.'|-|>'.$word.'</-|>'; } else { $span = '<|||'.$title.'|||>'.$word.'</||>'; }*/ $suggs = implode(' ', $suggestions); if ($suggs != " ") { $errorlist .= "*" . $word . ":* " . $suggs . "\n\n"; } else { $noidea[] = $word; } # $text = str_replace($word, $span, $text); #$text = preg_replace("/(\W|^)$word(\W|\$)/i", "$1$span$2", $text); } /* //if ($title == ""){ $text = str_replace('<|-|', '<span class="spellNoSuggest"', $text); $text = str_replace('|-|>', '>', $text); $text = str_replace('</-|>', '</span>', $text); //} else { $text = str_replace('<|||', '<span class="spellCorrect" title="', $text); $text = str_replace('|||>', '">', $text); $text = str_replace('</||>', '</span>', $text); //}*/ } if ($noidea) { $errorlist .= "*No idea about:* " . implode(' ', $noidea) . "\n\n"; } #$out .= $text; $out .= $errorlist . "\n"; $text = stripslashes($_POST['content']); break; case "Post": $page = array_shift($dataSource->getPage($article)); if ($page['rev_created'] > $_POST['edittime']) { $content[2] .= collision_detection($page, $_POST); $text = $_POST['content']; //$form = false; } else { $dataSource->post($article, $_POST['content'], $_POST['comment']); $form = false; header("location: {$url}"); } } if ($text) { $_EXTRAS['textarea'] = $text; } elseif (!$dataSource->pageExists($article)) { $_POST['comment'] = "Start of a brand new world"; $_EXTRAS['textarea'] = ""; } else { $_EXTRAS['textarea'] = stripslashes($dataSource->getContent($article)); } preg_match_all("/\\[\\[LOCKED\\|(.*?)\\]\\]/", $_EXTRAS['textarea'], $matches); foreach ($matches[0] as $index => $match) { $users = $matches[1][$index]; doAuth($users, "view this"); } if ($form) { $out .= "<form method=post action=\"" . $_SERVER['REQUEST_URI'] . "\" class=\"shiny wikiedit\">"; $out .= '<h2>Editing "' . $content[1] . '"</h2>'; $out .= "<p>You should read the ((help)). If you are having problems with the formatting, post it and add a note explaining the problem to ((formattingProblems)) and I'll dive in and fix it. If you believe you've found a bug in the wiki software, post your problem to \"the bug tracker\":http://trac.aqxs.net/aqwiki/newticket and I'll dive in and fix that too.</p>\n"; //$out .= "<label for=\"creator\">Author</label>\n"; //$out .= $_EXTRAS['me']."<br>\n"; $out .= "<label for=\"content\">Content of page \"" . $content[1] . "\"</label>\n"; $out .= "<textarea name=\"content\" id=\"content\" rows=\"30\" cols=\"72\">[[TEXTAREA]]</textarea>\n<br>\n"; $out .= "<label for=\"comment\">Comment</label>\n"; $out .= "<input type=\"text\" name=\"comment\" id=\"comment\" size=\"72\" value=\"" . $_POST['comment'] . "\"><br>\n"; $out .= "<input class=\"submit\" type=\"hidden\" name=\"edittime\" value=\"" . time() . "\">\n"; $out .= "<input class=\"submit\" type=\"submit\" name=\"submit\" value=\"Post\"> "; $out .= "<input class=\"submit\" type=\"submit\" name=\"submit\" value=\"Preview\"> "; $out .= "<input class=\"submit\" type=\"submit\" name=\"submit\" value=\"Spell Check\"> "; $out .= "<input class=\"submit\" type=\"reset\" name=\"revert\" value=\"Revert to pre-editing\">\n"; $out .= "</form>"; $content[2] .= $out; break; } case "allrev": if (!$dataSource->pageExists($article)) { $content[2] = 'Error: Page doesn\'t exist. What are you playing at?'; break; } $content[2] = '<form method="GET" action="' . $url . '" style="width: auto;">'; $content[2] .= '<h2>Viewing all revisions for ((' . $article . "))</h2>\n\n"; $content[2] .= 'Select the <input type="radio" /> boxes to compare two revisions' . "\n\n"; $pages = $dataSource->getPage($article); $pages = array_reverse($pages); foreach ($pages as $row) { $line = '<input type="radio" name="from" value="' . $row['revision'] . '">'; $line .= '<input type="radio" name="to" value="' . $row['revision'] . '">'; $line .= date("Y-m-d H:i", $row['created']) . " - " . userlink($row['creator']); if ($row['comment']) { $line .= " : " . $row['comment']; } $content[2] .= "# " . $line . " [ <a href=\"" . $url . "?action=viewrev&id=" . $row['revision'] . "\" title=\"View this revision\">View</a> |" . " <a href=\"" . $url . "?action=diff&from=" . $row['revision'] . "\"\" title=\"View differences between this and the current revision\">Diff</a> ]\n"; } $content[2] .= '<input type="submit" value="Compare Revisions"> <input type="hidden" value="diff" name="action"> </form>'; break; case "revert": if (!in_array($_EXTRAS['me'], $_EXTRAS['admins'])) { panic('AqWiki Reversion', 'You\'re not an admin, you can\'t do this shit'); } if (!$_GET['id']) { die("Parameters incorrect"); } $id = $_GET['id']; $pages = $dataSource->getPage($article); $oldVersion = $pages[$id]; //die($oldVersion['content']); $dataSource->post($article, $oldVersion['content'], 'reverted back to version ' . $id); $form = false; $content[2] = 'Reverted ((' . $article . ')) back to version ' . $id; break; default: $_EXTRAS['versions'] = ""; if (!$dataSource->pageExists($article)) { if ($_EXTRAS['restrictNewPages'] || $_EXTRAS['reqEdit']) { if ($_EXTRAS['restrictNewPages'] == "register") { $message = "any registered users"; } else { $message = "only certain users"; } if (!isset($_EXTRAS['newPageMessage'])) { $npm = "This page doesn't exist yet. [[TYPES]] can create new pages. Do you want to do so?\n\n\"Go On Then\":[[EDITURL]]"; } else { $npm = $_EXTRAS['newPageMessage']; } $content[2] = str_replace(array("[[TYPES]]", "[[EDITURL]]"), array($message, $url . "?action=edit"), $npm); } else { $content[2] = "This page doesn't exist yet, Would you like to create it?\n\n\"Go On Then\":" . $url . "?action=edit"; } } else { $_EXTRAS['nearby'] = $dataSource->nearby($article); $pages = $dataSource->getPage($article); $row = array_shift($pages); if (strcmp($row['wiki'], $wiki) != 0) { $base = $_CONFIG['base'] . "/" . $row['wiki']; $url = $base . "/" . $article; header("location: " . $url); } $content[2] = $row['content']; $content[3] = $row['creator']; $content[4] = date("r", $row['created']); $line = date("r", $row['created']) . " - " . userlink($row['creator']); if ($row['comment']) { $line .= " : " . $row['comment']; } if ($_EXTRAS['current'] != $article) { $pages = $dataSource->getPage($_EXTRAS['current']); $row = array_shift($pages); } $_EXTRAS['versions'] .= "# " . $line . " [ Current ]\n"; $limit = 10; $current = 0; foreach ($pages as $row) { $line = date("Y-m-d\tH:i", $row['created']) . " - " . userlink($row['creator']); if ($row['comment']) { $line .= " : " . $row['comment']; } $_EXTRAS['versions'] .= "# " . $line . " [ <a href=\"" . $url . "?action=viewrev&id=" . $row['revision'] . "\" title=\"View this revision\">View</a> |" . " <a href=\"" . $url . "?action=diff&from=" . $row['revision'] . "\"\" title=\"View differences between this and the current revision\">Diff</a> ]\n"; $current++; if ($_GET['action'] != "allrev" && $current > $limit) { $_EXTRAS['versions'] .= "# \"Show list of revisions\":" . $url . "?action=allrev\n"; break; } } #$content[2] .= $out; } } return $content; }
function document_process ($root_table, $root_id, $root_template) { global $scanner, $dep, $db, $path_tail, $current_index, $current_indices, $default_document, $document_template, $debug, $list_offsets, $url_vars; list ($dirtype, $table, $id, $vdir, $path_tail, $name) = document_path_to_directory (explode ('/', $_SERVER['PATH_INFO']), $root_table, $root_id); # Check if the first unprocessed directory of the tail is a known # object class and use it as the template. If it's not, a default template # is used. $template = ''; if (sizeof ($path_tail) > 0) if ($db->select ('id', 'obj_classes', 'name=\'' . $path_tail[0] . '\'')) $template = $path_tail[0]; # Tail is a legal user template. if (!$template) if ($table == $root_table && $id == $root_id && !$vdir) $template = $root_template; # Show index page. else $template = $default_document[$dirtype]; # Use default template. # Fetch document template for this directory. # Don't use cms_fetch_object() here because there's no cursor. $dbobj = new DBOBJ ($db, $template, $dep, $table, $id, true); # Export public object as file. # This is done right here to skip all other activities and exit. if ($name == 'OBJ') { if (!is_array ($dbobj->active) || !$dbobj->active['id']) die ("'$template' is not an object class."); if (!$dbobj->active['is_public']) panic ('Object is not marked public!'); Header ('Content-type: ' . $dbobj['mime']); echo $dbobj->active['data']; # No run through scanner. exit; } if (!isset ($dbobj->active['data'])) die ('Kein Dokument für die Eingansseite definiert - stop.'); $document_template = $dbobj->active['data']; # Get index info. $tmp = $table; $rid = $id; dbitree_get_parent ($db, $tmp, $rid); if (!$tmp) die ('No such path.'); # Fetch result into array. for ($res = dbitree_get_children ($db, $table, $rid); $tmp = $res->get (); $set[$tmp['id_last']] = $tmp['id']); # Sort indices into $current_indices array and find the current one. for ($i = 1, $last = 0; isset ($set[$last]) && ($rid = $current_indices[$i] = $set[$last]); $last = $rid, $i++) if ($rid == $id) $current_index = $i; # Feed list offsets into URL vars. if (isset ($list_offsets)) foreach ($list_offsets as $key => $val) $url_vars["list_offsets[$key]"] = $val; # Open a new context. $scanner->push_context (); # XXX is this really required? cms_create_context ($dirtype, $table, $id); # Call document handler if the current directory is virtual. if ($vdir) { # Explicitly create context for virtual directory. # Call document handler. # TODO: Document handlers for any directory type. $func = 'document_' . strtolower ($dirtype); $func (); } if ($debug) echo "dirtype: $dirtype - tab: $table - id: $id - default template: $template<br>"; # Invoke scanner and evaluate the page. # TODO: This could depend on the document template's mime type. # see also the scanner in lib/scanner.class. $document_tree = $scanner->scan ($document_template); $out = $scanner->exec ($document_tree, $table, $id); eval ("?>$out<?"); }
function get_session($sess) { $res = pg_query_params('SELECT id, name, password, session, EXTRACT(EPOCH FROM (now() - session_timeout)) AS session_timeout, game, EXTRACT(EPOCH FROM (now() - game_timeout)) AS game_timeout, cards FROM bots WHERE session=$1 LIMIT 1;', [$sess]); if ($res === FALSE) { panic("Failed to query the database for the existence of your session."); } if (pg_affected_rows($res) !== 1) { failure("The session you provided, '{$sess}', is not currently active."); } $row = pg_fetch_assoc($res); pg_free_result($res); return $row; }
$dbh = $settings->getDatabase(); $statement = $dbh->prepare("SELECT * FROM bwlist;"); $statement->execute(); success_json($statement->fetchAll(PDO::FETCH_OBJ)); } if ($_GET['type'] == 'spamsettings') { $dbh = $settings->getDatabase(); $statement = $dbh->prepare("SELECT * FROM spamsettings;"); $statement->execute(); $result = array_map(function ($r) { $r['settings'] = json_decode($r['settings']); return $r; }, $statement->fetchAll(PDO::FETCH_ASSOC)); success_json($result); } panic('Unsupported API call'); function panic($message) { http_response_code(503); header('Content-Type: application/json; charset=UTF-8'); die(json_encode(array('error' => $message))); } function success_json($data) { header('Content-Type: application/json; charset=UTF-8'); die(json_encode($data)); } function success_text($data) { header('Content-Type: text/plain; charset=UTF-8'); die($data);
function query($sql) { $db = $this->db; $result = $db->query($sql); if (DB::isError($result)) { panic("database", $result->getMessage() . "\n\n" . mysql_error(), "<pre>{$sql}</pre>"); } return $result; }
break; case 'referer': $referer = $value; break; } } if ($accept != 'text/event-stream') { panic('Invalid Accept header. text/event-stream is the only possible value.'); } if (parse_url($referer, PHP_URL_HOST) != $_SERVER['HTTP_HOST']) { panic("Invalid Referer. {$_SERVER['HTTP_HOST']} is the only possible vale."); } $fp = @fopen('a', 'r'); if ($fp === false) { $error = error_get_last(); panic($error['message']); } fseek($fp, $offset, SEEK_SET); header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); for ($buffer = ''; true;) { // on EOF fread will return a zero-length string $buffer .= fread($fp, 4096); while (preg_match('/\\r|\\n|\\e\\[J\\r/', $buffer, $m, PREG_OFFSET_CAPTURE)) { $line = substr($buffer, 0, $m[0][1]); send($offset, $line); $skip = $m[0][1] + strlen($m[0][0]); $buffer = substr($buffer, $skip); $offset += $skip; } if (feof($fp)) {
g.bid2 AS bid2, r.bot1 AS r_bot1, r.bot2 AS r_bot2, r.card1 AS card1, r.card2 AS card2 FROM games AS g JOIN rounds AS r ON g.id=r.game AND (g.round=r.round OR g.round-1=r.round) WHERE g.id=$1 ORDER BY r.round DESC;', [$bot["game"]]); if ($res === FALSE || pg_affected_rows($res) === 0) { panic("The 'game' attached to your session, '{$bot['game']}', could not be crossreferenced against the 'rounds' table."); } $rows = pg_fetch_all($res); pg_free_result($res); // First handle the current round. $stat["round"] = (int) $rows[0]["round"]; $stat["opponent-current-card"] = opponent_card($rows[0]); if ($rows[0]["g_bot1"] === $bot["id"]) { $stat["opponent"] = (int) $rows[0]["g_bot2"]; // Only reveal the bid once you have bid. if (!is_null($rows[0]["bid1"])) { $stat["opponent-bid"] = (int) $rows[0]["bid2"]; } } else { $stat["opponent"] = (int) $rows[0]["g_bot1"]; // Only reveal the bid once you have bid.