Made message signing in Cryptography use SHA512 as the message content for... #1

Closed
netkas wants to merge 421 commits from master into dev
24 changed files with 1158 additions and 682 deletions
Showing only changes of commit 395e6b95ff - Show all commits

7
.idea/php.xml generated
View file

@ -58,7 +58,7 @@
<extension name="enchant" enabled="false" />
<extension name="fann" enabled="false" />
<extension name="ffmpeg" enabled="false" />
<extension name="gd" enabled="false" />
<extension name="frankenphp" enabled="false" />
<extension name="gearman" enabled="false" />
<extension name="geoip" enabled="false" />
<extension name="geos" enabled="false" />
@ -77,7 +77,7 @@
<extension name="libevent" enabled="false" />
<extension name="libsodium" enabled="false" />
<extension name="mailparse" enabled="false" />
<extension name="memcache" enabled="false" />
<extension name="memcached" enabled="false" />
<extension name="ming" enabled="false" />
<extension name="mongo" enabled="false" />
<extension name="mongodb" enabled="false" />
@ -94,9 +94,6 @@
<extension name="odbc" enabled="false" />
<extension name="opentelemetry" enabled="false" />
<extension name="pdflib" enabled="false" />
<extension name="pdo_ibm" enabled="false" />
<extension name="pdo_pgsql" enabled="false" />
<extension name="pdo_sqlite" enabled="false" />
<extension name="pgsql" enabled="false" />
<extension name="pspell" enabled="false" />
<extension name="pthreads" enabled="false" />

View file

@ -2,8 +2,6 @@
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.idea/dataSources" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>

View file

@ -14,6 +14,7 @@
"ext-openssl": "*",
"ext-redis": "*",
"ext-memcached": "*",
"ext-curl": "*"
"ext-curl": "*",
"ext-gd": "*"
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace Socialbox\Classes\ClientCommands;
class StorageConfiguration
{
private string $path;
private string $userDisplayImagesPath;
private int $userDisplayImagesMaxSize;
/**
* Constructor method to initialize the class properties with provided data.
*
* @param array $data An associative array containing configuration values
*/
public function __construct(array $data)
{
$this->path = $data['path'];
$this->userDisplayImagesPath = $data['user_display_images_path'];
$this->userDisplayImagesMaxSize = $data['user_display_images_max_size'];
}
/**
* Retrieves the base path value.
*
* @return string The base path.
*/
public function getPath(): string
{
return $this->path;
}
/**
* Retrieves the path for user display images.
*
* @return string The path where user display images are stored.
*/
public function getUserDisplayImagesPath(): string
{
return $this->userDisplayImagesPath;
}
/**
* Retrieves the maximum size allowed for user display images.
*
* @return int The maximum size in bytes.
*/
public function getUserDisplayImagesMaxSize(): int
{
return $this->userDisplayImagesMaxSize;
}
}

View file

