Restructuring repo
4
src/api/.htaccess
Normal file
|
@ -0,0 +1,4 @@
|
|||
RewriteEngine on
|
||||
RewriteCond %{HTTP:Authorization} ^(.*)
|
||||
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
|
||||
RewriteRule ^ index.php
|
20
src/api/index.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
$url = explode('/', $_SERVER['REQUEST_URI']);
|
||||
while ($url[0] !== "api") {
|
||||
array_shift($url);
|
||||
}
|
||||
array_shift($url);
|
||||
$count = 0;
|
||||
while (!empty($url[0])) {
|
||||
switch ($url[0]) {
|
||||
case 'asd':
|
||||
echo "asdasd";
|
||||
break;
|
||||
default:
|
||||
echo $url[0] . "\n";
|
||||
}
|
||||
$count += 1;
|
||||
array_shift($url);
|
||||
}
|
||||
echo "\n" . $count;
|
||||
?>
|
2
src/inc/.htaccess
Executable file
|
@ -0,0 +1,2 @@
|
|||
order deny,allow
|
||||
deny from all
|
196
src/inc/database.php
Executable file
|
@ -0,0 +1,196 @@
|
|||
<?php
|
||||
if(count(get_included_files()) ==1) {
|
||||
http_response_code(403);
|
||||
die("403: Forbidden");
|
||||
}
|
||||
class DataBase extends SQLite3 {
|
||||
function __construct() {
|
||||
$this->open('data/database.db');
|
||||
$this->exec('PRAGMA foreign_keys=ON;');
|
||||
$this->exec('PRAGMA full_column_names=ON;');
|
||||
$this->exec('PRAGMA short_column_names=OFF;');
|
||||
|
||||
$sql = "
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY UNIQUE,
|
||||
pass TEXT,
|
||||
email TEXT UNIQUE,
|
||||
handle TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
about TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS personas (
|
||||
id INTEGER PRIMARY KEY UNIQUE,
|
||||
userid INTEGER NOT NULL,
|
||||
handle TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
about TEXT,
|
||||
colour INTEGER,
|
||||
FOREIGN KEY (userid) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
UNIQUE (userid, handle)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS posts (
|
||||
id INTEGER PRIMARY KEY UNIQUE,
|
||||
time INTEGER NOT NULL,
|
||||
userid INTEGER NOT NULL,
|
||||
personaid INTEGER NOT NULL,
|
||||
text TEXT NOT NULL,
|
||||
FOREIGN KEY (userid) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
FOREIGN KEY (personaid) REFERENCES personas(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS comments (
|
||||
id INTEGER PRIMARY KEY UNIQUE,
|
||||
time INTEGER NOT NULL,
|
||||
userid INTEGER NOT NULL,
|
||||
personaid INTEGER,
|
||||
postid INTEGER NOT NULL,
|
||||
text TEXT NOT NULL,
|
||||
FOREIGN KEY (postid) REFERENCES posts(id),
|
||||
FOREIGN KEY (userid) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
FOREIGN KEY (personaid) REFERENCES personas(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tokens (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
userid INTEGER NOT NULL,
|
||||
token TEXT NOT NULL UNIQUE,
|
||||
lastuse TEXT NOT NULL,
|
||||
expires TEXT NOT NULL,
|
||||
FOREIGN KEY (userid) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO users (id, handle, name, about) VALUES ('0', 'SYSTEM', 'SYSTEM', 'SYSTEM');
|
||||
|
||||
";
|
||||
|
||||
$ret = $this->exec($sql);
|
||||
|
||||
}
|
||||
|
||||
function addUser($handle, $name, $about=NULL) {
|
||||
$id = hexdec(uniqid());
|
||||
$sql = "INSERT INTO users (id, handle, name, about) VALUES ('$id', '$handle', '$name', '$about')";
|
||||
$ret = $this->exec($sql);
|
||||
if(!$ret) {
|
||||
die($this->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
function getUserByHandle($handle) {
|
||||
$handle = $this->escapeString($handle);
|
||||
$sql = "SELECT * FROM users AS user WHERE handle='$handle';";
|
||||
$ret = $this->query($sql)->fetchArray(SQLITE3_ASSOC);
|
||||
if(!$ret) {
|
||||
return false;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function addPost($text, $userid=NULL, $personaid=NULL) {
|
||||
$id = hexdec(uniqid());
|
||||
$time = time();
|
||||
$sql = $this->prepare("INSERT INTO posts (id, time, userid, personaid, text) values ('$id', '$time', '$userid', :personaid, '$text')");
|
||||
$sql->bindParam(':personaid', $personaid, SQLITE3_INTEGER);
|
||||
$ret = $sql->execute();
|
||||
if(!$ret) {
|
||||
die($this->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
function addPersona($userid, $handle, $name, $about=NULL, $colour=NULL) {
|
||||
$id = hexdec(uniqid());
|
||||
$sql = "INSERT INTO personas (id, userid, handle, name, colour) VALUES ('$id', '$userid', '$handle', '$about', '$colour');";
|
||||
$ret = $this->exec($sql);
|
||||
if(!$ret) {
|
||||
die($this->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
function passwordSet($userid, $password=NULL) {
|
||||
$hash = empty($password) ? NULL : password_hash($password, PASSWORD_DEFAULT);
|
||||
$sql = "UPDATE USERS SET pass='$hash' WHERE id='$userid';";
|
||||
$ret = $this->exec($sql);
|
||||
if(!$ret) {
|
||||
die($this->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
function passwordVerify($userid, $password) {
|
||||
$sql = "SELECT pass FROM users WHERE id='$userid';";
|
||||
$ret = $this->query($sql)->fetchArray(SQLITE3_NUM);
|
||||
if(!$ret) {
|
||||
return false;
|
||||
}
|
||||
$dbhash = $ret[0];
|
||||
return password_verify($password, $dbhash);
|
||||
}
|
||||
|
||||
function tokenGen() {
|
||||
return random_bytes(32);
|
||||
}
|
||||
function tokenAdd($userid) {
|
||||
$token = $this->tokenGen();
|
||||
$hashed = hash('sha256', $token);
|
||||
$time = time();
|
||||
$expires = $time + 2592000; // 30 days
|
||||
$sql = "INSERT INTO tokens (userid, token, lastuse, expires) VALUES ('$userid', '$hashed', '$time', '$expires');";
|
||||
$ret = $this->exec($sql);
|
||||
if(!$ret) {
|
||||
die($this->lastErrorMsg());
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
function tokenRefresh($tokenid) {
|
||||
$time = time();
|
||||
$expires = $time + 2592000; // 30 days
|
||||
$sql = "UPDATE tokens SET lastuse='$time', expires='$expires' WHERE id='$tokenid';";
|
||||
$ret = $this->exec($sql);
|
||||
if(!$ret) {
|
||||
die($this->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
function tokenRemove($token) {
|
||||
$hashed = hash('sha256', $token);
|
||||
$sql = "DELETE FROM tokens WHERE token='$hashed';";
|
||||
$ret = $this->exec($sql);
|
||||
if(!$ret) {
|
||||
die($this->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
function getAuthedUserId($token=NULL) {
|
||||
if (empty($token)) {
|
||||
if (empty($_COOKIE['token'])) {
|
||||
return false;
|
||||
}
|
||||
$token = base64_decode($_COOKIE['token']);
|
||||
}
|
||||
$hashed = hash('sha256', $token);
|
||||
$sql = "SELECT id AS id, userid AS userid, expires AS expires FROM tokens WHERE token='$hashed';";
|
||||
$ret = $this->query($sql)->fetchArray(SQLITE3_ASSOC);
|
||||
if(!$ret) {
|
||||
return false;
|
||||
}
|
||||
if ($ret['expires'] < time()) {
|
||||
$this->tokenRemove($token);
|
||||
return false;
|
||||
}
|
||||
$this->tokenRefresh($ret['id']);
|
||||
return $ret['userid'];
|
||||
}
|
||||
|
||||
function getPosts($userid=NULL, $personaid = NULL) {
|
||||
$sql = "SELECT * FROM posts AS post LEFT JOIN users AS user ON post.userid=user.id LEFT JOIN personas AS persona ON post.personaid=persona.id;";
|
||||
|
||||
$ret = $this->query($sql);
|
||||
$array = array();
|
||||
while ($row = $ret->fetchArray(SQLITE3_ASSOC)) {
|
||||
array_push($array, $row);
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
?>
|
106
src/index.php
Executable file
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
require_once "inc/database.php";
|
||||
function getRandomIcon() {
|
||||
$files = glob('./snufficon/*.png');
|
||||
$random_file_num = array_rand($files);
|
||||
return $files[$random_file_num];;
|
||||
}
|
||||
$randomicon = getRandomIcon();
|
||||
$database = new DataBase();
|
||||
if(!$database) {
|
||||
die($database->lastErrorMsg());
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link rel="icon" type="image/x-icon" href="snufficon/mouthless.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Snuffler</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="flexout">
|
||||
|
||||
<div id="lpanel" class="flexpanel">
|
||||
<ul>
|
||||
<li>Kotisivu</li>
|
||||
<li>Viestit</li>
|
||||
<li>Kalavaleet</li>
|
||||
<li>Takasivu</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="rpanel" class="flexpanel">
|
||||
<ul>
|
||||
<li>Mikko Mällikäs<br /><small>@mmallikas</small></li>
|
||||
<li>Jarkko Toivanen<br /><small>@jt</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="centerbox">
|
||||
<div id="titlebox"><img src="<?php echo $randomicon; ?>" alt="" />Snuffler</div>
|
||||
|
||||
<?php
|
||||
if (!$database->getAuthedUserId()) {
|
||||
?>
|
||||
|
||||
<form id="loginform" method="post" action="login.php">
|
||||
<input type="text" name="name" placeholder="username" />
|
||||
<input type="password" name="pass" placeholder="password" />
|
||||
<input type="submit" name="submit" value="Log in" />
|
||||
</form>
|
||||
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<a href="logout.php">LOG OUT</a>
|
||||
<form id="postform">
|
||||
<textarea id="postformtextarea" name="text" rows="5" placeholder="Whatcha snuffin' about?"></textarea><br />
|
||||
<div id="postformactionrow">
|
||||
<select id="user" name="user">
|
||||
<option value=0>SYSTEM</option>
|
||||
<option value=1>User</option>
|
||||
</select>
|
||||
<input type="submit" id="submit" name="submit" value="Snuff!" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
//$database->addPost("Test post", 0);
|
||||
|
||||
$posts = array_reverse($database->getPosts());
|
||||
//var_dump($posts);
|
||||
foreach($posts as $post) {
|
||||
echo '<div class="post">';
|
||||
echo '<div class="postinfo">';
|
||||
echo '<strong>' . $post["user.name"] . '</strong>';
|
||||
echo '<br><small>@' . $post["user.handle"] . '</small>';
|
||||
echo '</div>';
|
||||
|
||||
echo '<p>' . $post["post.text"] . '</p>';
|
||||
echo '<hr><small>' . date("D j.n.Y \@ G:i", $post["post.time"]) . '</small>';
|
||||
echo '
|
||||
<span class="postactions">
|
||||
<img class="reactionaction" src="snufficon/thumbs_up.png" />
|
||||
<img class="reactionaction" src="snufficon/thumbs_down.png" />
|
||||
<img class="reactionaction" src="snufficon/joy.png" />
|
||||
<img class="reactionaction" src="snufficon/sob.png" />
|
||||
<img class="reactionaction" src="snufficon/heart_eyes.png" />
|
||||
</span>';
|
||||
echo "</div>";
|
||||
|
||||
}
|
||||
$database->close();
|
||||
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
16
src/login.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
if (empty($_POST) || !isset($_POST['submit'])) {
|
||||
die("Login canceled: no post / no submit");
|
||||
}
|
||||
|
||||
require_once('inc/database.php');
|
||||
$db = new DataBase();
|
||||
$user = $db->getUserByHandle($_POST['name']);
|
||||
if ($db->passwordVerify($user['user.id'], $_POST['pass'])) {
|
||||
$token = $db->tokenAdd($user['user.id']);
|
||||
$token64 = base64_encode($token);
|
||||
$expires = time() + 2592000; // 30 days
|
||||
setcookie('token', $token64, $expires);
|
||||
}
|
||||
header("Location: /");
|
||||
?>
|
7
src/logout.php
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
setcookie("token", "", 0);
|
||||
require_once('inc/database.php');
|
||||
$db = new DataBase();
|
||||
$db->tokenRemove(base64_decode($_COOKIE['token']));
|
||||
header("Location: /");
|
||||
?>
|
BIN
src/snufficon/angel.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
src/snufficon/angry.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
src/snufficon/cat_face.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/snufficon/clown.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
src/snufficon/cold.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
src/snufficon/cold_sweat.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/cowboy.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
src/snufficon/cross_eyes.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
src/snufficon/disappointed_relieved.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/snufficon/drool.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/snufficon/excited.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
src/snufficon/exploding_head.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/snufficon/expressionless.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
src/snufficon/fearful.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/snufficon/flush.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/snufficon/giggle.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/hand_over_mouth.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
src/snufficon/happy.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/snufficon/head_bandage.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
src/snufficon/heart_eyes.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/snufficon/holding_back_tears.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
src/snufficon/hot.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
src/snufficon/hug.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/joy.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
src/snufficon/kissing.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/kissing_heart.png
Normal file
After Width: | Height: | Size: 9 KiB |
BIN
src/snufficon/laughing.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
src/snufficon/lying.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
src/snufficon/mask.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
src/snufficon/melting.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/snufficon/money_face.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
src/snufficon/mouthless.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
src/snufficon/nerd.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
src/snufficon/partying.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
src/snufficon/peeking_eye.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/snufficon/pleading_face.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
src/snufficon/raging.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
src/snufficon/raised_eyebrow.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
src/snufficon/rolling_eyes.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
src/snufficon/sad.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
src/snufficon/saluting.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
src/snufficon/scream.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/see_no_evil.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
src/snufficon/shrug.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/snufficon/shush.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
src/snufficon/sick.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
src/snufficon/sleeping.png
Normal file
After Width: | Height: | Size: 9 KiB |
BIN
src/snufficon/smiling.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/snufficon/smiling_with_hearts.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/snufficon/smiling_with_stars.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/snufficon/smirk.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
src/snufficon/sneeze.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
src/snufficon/sob.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/snufficon/spiral_eyes.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/star_struck.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
src/snufficon/sunglasses.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
src/snufficon/swearing.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/snufficon/sweat.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
src/snufficon/sweat_smile.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/snufficon/thermometer.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/thinking.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/snufficon/thumbs_down.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/thumbs_up.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/snufficon/tongue_out.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
src/snufficon/tongue_out_closed_eyes.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
src/snufficon/tongue_out_winking.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
src/snufficon/triumph.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/snufficon/upside_down.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
src/snufficon/vomiting.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/snufficon/wink.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
src/snufficon/woozy.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/snufficon/yawning.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
src/snufficon/zany.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/snufficon/zipper_mouth.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
100
src/style.css
Normal file
|
@ -0,0 +1,100 @@
|
|||
body {
|
||||
font-family: Tahoma, Verdana, sans-serif;
|
||||
background-color: #000000;
|
||||
color: #ffc000;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #584200;
|
||||
}
|
||||
|
||||
|
||||
#flexout {
|
||||
display: flex;
|
||||
max-width: 75rem;
|
||||
margin: auto;
|
||||
justify-content: center;
|
||||
}
|
||||
#lpanel {
|
||||
order: 0;
|
||||
}
|
||||
#rpanel {
|
||||
order: 2;
|
||||
}
|
||||
#rpanel, #lpanel, .flexpanel {
|
||||
width: 15rem;
|
||||
border-radius: 1rem;
|
||||
padding: .5rem;
|
||||
background-color: #271d00;
|
||||
}
|
||||
|
||||
#loginform {
|
||||
text-align: center;
|
||||
}
|
||||
#titlebox {
|
||||
font-size: 5em;
|
||||
text-align: center;
|
||||
}
|
||||
#titlebox > img {
|
||||
height: 1.25em;
|
||||
vertical-align: sub;
|
||||
}
|
||||
#centerbox {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
background-color: #271d00;
|
||||
border-radius: 1rem;
|
||||
padding: .5rem;
|
||||
flex-grow: 1;
|
||||
order: 1;
|
||||
}
|
||||
#postform {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
#postformtextarea {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
#postformactionrow {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.post {
|
||||
position: relative;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
padding: 1rem;
|
||||
margin-top: 3rem;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
.postinfo {
|
||||
position: absolute;
|
||||
left: -1px;
|
||||
top: -2em;
|
||||
height: 3rem;
|
||||
min-width: 15rem;
|
||||
background-color: #ffc000;
|
||||
color: #000000;
|
||||
border-radius: 3rem;
|
||||
border-bottom-left-radius: 0;
|
||||
padding: .25rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
.postactions {
|
||||
/*float: right;*/
|
||||
position: absolute;
|
||||
background-color: #ffc000;
|
||||
padding: .25rem;
|
||||
border-radius: 2rem;
|
||||
border-top-right-radius: 0;
|
||||
right: -1px;
|
||||
bottom: -1rem;
|
||||
}
|
||||
.reactionaction {
|
||||
height: 2rem;
|
||||
vertical-align: bottom;
|
||||
}
|