From 777b5ca846638f2ff41beb80eac0f6134d5ab569 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Sun, 15 Feb 2026 16:40:56 -0700 Subject: [PATCH] worked out some bugs in exporting messages, not all in new code - mechanisms will be needed to cope with the bugs in the database --- .vscode/launch.json | 2 +- config/config.go | 10 ++++++++-- database/post.go | 16 ++++++++++++++-- docs/MISSINGFUNCS.md | 2 +- exports/vcif_xml.go | 35 +++++++++++++++++++---------------- 5 files changed, 43 insertions(+), 22 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 79982f5..be81ca1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -17,7 +17,7 @@ "request": "launch", "mode": "auto", "program": "${workspaceFolder}", - "args": ["-C", "${workspaceFolder}/test.yaml"] + "args": ["-C", "${workspaceFolder}/test.yaml", "--buggy-attachments"] }, ] } diff --git a/config/config.go b/config/config.go index a325a59..9ea0fac 100644 --- a/config/config.go +++ b/config/config.go @@ -20,6 +20,7 @@ import ( "strconv" argparse "github.com/alexflint/go-arg" + log "github.com/sirupsen/logrus" "gopkg.in/yaml.v3" ) @@ -31,8 +32,9 @@ const AMSTERDAM_COPYRIGHT = "2025-2026" // AmCLI is the command-line interface arguments structure. type AmCLI struct { - ConfigFile string `arg:"-C,--config" help:"Location of the configuration file."` - DebugPanic bool `arg:"--debug-panic" help:"Development Only - disable Echo panic recovery"` + ConfigFile string `arg:"-C,--config" help:"Location of the configuration file."` + DebugPanic bool `arg:"--debug-panic" help:"Development Only - disable Echo panic recovery"` + BuggyAttachments bool `arg:"--buggy-attachments" help:"Some attachments may be buggy - truncate data if necessary"` } // CommandLine is the command-line arguments passed to Amsterdam. @@ -239,6 +241,10 @@ func parseDataSize(s string) (int32, error) { func SetupConfig() { argparse.MustParse(&CommandLine) + if CommandLine.BuggyAttachments { + log.Warn("WARNING: --buggy-attachments flag set - NOT recommended for production usage") + } + if CommandLine.ConfigFile != "" { // load the data and use it to unmarshal the loaded configuration data, err := os.ReadFile(CommandLine.ConfigFile) diff --git a/database/post.go b/database/post.go index 0be8f78..48a3734 100644 --- a/database/post.go +++ b/database/post.go @@ -16,6 +16,7 @@ import ( "database/sql" "errors" "fmt" + "io" "strings" "time" @@ -127,12 +128,23 @@ func (p *PostHeader) AttachmentData(ctx context.Context) ([]byte, error) { if err != nil { return nil, err } - outdata := make([]byte, 0, datalen) + outdata := make([]byte, datalen) n, err := r.Read(outdata) r.Close() + if err == io.EOF && n == int(datalen) { + err = nil // we got everything, this isn't an error + } if err != nil || n < int(datalen) { if err == nil { - err = errors.New("unable to read entire attachment") + if config.CommandLine.BuggyAttachments { + log.Warnf("PostHeader.AttachmentData: bugged attachment on post #%d (expected %d bytes, got %d), truncating for retrieval", p.PostId, datalen, n) + outdata = outdata[:n] + } else { + log.Errorf("PostHeader.AttachmentData: unable to read entire attachment to post #%d (expected %d bytes, got %d)", p.PostId, datalen, n) + err = errors.New("unable to read entire attachment") + } + } else { + log.Errorf("PostHeader.AttachmentData: error (%v) reading attachment to post #%d (expected %d bytes, got %d)", err, p.PostId, datalen, n) } return nil, err } diff --git a/docs/MISSINGFUNCS.md b/docs/MISSINGFUNCS.md index 8b974a2..e04aef4 100644 --- a/docs/MISSINGFUNCS.md +++ b/docs/MISSINGFUNCS.md @@ -70,7 +70,7 @@ _(italicized items can be deferred)_ - ~~Custom appearance~~ - ~~Activity reports~~ - ~~E-mail~~ - - Export Messages + - ~~Export Messages~~ - Import Messages - Delete Conference - ~~Add to Hotlist/Remove from Hotlist~~ diff --git a/exports/vcif_xml.go b/exports/vcif_xml.go index f0affda..9a40b3d 100644 --- a/exports/vcif_xml.go +++ b/exports/vcif_xml.go @@ -93,7 +93,9 @@ func VCIFFromPost(ctx context.Context, target *VCIFPost, post *database.PostHead // Fill in the post text. target.Text, err = post.Text(ctx) - if err != nil { + if err == database.ErrNoPostData { + target.Text = "" + } else if err != nil { return err } @@ -113,24 +115,25 @@ func VCIFFromPost(ctx context.Context, target *VCIFPost, post *database.PostHead } // Fill in the attachment data. - ainfo, err := post.AttachmentInfo(ctx) - if err != nil { - return err - } - if ainfo != nil { - newAttachment := VCIFPostAttachment{ - Length: int(ainfo.Length), - MIMEType: ainfo.MIMEType, - Filename: ainfo.Filename, - } - data, err := post.AttachmentData(ctx) + target.Attachment = nil + if !post.IsScribbled() { + ainfo, err := post.AttachmentInfo(ctx) if err != nil { return err } - newAttachment.Base64Data = base64.StdEncoding.EncodeToString(data) - target.Attachment = &newAttachment - } else { - target.Attachment = nil + if ainfo != nil { + newAttachment := VCIFPostAttachment{ + Length: int(ainfo.Length), + MIMEType: ainfo.MIMEType, + Filename: ainfo.Filename, + } + data, err := post.AttachmentData(ctx) + if err != nil { + return err + } + newAttachment.Base64Data = base64.StdEncoding.EncodeToString(data) + target.Attachment = &newAttachment + } } // Fill in the rest of the data that can't fail.