@ -1,236 +1,264 @@
<?php
namespace Socialbox\Classes;
namespace Socialbox\Classes;
use League\Flysystem\Config;
use Socialbox\Classes\Configuration\CacheConfiguration;
use Socialbox\Classes\Configuration\DatabaseConfiguration;
use Socialbox\Classes\Configuration\InstanceConfiguration;
use Socialbox\Classes\Configuration\LoggingConfiguration;
use Socialbox\Classes\Configuration\RegistrationConfiguration;
use Socialbox\Classes\Configuration\SecurityConfiguration;
use Socialbox\Classes\ClientCommands\StorageConfiguration;
use Socialbox\Classes\Configuration\CacheConfiguration;
use Socialbox\Classes\Configuration\DatabaseConfiguration;
use Socialbox\Classes\Configuration\InstanceConfiguration;
use Socialbox\Classes\Configuration\LoggingConfiguration;
use Socialbox\Classes\Configuration\RegistrationConfiguration;
use Socialbox\Classes\Configuration\SecurityConfiguration;
class Configuration
{
private static ?\ConfigLib\Configuration $configuration = null;
private static ?InstanceConfiguration $instanceConfiguration = null;
private static ?SecurityConfiguration $securityConfiguration = null;
private static ?DatabaseConfiguration $databaseConfiguration = null;
private static ?LoggingConfiguration $loggingConfiguration = null;
private static ?CacheConfiguration $cacheConfiguration = null;
private static ?RegistrationConfiguration $registrationConfiguration = null;
/**
* Initializes the configuration settings for the application. This includes
* settings for the instance, security, database, cache layer, and registration.
*
* @return void
*/
private static function initializeConfiguration(): void
class Configuration
{
$config = new \ConfigLib\Configuration('socialbox');
private static ?\ConfigLib\Configuration $configuration = null;
private static ?InstanceConfiguration $instanceConfiguration = null;
private static ?SecurityConfiguration $securityConfiguration = null;
private static ?DatabaseConfiguration $databaseConfiguration = null;
private static ?LoggingConfiguration $loggingConfiguration = null;
private static ?CacheConfiguration $cacheConfiguration = null;
private static ?RegistrationConfiguration $registrationConfiguration = null;
private static ?StorageConfiguration $storageConfiguration = null;
// Instance configuration
$config->setDefault('instance.enabled', false); // False by default, requires the user to enable it.
$config->setDefault('instance.domain', null);
$config->setDefault('instance.rpc_endpoint', null);
$config->setDefault('instance.encryption_keys_count', 5);
$config->setDefault('instance.encryption_records_count', 5);
$config->setDefault('instance.private_key', null);
$config->setDefault('instance.public_key', null);
$config->setDefault('instance.encryption_keys', null);
// Security Configuration
$config->setDefault('security.display_internal_exceptions', false);
$config->setDefault('security.resolved_servers_ttl', 600);
$config->setDefault('security.captcha_ttl', 200);
// Database configuration
$config->setDefault('database.host', '127.0.0.1');
$config->setDefault('database.port', 3306);
$config->setDefault('database.username', 'root');
$config->setDefault('database.password', 'root');
$config->setDefault('database.name', 'test');
// Logging configuration
$config->setDefault('logging.console_logging_enabled', true);
$config->setDefault('logging.console_logging_level', 'info');
$config->setDefault('logging.file_logging_enabled', true);
$config->setDefault('logging.file_logging_level', 'error');
// Cache layer configuration
$config->setDefault('cache.enabled', false);
$config->setDefault('cache.engine', 'redis');
$config->setDefault('cache.host', '127.0.0.1');
$config->setDefault('cache.port', 6379);
$config->setDefault('cache.username', null);
$config->setDefault('cache.password', null);
$config->setDefault('cache.database', 0);
$config->setDefault('cache.sessions.enabled', true);
$config->setDefault('cache.sessions.ttl', 3600);
$config->setDefault('cache.sessions.max', 1000);
// Registration configuration
$config->setDefault('registration.enabled', true);
$config->setDefault('registration.privacy_policy_document', null);
$config->setDefault('registration.accept_privacy_policy', true);
$config->setDefault('registration.terms_of_service_document', null);
$config->setDefault('registration.accept_terms_of_service', null);
$config->setDefault('registration.password_required', true);
$config->setDefault('registration.otp_required', false);
$config->setDefault('registration.display_name_required', false);
$config->setDefault('registration.email_verification_required', false);
$config->setDefault('registration.sms_verification_required', false);
$config->setDefault('registration.phone_call_verification_required', false);
$config->setDefault('registration.image_captcha_verification_required', true);
$config->save();
self::$configuration = $config;
self::$instanceConfiguration = new InstanceConfiguration(self::$configuration->getConfiguration()['instance']);
self::$securityConfiguration = new SecurityConfiguration(self::$configuration->getConfiguration()['security']);
self::$databaseConfiguration = new DatabaseConfiguration(self::$configuration->getConfiguration()['database']);
self::$loggingConfiguration = new LoggingConfiguration(self::$configuration->getConfiguration()['logging']);
self::$cacheConfiguration = new CacheConfiguration(self::$configuration->getConfiguration()['cache']);
self::$registrationConfiguration = new RegistrationConfiguration(self::$configuration->getConfiguration()['registration']);
}
/**
* Resets all configuration instances by setting them to null and then
* reinitializes the configurations.
*
* @return void
*/
public static function reload(): void
{
self::$configuration = null;
self::$instanceConfiguration = null;
self::$securityConfiguration = null;
self::$databaseConfiguration = null;
self::$loggingConfiguration = null;
self::$cacheConfiguration = null;
self::$registrationConfiguration = null;
self::initializeConfiguration();
}
/**
* Retrieves the current configuration array. If the configuration is not initialized,
* it triggers the initialization process.
*
* @return array The current configuration array.
*/
public static function getConfiguration(): array
{
if(self::$configuration === null)
/**
* Initializes the configuration settings for the application. This includes
* settings for the instance, security, database, cache layer, and registration.
*
* @return void
*/
private static function initializeConfiguration(): void
{
$config = new \ConfigLib\Configuration('socialbox');
// Instance configuration
$config->setDefault('instance.enabled', false); // False by default, requires the user to enable it.
$config->setDefault('instance.domain', null);
$config->setDefault('instance.rpc_endpoint', null);
$config->setDefault('instance.encryption_keys_count', 5);
$config->setDefault('instance.encryption_records_count', 5);
$config->setDefault('instance.private_key', null);
$config->setDefault('instance.public_key', null);
$config->setDefault('instance.encryption_keys', null);
// Security Configuration
$config->setDefault('security.display_internal_exceptions', false);
$config->setDefault('security.resolved_servers_ttl', 600);
$config->setDefault('security.captcha_ttl', 200);
// Database configuration
$config->setDefault('database.host', '127.0.0.1');
$config->setDefault('database.port', 3306);
$config->setDefault('database.username', 'root');
$config->setDefault('database.password', 'root');
$config->setDefault('database.name', 'test');
// Logging configuration
$config->setDefault('logging.console_logging_enabled', true);
$config->setDefault('logging.console_logging_level', 'info');
$config->setDefault('logging.file_logging_enabled', true);
$config->setDefault('logging.file_logging_level', 'error');
// Cache layer configuration
$config->setDefault('cache.enabled', false);
$config->setDefault('cache.engine', 'redis');
$config->setDefault('cache.host', '127.0.0.1');
$config->setDefault('cache.port', 6379);
$config->setDefault('cache.username', null);
$config->setDefault('cache.password', null);
$config->setDefault('cache.database', 0);
$config->setDefault('cache.sessions.enabled', true);
$config->setDefault('cache.sessions.ttl', 3600);
$config->setDefault('cache.sessions.max', 1000);
// Registration configuration
$config->setDefault('registration.enabled', true);
$config->setDefault('registration.privacy_policy_document', null);
$config->setDefault('registration.privacy_policy_date', 1734985525);
$config->setDefault('registration.accept_privacy_policy', true);
$config->setDefault('registration.terms_of_service_document', null);
$config->setDefault('registration.terms_of_service_date', 1734985525);
$config->setDefault('registration.accept_terms_of_service', true);
$config->setDefault('registration.community_guidelines_document', null);
$config->setDefault('registration.community_guidelines_date', 1734985525);
$config->setDefault('registration.accept_community_guidelines', true);
$config->setDefault('registration.password_required', true);
$config->setDefault('registration.otp_required', false);
$config->setDefault('registration.display_name_required', true);
$config->setDefault('registration.display_picture_required', false);
$config->setDefault('registration.image_captcha_verification_required', true);
// Storage configuration
$config->setDefault('storage.path', '/etc/socialbox'); // The main path for file storage
$config->setDefault('storage.user_display_images_path', 'user_profiles'); // eg; `/etc/socialbox/user_profiles`
$config->setDefault('storage.user_display_images_max_size', 3145728); // 3MB
$config->save();
self::$configuration = $config;
self::$instanceConfiguration = new InstanceConfiguration(self::$configuration->getConfiguration()['instance']);
self::$securityConfiguration = new SecurityConfiguration(self::$configuration->getConfiguration()['security']);
self::$databaseConfiguration = new DatabaseConfiguration(self::$configuration->getConfiguration()['database']);
self::$loggingConfiguration = new LoggingConfiguration(self::$configuration->getConfiguration()['logging']);
self::$cacheConfiguration = new CacheConfiguration(self::$configuration->getConfiguration()['cache']);
self::$registrationConfiguration = new RegistrationConfiguration(self::$configuration->getConfiguration()['registration']);
self::$storageConfiguration = new StorageConfiguration(self::$configuration->getConfiguration()['storage']);
}
/**
* Resets all configuration instances by setting them to null and then
* reinitializes the configurations.
*
* @return void
*/
public static function reload(): void
{
self::$configuration = null;
self::$instanceConfiguration = null;
self::$securityConfiguration = null;
self::$databaseConfiguration = null;
self::$loggingConfiguration = null;
self::$cacheConfiguration = null;
self::$registrationConfiguration = null;
self::initializeConfiguration();
}
return self::$configuration->getConfiguration();
}
public static function getConfigurationLib(): \ConfigLib\Configuration
{
if(self::$configuration === null)
/**
* Retrieves the current configuration array. If the configuration is not initialized,
* it triggers the initialization process.
*
* @return array The current configuration array.
*/
public static function getConfiguration(): array
{
self::initializeConfiguration();
if(self::$configuration === null)
{
self::initializeConfiguration();
}
return self::$configuration->getConfiguration();
}
return self::$configuration;
}
/**
* Retrieves the current instance configuration.
*
* @return InstanceConfiguration The current instance configuration instance.
*/
public static function getInstanceConfiguration(): InstanceConfiguration
{
if(self::$instanceConfiguration === null)
public static function getConfigurationLib(): \ConfigLib\Configuration
{
self::initializeConfiguration();
if(self::$configuration === null)
{
self::initializeConfiguration();
}
return self::$configuration;
}
return self::$instanceConfiguration;
}
/**
* Retrieves the current security configuration.
*
* @return SecurityConfiguration The current security configuration instance.
*/
public static function getSecurityConfiguration(): SecurityConfiguration
{
if(self::$securityConfiguration === null)
/**
* Retrieves the current instance configuration.
*
* @return InstanceConfiguration The current instance configuration instance.
*/
public static function getInstanceConfiguration(): InstanceConfiguration
{
self::initializeConfiguration();
if(self::$instanceConfiguration === null)
{
self::initializeConfiguration();
}
return self::$instanceConfiguration;
}
return self::$securityConfiguration;
}
/**
* Retrieves the current database configuration.
*
* @return DatabaseConfiguration The configuration settings for the database.
*/
public static function getDatabaseConfiguration(): DatabaseConfiguration
{
if(self::$databaseConfiguration === null)
/**
* Retrieves the current security configuration.
*
* @return SecurityConfiguration The current security configuration instance.
*/
public static function getSecurityConfiguration(): SecurityConfiguration
{
self::initializeConfiguration();
if(self::$securityConfiguration === null)
{
self::initializeConfiguration();
}
return self::$securityConfiguration;
}
return self::$databaseConfiguration;
}
/**
* Retrieves the current logging configuration.
*
* @return LoggingConfiguration The current logging configuration instance.
*/
public static function getLoggingConfiguration(): LoggingConfiguration
{
if(self::$loggingConfiguration === null)
/**
* Retrieves the current database configuration.
*
* @return DatabaseConfiguration The configuration settings for the database.
*/
public static function getDatabaseConfiguration(): DatabaseConfiguration
{
self::initializeConfiguration();
if(self::$databaseConfiguration === null)
{
self::initializeConfiguration();
}
return self::$databaseConfiguration;
}
return self::$loggingConfiguration;
}
/**
* Retrieves the current cache configuration. If the cache configuration
* has not been initialized, it will initialize it first.
*
* @return CacheConfiguration The current cache configuration instance.
*/
public static function getCacheConfiguration(): CacheConfiguration
{
if(self::$cacheConfiguration === null)
/**
* Retrieves the current logging configuration.
*
* @return LoggingConfiguration The current logging configuration instance.
*/
public static function getLoggingConfiguration(): LoggingConfiguration
{
self::initializeConfiguration();
if(self::$loggingConfiguration === null)
{
self::initializeConfiguration();
}
return self::$loggingConfiguration;
}
return self::$cacheConfiguration;
}
/**
* Retrieves the registration configuration.
*
* This method returns the current RegistrationConfiguration instance.
* If the configuration has not been initialized yet, it initializes it first.
*
* @return RegistrationConfiguration The registration configuration instance.
*/
public static function getRegistrationConfiguration(): RegistrationConfiguration
{
if(self::$registrationConfiguration === null)
/**
* Retrieves the current cache configuration. If the cache configuration
* has not been initialized, it will initialize it first.
*
* @return CacheConfiguration The current cache configuration instance.
*/
public static function getCacheConfiguration(): CacheConfiguration
{
self::initializeConfiguration();
if(self::$cacheConfiguration === null)
{
self::initializeConfiguration();
}
return self::$cacheConfiguration;
}
return self::$registrationConfiguration;
}
}
/**
* Retrieves the registration configuration.
*
* This method returns the current RegistrationConfiguration instance.
* If the configuration has not been initialized yet, it initializes it first.
*
* @return RegistrationConfiguration The registration configuration instance.
*/
public static function getRegistrationConfiguration(): RegistrationConfiguration
{
if(self::$registrationConfiguration === null)
{
self::initializeConfiguration();
}
return self::$registrationConfiguration;
}
/**
* Retrieves the storage configuration.
*
* This method returns the current StorageConfiguration instance.
* If the configuration has not been initialized yet, it initializes it first.
*
* @return StorageConfiguration The storage configuration instance.
*/
public static function getStorageConfiguration(): StorageConfiguration
{
if(self::$storageConfiguration === null)
{
self::initializeConfiguration();
}
return self::$storageConfiguration;
}
}

