diff --git a/action.php b/action.php
index a645e9e..f8607fc 100644
--- a/action.php
+++ b/action.php
@@ -30,6 +30,9 @@ function returnToSender($msg, $arg = "") {
}
switch ($VARS['action']) {
+ case "sendpub":
+ die("not implemented yet.");
+ break;
case "editpub":
$insert = true;
if (is_empty($VARS['pubid'])) {
diff --git a/database.mwb b/database.mwb
index f14f636..0449ae7 100644
Binary files a/database.mwb and b/database.mwb differ
diff --git a/lang/en_us.php b/lang/en_us.php
index 45612db..4f6b85b 100644
--- a/lang/en_us.php
+++ b/lang/en_us.php
@@ -91,5 +91,12 @@ define("STRINGS", [
"publications" => "Publications",
"grid" => "Grid",
"list" => "List",
- "search" => "Search"
+ "search" => "Search",
+ "send" => "Send",
+ "send publication" => "Send Publication",
+ "subject" => "Subject",
+ "placeholder subject" => "Type an email subject",
+ "message" => "Message",
+ "default message" => "Hello, \nClick the link to view the newsletter:",
+ "cancel" => "Cancel"
]);
\ No newline at end of file
diff --git a/lib/iputils.php b/lib/iputils.php
index d818c74..16f92a4 100644
--- a/lib/iputils.php
+++ b/lib/iputils.php
@@ -4,7 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
/**
* Check if a given ipv4 address is in a given cidr
* @param string $ip IP to check in IPV4 format eg. 127.0.0.1
@@ -130,3 +129,25 @@ function getClientIP() {
return "0.0.0.0"; // This will not happen unless we aren't a web server
}
+
+/**
+ * Check if the client's IP has been doing too many brute-force-friendly
+ * requests lately.
+ * Kills the script with a "friendly" error and response code 429
+ * (Too Many Requests) if the last access time in the DB is too near.
+ *
+ * Also updates the rate_limit table with the latest data and purges old rows.
+ * @global type $database
+ */
+function engageRateLimit() {
+ global $database;
+ $delay = date("Y-m-d H:i:s", strtotime("-5 seconds"));
+ $database->delete('rate_limit', ["lastaction[<]" => $delay]);
+ if ($database->has('rate_limit', ["AND" => ["ipaddr" => getClientIP()]])) {
+ http_response_code(429);
+ die("You're going too fast. Wait a few seconds and try again.");
+ } else {
+ // Add a record for the IP address
+ $database->insert('rate_limit', ["ipaddr" => getClientIP(), "lastaction" => date("Y-m-d H:i:s")]);
+ }
+}
diff --git a/pages.php b/pages.php
index 4648738..1fb6281 100644
--- a/pages.php
+++ b/pages.php
@@ -69,6 +69,15 @@ define("PAGES", [
"static/js/editlist.js"
],
],
+ "send" => [
+ "title" => "send",
+ "navbar" => false,
+ "icon" => "fas fa-paper-plane",
+ "scripts" => [
+ "static/js/snarkdown.umd.js",
+ "static/js/send.js"
+ ]
+ ],
"404" => [
"title" => "404 error"
]
diff --git a/pages/content.php b/pages/content.php
index a8b6151..2995e5f 100644
--- a/pages/content.php
+++ b/pages/content.php
@@ -146,6 +146,7 @@ if ($pub === false) {
diff --git a/pages/send.php b/pages/send.php
new file mode 100644
index 0000000..b5eb16b
--- /dev/null
+++ b/pages/send.php
@@ -0,0 +1,78 @@
+has("publications", ['pubid' => $VARS['pubid']])) {
+ header('Location: app.php?page=home');
+ die();
+}
+
+$lists = $database->select("mail_lists", ['listid', 'listname']);
+?>
+
+
\ No newline at end of file
diff --git a/static/js/send.js b/static/js/send.js
new file mode 100644
index 0000000..3b7d77f
--- /dev/null
+++ b/static/js/send.js
@@ -0,0 +1,14 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+
+$("#subject").on("keyup", function () {
+ $("#subjectpreview").text($("#subject").val());
+});
+
+$("#message").on("keyup", function () {
+ $("#messagepreview").html(snarkdown($("#message").val()));
+});
\ No newline at end of file
diff --git a/static/js/snarkdown.umd.js b/static/js/snarkdown.umd.js
new file mode 100644
index 0000000..63671b4
--- /dev/null
+++ b/static/js/snarkdown.umd.js
@@ -0,0 +1 @@
+!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):e.snarkdown=n()}(this,function(){function e(e){return e.replace(RegExp("^"+(e.match(/^(\t| )+/)||"")[0],"gm"),"")}function n(e){return(e+"").replace(/"/g,""").replace(//g,">")}function r(o){function c(e){var n=t[e.replace(/\*/g,"_")[1]||""],r=f[f.length-1]==e;return n?n[1]?(f[r?"pop":"push"](e),n[0|r]):n[0]:e}function a(){for(var e="";f.length;)e+=c(f[f.length-1]);return e}var l,u,p,s,g,i=/((?:^|\n+)(?:\n---+|\* \*(?: \*)+)\n)|(?:^```(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:\!\[([^\]]*?)\]\(([^\)]+?)\))|(\[)|(\](?:\(([^\)]+?)\))?)|(?:(?:^|\n+)([^\s].*)\n(\-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,3})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*])/gm,f=[],m="",d=0,h={};for(o=o.replace(/^\[(.+?)\]:\s*(.+)$/gm,function(e,n,r){return h[n.toLowerCase()]=r,""}).replace(/^\n+|\n+$/g,"");p=i.exec(o);)u=o.substring(d,p.index),d=i.lastIndex,l=p[0],u.match(/[^\\](\\\\)*\\$/)||(p[3]||p[4]?l='
'+e(n(p[3]||p[4]).replace(/^\n+|\n+$/g,""))+"
":p[6]?(g=p[6],g.match(/\./)&&(p[5]=p[5].replace(/^\d+/gm,"")),s=r(e(p[5].replace(/^\s*[>*+.-]/gm,""))),">"===g?g="blockquote":(g=g.match(/\./)?"ol":"ul",s=s.replace(/^(.*)(\n|$)/gm,"
$1")),l="<"+g+">"+s+""+g+">"):p[8]?l='
':p[10]?(m=m.replace("
",''),l=a()+""):p[9]?l="
":p[12]||p[14]?(g="h"+(p[14]?p[14].length:"="===p[13][0]?1:2),l="<"+g+">"+r(p[12]||p[15])+""+g+">"):p[16]?l=""+n(p[16])+"
":(p[17]||p[1])&&(l=c(p[17]||"--"))),m+=u,m+=l;return(m+o.substring(d)+a()).trim()}var t={"":["",""],_:["",""],"\n":["
"]," ":["
"],"-":["
"]};return r});
\ No newline at end of file
diff --git a/style_dev/NOTE b/style_dev/NOTE
new file mode 100644
index 0000000..05c51f9
--- /dev/null
+++ b/style_dev/NOTE
@@ -0,0 +1 @@
+Add tile types to editor preview
\ No newline at end of file
diff --git a/unsubscribe.php b/unsubscribe.php
new file mode 100644
index 0000000..ba59dcc
--- /dev/null
+++ b/unsubscribe.php
@@ -0,0 +1,25 @@
+has('addresses', ['email' => $address])) {
+ $count = $database->count('addresses', ['email' => $address]);
+ $database->delete('addresses', ['email' => $address]);
+ die("$address has been removed from $count mailing " . ($count === 1 ? "list" : "lists") . ".");
+} else {
+ die("$address has already been removed.");
+}
\ No newline at end of file
diff --git a/view.php b/view.php
new file mode 100644
index 0000000..5cd134a
--- /dev/null
+++ b/view.php
@@ -0,0 +1,10 @@
+
+
+Redirect
+View Document
\ No newline at end of file