3 Commits
master ... v1.3

7 changed files with 162 additions and 121 deletions

View File

@@ -23,13 +23,6 @@ A light PHP web interface for managing [mlmmj](http://mlmmj.org/) mailing lists.
- Audit log of changes - Audit log of changes
- Notify admins about errors via Rocket:Chat bot implementation - Notify admins about errors via Rocket:Chat bot implementation
---
## IMPORTANT
In case of login issues: Please be aware that the password input field gets sanitized using the filter [FILTER_SANITIZE_FULL_SPECIAL_CHARS](https://www.php.net/manual/en/filter.filters.sanitize.php)
---
## Installation ## Installation
Clone the git repository to your webserver: Clone the git repository to your webserver:

View File

@@ -13,16 +13,16 @@ if (!isset($_SESSION["auth"]) || $_SESSION["auth"] != 1)
exit(); exit();
} }
// We do not print any error in the next three cases, because a legitimate
// user will never produce such results, even with disabled javascript
if ( preg_match("/[^a-z0-9_-]/", $list_name) ) if ( preg_match("/[^a-z0-9_-]/", $list_name) )
{ {
$_SESSION["error_code"] = 14;
header("Location: error.php"); header("Location: error.php");
exit(); exit();
} }
if ( strlen($list_name) > 30 ) if ( strlen($list_name) > 50 )
{ {
$_SESSION["error_code"] = 13;
header("Location: error.php"); header("Location: error.php");
exit(); exit();
} }
@@ -30,6 +30,7 @@ if ( strlen($list_name) > 30 )
// Test list existence // Test list existence
if( !is_dir("$lists_path/$domain/$list_name") || $list_name == "" ) if( !is_dir("$lists_path/$domain/$list_name") || $list_name == "" )
{ {
$_SESSION["error_code"] = 12;
header("Location: error.php"); header("Location: error.php");
exit(); exit();
} }

View File

@@ -81,7 +81,7 @@
<div id="column_middle"> <div id="column_middle">
<div id="column_middle_inner"> <div id="column_middle_inner">
<div id="table_div"> <div id="table_div">
<table id="table_middle" class="table_middle"> <table id="table_middle">
<tr> <tr>
<td> <td>
<div id="prefix_header"> <div id="prefix_header">
@@ -94,16 +94,14 @@
&nbsp;Prefix: &nbsp;Prefix:
</div> </div>
</td> </td>
</tr>
<tr>
<td> <td>
<input type="text" name="prefix" value="{$prefix|escape:'htmlall'}" id="prefix"> <input type="text" name="prefix" value="{$prefix|escape:'htmlall'}" id="prefix">
</td> </td>
</tr> </tr>
</table> </table>
<table class="table_middle"> <table style="width: 100%; text-align: center; margin-top: 50px; padding: 0 25px 0 25px;">
<tr> <tr>
<td > <td colspan="2">
<div id="listdescription_header"> <div id="listdescription_header">
<div class="tooltip"> <div class="tooltip">
<img src="help.svg" width=15 height=15> <img src="help.svg" width=15 height=15>
@@ -113,10 +111,6 @@
</div> </div>
&nbsp;List description: &nbsp;List description:
</div> </div>
</td>
</tr>
<tr>
<td>
<textarea name="listdescription" id="listdescription" style="height: 100%; width: 100%;">{$listdescription|escape:'htmlall'}</textarea> <textarea name="listdescription" id="listdescription" style="height: 100%; width: 100%;">{$listdescription|escape:'htmlall'}</textarea>
</td> </td>
</tr> </tr>

View File

@@ -36,6 +36,12 @@
There is an incorrect email in the moderators list. There is an incorrect email in the moderators list.
{elseif $error_code == 11} {elseif $error_code == 11}
You do not own this list. You do not own this list.
{elseif $error_code == 12}
The list does not exist within the mlmmj working folder.
{elseif $error_code == 13}
The list name exceeds the maximum length of 50 chars.
{elseif $error_code == 14}
The list name contains chars which are not allowed.
{else} {else}
Unknown error. Unknown error.
{/if} {/if}

View File

@@ -35,8 +35,7 @@
</div> </div>
<div id="login"> <div id="login">
<div id="login_form"> <div id="login_form">
<p>Please enter the credentials of your ECG account<br />(<strong>without</strong> <i>@ecogood.org</I>)</p> <p>Please enter the credentials of your ECG account<br />(<strong>without</strong> @ecogood.org)</p>
<br />
<form method="post" action="login.php" onsubmit="return validate_form()"> <form method="post" action="login.php" onsubmit="return validate_form()">
<div id="username"> <div id="username">
<div id="username_left"> <div id="username_left">
@@ -54,12 +53,10 @@
<input type="password" name="login_pass" id="password_input"> <input type="password" name="login_pass" id="password_input">
</div> </div>
</div> </div>
<a href="https://wiki.ecogood.org/display/PUBLIC/IT-Support" target="_blank"><p>Forgot your password?</p></a>
<div id="enter"> <div id="enter">
<input type="submit" name="submit" value="Login"> <input type="submit" name="submit" value="Login">
</div> </div>
<br />
<br />
<a href=" https://wiki.ecogood.org/x/DYQjB " target="_blank"><p>Forgot your password?</p></a>
</form> </form>
</div> </div>
</div> </div>

View File

@@ -32,16 +32,16 @@ if ( !isset($_SESSION["auth"]) || $_SESSION["auth"] != 1 )
$domain = $_SESSION["domain"]; $domain = $_SESSION["domain"];
// We do not print any error in the next four cases, because a legitimate
// user will never produce such results, even with disabled javascript
if ( preg_match("/[^a-z0-9_-]/", $list_name) ) if ( preg_match("/[^a-z0-9_-]/", $list_name) )
{ {
$_SESSION["error_code"] = 14;
header("Location: error.php"); header("Location: error.php");
exit(); exit();
} }
if ( strlen($list_name) > 30 ) if ( strlen($list_name) > 50 )
{ {
$_SESSION["error_code"] = 13;
header("Location: error.php"); header("Location: error.php");
exit(); exit();
} }
@@ -49,6 +49,7 @@ if ( strlen($list_name) > 30 )
// Test list existence // Test list existence
if( !is_dir("$lists_path/$domain/$list_name") || $list_name == "" ) if( !is_dir("$lists_path/$domain/$list_name") || $list_name == "" )
{ {
$_SESSION["error_code"] = 12;
header("Location: error.php"); header("Location: error.php");
exit(); exit();
} }

237
style.css
View File