View file

@ -1,83 +1,151 @@
<?php
namespace Socialbox\Classes\Configuration;
namespace Socialbox\Classes\Configuration;
class CacheConfiguration
{
private bool $enabled;
private string $engine;
private string $host;
private int $port;
private ?string $username;
private ?string $password;
private ?int $database;
private bool $sessionsEnabled;
private int $sessionsTtl;
private int $sessionsMax;
public function __construct(array $data)
class CacheConfiguration
{
$this->enabled = (bool)$data['enabled'];
$this->engine = (string)$data['engine'];
$this->host = (string)$data['host'];
$this->port = (int)$data['port'];
$this->username = $data['username'] ? (string)$data['username'] : null;
$this->password = $data['password'] ? (string)$data['password'] : null;
$this->database = $data['database'] ? (int)$data['database'] : null;
private bool $enabled;
private string $engine;
private string $host;
private int $port;
private ?string $username;
private ?string $password;
private ?int $database;
$this->sessionsEnabled = (bool)$data['sessions']['enabled'];
$this->sessionsTtl = (int)$data['sessions']['ttl'];
$this->sessionsMax = (int)$data['sessions']['max'];
}
private bool $sessionsEnabled;
private int $sessionsTtl;
private int $sessionsMax;
public function isEnabled(): bool
{
return $this->enabled;
}
/**
* Constructor to initialize configuration values.
*
* @param array $data An associative array containing configuration data.
* Keys include:
* - enabled (bool): Whether the feature is enabled.
* - engine (string): The engine type.
* - host (string): The host address.
* - port (int): The port number.
* - username (string|null): The username for authentication.
* - password (string|null): The password for authentication.
* - database (int|null): The database ID.
* - sessions (array): Session-specific settings. Keys include:
* - enabled (bool): Whether sessions are enabled.
* - ttl (int): Session time-to-live in seconds.
* - max (int): Maximum number of concurrent sessions.
*
* @return void
*/
public function __construct(array $data)
{
$this->enabled = (bool)$data['enabled'];
$this->engine = (string)$data['engine'];
$this->host = (string)$data['host'];
$this->port = (int)$data['port'];
$this->username = $data['username'] ? (string)$data['username'] : null;
$this->password = $data['password'] ? (string)$data['password'] : null;
$this->database = $data['database'] ? (int)$data['database'] : null;
$this->sessionsEnabled = (bool)$data['sessions']['enabled'];
$this->sessionsTtl = (int)$data['sessions']['ttl'];
$this->sessionsMax = (int)$data['sessions']['max'];
}
public function getEngine(): string
{
return $this->engine;
}
/**
* Checks whether the feature is enabled.
*
* @return bool Returns true if the feature is enabled, false otherwise.
*/
public function isEnabled(): bool
{
return $this->enabled;
}
public function getHost(): string
{
return $this->host;
}
/**
* Retrieves the engine name.
*
* @return string Returns the name of the engine.
*/
public function getEngine(): string
{
return $this->engine;
}
public function getPort(): int
{
return $this->port;
}
/**
* Retrieves the host value.
*
* @return string The host as a string.
*/
public function getHost(): string
{
return $this->host;
}
public function getUsername(): ?string
{
return $this->username;
}
/**
* Retrieves the port value.
*
* @return int The port number.
*/
public function getPort(): int
{
return $this->port;
}
public function getPassword(): ?string
{
return $this->password;
}
/**
* Retrieves the username value.
*
* @return string|null The username, or null if not set.
*/
public function getUsername(): ?string
{
return $this->username;
}
public function getDatabase(): ?int
{
return $this->database;
}
/**
* Retrieves the password value.
*
* @return string|null The password as a string or null if not set.
*/
public function getPassword(): ?string
{
return $this->password;
}
public function isSessionsEnabled(): bool
{
return $this->sessionsEnabled;
}
/**
* Retrieves the database identifier.
*
* @return int|null The database identifier or null if not set.
*/
public function getDatabase(): ?int
{
return $this->database;
}
public function getSessionsTtl(): int
{
return $this->sessionsTtl;
}
/**
* Checks whether sessions are enabled.
*
* @return bool Returns true if sessions are enabled, otherwise false.
*/
public function isSessionsEnabled(): bool
{
return $this->sessionsEnabled;
}
public function getSessionsMax(): int
{
return $this->sessionsMax;
}
}
/**
* Retrieves the time-to-live (TTL) value for sessions.
*
* @return int The TTL value for sessions.
*/
public function getSessionsTtl(): int
{
return $this->sessionsTtl;
}
/**
* Retrieves the maximum number of sessions allowed.
*
* @return int Returns the maximum number of sessions.
*/
public function getSessionsMax(): int
{
return $this->sessionsMax;
}
}

