code.pablomurad.com

bbs-hammer

SSH BBS with forums, chat, door games, retro terminals and a weather service, written in Go

fix: Lawn Mower URL, CRLF drop files
author
Pablo Murad
date
commit
75c838e8b0a00aa761b1a01641837195baaf0361
parent
43fa37d4fa2d16f6e32cf3e969a4066403cf8aa4
changes
5 files +14 −12
@@ -103,13 +103,14 @@ title: Lawn Mower     author: Shiru
     players: "1"
     license: Public domain
-    licenseUrl: https://web.archive.org/web/20250815101413id_/http://shiru.untergrund.net/files/nes/lawn_mower.zip
-    url: https://web.archive.org/web/20250815101413id_/http://shiru.untergrund.net/files/nes/lawn_mower.zip
+    licenseUrl: https://archive.org/details/lawn_mower
+    source: https://archive.org/download/lawn_mower/lawn_mower_src.zip
+    url: https://archive.org/download/lawn_mower/lawn_mower.zip
     sha256: af7378b522a7d11efd0306aebf15c193a2de31f5a7b130919699d4f1e7219f70
     member: Lawn_Mower.nes
     memberSha256: 181ef3ff1769a85ae98736e02809e65e5d758b453ebb43ec4b9fe60c93ad224c
     fetch: true
-    note: the public-domain grant is in manual.pdf inside the author's zip (archived copy)
+    note: the public-domain grant is in manual.pdf inside the author's zip; the same zip is in the Wayback Machine at https://web.archive.org/web/20250815101413id_/http://shiru.untergrund.net/files/nes/lawn_mower.zip
 
   - file: Lunar_Limit.nes
     title: Lunar Limit
@@ -30,7 +30,7 @@ fmt.Print("NO DROP FILE\r\n") 
 		return
 	}
-	lines := strings.Split(string(data), "\n")
+	lines := strings.Split(string(data), "\r\n")
 	fmt.Printf("DOOR HELLO %s\r\n", lines[3])
 
 	r := bufio.NewReader(os.Stdin)
@@ -33,7 +33,7 @@ fmt.Println("NO DROP FILE") 
 		return
 	}
-	lines := strings.Split(string(data), "\n")
+	lines := strings.Split(string(data), "\r\n")
 	fmt.Printf("HELLO %s NODE %s\n", lines[3], lines[17])
 	if os.Getenv("SECRET_FOR_TEST") != "" {
 		fmt.Println("LEAKED")
@@ -26,7 +26,8 @@ Node     int       // the node number (line 18) }
 
 // Bytes renders the drop file: BBSDEV.DRP 1.0, 19 lines, stdio
-// communications, UTF-8 text, LF line endings.
+// communications, CRLF line endings (what the format asks producers to
+// write; readers accept LF too).
 func (d Drop) Bytes() []byte {
 	deadline := ""
 	if !d.Deadline.IsZero() {
@@ -57,7 +58,7 @@ strconv.Itoa(max(d.Node, 0)),         // 18 node number 		"N",                                  // 19 local display
 	}
 
-	return []byte(strings.Join(lines, "\n") + "\n")
+	return []byte(strings.Join(lines, "\r\n") + "\r\n")
 }
 
 // field makes a value safe for one drop file line: no control characters
@@ -34,10 +34,10 @@ 	if bytes.HasPrefix(raw, []byte{0xef, 0xbb, 0xbf}) || strings.Contains(strings.ReplaceAll(text, "\r\n", ""), "\r") {
 		t.Fatal("no BOM and no bare CR allowed")
 	}
-	if !strings.HasSuffix(text, "\n") {
+	if !strings.HasSuffix(text, "\r\n") {
 		t.Fatal("must end with a newline")
 	}
-	l := strings.Split(strings.TrimSuffix(text, "\n"), "\n")
+	l := strings.Split(strings.TrimSuffix(text, "\r\n"), "\r\n")
 	if len(l) != 19 {
 		t.Fatalf("got %d lines, want 19", len(l))
 	}
@@ -75,7 +75,7 @@ } }
 
 func TestDropFileCleansAndDefaults(t *testing.T) {
-	l := strings.Split(string(Drop{Alias: " \x1bbad\u0085 nick\t", Width: -1, Height: 70000}.Bytes()), "\n")
+	l := strings.Split(string(Drop{Alias: " \x1bbad\u0085 nick\t", Width: -1, Height: 70000}.Bytes()), "\r\n")
 	if l[3] != "bad nick" {
 		t.Errorf("alias = %q", l[3])
 	}
@@ -92,7 +92,7 @@ if l[11] != "UTF-8" || l[12] != "en" || l[17] != "0" { 		t.Errorf("language %q, node %q", l[12], l[17])
 	}
 
-	if l := strings.Split(string(Drop{}.Bytes()), "\n"); l[3] != "player" {
+	if l := strings.Split(string(Drop{}.Bytes()), "\r\n"); l[3] != "player" {
 		t.Errorf("empty alias = %q", l[3])
 	}
 }
@@ -125,7 +125,7 @@ } }
 
 func TestDropFileEncoding(t *testing.T) {
-	l := strings.Split(string(Drop{Encoding: "IBM437"}.Bytes()), "\n")
+	l := strings.Split(string(Drop{Encoding: "IBM437"}.Bytes()), "\r\n")
 	if l[11] != "IBM437" {
 		t.Fatalf("line 12 = %q", l[11])
 	}