From 999437dbaac1993b6b7eb29c39af57486c4a1bfd Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Wed, 2 Oct 2024 16:40:41 -0700 Subject: [PATCH 1/9] donation.php: add notice about processing time Players were (reasonably) expecting their SMR credits to be processed automatically, and were confused when they were not showing up. This note at least notifies them that there will be a delay. --- src/templates/Default/engine/Default/donation.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/templates/Default/engine/Default/donation.php b/src/templates/Default/engine/Default/donation.php index 5629358c7..c6f693386 100644 --- a/src/templates/Default/engine/Default/donation.php +++ b/src/templates/Default/engine/Default/donation.php @@ -5,6 +5,7 @@ /** * @var Smr\Account $ThisAccount * @var int $TotalDonation + * @var string $ContactFormLink */ ?> @@ -13,6 +14,11 @@ making a donation! Your donation will translate into SMR credits that you can use in-game for name changes, message notifications, painting your ship, and more!

+

+Please allow a few days for processing. If you would like to receive your +SMR credits faster, you can send a message to the SMR Support Team using our +Contact Form. +

Current donation rate is: $ per month (within last 3 months).

From bb271795e061f9e79058ac7f75c66070c9b00b8e Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Wed, 2 Oct 2024 21:46:48 -0700 Subject: [PATCH 2/9] Bounty.php: prevent bounty credits database overflow The `bounty.amount` column is an UNSIGNED INT in the database, and so we need to prevent the value from increasing to beyond its maximum value. Otherwise, we get a "value out of range" SQL error. --- src/config.php | 9 +++++++-- src/lib/Smr/Bounty.php | 7 ++++++- test/SmrTest/lib/BountyTest.php | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/config.php b/src/config.php index 01ad67d9b..e70dc602a 100644 --- a/src/config.php +++ b/src/config.php @@ -25,6 +25,11 @@ const PAGE_PREFIX = ENABLE_DEBUG ? 'DEV: ' : (ENABLE_BETA ? 'BETA: ' : ''); const PAGE_TITLE = PAGE_PREFIX . 'Space Merchant Realms'; +/* + * Database constants + */ +const SQL_MAX_UNSIGNED_INT = 4_294_967_295; // 2^32-1 + /* * Special account IDs */ @@ -441,10 +446,10 @@ const MR_FACTOR = 15; const MIN_EXPERIENCE = 0; -const MAX_EXPERIENCE = 4294967295; // 2^32-1 +const MAX_EXPERIENCE = SQL_MAX_UNSIGNED_INT; const MAX_COUNCIL_MEMBERS = 5; -const MAX_MONEY = 4294967295; // 2^32-1 +const MAX_MONEY = SQL_MAX_UNSIGNED_INT; const SHIP_REFUND_PERCENT = .75; const WEAPON_REFUND_PERCENT = .5; const CDS_REFUND_PERCENT = .5; diff --git a/src/lib/Smr/Bounty.php b/src/lib/Smr/Bounty.php index a95874544..1c9536def 100644 --- a/src/lib/Smr/Bounty.php +++ b/src/lib/Smr/Bounty.php @@ -6,6 +6,11 @@ class Bounty { + /** + * Maximum amount of bounty.credits in the database + */ + private const MAX_CREDITS = SQL_MAX_UNSIGNED_INT; + /** * Returns a list of all active (not claimable) bounties for given location $type. * @@ -117,7 +122,7 @@ public function setClaimed(): void { } private function setCredits(int $credits): void { - if ($this->credits === $credits) { + if ($this->credits === $credits || $credits > self::MAX_CREDITS) { return; } $this->credits = $credits; diff --git a/test/SmrTest/lib/BountyTest.php b/test/SmrTest/lib/BountyTest.php index e3bfa8261..a190b902a 100644 --- a/test/SmrTest/lib/BountyTest.php +++ b/test/SmrTest/lib/BountyTest.php @@ -20,6 +20,25 @@ protected function tablesToTruncate(): array { return ['bounty']; } + public function test_max_credits(): void { + $bounty = new Bounty( + targetID: 1, + bountyID: 1, + gameID: 1, + type: BountyType::UG, + time: 0, + claimerID: 0, + credits: 0, + smrCredits: 0, + ); + // increase bounty credits to the maximum amount + $bounty->increaseCredits(SQL_MAX_UNSIGNED_INT); + self::assertEquals($bounty->getCredits(), SQL_MAX_UNSIGNED_INT); + // further increases don't change the value + $bounty->increaseCredits(1); + self::assertEquals($bounty->getCredits(), SQL_MAX_UNSIGNED_INT); + } + public function test_update(): void { // Calling update on a new bounty will add it to the database $bounty = new Bounty( From a174871f6c9bff4928d9e22ae318f18c826d64a3 Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Wed, 2 Oct 2024 22:11:47 -0700 Subject: [PATCH 3/9] logException: fix too long messages in admin box The `message_boxes.message_text` column is type TEXT, which has a limit on the string length. When logging exceptions, make sure we restrict the length of the message to this limit to avoid a database error. --- src/bootstrap.php | 8 +++++--- src/config.php | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bootstrap.php b/src/bootstrap.php index cbeaa2f01..890347911 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -84,14 +84,16 @@ function logException(Throwable $err): void { } // Send error message to the in-game auto bugs mailbox + // (Truncate the message if necessary to avoid database errors) + $boxMessage = substr($message, 0, SQL_MAX_TEXT_LENGTH); if (isset($session) && $session->hasGame()) { - $session->getPlayer()->sendMessageToBox(BOX_BUGS_AUTO, $message); + $session->getPlayer()->sendMessageToBox(BOX_BUGS_AUTO, $boxMessage); } elseif (isset($session) && $session->hasAccount()) { // Will be logged without a game_id - $session->getAccount()->sendMessageToBox(BOX_BUGS_AUTO, $message); + $session->getAccount()->sendMessageToBox(BOX_BUGS_AUTO, $boxMessage); } else { // Will be logged without a game_id or sender_id - Account::doMessageSendingToBox(0, BOX_BUGS_AUTO, $message, 0); + Account::doMessageSendingToBox(0, BOX_BUGS_AUTO, $boxMessage, 0); } // Send error message to e-mail so that we have a permanent record diff --git a/src/config.php b/src/config.php index e70dc602a..8b561a5a0 100644 --- a/src/config.php +++ b/src/config.php @@ -29,6 +29,7 @@ * Database constants */ const SQL_MAX_UNSIGNED_INT = 4_294_967_295; // 2^32-1 +const SQL_MAX_TEXT_LENGTH = 65_535; // 2^16-1 /* * Special account IDs From e32908b10bd906762a6064b82251428ecb49e3ff Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Wed, 2 Oct 2024 22:30:45 -0700 Subject: [PATCH 4/9] Escape message board thread with htmlentities This fixes libxml errors when the thread topic includes, e.g., an ampersand. --- src/pages/Player/AllianceMessageBoardView.php | 2 +- src/templates/Default/engine/Default/alliance_message.php | 2 +- .../Default/engine/Default/alliance_message_view.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/Player/AllianceMessageBoardView.php b/src/pages/Player/AllianceMessageBoardView.php index be3ba9f5e..7d9b00738 100644 --- a/src/pages/Player/AllianceMessageBoardView.php +++ b/src/pages/Player/AllianceMessageBoardView.php @@ -39,7 +39,7 @@ public function build(AbstractPlayer $player, Template $template): void { $thread_index = $this->threadIndex; $thread_id = $this->threadIDs[$thread_index]; - $template->assign('PageTopic', $this->threadTopics[$thread_index]); + $template->assign('PageTopic', htmlentities($this->threadTopics[$thread_index])); Menu::alliance($alliance->getAllianceID()); $db = Database::getInstance(); diff --git a/src/templates/Default/engine/Default/alliance_message.php b/src/templates/Default/engine/Default/alliance_message.php index a10052f9e..4895855f9 100644 --- a/src/templates/Default/engine/Default/alliance_message.php +++ b/src/templates/Default/engine/Default/alliance_message.php @@ -23,7 +23,7 @@ if ($Thread['Unread']) { ?> diff --git a/src/templates/Default/engine/Default/alliance_message_view.php b/src/templates/Default/engine/Default/alliance_message_view.php index d624246c4..c3ccf2d1a 100644 --- a/src/templates/Default/engine/Default/alliance_message_view.php +++ b/src/templates/Default/engine/Default/alliance_message_view.php @@ -12,14 +12,14 @@ if (isset($PrevThread)) { ?> Previous -    +      -    +    Next Date: Wed, 2 Oct 2024 22:37:30 -0700 Subject: [PATCH 5/9] updateIP: fix long host insertion into database The `account_has_ip.host` column is a varchar(64). Truncate the host if it is too long to avoid a database error. The full host name is not particularly important. --- src/lib/Smr/Account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/Smr/Account.php b/src/lib/Smr/Account.php index f140e3e10..a23241f3e 100644 --- a/src/lib/Smr/Account.php +++ b/src/lib/Smr/Account.php @@ -425,7 +425,7 @@ public function updateIP(): void { 'account_id' => $this->accountID, 'time' => Epoch::time(), 'ip' => $curr_ip, - 'host' => $host, + 'host' => substr($host, 0, 64), // column is varchar(64) ]); } From 1432f76662f01d79d914eb28ba33593a6284b9fe Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Wed, 2 Oct 2024 22:52:40 -0700 Subject: [PATCH 6/9] planet_ownership.php: restrict password/name length The `planet.password` and `planet.planet_name` columns are varchar(32), so use HTML5 to restrict the user to 32 characters to avoid a database error. --- src/templates/Default/engine/Default/planet_ownership.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/templates/Default/engine/Default/planet_ownership.php b/src/templates/Default/engine/Default/planet_ownership.php index 02282ba63..42bf8aac0 100644 --- a/src/templates/Default/engine/Default/planet_ownership.php +++ b/src/templates/Default/engine/Default/planet_ownership.php @@ -35,13 +35,13 @@ } else { ?>