@@ -1,4 +1,5 @@
body { body
{
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: sans-serif; font-family: sans-serif;
@@ -6,12 +7,14 @@ body {
height: 100%; height: 100%;
} }
form { form
{
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
a { a
{
margin-top: 0; margin-top: 0;
margin-bottom: 0; margin-bottom: 0;
cursor: pointer; cursor: pointer;
@@ -19,15 +22,18 @@ a {
text-decoration: none; text-decoration: none;
} }
a:hover { a:hover
{
color: #66ccff; color: #66ccff;
} }
td { td
{
padding-right: 8px; padding-right: 8px;
} }
#header { #header
{
font-size: 30px; font-size: 30px;
background-color: #222222; background-color: #222222;
color: #9d9d9d; color: #9d9d9d;
@@ -42,40 +48,48 @@ td {
justify-content: space-between; justify-content: space-between;
} }
#error { #error
{
padding-top: 15px; padding-top: 15px;
padding-left: 30px; padding-left: 30px;
} }
#header_left { #header_left
{
float: left; float: left;
} }
#header_left a { #header_left a
{
color: #9d9d9d; color: #9d9d9d;
} }
#header_left a:hover { #header_left a:hover
{
color: #66ccff; color: #66ccff;
} }
#header_right { #header_right
{
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 20px; font-size: 20px;
} }
#header_right a { #header_right a
{
color: #9d9d9d; color: #9d9d9d;
} }
#header_right a:hover { #header_right a:hover
{
color: #66ccff; color: #66ccff;
} }
#login { #login
{
width: 100%; width: 100%;
position: absolute; position: absolute;
top: 60px; top: 60px;
@@ -83,45 +97,45 @@ td {
display: flex; display: flex;
} }
#login_form { #login_form
width: 400px; {
width: 250px;
padding: 10px; padding: 10px;
margin: auto; margin: auto;
align-self: center; align-self: center;
} }
#login_form > form {
width: 300px;
}
#username, #password { #username, #password
{
width: 100%; width: 100%;
padding-bottom: 5px; padding-bottom: 5px;
display: flex; display: flex;
} }
#username_left, #password_left { #username_left, #password_left
{
align-self: center; align-self: center;
} }
#username_right, #password_right { #username_right, #password_right
{
margin-left: auto; margin-left: auto;
} }
#username_input, #password_input { #username_input, #password_input
{
width: 170px; width: 170px;
} }
#enter { #enter
width: 100%; {
padding-top: 5px; padding-top: 5px;
display: inline-block; display: inline-block;
# margin-left: 80px; margin-left: 80px;
}
#enter > input {
width: 100%;
} }
#breadcrumbs { #breadcrumbs
{
height: 40px; height: 40px;
background-color: #f5f5f5; background-color: #f5f5f5;
margin-top: 20px; margin-top: 20px;
@@ -133,36 +147,43 @@ td {
align-items: center; align-items: center;
} }
#index { #index
{
margin-left: 30px; margin-left: 30px;
} }
#lists_header { #lists_header
{
margin-bottom: 10px; margin-bottom: 10px;
display: flex; display: flex;
align-items: center; align-items: center;
} }
#lists { #lists
{
padding-left: 17px; padding-left: 17px;
margin-bottom: 5px; margin-bottom: 5px;
} }
#add_list { #add_list
{
display: flex; display: flex;
padding-left: 20px; padding-left: 20px;
} }
#add_list_input { #add_list_input
{
width: 170px; width: 170px;
} }
.tooltip { .tooltip
{
position: relative; position: relative;
display: inline-block; display: inline-block;
} }
.tooltip .help_add_list { .tooltip .help_add_list
{
visibility: hidden; visibility: hidden;
width: 450px; width: 450px;
background-color: #111; background-color: #111;
@@ -176,7 +197,8 @@ td {
left: 170%; left: 170%;
} }
.tooltip .help_add_list::after { .tooltip .help_add_list::after
{
content: ""; content: "";
position: absolute; position: absolute;
top: 5px; top: 5px;
@@ -187,131 +209,142 @@ td {
border-color: transparent #111 transparent transparent; border-color: transparent #111 transparent transparent;
} }
.tooltip:hover .help_add_list { .tooltip:hover .help_add_list
{
visibility: visible; visibility: visible;
} }
#edit_page { #edit_page
{
display: table; display: table;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.success { .success
{
font-weight: bold; font-weight: bold;
color: #00aa00; color: #00aa00;
text-align: center; text-align: center;
} }
#save_list { #save_list
background-color: #f5f5f5; {
margin-top: 20px; margin-top: 20px;
margin-bottom: 20px; margin-bottom: 20px;
margin-left: 30px; margin-left: 30px;
margin-right: 30px; margin-right: 30px;
height: calc(100% - 280px); height: calc(100% - 170px);
min-height: 400px; min-height: 400px;
width: calc(100% - 60px); width: calc(100% - 60px);
} }
#column_left { #column_left
{
height: 100%; height: 100%;
display: table-cell; display: table-cell;
min-width: 300px; min-width: 300px;
} }
#subscribers_header { #subscribers_header
{
height: 30px; height: 30px;
width: 350px; width: 300px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-left: auto; margin-left: auto;
} }
#subscribers_body { #subscribers_body
height: calc(100% - 50px); {
width: 350px; height: calc(100% - 100px);
width: 300px;
margin-left: auto; margin-left: auto;
} }
#subscribers { #subscribers
{
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
#column_right { #column_right
{
height: 100%; height: 100%;
display: table-cell; display: table-cell;
min-width: 320px; min-width: 320px;
} }
#moderators_header { #moderators_header
{
height: 30px; height: 30px;
width: 350px; width: 300px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
#moderators_body { #moderators_body
height: calc(100% - 50px); {
width: 350px; height: calc(100% - 100px);
width: 300px;
} }
#moderators { #moderators
{
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
#column_middle { #column_middle
{
padding-top: 30px; padding-top: 30px;
width: 500px; width: 500px;
height: 100%;
display: table-cell; display: table-cell;
min-width: 440px; min-width: 440px;
vertical-align: top; vertical-align: top;
padding-bottom: 20px; padding-bottom: 20px;
} }
#column_middle_inner { #column_middle_inner
{
height: 100%; height: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
flex-direction: column; flex-direction: column;
} }
.table_middle { #table_middle
width: 100%; {
# text-align: center; text-align: right;
margin-bottom: 30px; margin: auto;
padding: 0 25px 0 25px;
} }
#table_middle td { #table_middle td
{
padding-bottom: 10px; padding-bottom: 10px;
} }
#prefix, #list_type { #prefix, #list_type
{
width: 100%; width: 100%;
} }
#footer { #footer
{
width: 100%; width: 100%;
height: 100px; height: 100px;
} }
#save_btn { #save_btn
{
text-align: center; text-align: center;
width: 100%;
height: 30px;
}
#save_btn > input {
text-align: center;
height: 30px;
width: 50%;
} }
.tooltip .help_sub, .tooltip .help_mod { .tooltip .help_sub, .tooltip .help_mod
{
visibility: hidden; visibility: hidden;
width: 250px; width: 250px;
background-color: #111; background-color: #111;
@@ -326,7 +359,8 @@ td {
margin-left: -133px; margin-left: -133px;
} }
.tooltip .help_sub::after, .tooltip .help_mod::after { .tooltip .help_sub::after, .tooltip .help_mod::after
{
content: ""; content: "";
position: absolute; position: absolute;
bottom: 100%; bottom: 100%;
@@ -337,11 +371,13 @@ td {
border-color: transparent transparent #111 transparent; border-color: transparent transparent #111 transparent;
} }
.tooltip:hover .help_sub, .tooltip:hover .help_mod { .tooltip:hover .help_sub, .tooltip:hover .help_mod
{
visibility: visible; visibility: visible;
} }
.tooltip .help_list_type { .tooltip .help_list_type
{
visibility: hidden; visibility: hidden;
width: 300px; width: 300px;
background-color: #111; background-color: #111;
@@ -355,7 +391,8 @@ td {
right: 170%; right: 170%;
} }
.tooltip .help_list_type::after { .tooltip .help_list_type::after
{
content: ""; content: "";
position: absolute; position: absolute;
top: 5px; top: 5px;
@@ -366,16 +403,19 @@ td {
border-color: transparent transparent transparent #111; border-color: transparent transparent transparent #111;
} }
.tooltip:hover .help_list_type { .tooltip:hover .help_list_type
{
visibility: visible; visibility: visible;
} }
#list_type_header, #prefix_header, #footer_header, #notmetoo_header, #listdescription_header { #list_type_header, #prefix_header, #footer_header, #notmetoo_header
{
display: flex; display: flex;
align-items: center; align-items: center;
} }
.tooltip .help_prefix { .tooltip .help_prefix
{
visibility: hidden; visibility: hidden;
width: 200px; width: 200px;
background-color: #111; background-color: #111;
@@ -389,7 +429,8 @@ td {
right: 160%; right: 160%;
} }
.tooltip .help_prefix::after { .tooltip .help_prefix::after
{
content: ""; content: "";
position: absolute; position: absolute;
top: 50%; top: 50%;
@@ -400,11 +441,13 @@ td {
border-color: transparent transparent transparent #111; border-color: transparent transparent transparent #111;
} }
.tooltip:hover .help_prefix { .tooltip:hover .help_prefix
{
visibility: visible; visibility: visible;
} }
.tooltip .help_footer { .tooltip .help_footer
{
visibility: hidden; visibility: hidden;
width: 200px; width: 200px;
background-color: #111; background-color: #111;
@@ -418,7 +461,8 @@ td {
right: 160%; right: 160%;
} }
.tooltip .help_footer::after { .tooltip .help_footer::after
{
content: ""; content: "";
position: absolute; position: absolute;
top: 50%; top: 50%;
@@ -429,16 +473,19 @@ td {
border-color: transparent transparent transparent #111; border-color: transparent transparent transparent #111;
} }
.tooltip:hover .help_footer { .tooltip:hover .help_footer
{
visibility: visible; visibility: visible;
} }
#notmetoo_checkbox { #notmetoo_checkbox
{
margin-left: 5px; margin-left: 5px;
margin-right: 5px; margin-right: 5px;
} }
.tooltip .help_notmetoo { .tooltip .help_notmetoo
{
visibility: hidden; visibility: hidden;
width: 300px; width: 300px;
background-color: #111; background-color: #111;
@@ -452,7 +499,8 @@ td {
right: 160%; right: 160%;
} }
.tooltip .help_notmetoo::after { .tooltip .help_notmetoo::after
{
content: ""; content: "";
position: absolute; position: absolute;
top: 50%; top: 50%;
@@ -463,6 +511,7 @@ td {
border-color: transparent transparent transparent #111; border-color: transparent transparent transparent #111;
} }
.tooltip:hover .help_notmetoo { .tooltip:hover .help_notmetoo
{
visibility: visible; visibility: visible;
} }