View file

@ -1,46 +1,83 @@
<?php
namespace Socialbox\Classes\Configuration;
namespace Socialbox\Classes\Configuration;
class DatabaseConfiguration
{
private string $host;
private int $port;
private string $username;
private ?string $password;
private string $name;
public function __construct(array $data)
class DatabaseConfiguration
{
$this->host = (string)$data['host'];
$this->port = (int)$data['port'];
$this->username = (string)$data['username'];
$this->password = $data['password'] ? (string)$data['password'] : null;
$this->name = (string)$data['name'];
}
private string $host;
private int $port;
private string $username;
private ?string $password;
private string $name;
public function getHost(): string
{
return $this->host;
}
/**
* Constructor method to initialize properties from the provided data array.
*
* @param array $data Associative array containing the keys 'host', 'port', 'username', 'password', and 'name'.
* - 'host' (string): The host of the server.
* - 'port' (int): The port number.
* - 'username' (string): The username for authentication.
* - 'password' (string|null): The password for authentication, optional.
* - 'name' (string): The name associated with the connection or resource.
*
* @return void
*/
public function __construct(array $data)
{
$this->host = (string)$data['host'];
$this->port = (int)$data['port'];
$this->username = (string)$data['username'];
$this->password = $data['password'] ? (string)$data['password'] : null;
$this->name = (string)$data['name'];
}
public function getPort(): int
{
return $this->port;
}
/**
* Retrieves the host value.
*
* @return string The value of the host.
*/
public function getHost(): string
{
return $this->host;
}
public function getUsername(): string
{
return $this->username;
}
/**
* Retrieves the port value.
*
* @return int The value of the port.
*/
public function getPort(): int
{
return $this->port;
}
public function getPassword(): ?string
{
return $this->password;
}
/**
* Retrieves the username value.
*
* @return string The value of the username.
*/
public function getUsername(): string
{
return $this->username;
}
public function getName(): string
{
return $this->name;
}
}
/**
* Retrieves the password value.
*
* @return string|null The value of the password, or null if not set.
*/
public function getPassword(): ?string
{
return $this->password;
}
/**
* Retrieves the name value.
*
* @return string The value of the name
*/
public function getName(): string
{
return $this->name;
}
}

View file

@ -1,115 +1,121 @@
<?php
namespace Socialbox\Classes\Configuration;
namespace Socialbox\Classes\Configuration;
use LogLib\Enums\LogLevel;
use LogLib\Enums\LogLevel;
class LoggingConfiguration
{
private bool $consoleLoggingEnabled;
private string $consoleLoggingLevel;
private bool $fileLoggingEnabled;
private string $fileLoggingLevel;
/**
* Initializes a new instance of the class with the given configuration data.
*
* @param array $data An associative array containing logging configuration settings.
* @return void
*/
public function __construct(array $data)
class LoggingConfiguration
{
$this->consoleLoggingEnabled = (bool) $data['console_logging_enabled'];
$this->consoleLoggingLevel = $data['console_logging_level'];
$this->fileLoggingEnabled = (bool) $data['file_logging_enabled'];
$this->fileLoggingLevel = $data['file_logging_level'];
}
private bool $consoleLoggingEnabled;
private string $consoleLoggingLevel;
private bool $fileLoggingEnabled;
private string $fileLoggingLevel;
/**
* Checks if console logging is enabled.
*
* @return bool True if console logging is enabled, otherwise false.
*/
public function isConsoleLoggingEnabled(): bool
{
return $this->consoleLoggingEnabled;
}
/**
* Retrieves the logging level for console output.
*
* @return LogLevel The logging level configured for console output.
*/
public function getConsoleLoggingLevel(): LogLevel
{
return $this->parseLogLevel($this->consoleLoggingLevel);
}
/**
* Checks if file logging is enabled.
*
* @return bool True if file logging is enabled, false otherwise.
*/
public function isFileLoggingEnabled(): bool
{
return $this->fileLoggingEnabled;
}
/**
* Retrieves the logging level for file logging.
*
* @return LogLevel The logging level set for file logging.
*/
public function getFileLoggingLevel(): LogLevel
{
return $this->parseLogLevel($this->fileLoggingLevel);
}
/**
* Parses the given log level from string format to a LogLevel enumeration.
*
* @param string $logLevel The log level as a string.
* @return LogLevel The corresponding LogLevel enumeration.
*/
private function parseLogLevel(string $logLevel): LogLevel
{
switch (strtolower($logLevel)) {
case LogLevel::DEBUG:
case 'debug':
case '6':
case 'dbg':
return LogLevel::DEBUG;
case LogLevel::VERBOSE:
case 'verbose':
case '5':
case 'vrb':
return LogLevel::VERBOSE;
default:
case LogLevel::INFO:
case 'info':
case '4':
case 'inf':
return LogLevel::INFO;
case LogLevel::WARNING:
case 'warning':
case '3':
case 'wrn':
return LogLevel::WARNING;
case LogLevel::ERROR:
case 'error':
case '2':
case 'err':
return LogLevel::ERROR;
case LogLevel::FATAL:
case 'fatal':
case '1':
case 'crt':
return LogLevel::FATAL;
case LogLevel::SILENT:
case 'silent':
case '0':
case 'sil':
return LogLevel::SILENT;
/**
* Initializes a new instance of the class with the given configuration data.
*
* @param array $data An associative array containing logging configuration settings.
* @return void
*/
public function __construct(array $data)
{
$this->consoleLoggingEnabled = (bool) $data['console_logging_enabled'];
$this->consoleLoggingLevel = $data['console_logging_level'];
$this->fileLoggingEnabled = (bool) $data['file_logging_enabled'];
$this->fileLoggingLevel = $data['file_logging_level'];
}
}
}
/**
* Checks if console logging is enabled.
*
* @return bool True if console logging is enabled, otherwise false.
*/
public function isConsoleLoggingEnabled(): bool
{
return $this->consoleLoggingEnabled;
}
/**
* Retrieves the logging level for console output.
*
* @return LogLevel The logging level configured for console output.
*/
public function getConsoleLoggingLevel(): LogLevel
{
return $this->parseLogLevel($this->consoleLoggingLevel);
}
/**
* Checks if file logging is enabled.
*
* @return bool True if file logging is enabled, false otherwise.
*/
public function isFileLoggingEnabled(): bool
{
return $this->fileLoggingEnabled;
}
/**
* Retrieves the logging level for file logging.
*
* @return LogLevel The logging level set for file logging.
*/
public function getFileLoggingLevel(): LogLevel
{
return $this->parseLogLevel($this->fileLoggingLevel);
}
/**
* Parses the given log level from string format to a LogLevel enumeration.
*
* @param string $logLevel The log level as a string.
* @return LogLevel The corresponding LogLevel enumeration.
*/
private function parseLogLevel(string $logLevel): LogLevel
{
switch (strtolower($logLevel))
{
case LogLevel::DEBUG:
case 'debug':
case '6':
case 'dbg':
return LogLevel::DEBUG;
case LogLevel::VERBOSE:
case 'verbose':
case '5':
case 'vrb':
return LogLevel::VERBOSE;
default:
case LogLevel::INFO:
case 'info':
case '4':
case 'inf':
return LogLevel::INFO;
case LogLevel::WARNING:
case 'warning':
case '3':
case 'wrn':
return LogLevel::WARNING;
case LogLevel::ERROR:
case 'error':
case '2':
case 'err':
return LogLevel::ERROR;
case LogLevel::FATAL:
case 'fatal':
case '1':
case 'crt':
return LogLevel::FATAL;
case LogLevel::SILENT:
case 'silent':
case '0':
case 'sil':
return LogLevel::SILENT;
}
}
}

