Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1102200
SecurityGeneratorPromise.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Aug 18, 5:37 AM
Size
5 KB
Mime Type
text/x-php
Expires
Wed, Aug 20, 5:37 AM (1 d, 1 h)
Engine
blob
Format
Raw Data
Handle
713993
Attached To
rINP In-Portal
SecurityGeneratorPromise.php
View Options
<?php
/**
* @version $Id: SecurityGeneratorPromise.php 16727 2022-08-29 07:58:21Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2018 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined
(
'FULL_PATH'
)
or
die
(
'restricted access!'
);
final
class
SecurityGeneratorPromise
{
/**
* Promise, that returns random integer number.
*/
const
TYPE_NUMBER
=
1
;
/**
* Promise, that returns random string.
*/
const
TYPE_STRING
=
2
;
/**
* Promise, that returns random bytes.
*/
const
TYPE_BYTES
=
3
;
/**
* Generator method.
*
* @var string
*/
protected
$method
;
/**
* Generator method arguments.
*
* @var array
*/
protected
$arguments
=
array
();
/**
* Resolved value (only, when was resolved).
*
* @var string
*/
protected
$resolvedValue
;
/**
* Return signature of resolved value.
*
* @var boolean
*/
protected
$asSignature
=
false
;
/**
* Return raw resolved value's signature representation.
*
* @var boolean
*/
protected
$signatureRawOutput
=
false
;
/**
* Alternative key used for creating signature of resolved value.
*
* @var string
*/
protected
$signatureKeyOverride
;
/**
* SecurityGeneratorPromise constructor.
*
* @param integer $type Promise type.
* @param array $arguments Generator method arguments.
*
* @throws InvalidArgumentException When unsupported promise type is given.
*/
public
function
__construct
(
$type
,
array
$arguments
=
array
())
{
$mapping
=
array
(
self
::
TYPE_NUMBER
=>
'generateNumber'
,
self
::
TYPE_STRING
=>
'generateString'
,
self
::
TYPE_BYTES
=>
'generateBytes'
,
);
if
(
!
isset
(
$mapping
[
$type
])
)
{
throw
new
InvalidArgumentException
(
'The "'
.
$type
.
'" promise type is not supported.'
);
}
$this
->
method
=
$mapping
[
$type
];
$this
->
arguments
=
$arguments
;
}
/**
* Makes sure, that resolved value isn't already used in the given database table's column.
*
* @param string $prefix_or_table Unit config prefix or table name.
* @param string $column Column in specified table.
*
* @return mixed
* @throws LogicException When after 10 retries still unable to generate unique value for database.
*/
public
function
resolveForPersisting
(
$prefix_or_table
,
$column
)
{
$application
=&
kApplication
::
Instance
();
if
(
$application
->
prefixRegistred
(
$prefix_or_table
)
)
{
$table
=
$application
->
getUnitConfig
(
$prefix_or_table
)->
getTableName
();
}
else
{
$table
=
$prefix_or_table
;
}
$retries
=
0
;
do
{
$resolved_value
=
$this
->
resolve
();
$sql
=
'SELECT '
.
$column
.
'
FROM '
.
$table
.
'
WHERE '
.
$column
.
' = '
.
$application
->
Conn
->
qstr
(
$resolved_value
);
$found
=
$application
->
Conn
->
GetOne
(
$sql
)
!==
false
;
if
(
$found
)
{
$this
->
resolvedValue
=
null
;
$retries
++;
}
}
while
(
$found
&&
$retries
<
10
);
if
(
$found
)
{
throw
new
LogicException
(
sprintf
(
'Unable to generate unique value for "%s" column with current generator configuration.'
,
$table
.
'.'
.
$column
));
}
return
$resolved_value
;
}
/**
* Resolves a promise.
*
* @return mixed
*/
public
function
resolve
()
{
if
(
!
$this
->
isResolved
()
)
{
$this
->
resolvedValue
=
call_user_func_array
(
array
(
$this
,
$this
->
method
),
$this
->
arguments
);
}
if
(
!
$this
->
asSignature
)
{
return
$this
->
resolvedValue
;
}
$application
=&
kApplication
::
Instance
();
/** @var SecurityEncrypter $encrypter */
$encrypter
=
$application
->
recallObject
(
'SecurityEncrypter'
);
return
$encrypter
->
createSignature
(
$this
->
resolvedValue
,
$this
->
signatureRawOutput
,
$this
->
signatureKeyOverride
);
}
/**
* Configures promise to return signature of a resolved value.
*
* @param boolean $raw_output Return raw signature value during resolving.
* @param string|null $key_override Alternative key used for creating signature of resolved value.
*
* @return self
*/
public
function
asSignature
(
$raw_output
=
false
,
$key_override
=
null
)
{
$this
->
asSignature
=
true
;
$this
->
signatureRawOutput
=
$raw_output
;
$this
->
signatureKeyOverride
=
$key_override
;
return
$this
;
}
/**
* Configures promise to return resolved value as-is.
*
* @return self
*/
public
function
asValue
()
{
$this
->
asSignature
=
false
;
$this
->
signatureRawOutput
=
false
;
$this
->
signatureKeyOverride
=
null
;
return
$this
;
}
/**
* Generate a random string of specified length using supplied character list.
*
* @param integer $length The length of the generated string.
* @param mixed $characters List of characters to use.
*
* @return string
*/
protected
function
generateString
(
$length
,
$characters
)
{
$ret
=
''
;
$max_index
=
mb_strlen
(
$characters
)
-
1
;
for
(
$i
=
0
;
$i
<
$length
;
$i
++
)
{
$ret
.=
mb_substr
(
$characters
,
$this
->
generateNumber
(
0
,
$max_index
),
1
);
}
return
$ret
;
}
/**
* Generates a random number.
*
* @param integer $min Smallest value.
* @param integer $max Largest value.
*
* @return integer
*/
protected
function
generateNumber
(
$min
,
$max
)
{
return
random_int
(
$min
,
$max
);
}
/**
* Generates random bytes.
*
* @param integer $length Raw result length.
* @param boolean $raw_output Return raw result.
*
* @return string
*/
protected
function
generateBytes
(
$length
=
16
,
$raw_output
=
false
)
{
$ret
=
random_bytes
(
$length
);
return
$raw_output
?
$ret
:
bin2hex
(
$ret
);
}
/**
* Determines if promise was already resolved.
*
* @return boolean
*/
protected
function
isResolved
()
{
return
$this
->
resolvedValue
!==
null
;
}
/**
* Returns promise resolved value casted to string.
*
* @return string
*/
public
function
__toString
()
{
return
(
string
)
$this
->
resolve
();
}
}
Event Timeline
Log In to Comment