Создание поста
Метод API для создания поста; страница фронта и стили для него; новый тип ошибки при неудачной загрузке файла; фикс функции проверки строки на соответствие кодировке ASCII; фикс парсинга тегов; умное создание превью (проверка на случай, если превью получилось больше оригинала); исправление функции сохранения изображения; фикс функции создания поста, которая взаимодействует с БД; добавлена проверка корректности подписи к посту; добавление новых пунктов в навигацию; небольшое улучшение QoL в плане конфига.
This commit is contained in:
parent
de456dea0a
commit
705e8cd6a2
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ test.png
|
|||||||
TODO.md
|
TODO.md
|
||||||
front/images/*
|
front/images/*
|
||||||
front/images/counter/*
|
front/images/counter/*
|
||||||
|
config.json
|
||||||
|
@ -11,4 +11,6 @@ sudo rm -r /usr/share/nginx/html/testing/E949 && sudo cp -R . /usr/share/nginx/h
|
|||||||
mysql -u e949 -p
|
mysql -u e949 -p
|
||||||
|
|
||||||
#049e59 -> #094e59
|
#049e59 -> #094e59
|
||||||
|
|
||||||
|
php requires extensions: mysqli gd intl
|
||||||
-->
|
-->
|
@ -19,6 +19,7 @@ const E_UIN_FILETYPE = 204; // Wrong file type
|
|||||||
const E_UIN_IMGBADRES = 205; // Invalid image resolution
|
const E_UIN_IMGBADRES = 205; // Invalid image resolution
|
||||||
const E_UIN_INSUFARGS = 206; // Not enough arguments was supplied to method
|
const E_UIN_INSUFARGS = 206; // Not enough arguments was supplied to method
|
||||||
const E_UIN_BADARGS = 207; // Bad arguments
|
const E_UIN_BADARGS = 207; // Bad arguments
|
||||||
|
const E_UIN_FAIL2UPLD = 208; // Failed to upload file
|
||||||
// Authentication errors
|
// Authentication errors
|
||||||
const E_AUT_ALRLOGIN = 301; // User is already logged in
|
const E_AUT_ALRLOGIN = 301; // User is already logged in
|
||||||
const E_AUT_REGCLOSED = 302; // Registrations are closed
|
const E_AUT_REGCLOSED = 302; // Registrations are closed
|
||||||
@ -52,6 +53,7 @@ $Errors_Enum = array(
|
|||||||
array("uin.imgbadres", E_UIN_IMGBADRES, "invalid image resolution"),
|
array("uin.imgbadres", E_UIN_IMGBADRES, "invalid image resolution"),
|
||||||
array("uin.insufargs", E_UIN_INSUFARGS, "not enough arguments was supplied to method"),
|
array("uin.insufargs", E_UIN_INSUFARGS, "not enough arguments was supplied to method"),
|
||||||
array("uin.badargs", E_UIN_BADARGS, "bad arguments"),
|
array("uin.badargs", E_UIN_BADARGS, "bad arguments"),
|
||||||
|
array("uin.fail2upld", E_UIN_FAIL2UPLD, "failed to upload file"),
|
||||||
// Authentication errors
|
// Authentication errors
|
||||||
array("aut.alrlogin", E_AUT_ALRLOGIN, "already logged in"),
|
array("aut.alrlogin", E_AUT_ALRLOGIN, "already logged in"),
|
||||||
array("aut.regclosed", E_AUT_REGCLOSED, "registrations are closed"),
|
array("aut.regclosed", E_AUT_REGCLOSED, "registrations are closed"),
|
||||||
|
@ -39,7 +39,7 @@ function Utils_JoinPaths () {
|
|||||||
|
|
||||||
// Check if string is valid ASCII
|
// Check if string is valid ASCII
|
||||||
function Utils_IsAscii (string $str): bool {
|
function Utils_IsAscii (string $str): bool {
|
||||||
return (bool)!preg_match("/[\\x80-\\xff]+/", $string);
|
return (bool)!preg_match("/[\\x80-\\xff]+/", $str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,15 +38,16 @@ function Post_ParseRawTagString (string $str): ReturnT {
|
|||||||
$currTag = "";
|
$currTag = "";
|
||||||
$result = array();
|
$result = array();
|
||||||
|
|
||||||
for ($i = 0; $i < $strLength; ++$i) {
|
for ($i = 0; $i <= $strLength; ++$i) {
|
||||||
if ($str[$i] === ",") {
|
if ($i === $strLength || $str[$i] === ",") {
|
||||||
if ($currLen) {
|
if ($currLen > 0) {
|
||||||
$result[] = $currTag;
|
$result[] = $currTag;
|
||||||
$currLen = 0;
|
$currLen = 0;
|
||||||
|
$currTag = "";
|
||||||
} else {
|
} else {
|
||||||
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "syntax error while trying to parse tags");
|
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "syntax error while trying to parse tags");
|
||||||
}
|
}
|
||||||
} elseif ($str[$i] !== " " && $str[$i] !== "\t") {
|
} elseif (!IntlChar::isspace($str[$i])) {
|
||||||
$currTag .= $str[$i];
|
$currTag .= $str[$i];
|
||||||
if (++$currLen > $maxTagLength)
|
if (++$currLen > $maxTagLength)
|
||||||
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag too large: $currTag");
|
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag too large: $currTag");
|
||||||
@ -54,9 +55,12 @@ function Post_ParseRawTagString (string $str): ReturnT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$preg_str = "/[^" . $allowedSymbols . "]/";
|
$preg_str = "/[^" . $allowedSymbols . "]/";
|
||||||
|
|
||||||
foreach ($result as $tag) {
|
foreach ($result as $tag) {
|
||||||
if (preg_match($preg_str, $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(err_code: E_UIN_BADARGS, err_desc: "only allowed symbols in tags are: " . $allowedSymbols);
|
||||||
|
elseif (!$tag)
|
||||||
|
unset($tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ReturnT(data: $result);
|
return new ReturnT(data: $result);
|
||||||
@ -94,10 +98,17 @@ function Post_CreatePreviewFromImage (string $src, string $dst): ReturnT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Saving it as LQ JPEG
|
// Saving it as LQ JPEG
|
||||||
imagejpeg($img, $dst, 30);
|
$saveResult = imagejpeg($img, $dst, 30);
|
||||||
|
|
||||||
if (!file_exists($dst)) // $src isnt our responsibility, $dst is
|
if (!$saveResult) {
|
||||||
|
if (file_exists($dst)) // $src isnt our responsibility, $dst is
|
||||||
|
unlink($dst);
|
||||||
return new ReturnT(err_code: E_UNS_UNEXPECTED, err_desc: "failed to create preview");
|
return new ReturnT(err_code: E_UNS_UNEXPECTED, err_desc: "failed to create preview");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if preview is bigger or same size as original...
|
||||||
|
if (filesize($src) < filesize($dst))
|
||||||
|
unlink($dst); // ...then we can just delete preview. Frontend will use preview only when it exist
|
||||||
|
|
||||||
return new ReturnT(data: true);
|
return new ReturnT(data: true);
|
||||||
}
|
}
|
||||||
@ -107,28 +118,42 @@ function Post_CreatePreviewFromImage (string $src, string $dst): ReturnT {
|
|||||||
* Stores image and returns paths to picture and its preview
|
* Stores image and returns paths to picture and its preview
|
||||||
*/
|
*/
|
||||||
function Post_StoreImage (string $path): ReturnT {
|
function Post_StoreImage (string $path): ReturnT {
|
||||||
global $Config;
|
global $Config, $IS_FRONTEND;
|
||||||
|
|
||||||
|
// Original extension
|
||||||
|
$ext = "";
|
||||||
|
if (mime_content_type($path) === "image/jpeg")
|
||||||
|
$ext = "jpg";
|
||||||
|
elseif (mime_content_type($path) === "image/png")
|
||||||
|
$ext = "png";
|
||||||
|
else
|
||||||
|
return new ReturnT(err_code: E_UNS_UNEXPECTED, err_desc: "failed to determine correctly mime type of image");
|
||||||
|
|
||||||
// Paths
|
// Paths
|
||||||
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
$fileName = strval(time()) . "_" . Utils_GenerateRandomString(4);
|
||||||
$fileName = strval(time()) . "_" . GenerateRandomString(4);
|
// Defining base dir
|
||||||
$targetDir = "../../" . $Config["media"]["pics_path"];
|
$baseDir = "";
|
||||||
|
if (isset($IS_FRONTEND) && $IS_FRONTEND)
|
||||||
|
$baseDir = "./";
|
||||||
|
else
|
||||||
|
$baseDir = "../../";
|
||||||
|
$targetDir = $baseDir . $Config["media"]["pics_path"];
|
||||||
$targetPath = Utils_JoinPaths($targetDir, $fileName . "." . $ext);
|
$targetPath = Utils_JoinPaths($targetDir, $fileName . "." . $ext);
|
||||||
|
|
||||||
|
// Moving original picture
|
||||||
|
$moveResult = move_uploaded_file($path, $targetPath);
|
||||||
|
if (!$moveResult)
|
||||||
|
return new ReturnT(err_code: E_UNS_UNEXPECTED, err_desc: "failed to move uploaded file");
|
||||||
|
|
||||||
// Creating preview file
|
// Creating preview file
|
||||||
if ($Config["media"]["previews_enabled"]) {
|
if ($Config["media"]["previews_enabled"]) {
|
||||||
$previewDir = "../../" . $Config["media"]["prevs_path"];
|
$previewDir = $baseDir . $Config["media"]["prevs_path"];
|
||||||
$previewPath = Utils_JoinPaths($previewDir, $fileName . ".jpg");
|
$previewPath = Utils_JoinPaths($previewDir, $fileName . ".jpg");
|
||||||
$res = Post_CreatePreviewFromImage($path, $previewPath);
|
$res = Post_CreatePreviewFromImage($targetPath, $previewPath);
|
||||||
if ($res->IsError()) // $path isnt our responsibility
|
if ($res->IsError()) // $path and $targetPath arent our responsibility, neither is $previewPath
|
||||||
return $res;
|
return $res;
|
||||||
}
|
if (!file_exists($previewPath)) // If no preview was created - then just nullify path
|
||||||
|
$previewPath = null;
|
||||||
move_uploaded_file($path, $targetPath);
|
|
||||||
|
|
||||||
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(
|
return new ReturnT(data: array(
|
||||||
@ -159,8 +184,8 @@ function Post_Create (
|
|||||||
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");
|
||||||
|
|
||||||
// Performing SQL query
|
// Performing SQL query
|
||||||
$s = $db->prepare("INSERT INTO posts (author_id,comment_section_id,tags,title,pic_path,preview_path,comments_enabled,edit_lock) VALUES (?,?,?,?,?,?,?,?)");
|
$s = $db->prepare("INSERT INTO posts (author_id,tags,title,pic_path,preview_path,comments_enabled,edit_lock) VALUES (?,?,?,?,?,?,?)");
|
||||||
$s->bind_param("ssssssss", $author_id, null, $tags, $title, $pic_path, $prev_path, $comms_enabled, $edit_lock);
|
$s->bind_param("issssii", $author_id, $tags, $title, $pic_path, $prev_path, $comms_enabled, $edit_lock);
|
||||||
|
|
||||||
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");
|
||||||
@ -181,12 +206,11 @@ function Post_Create (
|
|||||||
function Post_Create_Method (array $req, array $files): ReturnT {
|
function Post_Create_Method (array $req, array $files): ReturnT {
|
||||||
global $Config, $LOGGED_IN, $THIS_USER;
|
global $Config, $LOGGED_IN, $THIS_USER;
|
||||||
|
|
||||||
$author_id = $THIS_USER;
|
|
||||||
$tags = null;
|
$tags = null;
|
||||||
$pic_path = null;
|
$pic_path = null;
|
||||||
$title = null;
|
$title = null;
|
||||||
$prev_path = null;
|
$prev_path = null;
|
||||||
$comms_enabled = false;
|
$comms_enabled = false; // TODO: support for this option at post creation
|
||||||
|
|
||||||
// Input sanity checks
|
// Input sanity checks
|
||||||
|
|
||||||
@ -195,14 +219,15 @@ function Post_Create_Method (array $req, array $files): ReturnT {
|
|||||||
return new ReturnT(err_code: E_AUT_NOTAUTHED, err_desc: "you must be logged in to create posts");
|
return new ReturnT(err_code: E_AUT_NOTAUTHED, err_desc: "you must be logged in to create posts");
|
||||||
|
|
||||||
// Check if there are necessary input
|
// Check if there are necessary input
|
||||||
if (!(isset($req["tags"]) && isset($files["pic"])))
|
if (!isset($req["tags"]) || !isset($files["pic"]) || is_array($files["pic"]["error"]) || $files["pic"]["error"] === UPLOAD_ERR_NO_FILE)
|
||||||
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");
|
||||||
|
|
||||||
// Check tags
|
// Check tags
|
||||||
// If raw string length not fits into limit
|
// If raw string length not fits into limit
|
||||||
$tagsLen = strlen($req["tags"]);
|
$tagsLen = strlen($req["tags"]);
|
||||||
if ($tagsLen > $Config["posting"]["tags"]["max_raw_input_str_length"])
|
$tagsMaxLen = $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"]));
|
if ($tagsLen > $tagsMaxLen)
|
||||||
|
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags string length exceeds limit: " . $tagsMaxLen);
|
||||||
elseif ($tagsLen < 1)
|
elseif ($tagsLen < 1)
|
||||||
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags cant be empty");
|
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags cant be empty");
|
||||||
// Check if supplied string is ASCII
|
// Check if supplied string is ASCII
|
||||||
@ -216,7 +241,7 @@ function Post_Create_Method (array $req, array $files): ReturnT {
|
|||||||
// Check if tags are approved
|
// Check if tags are approved
|
||||||
foreach ($parsedTags as $singleTag) {
|
foreach ($parsedTags as $singleTag) {
|
||||||
if (!Tags_IsTagApproved($singleTag))
|
if (!Tags_IsTagApproved($singleTag))
|
||||||
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag $singleTag is not approved");
|
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag \"$singleTag\" is not approved");
|
||||||
}
|
}
|
||||||
// Concatenating parsed tags to single comma-separated string
|
// Concatenating parsed tags to single comma-separated string
|
||||||
$tags = implode(",", $parsedTags);
|
$tags = implode(",", $parsedTags);
|
||||||
@ -225,15 +250,56 @@ function Post_Create_Method (array $req, array $files): ReturnT {
|
|||||||
if (User_HasRole($THIS_USER, "newbie")->GetData())
|
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");
|
||||||
|
|
||||||
|
// Checking title
|
||||||
|
if (isset($req["title"])) {
|
||||||
|
// Title length
|
||||||
|
$maxTitleLen = $Config["posting"]["title"]["max_length"];
|
||||||
|
$realTitleLen = strlen($req["title"]);
|
||||||
|
if ($realTitleLen > $maxTitleLen)
|
||||||
|
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "title length exceeds maximum value");
|
||||||
|
// Cleaning off all bad symbols (no script injection allowed here)
|
||||||
|
for ($i = 0; $i < $realTitleLen; ++$i) {
|
||||||
|
switch ($req["title"][$i]) {
|
||||||
|
case "<":
|
||||||
|
$title .= "<";
|
||||||
|
break;
|
||||||
|
case ">":
|
||||||
|
$title .= ">";
|
||||||
|
break;
|
||||||
|
case "/":
|
||||||
|
$title .= "/";
|
||||||
|
break;
|
||||||
|
case "\\":
|
||||||
|
$title .= "\";
|
||||||
|
break;
|
||||||
|
case "?":
|
||||||
|
$title .= "?";
|
||||||
|
break;
|
||||||
|
case "&":
|
||||||
|
$title .= "&";
|
||||||
|
break;
|
||||||
|
case "\n":
|
||||||
|
$title .= "<br>";
|
||||||
|
break;
|
||||||
|
case "\t":
|
||||||
|
$title .= " ";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$title .= $req["title"][$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strlen($title) > $maxTitleLen)
|
||||||
|
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "title length exceeds maximum value after escaping");
|
||||||
|
}
|
||||||
|
|
||||||
// Check image properties
|
// Check image properties
|
||||||
|
// If error happened while uploading
|
||||||
|
if ($files["pic"]["error"] !== UPLOAD_ERR_OK)
|
||||||
|
return new ReturnT(err_code: E_UIN_FAIL2UPLD, err_desc: "error while uploading file: " . strval($files["pic"]["error"]));
|
||||||
// If size is too large
|
// If size is too large
|
||||||
if ($files["pic"]["size"] > $Config["media"]["max_pic_size"])
|
if ($files["pic"]["size"] > $Config["media"]["max_pic_size"])
|
||||||
return new ReturnT(err_code: E_UIN_FILE2LARGE, err_desc: "picture size is too large");
|
return new ReturnT(err_code: E_UIN_FILE2LARGE, err_desc: "picture size is too large");
|
||||||
$TmpFilePath = $_FILES["pic"]["tmp_name"];
|
$TmpFilePath = $files["pic"]["tmp_name"];
|
||||||
$Ext = strtolower(pathinfo($TmpFilePath, PATHINFO_EXTENSION));
|
|
||||||
// If file extension is not in list of allowed
|
|
||||||
if (!in_array($Ext, $Config["media"]["allowed_exts"]))
|
|
||||||
return new ReturnT(err_code: E_UIN_FILETYPE, err_desc: "picture extension is invalid");
|
|
||||||
// If file mime type is not in list of allowed
|
// If file mime type is not in list of allowed
|
||||||
if (!in_array(mime_content_type($TmpFilePath), $Config["media"]["allowed_mimetypes"]))
|
if (!in_array(mime_content_type($TmpFilePath), $Config["media"]["allowed_mimetypes"]))
|
||||||
return new ReturnT(err_code: E_UIN_FILETYPE, err_desc: "picture mime type is invalid");
|
return new ReturnT(err_code: E_UIN_FILETYPE, err_desc: "picture mime type is invalid");
|
||||||
@ -250,10 +316,17 @@ function Post_Create_Method (array $req, array $files): ReturnT {
|
|||||||
unlink($TmpFilePath);
|
unlink($TmpFilePath);
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
$res = $res->GetData();
|
||||||
$pic_path = $res["picture"];
|
$pic_path = $res["picture"];
|
||||||
$prev_path = $res["preview"];
|
$prev_path = $res["preview"];
|
||||||
|
|
||||||
return Post_Create($author_id, $tags, $pic_path, $title, $prev_path, $comms_enabled, false);
|
$res = Post_Create($THIS_USER, $tags, $pic_path, $title, $prev_path, $comms_enabled, false);
|
||||||
|
if ($res->IsError()) { // Cleaning up all processed pics
|
||||||
|
unlink($pic_path);
|
||||||
|
if ($prev_path)
|
||||||
|
unlink($prev_path);
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -261,7 +334,13 @@ 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
|
$result = Post_Create_Method($_POST, $_FILES);
|
||||||
|
|
||||||
|
// Checking result
|
||||||
|
if ($result->IsError())
|
||||||
|
$result->ThrowJSONError();
|
||||||
|
else
|
||||||
|
JSON_ReturnData(["success" => $result->GetData()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@ -43,6 +43,8 @@
|
|||||||
"max_raw_input_str_length": 1536,
|
"max_raw_input_str_length": 1536,
|
||||||
"allowed_syms": "a-zA-Z0-9_"
|
"allowed_syms": "a-zA-Z0-9_"
|
||||||
},
|
},
|
||||||
"max_title_length": 4096
|
"title": {
|
||||||
|
"max_length": 4096
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
50
config.json.example
Normal file
50
config.json.example
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"debug": true,
|
||||||
|
"db": {
|
||||||
|
"addr": "localhost",
|
||||||
|
"name": "e949",
|
||||||
|
"user": "e949",
|
||||||
|
"pass": "password"
|
||||||
|
},
|
||||||
|
"registration": {
|
||||||
|
"active": true,
|
||||||
|
"need_email": false,
|
||||||
|
"need_invite": false,
|
||||||
|
"allowed_syms": "a-zA-Z0-9_=+-",
|
||||||
|
"min_passw_len": 8
|
||||||
|
},
|
||||||
|
"accounts": {
|
||||||
|
"external_avatars": false
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"pics_path": "media/pics/",
|
||||||
|
"prevs_path": "media/prevs/",
|
||||||
|
"previews_enabled": true,
|
||||||
|
"max_pic_size": 56623104,
|
||||||
|
"max_pic_res": {
|
||||||
|
"x": 8192,
|
||||||
|
"y": 8192,
|
||||||
|
"ratio": 20
|
||||||
|
},
|
||||||
|
"allowed_exts": [
|
||||||
|
"jpg",
|
||||||
|
"jpeg",
|
||||||
|
"png"
|
||||||
|
],
|
||||||
|
"allowed_mimetypes": [
|
||||||
|
"image/jpeg",
|
||||||
|
"image/png"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"posting": {
|
||||||
|
"tags": {
|
||||||
|
"max_per_post": 256,
|
||||||
|
"max_single_length": 256,
|
||||||
|
"max_raw_input_str_length": 1536,
|
||||||
|
"allowed_syms": "a-zA-Z0-9_"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"max_length": 4096
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,12 +22,16 @@ require_once("api/user/index.php");
|
|||||||
<?php
|
<?php
|
||||||
// If user is logged in
|
// If user is logged in
|
||||||
if ($LOGGED_IN) {
|
if ($LOGGED_IN) {
|
||||||
|
// Showing user profile button
|
||||||
$res = User_GetInfoByID($THIS_USER);
|
$res = User_GetInfoByID($THIS_USER);
|
||||||
if ($res->IsError())
|
if ($res->IsError())
|
||||||
$res->ThrowJSONError();
|
$res->ThrowJSONError();
|
||||||
$uname = $res->GetData()["login"];
|
$uname = $res->GetData()["login"];
|
||||||
echo "<a class=\"useraccount\" title=\"Account page\" href=\"./?do=user_info&id=$THIS_USER\">$uname</a>";
|
echo "<a class=\"useraccount\" title=\"Account page\" href=\"./?do=user_info&id=$THIS_USER\">$uname</a>\n";
|
||||||
unset($res);
|
unset($res);
|
||||||
|
|
||||||
|
// Showing post creation button
|
||||||
|
echo "<a title=\"Create new post\" href=\"./?do=new_post\">New post</a>\n";
|
||||||
} else { // If user is NOT logged in
|
} else { // If user is NOT logged in
|
||||||
?>
|
?>
|
||||||
<a title="Login in existing account" href="./?do=login">Login</a>
|
<a title="Login in existing account" href="./?do=login">Login</a>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Login page
|
// Login page
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
require_once("api/user/login.php");
|
require_once("api/user/login.php");
|
||||||
require_once("front/pages/main_nav.php");
|
require_once("front/pages/main_nav.php");
|
||||||
@ -34,7 +35,7 @@ NTFY_EchoAllNotices();
|
|||||||
?>
|
?>
|
||||||
<div class="visualbox">
|
<div class="visualbox">
|
||||||
<h1>Login</h1>
|
<h1>Login</h1>
|
||||||
<form class="login" action="./?do=login" accept-charset="UTF-8" method="post">
|
<form class="basicform" action="./?do=login" accept-charset="UTF-8" method="post">
|
||||||
<div>
|
<div>
|
||||||
<label for="login">Username</label><br>
|
<label for="login">Username</label><br>
|
||||||
<input type="text" name="login" id="login" <?php if (isset($_POST["login"])) { echo "value=\"" . $_POST["login"] . "\""; } ?>>
|
<input type="text" name="login" id="login" <?php if (isset($_POST["login"])) { echo "value=\"" . $_POST["login"] . "\""; } ?>>
|
||||||
|
@ -3,47 +3,51 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
$MARKUP_CURRENT_PAGE = "class=\"current\"";
|
|
||||||
$MARKUP_CURRENT_PAGE_LOGIN = "";
|
|
||||||
$MARKUP_CURRENT_PAGE_REGISTER = "";
|
|
||||||
$MARKUP_CURRENT_PAGE_VIEWTAGS = "";
|
|
||||||
$MARKUP_CURRENT_PAGE_STATS = "";
|
|
||||||
|
|
||||||
if ($WHAT_PAGE_IS_CURRENT["login"])
|
|
||||||
$MARKUP_CURRENT_PAGE_LOGIN = $MARKUP_CURRENT_PAGE;
|
|
||||||
elseif ($WHAT_PAGE_IS_CURRENT["register"])
|
|
||||||
$MARKUP_CURRENT_PAGE_REGISTER = $MARKUP_CURRENT_PAGE;
|
|
||||||
elseif ($WHAT_PAGE_IS_CURRENT["view_tags"])
|
|
||||||
$MARKUP_CURRENT_PAGE_VIEWTAGS = $MARKUP_CURRENT_PAGE;
|
|
||||||
elseif ($WHAT_PAGE_IS_CURRENT["view_stats"])
|
|
||||||
$MARKUP_CURRENT_PAGE_STATS = $MARKUP_CURRENT_PAGE;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<nav class="main">
|
<nav class="main">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p><a title="Main site page" href="./?do=main">Index</p></a>
|
<p><a title="Main site page" href="./?do=main">Main</p></a>
|
||||||
</li>
|
</li>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<li <?php echo $MARKUP_CURRENT_PAGE_LOGIN; ?>>
|
<?php
|
||||||
|
if ($LOGGED_IN) {
|
||||||
|
// Getting user nickname
|
||||||
|
$res = User_GetInfoByID($THIS_USER);
|
||||||
|
if ($res->IsError())
|
||||||
|
$res->ThrowJSONError();
|
||||||
|
$uname = $res->GetData()["login"];
|
||||||
|
?>
|
||||||
|
<li>
|
||||||
|
<p><a title="User page" href="./?do=user_info&id=<?php echo $THIS_USER; ?>">Me (<?php echo $uname; ?>)</p></a>
|
||||||
|
</li>
|
||||||
|
<span>|</span>
|
||||||
|
<li>
|
||||||
|
<p><a title="Create new post" href="./?do=new_post">New post</p></a>
|
||||||
|
</li>
|
||||||
|
<?php
|
||||||
|
} else {
|
||||||
|
?>
|
||||||
|
<li>
|
||||||
<p><a title="Login in existing account" href="./?do=login">Login</p></a>
|
<p><a title="Login in existing account" href="./?do=login">Login</p></a>
|
||||||
</li>
|
</li>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<li <?php echo $MARKUP_CURRENT_PAGE_REGISTER; ?>>
|
<li>
|
||||||
<p><a title="Create new account" href="./?do=register">Register</p></a>
|
<p><a title="Create new account" href="./?do=register">Register</p></a>
|
||||||
</li>
|
</li>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<li>
|
<li>
|
||||||
<p><a title="A paginated list of every post" href="./?do=search_posts">Posts</p></a>
|
<p><a title="A paginated list of every post" href="./?do=search_posts">Posts</p></a>
|
||||||
</li>
|
</li>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<li <?php echo $MARKUP_CURRENT_PAGE_VIEWTAGS; ?>>
|
<li>
|
||||||
<p><a title="A paginated list of every tag" href="./?do=view_tags">Tags</p></a>
|
<p><a title="A paginated list of every tag" href="./?do=view_tags">Tags</p></a>
|
||||||
</li>
|
</li>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<li <?php echo $MARKUP_CURRENT_PAGE_STATS; ?>>
|
<li>
|
||||||
<p><a title="Statistics of current instance" href="./?do=view_stats">Stats</p></a>
|
<p><a title="Statistics of current instance" href="./?do=view_stats">Stats</p></a>
|
||||||
</li>
|
</li>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
|
61
front/pages/new_post/page.php
Normal file
61
front/pages/new_post/page.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
// Post creation page
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Includes
|
||||||
|
require_once("api/post/create.php");
|
||||||
|
require_once("front/pages/main_nav.php");
|
||||||
|
require_once("front/notifications.php");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Redirecting to main page if not logged in
|
||||||
|
if (!$LOGGED_IN) {
|
||||||
|
header("Location: .");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processing POST-request
|
||||||
|
if (isset($_POST) && $_POST) {
|
||||||
|
if (isset($_POST["tags"]) && $_POST["tags"] && isset($_FILES["pic"])) {
|
||||||
|
if (isset($_POST["title"]) && !$_POST["title"])
|
||||||
|
unset($_POST["title"]);
|
||||||
|
|
||||||
|
$result = Post_Create_Method($_POST, $_FILES);
|
||||||
|
if ($result->IsError()) { // Something happened
|
||||||
|
NTFY_AddNotice("Failed to create post! Reason:<br>" . $result->GetError());
|
||||||
|
} /*else { // All OK
|
||||||
|
header("Location: .");
|
||||||
|
exit();
|
||||||
|
} TODO: redirect to page with new post */
|
||||||
|
} else {
|
||||||
|
NTFY_AddNotice("You must supply image and tags for post");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTFY_EchoAllNotices();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
<div class="visualbox">
|
||||||
|
<h1>New post</h1>
|
||||||
|
<form class="basicform" action="./?do=new_post" accept-charset="UTF-8" method="post" enctype="multipart/form-data">
|
||||||
|
<div>
|
||||||
|
<label for="pic">Select image:</label><br>
|
||||||
|
<input type="file" name="pic" id="pic">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="tags">Comma-separated tags list:</label><br>
|
||||||
|
<textarea placeholder="tag_1, tag_2, tag_3, ..., tag_N" name="tags" id="tags" style="width: 98%;" rows="1"><?php if (isset($_POST["tags"])) { echo $_POST["tags"]; } ?></textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="title">Post title:</label><br>
|
||||||
|
<textarea placeholder="Lorem ipsum dolor sit amet..." name="title" id="title" style="width: 98%;" rows="2"><?php if (isset($_POST["title"]) && !$_POST["title"]) { echo $_POST["title"]; } ?></textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -50,7 +50,7 @@ NTFY_EchoAllNotices();
|
|||||||
<?php
|
<?php
|
||||||
if ($REGISTRATION_IS_OPEN) {
|
if ($REGISTRATION_IS_OPEN) {
|
||||||
?>
|
?>
|
||||||
<form class="login" action="./?do=register" accept-charset="UTF-8" method="post">
|
<form class="basicform" action="./?do=register" accept-charset="UTF-8" method="post">
|
||||||
<div>
|
<div>
|
||||||
<label for="login">Your desired username:</label><br>
|
<label for="login">Your desired username:</label><br>
|
||||||
<input type="text" name="login" id="login" spellcheck="false" <?php if (isset($_POST["login"])) { echo "value=\"" . $_POST["login"] . "\""; } ?>>
|
<input type="text" name="login" id="login" spellcheck="false" <?php if (isset($_POST["login"])) { echo "value=\"" . $_POST["login"] . "\""; } ?>>
|
||||||
|
@ -92,7 +92,7 @@ div.notification_success {
|
|||||||
/* Input */
|
/* Input */
|
||||||
|
|
||||||
/* Text input */
|
/* Text input */
|
||||||
input[type=text], input[type=password] {
|
input[type=text], input[type=password], textarea {
|
||||||
color: #00c07c;
|
color: #00c07c;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 2px solid #009049;
|
border: 2px solid #009049;
|
||||||
@ -102,11 +102,11 @@ input[type=text], input[type=password] {
|
|||||||
text-shadow: 0 0 6px black;
|
text-shadow: 0 0 6px black;
|
||||||
transition: all 0.25s;
|
transition: all 0.25s;
|
||||||
}
|
}
|
||||||
input[type=text]:hover, input[type=password]:hover {
|
input[type=text]:hover, input[type=password]:hover, textarea:hover {
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
border-bottom: 2px solid #009049;
|
border-bottom: 2px solid #009049;
|
||||||
}
|
}
|
||||||
input[type=text]:focus, input[type=password]:focus {
|
input[type=text]:focus, input[type=password]:focus, textarea:focus {
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
border-bottom: 2px solid #49f49f;
|
border-bottom: 2px solid #49f49f;
|
||||||
outline: none;
|
outline: none;
|
||||||
@ -139,3 +139,33 @@ input[type=submit]:focus {
|
|||||||
input[type=checkbox] {
|
input[type=checkbox] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* File picker */
|
||||||
|
input[type=file] {
|
||||||
|
color: #00c07c;
|
||||||
|
text-shadow: 0 0 6px #000a;
|
||||||
|
font-family: Verdana, Sans-Serif;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
input[type=file]::file-selector-button {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 2px solid #009049;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #00c07c;
|
||||||
|
text-shadow: 0 0 6px #000a;
|
||||||
|
font-family: Verdana, Sans-Serif;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
input[type=file]::file-selector-button:hover {
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-bottom: 2px solid #009049;
|
||||||
|
background-color: #009049a0;
|
||||||
|
color: #49f49f;
|
||||||
|
}
|
||||||
|
input[type=file]::file-selector-button:focus {
|
||||||
|
border: 2px solid #49f49f;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
@ -32,12 +32,14 @@ nav.main ul {
|
|||||||
box-shadow: 0 0 5px #000;
|
box-shadow: 0 0 5px #000;
|
||||||
text-shadow: 0 0 2px black, 0 0 6px black;
|
text-shadow: 0 0 2px black, 0 0 6px black;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav.main ul li {
|
nav.main ul li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 2.5vw;
|
|
||||||
margin-right: 2.5vw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nav.main ul li a {
|
nav.main ul li a {
|
||||||
@ -90,15 +92,19 @@ td {
|
|||||||
|
|
||||||
/* Other */
|
/* Other */
|
||||||
|
|
||||||
form.login div {
|
/* Basic form form login and registration */
|
||||||
|
|
||||||
|
form.basicform div {
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.login a {
|
form.basicform a {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.login label[for="tos_check"] {
|
/* Additionals for form */
|
||||||
|
|
||||||
|
form.basicform label[for="tos_check"] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
index.php
20
index.php
@ -24,41 +24,36 @@ if (isset($_GET["do"]))
|
|||||||
else
|
else
|
||||||
$PICKED_PAGE = "";
|
$PICKED_PAGE = "";
|
||||||
|
|
||||||
$WHAT_PAGE_IS_CURRENT = array(
|
|
||||||
"main" => false,
|
|
||||||
"login" => false,
|
|
||||||
"register" => false,
|
|
||||||
"view_tags" => false,
|
|
||||||
"view_stats" => false
|
|
||||||
);
|
|
||||||
|
|
||||||
// Picking current page
|
// Picking current page
|
||||||
switch ($PICKED_PAGE) {
|
switch ($PICKED_PAGE) {
|
||||||
|
// Available-on-login pages
|
||||||
|
// Post creation page
|
||||||
|
case "new_post":
|
||||||
|
$PAGE_TITLE = "Create new post";
|
||||||
|
$PAGE_STYLE = "front/styles/main.css";
|
||||||
|
$PAGE_FILE = "front/pages/new_post/page.php";
|
||||||
|
break;
|
||||||
// Navigable pages
|
// Navigable pages
|
||||||
// Common instance statistics
|
// Common instance statistics
|
||||||
case "view_stats":
|
case "view_stats":
|
||||||
$WHAT_PAGE_IS_CURRENT["view_stats"] = true;
|
|
||||||
$PAGE_TITLE = "Instance statistics";
|
$PAGE_TITLE = "Instance statistics";
|
||||||
$PAGE_STYLE = "front/styles/main.css";
|
$PAGE_STYLE = "front/styles/main.css";
|
||||||
$PAGE_FILE = "front/pages/stats/page.php";
|
$PAGE_FILE = "front/pages/stats/page.php";
|
||||||
break;
|
break;
|
||||||
// Approved tags viewer
|
// Approved tags viewer
|
||||||
case "view_tags":
|
case "view_tags":
|
||||||
$WHAT_PAGE_IS_CURRENT["view_tags"] = true;
|
|
||||||
$PAGE_TITLE = "Approved tags list";
|
$PAGE_TITLE = "Approved tags list";
|
||||||
$PAGE_STYLE = "front/styles/main.css";
|
$PAGE_STYLE = "front/styles/main.css";
|
||||||
$PAGE_FILE = "front/pages/tags_viewer/page.php";
|
$PAGE_FILE = "front/pages/tags_viewer/page.php";
|
||||||
break;
|
break;
|
||||||
// Registration page
|
// Registration page
|
||||||
case "register":
|
case "register":
|
||||||
$WHAT_PAGE_IS_CURRENT["register"] = true;
|
|
||||||
$PAGE_TITLE = "Register";
|
$PAGE_TITLE = "Register";
|
||||||
$PAGE_STYLE = "front/styles/main.css";
|
$PAGE_STYLE = "front/styles/main.css";
|
||||||
$PAGE_FILE = "front/pages/register/page.php";
|
$PAGE_FILE = "front/pages/register/page.php";
|
||||||
break;
|
break;
|
||||||
// Login page
|
// Login page
|
||||||
case "login":
|
case "login":
|
||||||
$WHAT_PAGE_IS_CURRENT["login"] = true;
|
|
||||||
$PAGE_TITLE = "Login";
|
$PAGE_TITLE = "Login";
|
||||||
$PAGE_STYLE = "front/styles/main.css";
|
$PAGE_STYLE = "front/styles/main.css";
|
||||||
$PAGE_FILE = "front/pages/login/page.php";
|
$PAGE_FILE = "front/pages/login/page.php";
|
||||||
@ -67,7 +62,6 @@ switch ($PICKED_PAGE) {
|
|||||||
case "index":
|
case "index":
|
||||||
case "main":
|
case "main":
|
||||||
default:
|
default:
|
||||||
$WHAT_PAGE_IS_CURRENT["main"] = true;
|
|
||||||
$PAGE_TITLE = "Index";
|
$PAGE_TITLE = "Index";
|
||||||
$PAGE_STYLE = "front/styles/index.css";
|
$PAGE_STYLE = "front/styles/index.css";
|
||||||
$PAGE_FILE = "front/pages/index/page.php";
|
$PAGE_FILE = "front/pages/index/page.php";
|
||||||
|
Loading…
Reference in New Issue
Block a user