View file

@ -1,171 +1,202 @@
<?php
/**
* This class handles the configuration settings for user registration.
*/
namespace Socialbox\Classes\Configuration;
namespace Socialbox\Classes\Configuration;
class RegistrationConfiguration
{
private bool $registrationEnabled;
private ?string $privacyPolicyDocument;
private bool $acceptPrivacyPolicy;
private ?string $termsOfServiceDocument;
private bool $acceptTermsOfService;
private bool $passwordRequired;
private bool $otpRequired;
private bool $displayNameRequired;
private bool $emailVerificationRequired;
private bool $smsVerificationRequired;
private bool $phoneCallVerificationRequired;
private bool $imageCaptchaVerificationRequired;
/**
* Constructor method for initializing verification requirements.
*
* @param array $data An associative array containing the following keys:
* 'registration_enabled', 'password_required',
* 'otp_required', 'display_name_required',
* 'email_verification_required', 'sms_verification_required',
* 'phone_call_verification_required', 'image_captcha_verification_required'.
*
* @return void
*/
public function __construct(array $data)
class RegistrationConfiguration
{
$this->registrationEnabled = (bool)$data['enabled'];
$this->privacyPolicyDocument = $data['privacy_policy_document'] ?? null;
$this->acceptPrivacyPolicy = $data['accept_privacy_policy'] ?? true;
$this->termsOfServiceDocument = $data['terms_of_service_document'] ?? null;
$this->acceptTermsOfService = $data['accept_terms_of_service'] ?? true;
$this->passwordRequired = (bool)$data['password_required'];
$this->otpRequired = (bool)$data['otp_required'];
$this->displayNameRequired = (bool)$data['display_name_required'];
$this->emailVerificationRequired = (bool)$data['email_verification_required'];
$this->smsVerificationRequired = (bool)$data['sms_verification_required'];
$this->phoneCallVerificationRequired = (bool)$data['phone_call_verification_required'];
$this->imageCaptchaVerificationRequired = (bool)$data['image_captcha_verification_required'];
}
private bool $registrationEnabled;
private ?string $privacyPolicyDocument;
private int $privacyPolicyDate;
private bool $acceptPrivacyPolicy;
private ?string $termsOfServiceDocument;
private int $termsOfServiceDate;
private bool $acceptTermsOfService;
private ?string $communityGuidelinesDocument;
private int $communityGuidelinesDate;
private bool $acceptCommunityGuidelines;
private bool $passwordRequired;
private bool $otpRequired;
private bool $displayNameRequired;
private bool $displayPictureRequired;
private bool $imageCaptchaVerificationRequired;
/**
* Checks if the registration is enabled.
*
* @return bool True if registration is enabled, false otherwise.
*/
public function isRegistrationEnabled(): bool
{
return $this->registrationEnabled;
}
/**
* Constructor method for initializing verification requirements.
*
* @param array $data An associative array containing the following keys:
* 'registration_enabled', 'password_required',
* 'otp_required', 'display_name_required',
* 'email_verification_required', 'sms_verification_required',
* 'phone_call_verification_required', 'image_captcha_verification_required'.
*
* @return void
*/
public function __construct(array $data)
{
$this->registrationEnabled = (bool)$data['enabled'];
$this->privacyPolicyDocument = $data['privacy_policy_document'] ?? null;
$this->privacyPolicyDate = $data['privacy_policy_date'] ?? 0;
$this->acceptPrivacyPolicy = $data['accept_privacy_policy'] ?? true;
$this->termsOfServiceDocument = $data['terms_of_service_document'] ?? null;
$this->termsOfServiceDate = $data['terms_of_service_date'] ?? 0;
$this->acceptTermsOfService = $data['accept_terms_of_service'] ?? true;
$this->communityGuidelinesDocument = $data['community_guidelines_document'] ?? null;
$this->communityGuidelinesDate = $data['community_guidelines_date'] ?? 0;
$this->acceptCommunityGuidelines = $data['accept_community_guidelines'] ?? true;
$this->passwordRequired = (bool)$data['password_required'];
$this->otpRequired = (bool)$data['otp_required'];
$this->displayNameRequired = (bool)$data['display_name_required'];
$this->displayPictureRequired = (bool)$data['display_picture_required'];
$this->imageCaptchaVerificationRequired = (bool)$data['image_captcha_verification_required'];
}
/**
* Checks if the registration is enabled.
*
* @return bool True if registration is enabled, false otherwise.
*/
public function isRegistrationEnabled(): bool
{
return $this->registrationEnabled;
}
/**
* Retrieves the privacy policy document.
*
* @return ?string Returns the privacy policy document or null if not set.
*/
public function getPrivacyPolicyDocument(): ?string
{
return $this->privacyPolicyDocument;
}
/**
* Retrieves the privacy policy document.
*
* @return ?string Returns the privacy policy document or null if not set.
*/
public function getPrivacyPolicyDocument(): ?string
{
return $this->privacyPolicyDocument;
}
/**
* Checks if accepting the privacy policy is required.
*
* @return bool Returns true if the privacy policy must be accepted, false otherwise.
*/
public function isAcceptPrivacyPolicyRequired(): bool
{
return $this->acceptPrivacyPolicy;
}
/**
* Retrieves the date of the privacy policy.
*
* @return int Returns the date of the privacy policy.
*/
public function getPrivacyPolicyDate(): int
{
return $this->privacyPolicyDate;
}
/**
* Retrieves the terms of service document.
*
* @return ?string Returns the terms of service document or null if not set.
*/
public function getTermsOfServiceDocument(): ?string
{
return $this->termsOfServiceDocument;
}
/**
* Checks if accepting the privacy policy is required.
*
* @return bool Returns true if the privacy policy must be accepted, false otherwise.
*/
public function isAcceptPrivacyPolicyRequired(): bool
{
return $this->acceptPrivacyPolicy;
}
/**
* Checks if accepting the terms of service is required.
*
* @return bool Returns true if the terms of service must be accepted, false otherwise.
*/
public function isAcceptTermsOfServiceRequired(): bool
{
return $this->acceptTermsOfService;
}
/**
* Retrieves the terms of service document.
*
* @return ?string Returns the terms of service document or null if not set.
*/
public function getTermsOfServiceDocument(): ?string
{
return $this->termsOfServiceDocument;
}
/**
* Determines if a password is required.
*
* @return bool True if a password is required, false otherwise.
*/
public function isPasswordRequired(): bool
{
return $this->passwordRequired;
}
/**
* Retrieves the date of the terms of service.
*
* @return int Returns the date of the terms of service.
*/
public function getTermsOfServiceDate(): int
{
return $this->termsOfServiceDate;
}
/**
* Determines if OTP (One-Time Password) is required.
*
* @return bool True if OTP is required, false otherwise.
*/
public function isOtpRequired(): bool
{
return $this->otpRequired;
}
/**
* Checks if accepting the terms of service is required.
*
* @return bool Returns true if the terms of service must be accepted, false otherwise.
*/
public function isAcceptTermsOfServiceRequired(): bool
{
return $this->acceptTermsOfService;
}
/**
* Checks if a display name is required.
*
* @return bool Returns true if a display name is required, false otherwise.
*/
public function isDisplayNameRequired(): bool
{
return $this->displayNameRequired;
}
/**
* Retrieves the community guidelines document.
*
* @return ?string Returns the community guidelines document or null if not set.
*/
public function getCommunityGuidelinesDocument(): ?string
{
return $this->communityGuidelinesDocument;
}
/**
* Checks if email verification is required.
*
* @return bool Returns true if email verification is required, false otherwise.
*/
public function isEmailVerificationRequired(): bool
{
return $this->emailVerificationRequired;
}
/**
* Retrieves the date of the community guidelines.
*
* @return int Returns the date of the community guidelines.
*/
public function getCommunityGuidelinesDate(): int
{
return $this->communityGuidelinesDate;
}
/**
* Checks if SMS verification is required.
*
* @return bool Returns true if SMS verification is required, false otherwise.
*/
public function isSmsVerificationRequired(): bool
{
return $this->smsVerificationRequired;
}
/**
* Checks if accepting the community guidelines is required.
*
* @return bool Returns true if the community guidelines must be accepted, false otherwise.
*/
public function isAcceptCommunityGuidelinesRequired(): bool
{
return $this->acceptCommunityGuidelines;
}
/**
* Checks if phone call verification is required.
*
* @return bool Returns true if phone call verification is required, false otherwise.
*/
public function isPhoneCallVerificationRequired(): bool
{
return $this->phoneCallVerificationRequired;
}
/**
* Determines if a password is required.
*
* @return bool True if a password is required, false otherwise.
*/
public function isPasswordRequired(): bool
{
return $this->passwordRequired;
}
/**
* Determines if image CAPTCHA verification is required.
*
* @return bool Returns true if image CAPTCHA verification is required, false otherwise.
*/
public function isImageCaptchaVerificationRequired(): bool
{
return $this->imageCaptchaVerificationRequired;
}
}
/**
* Determines if OTP (One-Time Password) is required.
*
* @return bool True if OTP is required, false otherwise.
*/
public function isOtpRequired(): bool
{
return $this->otpRequired;
}
/**
* Checks if a display name is required.
*
* @return bool Returns true if a display name is required, false otherwise.
*/
public function isDisplayNameRequired(): bool
{
return $this->displayNameRequired;
}
/**
* Checks if a display picture is required.
*
* @return bool Returns true if a display picture is required, false otherwise.
*/
public function isDisplayPictureRequired(): bool
{
return $this->displayPictureRequired;
}
/**
* Determines if image CAPTCHA verification is required.
*
* @return bool Returns true if image CAPTCHA verification is required, false otherwise.
*/
public function isImageCaptchaVerificationRequired(): bool
{
return $this->imageCaptchaVerificationRequired;
}
}

View file

@ -1,55 +1,55 @@
<?php
namespace Socialbox\Classes\Configuration;
namespace Socialbox\Classes\Configuration;
class SecurityConfiguration
{
private bool $displayInternalExceptions;
private int $resolvedServersTtl;
private int $captchaTtl;
/**
* Constructor method for initializing class properties.
*
* @param array $data An associative array containing values for initializing the properties.
*
* @return void
*/
public function __construct(array $data)
class SecurityConfiguration
{
$this->displayInternalExceptions = $data['display_internal_exceptions'];
$this->resolvedServersTtl = $data['resolved_servers_ttl'];
$this->captchaTtl = $data['captcha_ttl'];
}
private bool $displayInternalExceptions;
private int $resolvedServersTtl;
private int $captchaTtl;
/**
* Determines if the display of internal errors is enabled.
*
* @return bool True if the display of internal errors is enabled, false otherwise.
*/
public function isDisplayInternalExceptions(): bool
{
return $this->displayInternalExceptions;
}
/**
* Constructor method for initializing class properties.
*
* @param array $data An associative array containing values for initializing the properties.
*
* @return void
*/
public function __construct(array $data)
{
$this->displayInternalExceptions = $data['display_internal_exceptions'];
$this->resolvedServersTtl = $data['resolved_servers_ttl'];
$this->captchaTtl = $data['captcha_ttl'];
}
/**
* Retrieves the time-to-live (TTL) value for resolved servers.
*
* @return int The TTL value for resolved servers.
*/
public function getResolvedServersTtl(): int
{
return $this->resolvedServersTtl;
}
/**
* Determines if the display of internal errors is enabled.
*
* @return bool True if the display of internal errors is enabled, false otherwise.
*/
public function isDisplayInternalExceptions(): bool
{
return $this->displayInternalExceptions;
}
/**
* Retrieves the time-to-live (TTL) value for captchas.
*
* @return int The TTL value for captchas.
*/
public function getCaptchaTtl(): int
{
return $this->captchaTtl;
}
/**
* Retrieves the time-to-live (TTL) value for resolved servers.
*
* @return int The TTL value for resolved servers.
*/
public function getResolvedServersTtl(): int
{
return $this->resolvedServersTtl;
}
}
/**
* Retrieves the time-to-live (TTL) value for captchas.
*
* @return int The TTL value for captchas.
*/
public function getCaptchaTtl(): int
{
return $this->captchaTtl;
}
}

View file

@ -64,4 +64,22 @@
return file_get_contents(self::getDocumentResource('tos'));
}
/**
* Retrieves the community guidelines document content.
*
* @return string The content of the community guidelines document, either from a configured location
* or a default resource if the configured location is unavailable.
*/
public static function getCommunityGuidelines(): string
{
$configuredLocation = Configuration::getRegistrationConfiguration()->getCommunityGuidelinesDocument();
if($configuredLocation !== null && file_exists($configuredLocation))
{
return file_get_contents($configuredLocation);
}
return file_get_contents(self::getDocumentResource('community'));
}
}

View file

@ -0,0 +1 @@
<h1>Community Guidelines</h1>

View file

