Slim app upload stable

parent c498b7e7
This diff is collapsed.
......@@ -37,7 +37,9 @@ $autoloader->addPsr4('Gr\Gov\Minedu\Osteam\Slim\\', __DIR__ . '/../src/osteam');
$container['errorHandler'] = function ($c) {
return function ($request, $response, $exception) use ($c) {
return $c['response']->withJson([
'message' => 'Προέκυψε λάθος',
'success' => false,
'timestamp' => date('c'),
'message' => 'An error occured',
'in' => $exception->getMessage()
], intval($code = $exception->getCode()) > 0 ? $code : null
);
......
......@@ -8,5 +8,9 @@ $password = isset($settings['app']['secure_endpoint_password']) ? $settings['app
// e.g: $app->add(new \Slim\Csrf\Guard);
$app->getContainer()->get('router')
->getNamedRoute('validate')
->getNamedRoute('validate.base64')
->add(new Gr\Gov\Minedu\Osteam\Slim\AuthorizationGuard($username, $password));
$app->getContainer()->get('router')
->getNamedRoute('validate.binary')
->add(new Gr\Gov\Minedu\Osteam\Slim\AuthorizationGuard($username, $password));
......@@ -7,16 +7,17 @@ use Slim\Http\Body;
use Gr\Gov\Minedu\Osteam\Slim\Client;
/**
* Description of app
*
* @author spapad
*/
* Description of app
*
* @author spapad
*/
class App
{
protected $ci = null;
protected $logger = null;
protected $savePath;
protected $saveFileTTL;
public function __construct(ContainerInterface $ci)
{
......@@ -27,34 +28,88 @@ class App
$settings = $this->ci->get('settings');
if (isset($settings['app'])) {
$this->savePath = (isset($settings['app']['save_path']) ? $settings['app']['save_path'] : 'tmp');
$this->saveFileTTL = (isset($settings['app']['save_file_ttl']) ? $settings['app']['save_file_ttl'] : 0);
}
}
/**
* Χαιρετισμός - οδηγίες.
*
* @param Psr\Http\Message\ServerRequestInterface $req
* @param Psr\Http\Message\ResponseInterface $res
* @param $args
* @throws \Exception
* @return Response
*/
* Χαιρετισμός - οδηγίες.
*
* @param Psr\Http\Message\ServerRequestInterface $req
* @param Psr\Http\Message\ResponseInterface $res
* @param $args
* @throws \Exception
* @return Response
*/
public function greet($req, $res, $args)
{
return $res->withJson([
'message' => 'Only POST is available'
], 401);
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'Only POST is available'
]), 405);
}
/**
* Έλεγχος.
*
* @param Psr\Http\Message\ServerRequestInterface $req
* @param Psr\Http\Message\ResponseInterface $res
* @throws \Exception
* @return Response
*/
public function validate($req, $res, $args)
* Έλεγχος.
*
* @param Psr\Http\Message\ServerRequestInterface $req
* @param Psr\Http\Message\ResponseInterface $res
* @param array $args
* @throws \Exception
* @return Response
*/
public function validateBinary($req, $res, $args)
{
$files = $req->getUploadedFiles();
if (count($files) == 0) {
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'File is mandatory'
]), 400);
}
if (!$this->checkSavePath($this->savePath)) {
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'File location does not exist or is not writeable'
]), 501);
}
foreach ($files as $id => $file) {
if ($file->getError() === UPLOAD_ERR_OK) {
// $contents = base64_encode($file->getStream()->getContents());
$filename = $file->getClientFilename();
$store_filename = $this->savePath . DIRECTORY_SEPARATOR . uniqid() . '_' .
$this->sanitizeFilename($filename);
try {
$file->moveTo($store_filename);
} catch (\Exception $e) {
$this->vaccuumSavePath();
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'Cannot save file for processing'
]), 501);
}
$this->logger->info("validate binary upload::{$store_filename}");
}
}
$this->vaccuumSavePath();
return $res->withJson(array_merge($this->coreResponseData(true), [
'message' => array_reduce($files, function ($c, $v) {
return $c . $v->getClientFilename() . ", ";
}, '') . "processed"
]), 200);
}
/**
* Έλεγχος.
*
* @param Psr\Http\Message\ServerRequestInterface $req
* @param Psr\Http\Message\ResponseInterface $res
* @param array $args
* @throws \Exception
* @return Response
*/
public function validateBase64($req, $res, $args)
{
// $body = $req->getBody();
// $contents = $body->getContents();
......@@ -62,40 +117,94 @@ class App
$filename = $req->getParsedBodyParam('filename', null);
$content = $req->getParsedBodyParam('base64content', null);
if ($filename === null || $content === null) {
return $res->withJson(['message' => 'Filename and file content is mandatory'], 401);
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'Filename and file content is mandatory'
]), 400);
}
if (($filecontent = base64_decode($content)) === false) {
return $res->withJson(['message' => 'File content is not valid base64 encoded'], 401);
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'File content is not valid base64 encoded'
]), 400);
}
if (!is_dir($this->savePath) || !is_writable($this->savePath)) {
return $res->withJson(['message' => 'File location does not exist or is not writeable'], 401);
if (!$this->checkSavePath($this->savePath)) {
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'File location does not exist or is not writeable'
]), 501);
}
// TODO check filename
$store_filename = $this->savePath . DIRECTORY_SEPARATOR . $filename;
// manipulate filename
$store_filename = $this->savePath . DIRECTORY_SEPARATOR . uniqid() . '_' .
$this->sanitizeFilename($filename);
if (($save = file_put_contents($store_filename, $filecontent)) === false) {
return $res->withJson(['message' => 'Cannot save file for processing'], 401);
return $res->withJson(array_merge($this->coreResponseData(false), [
'message' => 'Cannot save file for processing'
]), 501);
}
$this->logger->info("validate::{$store_filename}");
$this->logger->info("validate base64 upload::{$store_filename}");
// delete any leftover files
// delete file immediately after work; OBSOLETE
// if ($this->saveFileTTL === 0) { @unlink($store_filename); }
$this->vaccuumSavePath();
return $res->withJson([
'ok' => 'done',
'file' => $store_filename,
// 'parsedBody' => $parsedBody,
// 'content' => $contents,
], 200);
return $res->withJson(array_merge($this->coreResponseData(true), [
'message' => "{$filename} processed"// $store_filename,
]), 200);
}
/**
* Clean save path.
* Delete all files older than saveFileTTL seconds
*/
private function vaccuumSavePath()
{
$files = glob($this->savePath . DIRECTORY_SEPARATOR . '*');
$files = is_array($files) ? $files : [];
$now = time();
$rmv = array_walk($files, function ($v, $k) use ($now) {
if ($now - fileatime($v) > $this->saveFileTTL) {
@unlink($v);
}
});
}
/**
* Check if path exists and is writeable
*/
private function checkSavePath($save_path)
{
return (is_dir($save_path) && is_writable($save_path));
}
/**
* Manipulate the filename provided to strip out unsafe characters
*
* @param string $filename
* @return string
*/
private function sanitizeFilename($filename)
{
return mb_ereg_replace("([^\w\s\d\-_,.])", '_', $filename);
}
public function setDebug($debug = true)
{
$this->client->setDebug($debug === true);
return;
}
private function coreResponseData($success)
{
return [
'success' => $success === true,
'timestamp' => date('c')
];
}
/**
* Send a JSON formatted string as JSON response to the client.
*
......
......@@ -2,8 +2,10 @@
$app->get('/validate', '\Gr\Gov\Minedu\Osteam\Slim\App:greet');
$app->post('/validate', '\Gr\Gov\Minedu\Osteam\Slim\App:validate')
->setName('validate');
$app->post('/validateBase64', '\Gr\Gov\Minedu\Osteam\Slim\App:validateBase64')
->setName('validate.base64');
$app->post('/validateBinary', '\Gr\Gov\Minedu\Osteam\Slim\App:validateBinary')
->setName('validate.binary');
$app->any('/[{anythingelse}]', function ($request, $response, $args) {
$this->logger->info("Void response, no action route was enabled");
......
......@@ -17,7 +17,8 @@ return [
//
// app custom settings
'app' => [
'save_path' => __DIR__ . '/../logs',
'save_path' => __DIR__ . '/../files', // upload file location
'save_file_ttl' => 0, // if 0 delete file after doing work; if Nr delete some time after Nr seconds
'secure_endpoint_username' => 'username-for-this-wrapper',
'secure_endpoint_password' => 'password-for-this-wrapper'
]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment