Продолжение запила API

Создание постов, новые настройки в конфиге
This commit is contained in:
Shr3dd3r 2024-01-20 00:02:51 +03:00
parent c48f837738
commit e180c04e44
3 changed files with 103 additions and 27 deletions

View File

@ -22,6 +22,44 @@ if ($IS_FRONTEND) {
// Functions // Functions
/*
* FUNCTION
* Parse tags from raw string
*/
function Post_ParseRawTagString (string $str): ReturnT {
global $Config;
$allowedSymbols = $Config["posting"]["tags"]["allowed_syms"];
$maxTagLength = $Config["posting"]["tags"]["max_single_length"];
$strLength = strlen($str);
$currLen = 0;
$currTag = "";
$result = array();
for ($i = 0; $i < $strLength; ++$i) {
if ($str[$i] === ",") {
if ($currLen) {
$result[] = $currTag;
$currLen = 0;
} else {
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "syntax error while trying to parse tags");
}
} elseif ($str[$i] !== " " && $str[$i] !== "\t") {
$currTag .= $str[$i];
if (++$currLen > $maxTagLength)
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag too large: $currTag");
}
}
$preg_str = "/[^" . $allowedSymbols . "]/";
foreach ($result as $tag) {
if (preg_match($preg_str, $tag))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "only allowed symbols in tags are: " . $allowedSymbols);
}
return new ReturnT(data: $result);
}
/* /*
* FUNCTION * FUNCTION
* Check if image size properties are valid * Check if image size properties are valid
@ -38,7 +76,7 @@ function Post_ImgResIsValid ($x, $y): bool {
* FUNCTION * FUNCTION
* Create preview version of image * Create preview version of image
*/ */
function Post_CreatePreviewFromImage ($src, $dst): ReturnT { function Post_CreatePreviewFromImage (string $src, string $dst): ReturnT {
$img = null; $img = null;
// Reading image from source path // Reading image from source path
@ -56,34 +94,45 @@ function Post_CreatePreviewFromImage ($src, $dst): ReturnT {
// Saving it as LQ JPEG // Saving it as LQ JPEG
imagejpeg($img, $dst, 30); imagejpeg($img, $dst, 30);
if (!file_exists($dst)) // $src isnt our responsibility, $dst is
return new ReturnT(err_code: E_UNS_UNEXPECTED, err_desc: "failed to create preview");
return new ReturnT(data: true); return new ReturnT(data: true);
} }
/* /*
* FUNCTION * FUNCTION
* Store image * Stores image and returns paths to picture and its preview
*/ */
function Post_StoreImage ($path, $preview = true): ReturnT { function Post_StoreImage (string $path): ReturnT {
global $Config; global $Config;
// Paths // Paths
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
$fileName = strval(time()) . "_" . GenerateRandomString(4); $fileName = strval(time()) . "_" . GenerateRandomString(4);
$targetDir = "../../" . $Config["media"]["pics_path"]; $targetDir = "../../" . $Config["media"]["pics_path"];
$targetPath = JoinPaths($targetDir, $fileName . "." . $ext); $targetPath = Utils_JoinPaths($targetDir, $fileName . "." . $ext);
// Creating preview file // Creating preview file
if ($Config["media"]["previews_enabled"] && $preview) { if ($Config["media"]["previews_enabled"]) {
$previewDir = "../../" . $Config["media"]["prevs_path"]; $previewDir = "../../" . $Config["media"]["prevs_path"];
$previewPath = JoinPaths($previewDir, $fileName . ".jpg"); $previewPath = Utils_JoinPaths($previewDir, $fileName . ".jpg");
$res = Post_CreatePreviewFromImage($path, $previewPath); $res = Post_CreatePreviewFromImage($path, $previewPath);
if ($res.IsError()) if ($res->IsError()) // $path isnt our responsibility
return $res; return $res;
} }
move_uploaded_file($path, $targetPath); move_uploaded_file($path, $targetPath);
return new ReturnT(data: true); if (!file_exists($targetPath)) { // however, $previewPath IS our responsibility
unlink($previewPath);
return new ReturnT(err_code: E_UNS_UNEXPECTED, err_desc: "failed to move uploaded file");
}
return new ReturnT(data: array(
"preview" => $previewPath,
"picture" => $targetPath
));
} }
/* /*
@ -103,7 +152,7 @@ function Post_Create (
$result = null; $result = null;
// Author ID should exist // Author ID must exist
if (!User_IDExist($author_id)) if (!User_IDExist($author_id))
return new ReturnT(err_code: E_UIN_WRONGID, err_desc: "specified user id does not exist"); return new ReturnT(err_code: E_UIN_WRONGID, err_desc: "specified user id does not exist");
@ -114,6 +163,8 @@ function Post_Create (
if ($s->execute() === false) if ($s->execute() === false)
return new ReturnT(err_code: E_DBE_INSERTFAIL, err_desc: "failed to create post record in DB"); return new ReturnT(err_code: E_DBE_INSERTFAIL, err_desc: "failed to create post record in DB");
$result = true;
return new ReturnT(data: $result); return new ReturnT(data: $result);
} }
@ -145,9 +196,23 @@ function Post_Create_Method (array $req, array $files): ReturnT {
if (!(isset($req["tags"]) && isset($files["pic"]))) if (!(isset($req["tags"]) && isset($files["pic"])))
return new ReturnT(err_code: E_UIN_INSUFARGS, err_desc: "tags and picture are necessary"); return new ReturnT(err_code: E_UIN_INSUFARGS, err_desc: "tags and picture are necessary");
// TODO: add rate-limiting, instead of this // Check tags
// Check user role // If raw string length not fits into limit
if (User_HasRole($THIS_USER, "newbie").GetData()) $tagsLen = strlen($req["tags"]);
if ($tagsLen > $Config["posting"]["tags"]["max_raw_input_str_length"])
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags string length exceeds limit: " . strval($Config["posting"]["tags"]["max_raw_input_str_length"]));
elseif ($tagsLen < 1)
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags cant be empty");
// TODO: check if it is ASCII string
// Parsing tags
$parsedTags = Post_ParseRawTagString($req["tags"]);
if ($parsedTags->IsError())
return $parsedTags;
// TODO: check if tags are approved
$tags = implode(",", $parsedTags);
// Check user role TODO: add rate-limiting, instead of this
if (User_HasRole($THIS_USER, "newbie")->GetData())
return new ReturnT(err_code: E_ACS_INSUFROLE, err_desc: "newbies cant create posts"); return new ReturnT(err_code: E_ACS_INSUFROLE, err_desc: "newbies cant create posts");
// Check image properties // Check image properties
@ -167,15 +232,17 @@ function Post_Create_Method (array $req, array $files): ReturnT {
if (!Post_ImgResIsValid($SzX, $SzY)) if (!Post_ImgResIsValid($SzX, $SzY))
return new ReturnT(err_code: E_UIN_IMGBADRES, err_desc: "image with that resolution or aspect ratio cant be accepted"); return new ReturnT(err_code: E_UIN_IMGBADRES, err_desc: "image with that resolution or aspect ratio cant be accepted");
// Copy picture to storage folder
$res = Post_StoreImage($TmpFilePath, $Config["media"]["previews_enabled"]);
if ($res.IsError())
return $res;
// TODO
// Actions // Actions
// Copy picture to storage folder
$res = Post_StoreImage($TmpFilePath);
if ($res->IsError()) { // $TmpFilePath seemingly isnt our responsibility, BUT, only we know how and what to cleanup
unlink($TmpFilePath);
return $res;
}
$pic_path = $res["picture"];
$prev_path = $res["preview"];
return Post_Create($author_id, $tags, $pic_path, $title, $prev_path, $comms_enabled, false); return Post_Create($author_id, $tags, $pic_path, $title, $prev_path, $comms_enabled, false);
} }
@ -184,7 +251,7 @@ function Post_Create_Method (array $req, array $files): ReturnT {
if (Utils_ThisFileIsRequested(__FILE__)) { if (Utils_ThisFileIsRequested(__FILE__)) {
require_once("../_json.php"); require_once("../_json.php");
// TODO: cleanup if bad result // TODO
} }
?> ?>

View File

@ -35,5 +35,14 @@
"image/jpeg", "image/jpeg",
"image/png" "image/png"
] ]
},
"posting": {
"tags": {
"max_per_post": 256,
"max_single_length": 256,
"max_raw_input_str_length": 1536,
"allowed_syms": "a-zA-Z0-9_"
},
"max_title_length": 4096
} }
} }

View File

@ -3,20 +3,20 @@
// Notices stack // Notices queue
$NTFY_NoticesStack = array(); $NTFY_NoticesQueue = array();
// Add new notice with selected type // Add new notice with selected type
function NTFY_AddNotice (string $text, string $type = "fail") { function NTFY_AddNotice (string $text, string $type = "fail") {
global $NTFY_NoticesStack; global $NTFY_NoticesQueue;
switch ($type) { switch ($type) {
case "fail": case "fail":
$NTFY_NoticesStack[] = "<div class=\"notification_fail\"><p>$text</p></div>"; $NTFY_NoticesQueue[] = "<div class=\"notification_fail\"><p>$text</p></div>";
break; break;
case "success": case "success":
$NTFY_NoticesStack[] = "<div class=\"notification_success\"><p>$text</p></div>"; $NTFY_NoticesQueue[] = "<div class=\"notification_success\"><p>$text</p></div>";
break; break;
default: default:
die("invalid notification type: $type"); die("invalid notification type: $type");
@ -25,8 +25,8 @@ function NTFY_AddNotice (string $text, string $type = "fail") {
// Echo all notifications // Echo all notifications
function NTFY_EchoAllNotices () { function NTFY_EchoAllNotices () {
global $NTFY_NoticesStack; global $NTFY_NoticesQueue;
foreach ($NTFY_NoticesStack as $notice) { foreach ($NTFY_NoticesQueue as $notice) {
echo "$notice\n"; echo "$notice\n";
} }
} }