getID() == $b->getID()' comparisons always work. //During upgrade from V10.x (pre-UUID) to v11 (post-UUID), we need numeric IDs to be left as integers to avoid SQL errors. global $PRIMARY_KEY_IS_UUID; if ( $PRIMARY_KEY_IS_UUID == false && is_numeric( $uuid ) ) { return $uuid; } if ( is_string( $uuid ) && $uuid != '' && preg_match( self::getRegex(), $uuid ) ) { return true; } return false; } /** * @param $uuid * @param int $group * @return bool */ static function getUUIDGroup( $uuid, $group = 4 ) { $bits = explode( '-', $uuid ); if ( isset( $bits[$group] ) ) { return $bits[$group]; } return false; } /** * @param string $uuid UUID * @return int */ static function convertUUIDtoInt( $uuid ) { $bits = explode( '-', $uuid ); return (int)$bits[( count( $bits ) - 1 )]; } /** * @param $int * @return int|string */ static function convertIntToUUID( $int ) { if ( is_numeric( $int ) ) { if ( $int === 0 ) { return self::getZeroID(); } else if ( $int === -1 ) { return self::getNotExistID(); } return self::getConversionPrefix() . '-' . str_pad( $int, 12, '0', STR_PAD_LEFT ); } else { return $int; } } /** * @param $str string * @return string */ static function convertStringToUUID( $str ) { $str = str_pad( str_replace( '-', '', $str ), 32, 'f', STR_PAD_LEFT ); //Make sure there is at least enough data to make a full 32 char UUID. $retval = substr( $str, 0, 8 ) . '-' . substr( $str, 8, 4 ) . '-' . substr( $str, 12, 4 ) . '-' . substr( $str, 16, 4 ) . '-' . substr( $str, 20, 12 ); return $retval; } /** * @param bool $fail_to_random * @return bool|string */ static function getSeed( $fail_to_random = false ) { global $config_vars; if ( isset( $config_vars['other']['uuid_seed'] ) && strlen( $config_vars['other']['uuid_seed'] ) == 12 && preg_match( '/^[a-z0-9]{12}$/', $config_vars['other']['uuid_seed'] ) ) { return strtolower( trim( $config_vars['other']['uuid_seed'] ) ); } if ( $fail_to_random == true ) { Debug::text( ' WARNING: Generating random seed!', __FILE__, __LINE__, __METHOD__, 9 ); return self::generateRandomSeed(); } return false; } /** * @return string */ static function generateRandomSeed() { return bin2hex( openssl_random_pseudo_bytes( 6 ) ); } /** * @return bool|string */ static function generateSeed() { //Once the seed is generated, it must not be ever generated to something different. Especially if the upgrade failed half way through and is run later on, or even on a different server. global $config_vars; if ( isset( $config_vars['other']['uuid_seed'] ) && strlen( $config_vars['other']['uuid_seed'] ) == 12 && preg_match( '/^[a-z0-9]{12}$/', $config_vars['other']['uuid_seed'] ) ) { return strtolower( trim( $config_vars['other']['uuid_seed'] ) ); } global $db; //Make sure we check that the database/system_setting table exists before we attempt to use it. Otherwise it may fail on initial installation. $install_obj = new Install(); $install_obj->setDatabaseConnection( $db ); //Default connection if ( $install_obj->checkSystemSettingTableExists() == true ) { $registration_key = SystemSettingFactory::getSystemSettingValueByKey( 'registration_key' ); } else { Debug::text( 'Database or system_setting table does not exist yet, generating temporary registration key...', __FILE__, __LINE__, __METHOD__, 9 ); $registration_key = md5( uniqid( null, true ) ); } $obj_class = "\124\124\114\x69\x63\x65\x6e\x73\x65"; $license = @new $obj_class; //Make sure the UUID key used for upgrading is as unique as possible, so we can avoid the chance of conflicts as best as possible. // Include the database type and database name to further help make this unique in the event that a database was copied on the same server (hardware_id), it should at least have a different name. // Be sure to use CONFIG_FILE file creation time rather than mtime as the config file gets changed during upgrade/installs and can cause the seed to then change. // Seed should only be exactly 12 characters $uuid_seed = substr( sha1( $registration_key . $license->getHardwareID() . $db->databaseType . $db->database . filectime( CONFIG_FILE ) ), 0, 12 ); $config_vars['other']['uuid_seed'] = $uuid_seed; //Save UUID_SEED to any in memory $config_vars to its able to be used immediately. Debug::text( ' Generated Seed: ' . $uuid_seed . ' From Registration Key: ' . $registration_key . ' Hardware ID: ' . $license->getHardwareID() . ' Database Type: ' . $db->databaseType . ' DB Name: ' . $db->database . ' Config File: ' . CONFIG_FILE . ' ctime: ' . filectime( CONFIG_FILE ), __FILE__, __LINE__, __METHOD__, 9 ); $tmp_config_data = []; $tmp_config_data['other']['uuid_seed'] = $uuid_seed; if ( isset( $config_vars['other']['primary_company_id'] ) && is_numeric( $config_vars['other']['primary_company_id'] ) ) { //Convert to UUID while we are at it. $uuid_primary_company_id = TTUUID::convertIntToUUID( $config_vars['other']['primary_company_id'] ); $config_vars['other']['primary_company_id'] = $uuid_primary_company_id; //Save UUID primary_company_id to any in memory $config_vars to its able to be used immediately. $tmp_config_data['other']['primary_company_id'] = $uuid_primary_company_id; } if ( $install_obj->writeConfigFile( $tmp_config_data ) !== true ) { return false; } return $uuid_seed; } /** * @return bool|string */ static function getConversionPrefix() { $uuid_seed = self::generateSeed(); if ( $uuid_seed !== false ) { $uuid_key = $uuid_seed . substr( sha1( $uuid_seed ), 12 ); //Make sure we sha1() the seed just to pad out to at least 24 characters. Make the first 12 characters the original seed for consistency though. $uuid_prefix = substr( $uuid_key, 0, 8 ) . '-' . substr( $uuid_key, 8, 2 ) . substr( substr( $uuid_key, -10 ), 0, 2 ) . '-' . substr( substr( $uuid_key, -8 ), 0, 4 ) . '-' . substr( $uuid_key, -4 ); //Debug::text( 'UUID Key: ' . $uuid_key . ' UUID PREFIX: ' . $uuid_prefix, __FILE__, __LINE__, __METHOD__, 9 ); return $uuid_prefix; } return false; } /** * @param $uuid * @param $length * @param bool $include_dashes * @return string */ static function truncateUUID( $uuid, $length, $include_dashes = true ) { //Re-arrange UUID so most unique data is at the beginning. if ( is_numeric( self::getUUIDGroup( $uuid, 4 ) ) && stripos( self::getSeed( false ), self::getUUIDGroup( $uuid, 0 ) ) !== false ) { //If its a legacy UUID converted from an INT, the only unique part is group 4, so it needs to be at the begining. // However in cases where the SEED changes in the .ini file for some reason, this won't work anymore. Alternatively we could maybe just check that the first two digits of group 4 are '00' as well as being numeric. The chances of that happening are quite rare, but still possible. $tmp_uuid = self::getUUIDGroup( $uuid, 4 ) . '-' . self::getUUIDGroup( $uuid, 1 ) . '-' . self::getUUIDGroup( $uuid, 2 ) . '-' . self::getUUIDGroup( $uuid, 3 ) . '-' . self::getUUIDGroup( $uuid, 0 ); } else { $tmp_uuid = self::getUUIDGroup( $uuid, 1 ) . '-' . self::getUUIDGroup( $uuid, 2 ) . '-' . self::getUUIDGroup( $uuid, 3 ) . '-' . self::getUUIDGroup( $uuid, 0 ) . '-' . self::getUUIDGroup( $uuid, 4 ); } if ( $include_dashes == false ) { $tmp_uuid = str_replace( '-', '', $tmp_uuid ); } return trim( substr( $tmp_uuid, 0, $length ), '-' ); } } ?>