You own this planet!

-     +    

-     +    
Date: Wed, 2 Oct 2024 23:09:16 -0700 Subject: [PATCH 7/9] preferences: restrict fontsize input Use HTML5 to restrict the fontsize input to its (arbitrary) minimum value and its (database-driven) maximum value. The type of the `account.fontsize` column is UNSIGNED TINYINT. --- src/config.php | 3 +++ src/pages/Account/PreferencesProcessor.php | 4 ++-- src/templates/Default/engine/Default/preferences.php | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/config.php b/src/config.php index 8b561a5a0..f8dc7a394 100644 --- a/src/config.php +++ b/src/config.php @@ -29,6 +29,7 @@ * Database constants */ const SQL_MAX_UNSIGNED_INT = 4_294_967_295; // 2^32-1 +const SQL_MAX_UNSIGNED_TINYINT = 255; // 2^8-1 const SQL_MAX_TEXT_LENGTH = 65_535; // 2^16-1 /* @@ -449,6 +450,8 @@ const MIN_EXPERIENCE = 0; const MAX_EXPERIENCE = SQL_MAX_UNSIGNED_INT; const MAX_COUNCIL_MEMBERS = 5; +const MIN_FONTSIZE_PERCENT = 50; +const MAX_FONTSIZE_PERCENT = SQL_MAX_UNSIGNED_TINYINT; const MAX_MONEY = SQL_MAX_UNSIGNED_INT; const SHIP_REFUND_PERCENT = .75; diff --git a/src/pages/Account/PreferencesProcessor.php b/src/pages/Account/PreferencesProcessor.php index 4519c9b7b..21bfd3808 100644 --- a/src/pages/Account/PreferencesProcessor.php +++ b/src/pages/Account/PreferencesProcessor.php @@ -143,8 +143,8 @@ public function build(Account $account): never { } elseif ($action === 'Change Size') { $fontsize = Request::getInt('fontsize'); - if ($fontsize < 50) { - create_error('Minimum font size is 50%'); + if ($fontsize < MIN_FONTSIZE_PERCENT) { + create_error('Minimum font size is ' . MIN_FONTSIZE_PERCENT . '%'); } $account->setFontSize($fontsize); $message = 'SUCCESS: You have changed your font size.'; diff --git a/src/templates/Default/engine/Default/preferences.php b/src/templates/Default/engine/Default/preferences.php index e757a434f..52d227e90 100644 --- a/src/templates/Default/engine/Default/preferences.php +++ b/src/templates/Default/engine/Default/preferences.php @@ -334,7 +334,7 @@ Font size: - Minimum font size is 50% + Minimum font size is % From 4970d1b93ee60e4e59d19a2f064d15f279d5ef68 Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Wed, 2 Oct 2024 23:20:45 -0700 Subject: [PATCH 8/9] Alliance: add max length of name/description Use HTML5 to prevent users from entering in an alliance name/description that will result in a database error. --- src/lib/Smr/Alliance.php | 4 ++++ src/templates/Default/engine/Default/alliance_create.php | 4 ++-- src/templates/Default/engine/Default/alliance_stat.php | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/lib/Smr/Alliance.php b/src/lib/Smr/Alliance.php index eba9aebb1..8d3f76794 100644 --- a/src/lib/Smr/Alliance.php +++ b/src/lib/Smr/Alliance.php @@ -40,6 +40,10 @@ class Alliance { public const RECRUIT_CLOSED = 'closed'; public const RECRUIT_PASSWORD = 'password'; + // Database constraints + public const MAXLENGTH_NAME = 36; // varchar(36) + public const MAXLENGTH_DESCRIPTION = 255; // varchar(255) + public static function clearCache(): void { self::$CACHE_ALLIANCES = []; } diff --git a/src/templates/Default/engine/Default/alliance_create.php b/src/templates/Default/engine/Default/alliance_create.php index 54511e389..2c5fd9cf9 100644 --- a/src/templates/Default/engine/Default/alliance_create.php +++ b/src/templates/Default/engine/Default/alliance_create.php @@ -11,11 +11,11 @@ - + - + diff --git a/src/templates/Default/engine/Default/alliance_stat.php b/src/templates/Default/engine/Default/alliance_stat.php index debcec274..9a0f236eb 100644 --- a/src/templates/Default/engine/Default/alliance_stat.php +++ b/src/templates/Default/engine/Default/alliance_stat.php @@ -36,7 +36,7 @@ if ($CanChangeDescription) { ?> - + Date: Wed, 2 Oct 2024 23:28:44 -0700 Subject: [PATCH 9/9] bar_talk_bartender.php: limit gossip length The `bar_tender.message` column is a VARCHAR(255), so limit the message length to 255 to avoid a database error. --- src/templates/Default/engine/Default/bar_talk_bartender.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/Default/engine/Default/bar_talk_bartender.php b/src/templates/Default/engine/Default/bar_talk_bartender.php index 1dfd9a72d..73f2be572 100644 --- a/src/templates/Default/engine/Default/bar_talk_bartender.php +++ b/src/templates/Default/engine/Default/bar_talk_bartender.php @@ -13,7 +13,7 @@
- +

Name:
Description:
Members start with:   
Description: Description: