commit 9b7057de363aaa3fdf35651f71f5622dc8670a9d
parent c6ab1de63926ff7f6e29a260e3e7f2473855c9c7
Author: William Casarin <jb55@jb55.com>
Date: Wed, 19 Oct 2022 09:51:25 -0700
make url and invoice parsing case-insensitive
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
3 files changed, 53 insertions(+), 19 deletions(-)
diff --git a/damus-c/damus.c b/damus-c/damus.c
@@ -79,17 +79,26 @@ static int parse_digit(struct cursor *cur, int *digit) {
}
static int parse_str(struct cursor *cur, const char *str) {
- unsigned long len = strlen(str);
+ int i;
+ char c, cs;
+ unsigned long len;
+
+ len = strlen(str);
if (cur->p + len >= cur->end)
return 0;
- if (!memcmp(cur->p, str, len)) {
- cur->p += len;
- return 1;
+ for (i = 0; i < len; i++) {
+ c = tolower(cur->p[i]);
+ cs = tolower(str[i]);
+
+ if (c != cs)
+ return 0;
}
- return 0;
+ cur->p += len;
+
+ return 1;
}
static int parse_mention(struct cursor *cur, struct block *block) {
@@ -158,6 +167,9 @@ static int add_text_block(struct blocks *blocks, const u8 *start, const u8 *end)
{
struct block b;
+ if (start == end)
+ return 1;
+
b.type = BLOCK_TEXT;
b.block.str.start = (const char*)start;
b.block.str.end = (const char*)end;
@@ -171,7 +183,7 @@ static int parse_url(struct cursor *cur, struct block *block) {
if (!parse_str(cur, "http"))
return 0;
- if (parse_char(cur, 's')) {
+ if (parse_char(cur, 's') || parse_char(cur, 'S')) {
if (!parse_str(cur, "://")) {
cur->p = start;
return 0;
@@ -231,7 +243,7 @@ static int parse_invoice(struct cursor *cur, struct block *block) {
return 1;
}
-static int add_text_then_block(struct cursor *cur, struct blocks *blocks, struct block block, u8 **start, u8 *pre_mention)
+static int add_text_then_block(struct cursor *cur, struct blocks *blocks, struct block block, const u8 **start, const u8 *pre_mention)
{
if (!add_text_block(blocks, *start, pre_mention))
return 0;
@@ -248,7 +260,7 @@ int damus_parse_content(struct blocks *blocks, const char *content) {
int cp, c;
struct cursor cur;
struct block block;
- u8 *start, *pre_mention;
+ const u8 *start, *pre_mention;
blocks->num_blocks = 0;
make_cursor(&cur, (const u8*)content, strlen(content));
@@ -264,11 +276,11 @@ int damus_parse_content(struct blocks *blocks, const char *content) {
if (!add_text_then_block(&cur, blocks, block, &start, pre_mention))
return 0;
continue;
- } else if (c == 'h' && parse_url(&cur, &block)) {
+ } else if ((c == 'h' || c == 'H') && parse_url(&cur, &block)) {
if (!add_text_then_block(&cur, blocks, block, &start, pre_mention))
return 0;
continue;
- } else if (c == 'l' && parse_invoice(&cur, &block)) {
+ } else if ((c == 'l' || c == 'L') && parse_invoice(&cur, &block)) {
if (!add_text_then_block(&cur, blocks, block, &start, pre_mention))
return 0;
continue;
diff --git a/damusTests/InvoiceTests.swift b/damusTests/InvoiceTests.swift
@@ -17,16 +17,31 @@ final class InvoiceTests: XCTestCase {
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
-
+
+ func testParseInvoiceUpper() throws {
+ let invstr = "LNBC100N1P357SL0SP5T9N56WDZTUN39LGDQLR30XQWKSG3K69Q4Q2RKR52APLUJW0ESN0QPP5MRQGLJK62Z20Q4NVGR6LZCYN6FHYLZCCWDVU4K77APG3ZMRKUJJQDPZW35XJUEQD9EJQCFQV3JHXCMJD9C8G6T0DCXQYJW5QCQPJRZJQT56H4GVP5YX36U2UZQA6QWCSK3E2DUUNFXPPZJ9VHYPC3WFE2WSWZ607UQQ3XQQQSQQQQQQQQQQQLQQYG9QYYSGQAGX5H20AEULJ3GDWX3KXS8U9F4MCAKDKWUAKASAMM9562FFYR9EN8YG20LG0YGNR9ZPWP68524KMDA0T5XP2WYTEX35PU8HAPYJAJXQPSQL29R"
+ let parsed = parse_mentions(content: invstr, tags: [])
+
+ XCTAssertNotNil(parsed)
+ XCTAssertEqual(parsed.count, 1)
+ XCTAssertNotNil(parsed[0].is_invoice)
+ guard let invoice = parsed[0].is_invoice else {
+ return
+ }
+ XCTAssertEqual(invoice.amount, 10000)
+ XCTAssertEqual(invoice.expiry, 604800)
+ XCTAssertEqual(invoice.created_at, 1666139119)
+ XCTAssertEqual(invoice.string, invstr)
+ }
+
func testParseInvoice() throws {
let invstr = "lnbc100n1p357sl0sp5t9n56wdztun39lgdqlr30xqwksg3k69q4q2rkr52aplujw0esn0qpp5mrqgljk62z20q4nvgr6lzcyn6fhylzccwdvu4k77apg3zmrkujjqdpzw35xjueqd9ejqcfqv3jhxcmjd9c8g6t0dcxqyjw5qcqpjrzjqt56h4gvp5yx36u2uzqa6qwcsk3e2duunfxppzj9vhypc3wfe2wswz607uqq3xqqqsqqqqqqqqqqqlqqyg9qyysgqagx5h20aeulj3gdwx3kxs8u9f4mcakdkwuakasamm9562ffyr9en8yg20lg0ygnr9zpwp68524kmda0t5xp2wytex35pu8hapyjajxqpsql29r"
let parsed = parse_mentions(content: invstr, tags: [])
XCTAssertNotNil(parsed)
- XCTAssertEqual(parsed.count, 2)
- XCTAssertEqual(parsed[0].is_text, "")
- XCTAssertNotNil(parsed[1].is_invoice)
- guard let invoice = parsed[1].is_invoice else {
+ XCTAssertEqual(parsed.count, 1)
+ XCTAssertNotNil(parsed[0].is_invoice)
+ guard let invoice = parsed[0].is_invoice else {
return
}
XCTAssertEqual(invoice.amount, 10000)
diff --git a/damusTests/damusTests.swift b/damusTests/damusTests.swift
@@ -64,6 +64,14 @@ class damusTests: XCTestCase {
XCTAssertNotNil(parsed[0].is_text)
}
+ func testParseUrlUpper() {
+ let parsed = parse_mentions(content: "a HTTPS://jb55.COM b", tags: [])
+
+ XCTAssertNotNil(parsed)
+ XCTAssertEqual(parsed.count, 3)
+ XCTAssertEqual(parsed[1].is_url?.absoluteString, "HTTPS://jb55.COM")
+ }
+
func testParseUrl() {
let parsed = parse_mentions(content: "a https://jb55.com b", tags: [])
@@ -85,10 +93,9 @@ class damusTests: XCTestCase {
let parsed = parse_mentions(content: "https://jb55.com br", tags: [])
XCTAssertNotNil(parsed)
- XCTAssertEqual(parsed.count, 3)
- XCTAssertEqual(parsed[0].is_text, "")
- XCTAssertEqual(parsed[1].is_url?.absoluteString, "https://jb55.com")
- XCTAssertEqual(parsed[2].is_text, " br")
+ XCTAssertEqual(parsed.count, 2)
+ XCTAssertEqual(parsed[0].is_url?.absoluteString, "https://jb55.com")
+ XCTAssertEqual(parsed[1].is_text, " br")
}
func testParseMentionBlank() {