diff --git a/api/_auth.php b/api/_auth.php index 531f3cf..24f5fd5 100644 --- a/api/_auth.php +++ b/api/_auth.php @@ -4,7 +4,7 @@ // Includes -if ($IS_FRONTEND) +if (isset($IS_FRONTEND) && $IS_FRONTEND) require_once("api/_db.php"); else require_once("_db.php"); diff --git a/api/_config.php b/api/_config.php index 7c94eb5..8161047 100644 --- a/api/_config.php +++ b/api/_config.php @@ -35,7 +35,7 @@ function CreateDirIfNotExist ($path) { } // Creating dirs at correct path -if ($IS_FRONTEND) { +if (isset($IS_FRONTEND) && $IS_FRONTEND) { CreateDirIfNotExist($Config["media"]["pics_path"]); CreateDirIfNotExist($Config["media"]["prevs_path"]); } else { diff --git a/api/_db.php b/api/_db.php index 868e429..e4cfee0 100644 --- a/api/_db.php +++ b/api/_db.php @@ -4,7 +4,7 @@ // Includes -if ($IS_FRONTEND) +if (isset($IS_FRONTEND) && $IS_FRONTEND) require_once("api/_config.php"); else require_once("_config.php"); diff --git a/api/_json.php b/api/_json.php index 2d4a138..05a847c 100644 --- a/api/_json.php +++ b/api/_json.php @@ -4,7 +4,7 @@ // Includes -if ($IS_FRONTEND) +if (isset($IS_FRONTEND) && $IS_FRONTEND) require_once("api/_errorslist.php"); else require_once("_errorslist.php"); diff --git a/api/_types.php b/api/_types.php index 0624b40..4bd43fa 100644 --- a/api/_types.php +++ b/api/_types.php @@ -4,7 +4,7 @@ // Includes -if ($IS_FRONTEND) { +if (isset($IS_FRONTEND) && $IS_FRONTEND) { require_once("api/_errorslist.php"); require_once("api/_json.php"); } else { diff --git a/api/_utils.php b/api/_utils.php index fd6b934..93657eb 100644 --- a/api/_utils.php +++ b/api/_utils.php @@ -18,7 +18,7 @@ function Utils_GenerateRandomString (int $length, string $keyspace = "abcdefghij for ($i = 0; $i < $length; ++$i) { $pieces []= $keyspace[random_int(0, $max)]; } - return implode('', $pieces); + return implode("", $pieces); } // Get ratio from two values @@ -37,6 +37,11 @@ function Utils_JoinPaths () { return preg_replace('#/+#','/',join('/', $paths)); } +// Check if string is valid ASCII +function Utils_IsAscii (string $str): bool { + return (bool)!preg_match("/[\\x80-\\xff]+/", $string); +} + ?> \ No newline at end of file diff --git a/api/post/create.php b/api/post/create.php index 5df2add..fe32f33 100644 --- a/api/post/create.php +++ b/api/post/create.php @@ -4,18 +4,20 @@ // Includes -if ($IS_FRONTEND) { +if (isset($IS_FRONTEND) && $IS_FRONTEND) { require_once("api/_auth.php"); require_once("api/_utils.php"); require_once("api/_errorslist.php"); require_once("api/_types.php"); require_once("api/user/index.php"); + require_once("api/tags/index.php"); } else { require_once("../_auth.php"); require_once("../_utils.php"); require_once("../_errorslist.php"); require_once("../_types.php"); require_once("../user/index.php"); + require_once("../tags/index.php"); } @@ -203,12 +205,20 @@ function Post_Create_Method (array $req, array $files): ReturnT { 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 + // Check if supplied string is ASCII + if (!Utils_IsAscii($req["tags"])) + return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags must be ASCII-only"); // Parsing tags $parsedTags = Post_ParseRawTagString($req["tags"]); if ($parsedTags->IsError()) return $parsedTags; - // TODO: check if tags are approved + $parsedTags = $parsedTags->GetData(); + // Check if tags are approved + foreach ($parsedTags as $singleTag) { + if (!Tags_IsTagApproved($singleTag)) + return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag $singleTag is not approved"); + } + // Concatenating parsed tags to single comma-separated string $tags = implode(",", $parsedTags); // Check user role TODO: add rate-limiting, instead of this diff --git a/api/post/index.php b/api/post/index.php index 8bb0e3f..4e88f27 100644 --- a/api/post/index.php +++ b/api/post/index.php @@ -87,7 +87,7 @@ function Post_GetByID (int $id): ReturnT { $result["edit_lock"] = $d["edit_lock"]; $r = Post_AddView($id); // TODO: add rate-limit or completely rework - if ($r.IsError()) + if ($r->IsError()) return $r; return new ReturnT(data: $result); diff --git a/api/tags/index.php b/api/tags/index.php new file mode 100644 index 0000000..1f65376 --- /dev/null +++ b/api/tags/index.php @@ -0,0 +1,122 @@ +prepare("SELECT * FROM approved_tags ORDER BY value"); + $s->execute(); + $d = $s->get_result(); + + if (!(bool)$d) + return $result; + + while ($row = $d->fetch_array()) { + $result[] = $row["value"]; + } + + return $result; +} + +/* + * FUNCTION + * Check if tag is in list of approved tags + */ +function Tags_IsTagApproved (string $str): bool { + global $db; + + $s = $db->prepare("SELECT value FROM approved_tags WHERE value = ?"); + $s->bind_param("s", $str); + $s->execute(); + + return (bool)$s->get_result()->fetch_assoc(); +} + + + +// Methods + +/* + * METHOD + * Check if tag is approved + */ +function Tags_IsTagApproved_Method (array $req): ReturnT { + global $Config; + + $requestedTag = $req["value"]; + + // Input sanity checks + + // Check length + $maxTagLen = $Config["posting"]["tags"]["max_single_length"]; + $realLen = strlen($requestedTag); + if ($realLen > $maxTagLen) + return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag length must be equal to or less than " . strval($maxTagLen)); + elseif ($realLen < 1) + return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag can not be empty"); + + // Check symbols + $allowedSymbols = $Config["posting"]["tags"]["allowed_syms"]; + $preg_str = "/[^" . $allowedSymbols . "]/"; + if (preg_match($preg_str, $requestedTag)) + return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "only allowed symbols in tags are: " . $allowedSymbols); + + // Actions + + return new ReturnT(data: array( + "tag" => $requestedTag, + "is_approved" => Tags_IsTagApproved($requestedTag) + )); +} + +/* + * METHOD + * Get list of all approved tags + */ +function Tags_GetListOfApproved_Method (): ReturnT { + // Actions + return new ReturnT(data: Tags_GetListOfApproved()); +} + + + +if (Utils_ThisFileIsRequested(__FILE__)) { + require_once("../_json.php"); + + if (isset($_REQUEST["value"])) + $result = Tags_IsTagApproved_Method($_REQUEST); + else + $result = Tags_GetListOfApproved_Method(); + + if ($result->IsError()) + $result->ThrowJSONError(); + else + JSON_ReturnData($result->GetData()); +} + +?> \ No newline at end of file diff --git a/api/user/index.php b/api/user/index.php index a253fea..8aea5ef 100644 --- a/api/user/index.php +++ b/api/user/index.php @@ -27,7 +27,7 @@ if ($IS_FRONTEND) { function User_LoginExist (string $login): bool { global $db; - $s = $db->prepare("SELECT * FROM users WHERE login = ?"); + $s = $db->prepare("SELECT id FROM users WHERE login = ?"); $s->bind_param("s", $login); $s->execute(); @@ -41,7 +41,7 @@ function User_LoginExist (string $login): bool { function User_IDExist (int $id): bool { global $db; - $s = $db->prepare("SELECT * FROM users WHERE id = ?"); + $s = $db->prepare("SELECT id FROM users WHERE id = ?"); $s->bind_param("s", $id); $s->execute(); @@ -55,7 +55,7 @@ function User_IDExist (int $id): bool { function User_HasRole (int $id, string $role): ReturnT { global $db; - $s = $db->prepare("SELECT * FROM users WHERE id = ?"); + $s = $db->prepare("SELECT role FROM users WHERE id = ?"); $s->bind_param("s", $id); $s->execute(); $d = $s->get_result()->fetch_assoc(); @@ -73,7 +73,7 @@ function User_HasRole (int $id, string $role): ReturnT { function User_IsMod (int $id): ReturnT { global $db; - $s = $db->prepare("SELECT * FROM users WHERE id = ?"); + $s = $db->prepare("SELECT role FROM users WHERE id = ?"); $s->bind_param("s", $id); $s->execute(); $d = $s->get_result()->fetch_assoc();