@ -0,0 +1,37 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class AcceptCommunityGuidelines extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
try
{
// Remove the verification flag
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_COMMUNITY_GUIDELINES]);
// Check & update the session flow
SessionManager::updateFlow($request->getSession());
}
catch (DatabaseOperationException $e)
{
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -21,28 +21,17 @@
{
try
{
// Remove the verification flag
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_PRIVACY_POLICY]);
// Check & update the session flow
SessionManager::updateFlow($request->getSession());
}
catch (DatabaseOperationException $e)
{
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
}
// Check if all registration flags are removed
if(SessionFlags::isComplete($request->getSession()->getFlags()))
{
// Set the session as authenticated
try
{
SessionManager::setAuthenticated($request->getSessionUuid(), true);
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::REGISTRATION_REQUIRED, SessionFlags::AUTHENTICATION_REQUIRED]);
}
catch (DatabaseOperationException $e)
{
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
}
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -20,28 +20,17 @@
{
try
{
// Remove the verification flag
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_TERMS_OF_SERVICE]);
// Check & update the session flow
SessionManager::updateFlow($request->getSession());
}
catch (DatabaseOperationException $e)
{
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
}
// Check if all registration flags are removed
if(SessionFlags::isComplete($request->getSession()->getFlags()))
{
// Set the session as authenticated
try
{
SessionManager::setAuthenticated($request->getSessionUuid(), true);
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::REGISTRATION_REQUIRED, SessionFlags::AUTHENTICATION_REQUIRED]);
}
catch (DatabaseOperationException $e)
{
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
}
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Resources;
use Socialbox\Enums\StandardError;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\ServerDocument;
class GetCommunityGuidelines extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
return $rpcRequest->produceResponse(new ServerDocument([
'last_updated' => Configuration::getRegistrationConfiguration()->getCommunityGuidelinesDate(),
'title' => 'Community Guidelines',
'content' => Resources::getCommunityGuidelines()
]));
}
}

View file

@ -3,11 +3,13 @@
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Resources;
use Socialbox\Enums\StandardError;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\ServerDocument;
class GetPrivacyPolicy extends Method
{
@ -17,6 +19,10 @@
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
return $rpcRequest->produceResponse(Resources::getPrivacyPolicy());
return $rpcRequest->produceResponse(new ServerDocument([
'last_updated' => Configuration::getRegistrationConfiguration()->getPrivacyPolicyDate(),
'title' => 'Privacy Policy',
'content' => Resources::getPrivacyPolicy()
]));
}
}

View file

@ -3,11 +3,13 @@
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Resources;
use Socialbox\Enums\StandardError;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\ServerDocument;
class GetTermsOfService extends Method
{
@ -17,6 +19,10 @@
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
return $rpcRequest->produceResponse(Resources::getTermsOfService());
return $rpcRequest->produceResponse(new ServerDocument([
'last_updated' => Configuration::getRegistrationConfiguration()->getTermsOfServiceDate(),
'title' => 'Terms of Service',
'content' => Resources::getTermsOfService()
]));
}
}

View file

@ -60,6 +60,7 @@
// Build the captcha
// Returns HTML base64 encoded image of the captcha
// Important note: Must always be HTML-BASE64 which means it must be prefixed with `data:image/jpeg;base64,`
return $rpcRequest->produceResponse(new ImageCaptcha([
'expires' => $captchaRecord->getExpires(),
'content' => (new CaptchaBuilder($answer))->build()->inline()

View file

@ -194,6 +194,66 @@ class Utilities
return preg_replace('/[^a-zA-Z0-9-_]/', '', $name);
}
/**
* Sanitizes a Base64-encoded JPEG image by validating its data, decoding it,
* and re-encoding it to ensure it conforms to the JPEG format.
*
* @param string $data The Base64-encoded string potentially containing a JPEG image,
* optionally prefixed with "data:image/...;base64,".
* @return string A sanitized and re-encoded JPEG image as a binary string.
* @throws InvalidArgumentException If the input data is not valid Base64,
* does not represent an image, or is not in the JPEG format.
*/
public static function sanitizeBase64Jpeg(string $data): string
{
// Detect and strip the potential "data:image/...;base64," prefix, if present
if (str_contains($data, ','))
{
[, $data] = explode(',', $data, 2);
}
// Decode the Base64 string
$decodedData = base64_decode($data, true);
// Check if decoding succeeded
if ($decodedData === false)
{
throw new InvalidArgumentException("Invalid Base64 data.");
}
// Temporarily load the decoded data as an image
$tempResource = imagecreatefromstring($decodedData);
// Validate that the decoded data is indeed an image
if ($tempResource === false)
{
throw new InvalidArgumentException("The Base64 data does not represent a valid image.");
}
// Validate MIME type using getimagesizefromstring
$imageInfo = getimagesizefromstring($decodedData);
if ($imageInfo === false || $imageInfo['mime'] !== 'image/jpeg')
{
imagedestroy($tempResource); // Cleanup resources
throw new InvalidArgumentException("The image is not a valid JPEG format.");
}
// Capture the re-encoded image in memory and return it as a string
ob_start(); // Start output buffering
$saveResult = imagejpeg($tempResource, null, 100); // Max quality, save to output buffer
imagedestroy($tempResource); // Free up memory resources
if (!$saveResult)
{
ob_end_clean(); // Clean the output buffer if encoding failed
throw new InvalidArgumentException("Failed to encode the sanitized image.");
}
// Return the sanitized jpeg image as the result
return ob_get_clean();
}
/**
* Converts an array into a serialized string by joining the elements with a comma.
*

View file

@ -2,8 +2,10 @@
namespace Socialbox\Enums;
use Socialbox\Classes\StandardMethods\AcceptCommunityGuidelines;
use Socialbox\Classes\StandardMethods\AcceptPrivacyPolicy;
use Socialbox\Classes\StandardMethods\AcceptTermsOfService;
use Socialbox\Classes\StandardMethods\GetCommunityGuidelines;
use Socialbox\Classes\StandardMethods\GetPrivacyPolicy;
use Socialbox\Classes\StandardMethods\GetSessionState;
use Socialbox\Classes\StandardMethods\GetTermsOfService;
@ -74,11 +76,15 @@
self::ACCEPT_PRIVACY_POLICY => AcceptPrivacyPolicy::execute($request, $rpcRequest),
self::GET_TERMS_OF_SERVICE => GetTermsOfService::execute($request, $rpcRequest),
self::ACCEPT_TERMS_OF_SERVICE => AcceptTermsOfService::execute($request, $rpcRequest),
self::GET_COMMUNITY_GUIDELINES => GetCommunityGuidelines::execute($request, $rpcRequest),
self::ACCEPT_COMMUNITY_GUIDELINES => AcceptCommunityGuidelines::execute($request, $rpcRequest),
self::VERIFICATION_GET_IMAGE_CAPTCHA => VerificationGetImageCaptcha::execute($request, $rpcRequest),
self::VERIFICATION_ANSWER_IMAGE_CAPTCHA => VerificationAnswerImageCaptcha::execute($request, $rpcRequest),
self::SETTINGS_SET_PASSWORD => SettingsSetPassword::execute($request, $rpcRequest),
default => $rpcRequest->produceError(StandardError::METHOD_NOT_ALLOWED, sprintf("The method %s is not supported by the server", $rpcRequest->getMethod()))
};
}
@ -107,36 +113,59 @@
*/
public static function getAllowedMethods(ClientRequest $clientRequest): array
{
// These methods should always accessible
$methods = [
self::PING,
self::GET_SESSION_STATE,
self::GET_PRIVACY_POLICY,
self::GET_TERMS_OF_SERVICE,
// Important methods
self::PING, // Always allow the ping method
self::GET_SESSION_STATE, // The session state should always be accessible
self::GET_PRIVACY_POLICY, // The user should always be able to get the privacy policy
self::GET_TERMS_OF_SERVICE, // The user should always be able to get the terms of service
self::GET_COMMUNITY_GUIDELINES, // The user should always be able to get the community guidelines
];
$session = $clientRequest->getSession();
if(in_array(SessionFlags::VER_PRIVACY_POLICY, $session->getFlags()))
// If the flag `VER_PRIVACY_POLICY` is set, then the user can accept the privacy policy
if($session->flagExists(SessionFlags::VER_PRIVACY_POLICY))
{
$methods[] = self::ACCEPT_PRIVACY_POLICY;
}
if(in_array(SessionFlags::VER_TERMS_OF_SERVICE, $session->getFlags()))
// If the flag `VER_TERMS_OF_SERVICE` is set, then the user can accept the terms of service
if($session->flagExists(SessionFlags::VER_TERMS_OF_SERVICE))
{
$methods[] = self::ACCEPT_TERMS_OF_SERVICE;
}
if(in_array(SessionFlags::VER_IMAGE_CAPTCHA, $session->getFlags()))
// If the flag `VER_COMMUNITY_GUIDELINES` is set, then the user can accept the community guidelines
if($session->flagExists(SessionFlags::VER_COMMUNITY_GUIDELINES))
{
$methods[] = self::ACCEPT_COMMUNITY_GUIDELINES;
}
// If the flag `VER_IMAGE_CAPTCHA` is set, then the user has to get and answer an image captcha
if($session->flagExists(SessionFlags::VER_IMAGE_CAPTCHA))
{
$methods[] = self::VERIFICATION_GET_IMAGE_CAPTCHA;
$methods[] = self::VERIFICATION_ANSWER_IMAGE_CAPTCHA;
}
// If the flag `SET_PASSWORD` is set, then the user has to set a password
if(in_array(SessionFlags::SET_PASSWORD, $session->getFlags()))
{
$methods[] = self::SETTINGS_SET_PASSWORD;
}
// If the user is authenticated, then preform additional method calls
if($session->isAuthenticated())
{
// Always allow the authenticated user to change their password
if(!in_array(SessionFlags::SET_PASSWORD, $session->getFlags()))
{
$methods[] = self::SETTINGS_SET_PASSWORD;
}
}
return $methods;
}
}

View file

@ -454,4 +454,21 @@
throw new DatabaseOperationException('Failed to update authenticated peer', $e);
}
}
/**
* Marks the session as complete if all necessary conditions are met.
*
* @param SessionRecord $session The session record to evaluate and potentially mark as complete.
* @throws DatabaseOperationException If there is an error while updating the session in the database.
* @throws StandardException If the session record cannot be found or if there is an error during retrieval.
* @return void
*/
public static function updateFlow(SessionRecord $session): void
{
if(SessionFlags::isComplete($session->getFlags()))
{
SessionManager::setAuthenticated($session->getUuid(), true);
SessionManager::removeFlags($session->getUuid(), [SessionFlags::REGISTRATION_REQUIRED, SessionFlags::AUTHENTICATION_REQUIRED]);
}
}
}

