Public Access
Merge main (file sharing, v0.18.0) into the VPN branch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
#include <unity.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "share_rules.h"
|
||||
|
||||
using namespace roro::files;
|
||||
|
||||
void setUp() {}
|
||||
void tearDown() {}
|
||||
|
||||
void test_what_a_request_asks_for() {
|
||||
TEST_ASSERT_EQUAL_STRING("/notes/my list.txt", urlDecode("%2Fnotes%2Fmy%20list.txt").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("a+b", urlDecode("a+b").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("100%", urlDecode("100%").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("%zz", urlDecode("%zz").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("\xC3\xA9t\xC3\xA9", urlDecode("%C3%A9t%C3%a9").c_str());
|
||||
std::string v;
|
||||
TEST_ASSERT_TRUE(queryParam("path=%2Fnotes&replace=1", "path", v));
|
||||
TEST_ASSERT_EQUAL_STRING("/notes", v.c_str());
|
||||
TEST_ASSERT_TRUE(queryParam("path=%2Fnotes&replace=1", "replace", v));
|
||||
TEST_ASSERT_EQUAL_STRING("1", v.c_str());
|
||||
TEST_ASSERT_FALSE(queryParam("xpath=1&pathx=2", "path", v));
|
||||
TEST_ASSERT_FALSE(queryParam("", "path", v));
|
||||
TEST_ASSERT_TRUE(queryParam("a=&path=", "path", v));
|
||||
TEST_ASSERT_EQUAL_STRING("", v.c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("abc123", cookieValue("theme=dark; s=abc123; x=1", "s").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("abc123", cookieValue("s=abc123", "s").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("", cookieValue("ss=abc123; xs=1", "s").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("", cookieValue("", "s").c_str());
|
||||
}
|
||||
|
||||
void test_paths_a_browser_may_name() {
|
||||
TEST_ASSERT_EQUAL_STRING("", checkSharePath("/").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("", checkSharePath("/notes/my list (2).txt").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("", checkSharePath("/gemini/saved/\xC3\xA9t\xC3\xA9.gmi").c_str());
|
||||
for (const char* bad : {"", "notes", "/notes/", "/notes/../wifi", "/..", "/a//b", "/a/./b", "/a\\b", "/a/b\n", "/a:b", "/what?", "/a*"})
|
||||
TEST_ASSERT_TRUE_MESSAGE(!checkSharePath(bad).empty(), bad);
|
||||
TEST_ASSERT_TRUE(!checkSharePath("/" + std::string(300, 'a')).empty());
|
||||
}
|
||||
|
||||
void test_json() {
|
||||
TEST_ASSERT_EQUAL_STRING("\"plain\"", jsonString("plain").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("\"a \\\"b\\\" \\\\ c\"", jsonString("a \"b\" \\ c").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("\"tab\\u0009\"", jsonString("tab\t").c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("\"\xC3\xA9\"", jsonString("\xC3\xA9").c_str());
|
||||
ShareListing empty("/");
|
||||
TEST_ASSERT_EQUAL_STRING("{\"path\":\"/\",\"items\":[],\"more\":false}", empty.json(false).c_str());
|
||||
ShareListing l("/notes");
|
||||
l.add("a \"b\".txt", 12, false, 1791400000);
|
||||
l.add("old", 0, true, 0);
|
||||
TEST_ASSERT_EQUAL_size_t(2, l.count());
|
||||
TEST_ASSERT_EQUAL_STRING("{\"path\":\"/notes\",\"items\":[{\"n\":\"a \\\"b\\\".txt\",\"s\":12,\"d\":0,\"t\":1791400000},{\"n\":\"old\",\"s\":0,\"d\":1,\"t\":0}],\"more\":true}",
|
||||
l.json(true).c_str());
|
||||
}
|
||||
|
||||
void test_the_code_and_the_token() {
|
||||
ShareAuth auth;
|
||||
std::string token;
|
||||
const uint8_t r16[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
|
||||
TEST_ASSERT_TRUE(auth.login("000000", 0, r16, token) == ShareAuth::Result::Locked); // not started: nobody gets in
|
||||
TEST_ASSERT_FALSE(auth.allowed(""));
|
||||
const uint8_t r4[4] = {0x00, 0x00, 0x30, 0x39}; // 12345
|
||||
auth.begin(r4);
|
||||
TEST_ASSERT_EQUAL_STRING("012345", auth.code().c_str());
|
||||
TEST_ASSERT_FALSE(auth.allowed(""));
|
||||
TEST_ASSERT_TRUE(auth.login("12345", 1000, r16, token) == ShareAuth::Result::Wrong); // the leading zero counts
|
||||
TEST_ASSERT_TRUE(token.empty());
|
||||
TEST_ASSERT_TRUE(auth.login("012 345", 2000, r16, token) == ShareAuth::Result::Ok); // typed as the screen groups it
|
||||
TEST_ASSERT_EQUAL_STRING("00112233445566778899aabbccddeeff", token.c_str());
|
||||
TEST_ASSERT_TRUE(auth.allowed(token));
|
||||
TEST_ASSERT_FALSE(auth.allowed(token + "0"));
|
||||
TEST_ASSERT_FALSE(auth.allowed("00112233445566778899aabbccddeef0"));
|
||||
// Sharing started again: a new code, and yesterday's browser is out.
|
||||
const uint8_t again[4] = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
auth.begin(again);
|
||||
TEST_ASSERT_EQUAL_size_t(6, auth.code().size());
|
||||
TEST_ASSERT_FALSE(auth.allowed(token));
|
||||
}
|
||||
|
||||
void test_five_wrong_codes_close_it_for_a_minute() {
|
||||
ShareAuth auth;
|
||||
const uint8_t r4[4] = {0, 0, 0, 7};
|
||||
const uint8_t r16[16] = {0};
|
||||
auth.begin(r4);
|
||||
std::string token;
|
||||
for (int i = 0; i < 4; i++) TEST_ASSERT_TRUE(auth.login("999999", 1000, r16, token) == ShareAuth::Result::Wrong);
|
||||
TEST_ASSERT_TRUE(auth.login("999999", 1000, r16, token) == ShareAuth::Result::Locked);
|
||||
TEST_ASSERT_TRUE(auth.login("000007", 30000, r16, token) == ShareAuth::Result::Locked); // the right one too
|
||||
TEST_ASSERT_TRUE(auth.login("000007", 62000, r16, token) == ShareAuth::Result::Ok);
|
||||
}
|
||||
|
||||
int main() {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_what_a_request_asks_for);
|
||||
RUN_TEST(test_paths_a_browser_may_name);
|
||||
RUN_TEST(test_json);
|
||||
RUN_TEST(test_the_code_and_the_token);
|
||||
RUN_TEST(test_five_wrong_codes_close_it_for_a_minute);
|
||||
return UNITY_END();
|
||||
}
|
||||
Reference in New Issue
Block a user