Sanitized public release v1.0.3

Source-Tag: v1.0.3
Manifest-SHA256: b7b09bf48f9e092ed8ad82f99c0319d6c3837d0a1549bd0cc4a374276c0f3896
This commit is contained in:
NIA Sanitized Release Publisher
2026-07-20 22:35:36 +00:00
commit 7141326ea0
41 changed files with 6397 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
:root { color-scheme: dark; --bg: #09040f; --panel: #170c22; --line: #62377d; --pink: #f45bd2; --cyan: #62e7ee; --text: #f5edf8; --muted: #b9a8c2; }
* { box-sizing: border-box; }
body { margin: 0; min-height: 100vh; background: radial-gradient(circle at 80% 0, #281139, transparent 42%), var(--bg); color: var(--text); font: 16px/1.5 "Atkinson Hyperlegible", monospace; }
main { width: min(1120px, calc(100% - 32px)); margin: 0 auto; padding: 48px 0 72px; }
header { border-left: 4px solid var(--pink); padding-left: 20px; margin-bottom: 36px; }
h1, h2, p { margin-top: 0; }
h1 { margin-bottom: 8px; font-size: clamp(2rem, 6vw, 4rem); letter-spacing: -.04em; }
h1 span { color: var(--pink); }
.kicker { color: var(--cyan); letter-spacing: .16em; font-size: .78rem; }
section { background: color-mix(in srgb, var(--panel) 90%, transparent); border: 1px solid var(--line); padding: 24px; margin-top: 22px; box-shadow: 8px 8px 0 #050208; }
form { display: grid; grid-template-columns: minmax(220px, 1fr) minmax(220px, .6fr) auto; gap: 16px; align-items: end; }
label { display: grid; gap: 7px; color: var(--muted); font-size: .85rem; text-transform: uppercase; letter-spacing: .08em; }
input, select, button { min-height: 44px; border: 1px solid var(--line); background: #0c0612; color: var(--text); padding: 9px 12px; font: inherit; }
button { cursor: pointer; border-color: var(--pink); }
button:hover, button:focus-visible { background: var(--pink); color: #16051a; outline: none; }
button:disabled { opacity: .55; cursor: wait; }
.progress { height: 8px; margin: 20px 0 12px; background: #08030c; border: 1px solid #3d254b; }
.progress span { display: block; width: 0; height: 100%; background: linear-gradient(90deg, var(--pink), var(--cyan)); transition: width .15s; }
#status { margin-bottom: 0; color: var(--cyan); }
#status.error { color: #ff829c; }
#retry { margin-top: 12px; }
.section-heading { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; min-width: 760px; }
th, td { padding: 12px 10px; border-top: 1px solid #3e294a; text-align: left; vertical-align: middle; }
th { color: var(--cyan); font-size: .78rem; text-transform: uppercase; letter-spacing: .09em; }
.actions { display: flex; gap: 8px; }
.actions button { min-height: 36px; padding: 5px 10px; }
.actions .danger { border-color: #ff607f; }
.muted { color: var(--muted); }
.hidden { display: none !important; }
@media (max-width: 760px) { main { width: min(100% - 20px, 1120px); padding-top: 24px; } section { padding: 16px; } form { grid-template-columns: 1fr; } .section-heading { align-items: flex-start; } }
+52
View File
@@ -0,0 +1,52 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#150a24">
<title>NeoDrop Management</title>
<link rel="stylesheet" href="/manage/style.css">
</head>
<body>
<main>
<header>
<p class="kicker">{{OPERATOR_LABEL}}</p>
<h1>NeoDrop <span>Management</span></h1>
<p>Files are encrypted in this browser. The storage service receives ciphertext only.</p>
</header>
<section class="upload-panel" aria-labelledby="upload-title">
<h2 id="upload-title">New encrypted drop</h2>
<form id="upload-form">
<label class="file-picker">File <input id="file" type="file" required></label>
<label>Retention
<select id="profile">
<option value="0">30 days, up to 50 MiB</option>
<option value="1">7 days, up to 1 GiB</option>
</select>
</label>
<button id="upload" type="submit">Encrypt and upload</button>
</form>
<div class="progress" aria-hidden="true"><span id="progress"></span></div>
<p id="status" role="status">Ready.</p>
<button id="retry" type="button" class="hidden">Retry catalog registration</button>
</section>
<section aria-labelledby="inventory-title">
<div class="section-heading">
<h2 id="inventory-title">Managed drops</h2>
<button id="refresh" type="button">Refresh</button>
</div>
<p id="empty" class="muted hidden">No managed drops.</p>
<div class="table-wrap">
<table>
<thead><tr><th>Name</th><th>Type</th><th>Size</th><th>Expires</th><th>Actions</th></tr></thead>
<tbody id="drops"></tbody>
</table>
</div>
</section>
</main>
<script src="/manage/neodrop-crypto.js"></script>
<script src="/manage/manage.js"></script>
</body>
</html>
+142
View File
@@ -0,0 +1,142 @@
"use strict";
(function() {
var pendingRegistration = null;
var busy = false;
var $ = function(id) { return document.getElementById(id); };
function formatSize(value) {
var units = ["B", "KiB", "MiB", "GiB"];
var size = Number(value);
var index = 0;
while (size >= 1024 && index < units.length - 1) { size /= 1024; index++; }
return size.toFixed(index ? 1 : 0) + " " + units[index];
}
function setStatus(message, error) {
$("status").textContent = message;
$("status").classList.toggle("error", Boolean(error));
}
async function api(path, options) {
var response = await fetch(path, Object.assign({cache: "no-store"}, options || {}));
var value;
try { value = await response.json(); } catch (_) { value = null; }
if (!response.ok) throw new Error("Management request failed.");
return value;
}
async function copyUrl(url) {
await navigator.clipboard.writeText(url);
setStatus("Share URL copied.", false);
}
function actionButton(label, handler, className) {
var button = document.createElement("button");
button.type = "button";
button.textContent = label;
if (className) button.className = className;
button.addEventListener("click", handler);
return button;
}
function render(rows) {
var body = $("drops");
body.textContent = "";
$("empty").classList.toggle("hidden", rows.length !== 0);
rows.forEach(function(row) {
var tr = document.createElement("tr");
[row.name, row.type || "application/octet-stream", formatSize(row.size),
new Date(row.expiresAt * 1000).toLocaleString()].forEach(function(value) {
var td = document.createElement("td");
td.textContent = value;
tr.appendChild(td);
});
var actions = document.createElement("td");
actions.className = "actions";
actions.appendChild(actionButton("Copy", function() { copyUrl(row.readUrl).catch(function() {
setStatus("Unable to copy the share URL.", true);
}); }));
actions.appendChild(actionButton("Open", function() {
window.open(row.readUrl, "_blank", "noopener,noreferrer");
}));
actions.appendChild(actionButton("Delete", async function() {
if (!window.confirm("Permanently delete " + row.name + "?")) return;
try {
await api("/manage/api/v1/drops/" + row.id, {method: "DELETE"});
await load();
setStatus("Drop deleted.", false);
} catch (_) { setStatus("Delete failed.", true); }
}, "danger"));
tr.appendChild(actions);
body.appendChild(tr);
});
}
async function load() {
var value = await api("/manage/api/v1/list", {
method: "POST", headers: {"Content-Type": "application/json"}, body: "{}"
});
render(Array.isArray(value.drops) ? value.drops : []);
}
async function register(result) {
await api("/manage/api/v1/register", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({readUrl: result.readUrl, deleteCapability: result.deleteCapability})
});
pendingRegistration = null;
$("retry").classList.add("hidden");
await load();
}
$("upload-form").addEventListener("submit", async function(event) {
event.preventDefault();
if (busy) return;
var file = $("file").files[0];
if (!file) return setStatus("Select a file.", true);
busy = true;
$("upload").disabled = true;
$("progress").style.width = "0";
setStatus("Encrypting and uploading...", false);
try {
var result = await NeoDropCrypto.upload(file, {
base: location.origin,
profile: Number($("profile").value),
onProgress: function(value) { $("progress").style.width = Math.round(value * 100) + "%"; }
});
pendingRegistration = result;
setStatus("Upload complete. Registering encrypted catalog entry...", false);
try {
await register(result);
$("upload-form").reset();
setStatus("Encrypted drop uploaded and registered.", false);
} catch (_) {
$("retry").classList.remove("hidden");
setStatus("Upload succeeded, but catalog registration must be retried in this tab.", true);
}
} catch (error) {
if (error.name !== "AbortError") setStatus(error.message || "Encrypted upload failed.", true);
} finally {
busy = false;
$("upload").disabled = false;
}
});
$("retry").addEventListener("click", async function() {
if (!pendingRegistration || busy) return;
busy = true;
try {
await register(pendingRegistration);
setStatus("Catalog registration completed.", false);
} catch (_) { setStatus("Catalog registration failed; retry from this tab.", true); }
finally { busy = false; }
});
$("refresh").addEventListener("click", function() {
load().then(function() { setStatus("Managed drops refreshed.", false); })
.catch(function() { setStatus("Unable to load managed drops.", true); });
});
load().catch(function() { setStatus("Unable to load managed drops.", true); });
}());
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,327 @@
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <weechat/weechat-plugin.h>
WEECHAT_PLUGIN_NAME("neodrop_manager")
WEECHAT_PLUGIN_DESCRIPTION("NeoDrop manager control buffer")
WEECHAT_PLUGIN_AUTHOR("{{PRODUCT_NAME}}")
WEECHAT_PLUGIN_VERSION("1.1")
WEECHAT_PLUGIN_LICENSE("GPL3")
#define CONTROL_SOCKET "{{MANAGER_CONTROL_SOCKET_PATH}}"
#define SEND_LIMIT 8192U
#define RECEIVE_LIMIT 16384U
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
struct t_weechat_plugin *weechat_plugin;
static struct t_gui_buffer *manager_buffer;
static struct t_hook *manager_fd_hook;
static int manager_fd = -1;
static char receive_buffer[RECEIVE_LIMIT];
static size_t receive_length;
static void print_error(const char *message)
{
if (manager_buffer != NULL)
weechat_printf(manager_buffer, "%s%s", weechat_color("lightred"), message);
}
static void disconnect_manager(int announce)
{
int was_connected = manager_fd >= 0;
if (manager_fd_hook != NULL) {
weechat_unhook(manager_fd_hook);
manager_fd_hook = NULL;
}
if (manager_fd >= 0)
close(manager_fd);
manager_fd = -1;
receive_length = 0;
if (announce && was_connected)
print_error("NeoDrop manager disconnected; reconnecting in the background.");
}
static void print_protocol_line(const char *line, size_t length)
{
const char *payload;
const char *color = NULL;
size_t payload_length;
size_t index;
char output[RECEIVE_LIMIT];
if (manager_buffer == NULL)
return;
if (length > 0 && line[length - 1] == '\r')
length--;
if (length >= 5 && memcmp(line, "LINE\t", 5) == 0) {
payload = line + 5;
payload_length = length - 5;
} else if (length >= 6 && memcmp(line, "ERROR\t", 6) == 0) {
payload = line + 6;
payload_length = length - 6;
color = "lightred";
} else {
print_error("NeoDrop manager sent an invalid response.");
return;
}
for (index = 0; index < payload_length; index++) {
unsigned char byte = (unsigned char)payload[index];
output[index] = (byte < 0x20U || byte == 0x7fU) ? ' ' : (char)byte;
}
output[payload_length] = '\0';
if (color != NULL)
weechat_printf(manager_buffer, "%s%s", weechat_color(color), output);
else
weechat_printf(manager_buffer, "%s", output);
}
static int manager_read_cb(const void *pointer, void *data, int fd)
{
ssize_t count;
size_t consumed = 0;
char *newline;
(void)pointer;
(void)data;
(void)fd;
if (receive_length >= RECEIVE_LIMIT - 1U) {
print_error("NeoDrop manager response exceeded the line limit.");
disconnect_manager(0);
return WEECHAT_RC_OK;
}
count = recv(manager_fd, receive_buffer + receive_length,
RECEIVE_LIMIT - receive_length - 1U, 0);
if (count < 0 && errno == EINTR)
return WEECHAT_RC_OK;
if (count <= 0) {
disconnect_manager(1);
return WEECHAT_RC_OK;
}
receive_length += (size_t)count;
while (consumed < receive_length) {
size_t available = receive_length - consumed;
newline = memchr(receive_buffer + consumed, '\n', available);
if (newline == NULL)
break;
print_protocol_line(receive_buffer + consumed,
(size_t)(newline - (receive_buffer + consumed)));
consumed = (size_t)(newline - receive_buffer) + 1U;
}
if (consumed > 0) {
receive_length -= consumed;
memmove(receive_buffer, receive_buffer + consumed, receive_length);
}
if (receive_length >= RECEIVE_LIMIT - 1U) {
print_error("NeoDrop manager response exceeded the line limit.");
disconnect_manager(0);
}
return WEECHAT_RC_OK;
}
static int connect_manager(void)
{
struct sockaddr_un address;
int fd;
if (manager_fd >= 0)
return 1;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
return 0;
#ifdef SO_NOSIGPIPE
{
int enabled = 1;
if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &enabled, sizeof(enabled)) != 0) {
close(fd);
return 0;
}
}
#endif
memset(&address, 0, sizeof(address));
address.sun_family = AF_UNIX;
memcpy(address.sun_path, CONTROL_SOCKET, sizeof(CONTROL_SOCKET));
if (connect(fd, (struct sockaddr *)&address, sizeof(address)) != 0) {
close(fd);
return 0;
}
manager_fd = fd;
manager_fd_hook = weechat_hook_fd(manager_fd, 1, 0, 0,
&manager_read_cb, NULL, NULL);
if (manager_fd_hook == NULL) {
disconnect_manager(0);
return 0;
}
return 1;
}
static void send_command(const char *command)
{
static const char prefix[] = "COMMAND\t";
char message[SEND_LIMIT];
size_t command_length;
size_t message_length;
size_t sent = 0;
if (command == NULL || command[0] == '\0')
return;
command_length = strlen(command);
if (command_length > SEND_LIMIT - sizeof("COMMAND\t\n")) {
print_error("NeoDrop manager command exceeded the line limit.");
return;
}
if (strpbrk(command, "\t\r\n") != NULL) {
print_error("NeoDrop manager commands cannot contain tabs or newlines.");
return;
}
if (!connect_manager()) {
print_error("Unable to connect to the NeoDrop manager.");
return;
}
memcpy(message, prefix, sizeof(prefix) - 1U);
memcpy(message + sizeof(prefix) - 1U, command, command_length);
message_length = sizeof(prefix) - 1U + command_length;
message[message_length++] = '\n';
while (sent < message_length) {
ssize_t count = send(manager_fd, message + sent, message_length - sent,
MSG_NOSIGNAL);
if (count < 0 && errno == EINTR)
continue;
if (count <= 0) {
disconnect_manager(1);
return;
}
sent += (size_t)count;
}
}
static int reconnect_cb(const void *pointer, void *data, int remaining_calls)
{
(void)pointer;
(void)data;
(void)remaining_calls;
(void)connect_manager();
return WEECHAT_RC_OK;
}
static int input_cb(const void *pointer, void *data, struct t_gui_buffer *buffer,
const char *input)
{
(void)pointer;
(void)data;
(void)buffer;
send_command(input);
return WEECHAT_RC_OK;
}
static int close_cb(const void *pointer, void *data, struct t_gui_buffer *buffer)
{
(void)pointer;
(void)data;
(void)buffer;
manager_buffer = NULL;
return WEECHAT_RC_OK;
}
static int ensure_buffer(void)
{
if (manager_buffer == NULL)
manager_buffer = weechat_buffer_search("neodrop_manager", "control");
if (manager_buffer == NULL) {
manager_buffer = weechat_buffer_new("control", &input_cb, NULL, NULL,
&close_cb, NULL, NULL);
if (manager_buffer == NULL)
return 0;
}
weechat_buffer_set_pointer(manager_buffer, "input_callback", &input_cb);
weechat_buffer_set_pointer(manager_buffer, "close_callback", &close_cb);
weechat_buffer_set(manager_buffer, "short_name", "NeoDrop");
weechat_buffer_set(manager_buffer, "title",
"NeoDrop | list | put-text NAME TEXT | show/read/download/delete ID | edit ID | help");
weechat_buffer_set(manager_buffer, "hidden", "0");
weechat_buffer_set(manager_buffer, "notify", "3");
weechat_buffer_set(manager_buffer, "localvar_set_no_log", "1");
weechat_buffer_set(manager_buffer, "localvar_set_pinned", "true");
weechat_buffer_set(manager_buffer, "localvar_set_type", "other");
return 1;
}
static int command_cb(const void *pointer, void *data, struct t_gui_buffer *buffer,
int argc, char **argv, char **argv_eol)
{
const char *command = NULL;
int background_registration;
(void)pointer;
(void)data;
(void)buffer;
(void)argv;
if (argc > 1 && argv_eol != NULL && argv_eol[1] != NULL && argv_eol[1][0] != '\0')
command = argv_eol[1];
background_registration = command != NULL && strncmp(command, "register ", 9) == 0;
if (!ensure_buffer())
return WEECHAT_RC_ERROR;
if (!background_registration)
weechat_buffer_set(manager_buffer, "display", "1");
if (command != NULL)
send_command(command);
else
send_command("list");
return WEECHAT_RC_OK;
}
int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[])
{
(void)argc;
(void)argv;
weechat_plugin = plugin;
if (!ensure_buffer())
return WEECHAT_RC_ERROR;
if (weechat_hook_command("drops", "open/control NeoDrop manager",
"list || status || help || put-text <name> <text> || show <selector> || read <selector> || download <selector> || delete <selector> || edit <selector> || line <number> <text> || insert <number> <text> || delete-line <number> || save || cancel",
"Manage encrypted NeoDrop files and text revisions",
"list|status|help|put-text|show|read|download|delete|edit|line|insert|delete-line|save|cancel",
&command_cb, NULL, NULL) == NULL)
return WEECHAT_RC_ERROR;
if (weechat_hook_timer(5000, 0, 0, &reconnect_cb, NULL, NULL) == NULL)
return WEECHAT_RC_ERROR;
return WEECHAT_RC_OK;
}
int weechat_plugin_end(struct t_weechat_plugin *plugin)
{
(void)plugin;
disconnect_manager(0);
return WEECHAT_RC_OK;
}