prepare("SELECT Name FROM public_users WHERE Id = :id"); $query->bindParam(":id", $id, PDO::PARAM_INT); $query->execute(); if(!$query->rowCount()){ return false; } $row = $query->fetch(PDO::FETCH_OBJ); return $row->Name; } function getUserInfoFromUid($id) { global $pdo; if(!filter_var($id, FILTER_VALIDATE_INT)){ return false; } $query = $pdo->prepare("SELECT * FROM public_users WHERE Id = :id"); $query->bindParam(":id", $id, PDO::PARAM_INT); $query->execute(); if(!$query->rowCount()){ return false; } $row = $query->fetch(PDO::FETCH_OBJ); return $row; } function getUserInfoFromName($name) { global $pdo; if (strcasecmp($name, "BrentDaMage") == 0) { $name = "Brent Da Mage"; } $query = $pdo->prepare("SELECT * FROM public_users WHERE Name = :name"); $query->bindParam(":name", $name, PDO::PARAM_STR); $query->execute(); if(!$query->rowCount()){ return false; } $row = $query->fetch(PDO::FETCH_OBJ); return $row; } function convertTimestampToTimeAgo($timestamp) { $difference = time() - $timestamp; $minutes = ceil($difference/60); $hours = ceil($difference/3600); $days = ceil($difference/86400); $months = ceil($difference/2628000); $years = ceil($difference/3154000); switch(true) { case ($minutes <= 30): return 'Just now'; break; case ($hours == 1): return '1 hour ago'; break; case ($hours < 24): return $hours.' hours ago'; break; case ($days == 1): return 'Yesterday'; break; case ($days < 31): return $days.' days ago'; break; case ($months == 1): return '1 month ago'; break; case ($months < 12): return $months.' months ago'; break; case ($years == 1): return '1 year ago'; break; default: return $years.' years ago'; break; } } function redirectToErrorPage($code = 400) { die(header("Location: /RobloniumDefaultErrorPage.aspx?code=$code")); } function checkIfFriends($user1, $user2, $type = 1) { global $pdo; if($user1 == $user2){ return 0; } //this is ugly - pls improve if you can switch($type) { case 2: // friends $pdoquery = "SELECT * FROM friends WHERE (requesterId = :userid OR receiverId = :userid) AND (requesterId = :recipientid OR receiverId = :recipientid) AND status = 1"; break; case 3: // best friends $pdoquery = "SELECT * FROM friends WHERE (requesterId = :userid OR receiverId = :userid) AND (requesterId = :recipientid OR receiverId = :recipientid) AND status = 1 AND isbestfriend = 1"; break; default: // pending $pdoquery = "SELECT * FROM friends WHERE (requesterId = :userid OR receiverId = :userid) AND (requesterId = :recipientid OR receiverId = :recipientid)"; } $checkquery = $pdo->prepare($pdoquery); $checkquery->bindParam(":userid", $user1, PDO::PARAM_INT); $checkquery->bindParam(":recipientid", $user2, PDO::PARAM_INT); $checkquery->execute(); return $checkquery->rowCount(); } function Unfriend($user1, $user2) { global $pdo; if(!checkIfFriends($user1, $user2)){ return false; } //this is ugly - pls improve if you can $friends = $pdo->prepare("DELETE FROM friends WHERE (requesterId = :userid1 OR receiverId = :userid2) AND (requesterId = :recipientid1 OR receiverId = :recipientid2) "); $friends->bindParam(":userid1", $user1, PDO::PARAM_INT); $friends->bindParam(":userid2", $user1, PDO::PARAM_INT); $friends->bindParam(":recipientid1", $user2, PDO::PARAM_INT); $friends->bindParam(":recipientid2", $user2, PDO::PARAM_INT); return $friends->execute(); } function BreakFriendship($invitationId) { global $pdo; //this is ugly - pls improve if you can $friends = $pdo->prepare("DELETE FROM friends WHERE Id = :invitationid "); $friends->bindParam(":invitationid", $invitationId, PDO::PsARAM_INT); return $friends->execute(); } // The behemoth of a load friends page function function loadFriendPage($displayedUserId, $pageNum, $view) { global $pdo; switch ($view) { case "Friends": $status = 1; $isBestFriend = 0; break; case "BestFriends": $status = 1; $isBestFriend = 1; break; case "FriendRequests": $status = 0; $isBestFriend = 0; break; default: return false; break; } $friendStrings = [ "FriendRequests" => ["Accept Friend Request","Decline Friend Request","accept-friend","decline-friend"], "Friends" => ["Add Best Friend","Remove Friend","add-best-friend","remove-friend"], "BestFriends" => ["Remove Best Friend","Remove Friend","remove-best-friend","remove-friend"] ]; $friends = $pdo->prepare("SELECT * FROM friends WHERE (receiverId = :displayedUserId)"); $friends->bindParam(":displayedUserId", $displayedUserId, PDO::PARAM_INT); //$friends->bindParam(":status ", $status , PDO::PARAM_INT); //$friends->bindParam(":isBestFriend ", $isBestFriend , PDO::PARAM_INT); $friends->execute(); $friends->fetch(PDO::FETCH_OBJ); die("success"); if(!$friends->rowCount()){ echo '

Find your friends on ROBLONIUM

'; return true; } ?>
fetch(PDO::FETCH_OBJ)){ $friend = getUserInfoFromUid($row->requesterId == $userid ? $row->receiverId : $row->requesterId); ?>
prepare("SELECT * FROM asset WHERE AssetId = :id"); $query->bindParam(":id", $assetId, PDO::PARAM_INT); $query->execute(); if(!$query->rowCount()){ return false; } $row = $query->fetch(PDO::FETCH_OBJ); return $row; } function grantItem($userId, $assetId) { global $pdo; $userInfo = getUserInfoFromUid($userId); $asset = getMarketplaceInfo($assetId); if(!$userInfo || !$asset){ return false; } $inv = json_decode($userInfo->Inventory, true); if (!$inv || in_array($assetId, $inv['Inventory'])) { return false; } array_push($inv['Inventory'], $assetId); //Add the item to the user's inventory $inventory = json_encode($inv); $query = $pdo->prepare("UPDATE public_users SET Inventory = :inventory WHERE Id = :userid"); $query->bindParam(":inventory", $inventory, PDO::PARAM_STR); $query->bindParam(":userid", $userId, PDO::PARAM_INT); $query->execute(); $updateSales = $asset->Sales+1; $query = $pdo->prepare("UPDATE asset SET Sales = :sales WHERE AssetId = :assetid"); $query->bindParam(":sales", $updateSales, PDO::PARAM_INT); $query->bindParam(":assetid", $assetId, PDO::PARAM_INT); return true; } function purchaseAsset($userId, $assetId, $expectedCurrency) { global $pdo; $assetInfo = getMarketplaceInfo($assetId); $userInfo = getUserInfoFromUid($userId); if(!$assetInfo || !$userInfo){ return "An error occurred while trying to fetch the requested item information."; } if($expectedCurrency == 2) { $currency = "Tickets"; $price = $assetInfo->PriceInTickets; $balanceAfterSale = $userInfo->Tickets - $price; $chargeUserQuery = "UPDATE public_users SET Tickets = :remainingbalance WHERE Id = :userid"; } else { $currency = "Robux"; $price = $assetInfo->PriceInRobux; $balanceAfterSale = $userInfo->Robux - $price; $chargeUserQuery = "UPDATE public_users SET Robux = :remainingbalance WHERE Id = :userid"; } if(!$assetInfo->IsForSale){ return "This item is no longer for sale."; } if ($userInfo->Robux < $price and $expectedCurrency == 1) { return "You don't have enough ROBUX to purchase this item."; } if ($userInfo->Tickets < $price and $expectedCurrency == 2) { return "You don't have enough Tickets to purchase this item."; } if ($userInfo->MembershipLevel < $assetInfo->MinimumMembershipLevel) { return "Your account doesn't meet the requirements to purchase this item."; } if(in_array($assetId, json_decode($userInfo->Inventory,true)['Inventory'])) { return "You already own this item."; } if(grantItem($userId, $assetId)) { $query = $pdo->prepare($chargeUserQuery); $query->bindParam(":remainingbalance", $balanceAfterSale, PDO::PARAM_INT); $query->bindParam(":userid", $userId, PDO::PARAM_INT); $query->execute(); return "Success"; } else { return "An unexpected error occurred"; } } function formatDate($time, $timestamp = false) { if($timestamp){ return date("m/d/Y", $time); } else{ return date("m/d/Y", strtotime($time)); } } function getIpAddress() { if (!empty($_SERVER['HTTP_CLIENT_IP'])) { return $_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { return $_SERVER['HTTP_X_FORWARDED_FOR']; } else { return $_SERVER['REMOTE_ADDR']; } } // Returns a RESTful API-like response which can be used to express success in an API request or return an error. function returnApiResponse($code = 200, $error_msg = "", $type = 0) { switch ($type) { case 0: $response = [ "error" => $code, "success" => $code == 200 ? true : false, // this might need to be reworked at some point "error_msg" => $error_msg ]; break; case 1: $response = [ "data" => [ "error" => $code, "success" => $code == 200 ? true : false, // this might need to be reworked at some point "error_msg" => $error_msg ] ]; break; default: die(http_response_code(500)); break; } header("HTTP/1.1 $code $error_msg"); die(json_encode($response)); } /// authentication stuff here //session system made by pizzaboxer function createSession($userId) { global $pdo; keygen: $sessionkey = md5(rand()).md5(rand()).md5(rand()).md5(rand()).md5(rand()).md5(rand()).md5(rand()).md5(rand()); //i need a better solution to session key generation lol as it probably takes up quite a few server resources but it is definitely secure //this generates a 256 character long unique key to identify user sessions // Maybe try using the UUID generator function in global_functions.php? Also the RCCService backend relies on that function for JobID generation, so it probably won't get removed anytime soon. Plus, ROBLOX uses UUIDs as their RCCService access keys. - Brent $query = $pdo->prepare("SELECT * FROM sessions WHERE sessionkey = :sesskey"); $query->bindParam(":sesskey", $sessionkey, PDO::PARAM_STR); $query->execute(); if($query->rowCount()){ goto keygen; } //if a session with the same key already exists then repeat key generation process $create = $pdo->prepare("INSERT INTO sessions (`SESSIONKEY`, `valid`, `userAgent`, `userId`, `loginIp`, `created`) VALUES (:sesskey, 1, :useragent, :userid, :ip, UNIX_TIMESTAMP())"); $create->bindParam(":sesskey", $sessionkey, PDO::PARAM_STR); $create->bindParam(":useragent", $_SERVER['HTTP_USER_AGENT'], PDO::PARAM_STR); $create->bindParam(":userid", $userId, PDO::PARAM_INT); $create->bindParam(":ip", getIpAddress(), PDO::PARAM_STR); $create->execute(); setcookie(".ROBLOSECURITY", $sessionkey, time()+(86400*3), "/"); //set time to 3 days $_SESSION['player'] = $userId; //utilization of php sessions are deprecated now thanks to this new session system but i'm keeping this here for legacy sakes //just in case some page is still using it } function requireLogin() { if(!SESSION){ die(header("Location: /newlogin")); } } function destroySession($sessionkey) { //todo } function invalidateSession($sesskey) { setcookie(".ROBLOSECURITY", $sesskey, 1, "/"); die(header("Refresh: 0")); } //now we set the user's session if(isset($_COOKIE['_ROBLOSECURITY'])) { $sessionkey = $_COOKIE['_ROBLOSECURITY']; $query = $pdo->prepare("SELECT * FROM sessions WHERE sessionkey = :sesskey"); $query->bindParam(":sesskey", $sessionkey, PDO::PARAM_STR); $query->execute(); if(!$query->rowCount()){ invalidateSession($sessionkey); } //reject the session if it doesnt exist $row = $query->fetch(PDO::FETCH_OBJ); if($row->created+(86400*3) < time()){ invalidateSession($sessionkey); } //todo - maybe set it up so it renews? if($row->userAgent != $_SERVER['HTTP_USER_AGENT']){ invalidateSession($sessionkey); } //strict - reject if user agent isnt the same if($row->loginIp != getIpAddress()){ invalidateSession($sessionkey); } //strict - reject if ip doesnt match //these last two checks in particular should help to stop potential cookie stealing attacks $userInfo = getUserInfoFromUid($row->userId); $incomingFRs = $pdo->prepare("SELECT COUNT(*) FROM friends WHERE receiverid = :id AND status = 0"); $incomingFRs->bindParam(":id", $row->userId, PDO::PARAM_INT); $incomingFRs->execute(); define ('SESSION', ["username"=>$userInfo->Name, "userid"=>(int)$userInfo->Id, "robux"=>(int)$userInfo->Robux, "tickets"=>(int)$userInfo->Tickets, "membershiplevel"=>(int)$userInfo->MembershipLevel, "friendrequests"=>(int)$incomingFRs->fetchColumn()]); } else { define('SESSION', false); }