Validate identifiers and file paths
This commit is contained in:
parent
607f3d8159
commit
571c24e5b7
@ -55,12 +55,6 @@ class JsonDatabase implements IJsonUnflattener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function migrate()
|
|
||||||
{
|
|
||||||
// TODO: This is a stub
|
|
||||||
// Make this function migrate between different settings
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getObjectPath($class, $name, ?int $time = null)
|
private function getObjectPath($class, $name, ?int $time = null)
|
||||||
{
|
{
|
||||||
$retPath = $this->storagePath;
|
$retPath = $this->storagePath;
|
||||||
@ -75,6 +69,10 @@ class JsonDatabase implements IJsonUnflattener
|
|||||||
|
|
||||||
$segments = array_filter(explode('\\', $class));
|
$segments = array_filter(explode('\\', $class));
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($segments); $i++) {
|
||||||
|
$segments[$i] = JsonDatabase::SanitizeIdentifier($segments[$i]);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->fullDomain)
|
if ($this->fullDomain)
|
||||||
$retPath .= DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $segments);
|
$retPath .= DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $segments);
|
||||||
else
|
else
|
||||||
@ -92,15 +90,24 @@ class JsonDatabase implements IJsonUnflattener
|
|||||||
|
|
||||||
public function load(string $class, string $name, ?int $timestamp = null): JsonSerializable|null
|
public function load(string $class, string $name, ?int $timestamp = null): JsonSerializable|null
|
||||||
{
|
{
|
||||||
// TODO: Do some basic validation of class and name to
|
if ($class == null || empty(trim($name)))
|
||||||
// avoid path traversal and make sure a class is specified
|
return null;
|
||||||
// This is really fucking important, implement it, or don't and watch someone use your code
|
|
||||||
// and get their production machine hacked
|
if ($name != null && !empty(trim(strval($name))))
|
||||||
|
$name = JSONDatabase::SanitizeIdentifier($name);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$class = trim($class);
|
||||||
|
|
||||||
if (!$this->audit && $timestamp != null)
|
if (!$this->audit && $timestamp != null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
$objPath = $this->getObjectPath($class, $name, ($timestamp != null));
|
$objPath = $this->getObjectPath($class, $name, ($timestamp != null));
|
||||||
|
|
||||||
|
if (strlen($objPath) > PHP_MAXPATHLEN)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (!is_file($objPath))
|
if (!is_file($objPath))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -115,22 +122,29 @@ class JsonDatabase implements IJsonUnflattener
|
|||||||
return JsonSerializable::Deserialize($json, $this->nested, $this, $class);
|
return JsonSerializable::Deserialize($json, $this->nested, $this, $class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save(JsonSerializable $obj, string $name = null)
|
public function save(JsonSerializable $obj, ?string $name = null)
|
||||||
{
|
{
|
||||||
if ($name == null || empty(trim(strval($name))))
|
if ($name != null && !empty(trim($name))) {
|
||||||
|
$name = JSONDatabase::SanitizeIdentifier($name);
|
||||||
|
} else {
|
||||||
if ($obj instanceof IJsonIdentifiable)
|
if ($obj instanceof IJsonIdentifiable)
|
||||||
$name = $obj->flatIdentifier() ?? uniqid();
|
$name = JSONDatabase::SanitizeIdentifier($obj->flatIdentifier() ?? uniqid());
|
||||||
else
|
else
|
||||||
$name = uniqid();
|
$name = uniqid();
|
||||||
|
}
|
||||||
$name = JSONDatabase::SanitizeIdentifier($name);
|
|
||||||
|
|
||||||
$objPath = $this->getObjectPath(get_class($obj), $name);
|
$objPath = $this->getObjectPath(get_class($obj), $name);
|
||||||
|
if (strlen($objPath) > PHP_MAXPATHLEN)
|
||||||
|
throw new Exception('JsonDatabase: Specified Path ' . $objPath . ' is longer than allowed.');
|
||||||
|
|
||||||
$objJson = $obj->Serialize(nested: $this->nested, to_array: false);
|
$objJson = $obj->Serialize(nested: $this->nested, to_array: false);
|
||||||
|
|
||||||
if ($this->audit)
|
if ($this->audit)
|
||||||
{
|
{
|
||||||
$historyPath = $this->getObjectPath(get_class($obj), $name, time());
|
$historyPath = $this->getObjectPath(get_class($obj), $name, time());
|
||||||
|
if (strlen($historyPath) > PHP_MAXPATHLEN)
|
||||||
|
throw new Exception('JsonDatabase: Specified Path ' . $objPath . ' is longer than allowed.');
|
||||||
|
|
||||||
// For Historic files we always save the whole Object Tree since
|
// For Historic files we always save the whole Object Tree since
|
||||||
// dependencies might have different timestamps
|
// dependencies might have different timestamps
|
||||||
// and resolving that would be annoying
|
// and resolving that would be annoying
|
||||||
@ -149,8 +163,15 @@ class JsonDatabase implements IJsonUnflattener
|
|||||||
return $name;
|
return $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore a JsonSerializable from the Database by using it's Identifier reference.
|
||||||
|
* @param string $className the full class name with domain of the JsonSerializable property
|
||||||
|
* @param $identifer The identifier that uniquely identifies the object
|
||||||
|
* @return JsonSerializable|null
|
||||||
|
*/
|
||||||
public function unflattenByID(string $className, $identifier) : JsonSerializable | null
|
public function unflattenByID(string $className, $identifier) : JsonSerializable | null
|
||||||
{
|
{
|
||||||
|
// Fetch JsonSerializable Object from Database using given Identifier
|
||||||
return $this->load($className, strval($identifier));
|
return $this->load($className, strval($identifier));
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user