View file

@ -0,0 +1,76 @@
<?php
namespace Socialbox\Objects\Standard;
use Socialbox\Interfaces\SerializableInterface;
class ServerDocument implements SerializableInterface
{
private int $lastUpdated;
private string $title;
private string $content;
/**
* Constructor method to initialize the object with provided data.
*
* @param array $data An associative array containing 'last_updated', 'content_type', 'title', and 'content' keys.
* @return void
*/
public function __construct(array $data)
{
$this->lastUpdated = $data['last_updated'];
$this->title = $data['title'];
$this->content = $data['content'];
}
/**
* Retrieves the timestamp of the last update.
*
* @return int The last updated timestamp.
*/
public function getLastUpdated(): int
{
return $this->lastUpdated;
}
/**
* Retrieves the title property.
*
* @return string The title value.
*/
public function getTitle(): string
{
return $this->title;
}
/**
* Retrieves the content stored in the instance.
*
* @return string The content as a string.
*/
public function getContent(): string
{
return $this->content;
}
/**
* @inheritDoc
*/
public static function fromArray(array $data): object
{
return new self($data);
}
/**
* @inheritDoc
*/
public function toArray(): array
{
return [
'last_updated' => $this->lastUpdated,
'content_type' => $this->contentType,
'title' => $this->title,
'content' => $this->content
];
}
}

View file

@ -13,6 +13,7 @@
use Socialbox\Objects\ExportedSession;
use Socialbox\Objects\PeerAddress;
use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\ServerDocument;
use Socialbox\Objects\Standard\SessionState;
class SocialClient extends RpcClient
@ -58,16 +59,16 @@
}
/**
* Retrieves the privacy policy from the server.
* Fetches the privacy policy document by sending a remote procedure call request.
*
* @return string Returns the privacy policy as a string.
* @return ServerDocument The privacy policy document retrieved from the server.
* @throws RpcException Thrown if the RPC request fails.
*/
public function getPrivacyPolicy(): string
public function getPrivacyPolicy(): ServerDocument
{
return $this->sendRequest(
return ServerDocument::fromArray($this->sendRequest(
new RpcRequest(StandardMethods::GET_PRIVACY_POLICY->value, Utilities::randomCrc32())
)->getResponse()->getResult();
)->getResponse()->getResult());
}
/**
@ -84,16 +85,16 @@
}
/**
* Retrieves the terms of service from the server.
* Retrieves the terms of service document by sending a remote procedure call request.
*
* @return string Returns the terms of service as a string.
* @return ServerDocument The terms of service document retrieved from the server.
* @throws RpcException Thrown if the RPC request fails.
*/
public function getTermsOfService(): string
public function getTermsOfService(): ServerDocument
{
return $this->sendRequest(
return ServerDocument::fromArray($this->sendRequest(
new RpcRequest(StandardMethods::GET_TERMS_OF_SERVICE->value, Utilities::randomCrc32())
)->getResponse()->getResult();
)->getResponse()->getResult());
}
/**
@ -110,16 +111,16 @@
}
/**
* Fetches the community guidelines by performing a remote procedure call request.
* Fetches the community guidelines document from the server by sending a remote procedure call request.
*
* @return string The content of the community guidelines.
* @throws RpcException Thrown if the RPC request encounters an error.
* @return ServerDocument The community guidelines document retrieved from the server.
* @throws RpcException Thrown if the RPC request fails.
*/
public function getCommunityGuidelines(): string
public function getCommunityGuidelines(): ServerDocument
{
return $this->sendRequest(
return ServerDocument::fromArray($this->sendRequest(
new RpcRequest(StandardMethods::GET_COMMUNITY_GUIDELINES->value, Utilities::randomCrc32())
)->getResponse()->getResult();
)->getResponse()->getResult());
}
/**