diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-03 17:20:55 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-03 17:20:55 +0200 |
| commit | fc815cb05c980161cb7e32c6421060a44e71c228 (patch) | |
| tree | 305c0e3d8af9905a06c95d8d72428e6665991721 /src/mimeparser.h | |
| parent | 7f505624b1f385a89c9ff32e15f4d4e68595e5b8 (diff) | |
| parent | abed584d02fdd89a22b37ef3da0b41f8d77f48b8 (diff) | |
| download | qtmaildir-fc815cb05c980161cb7e32c6421060a44e71c228.tar.gz qtmaildir-fc815cb05c980161cb7e32c6421060a44e71c228.zip | |
Merge branch 'feature/attachments'
Attachments become reachable: a paperclip column marks the threads that
carry one, and the message pane's attachment bar, an empty placeholder
since it was written, now lists them with save and save-all.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/mimeparser.h')
| -rw-r--r-- | src/mimeparser.h | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/mimeparser.h b/src/mimeparser.h index 64ea0ce..af7619f 100644 --- a/src/mimeparser.h +++ b/src/mimeparser.h @@ -44,8 +44,22 @@ struct Attachment /// Writes the attachment into directory. Returns the full path written, or /// an empty string on failure with *error set. + /// + /// **Overwrites an existing file of the same name.** That is right for a + /// single save the user just confirmed a location for, and wrong for + /// saving a batch: several messages in one thread commonly attach the + /// same filename. Use saveWithoutOverwriting() there. QString saveTo(const QString &directory, QString *error) const; + /// Writes the attachment into directory under a name that is not already + /// taken, appending " (2)", " (3)" and so on before the extension. + /// Returns the full path written, or an empty string on failure. + /// + /// Saving a thread's attachments with saveTo() silently destroyed files: + /// six of sixteen were lost to same-name collisions and every write still + /// reported success. + QString saveWithoutOverwriting(const QString &directory, QString *error) const; + /// True if candidatePath (need not exist) is directory itself or strictly /// beneath it, by path-boundary comparison after QDir::cleanPath on both /// sides (so ".." segments are resolved rather than compared textually). @@ -65,6 +79,21 @@ struct Attachment static bool isPathInsideDirectory(const QString &directory, const QString &candidatePath); }; +/// A directory name for a thread's saved attachments, "<date> <subject>". +/// +/// `rfc822Date` is a raw Date: header as ParsedMessage stores it; it is +/// reduced to "yyyy-MM-dd" when it parses and dropped when it does not. +/// +/// Both inputs are untrusted: a subject is attacker-controlled and may carry +/// path separators, "..", control characters, or nothing usable at all. The +/// result is always a single plain component, never a path, and never "." or +/// "..". Falls back to the date alone, then to a generated name, so it is +/// never empty. +/// +/// Length is capped: many filesystems limit one component to 255 bytes, and a +/// subject can be far longer than that. +QString attachmentFolderName(const QString &rfc822Date, const QString &subject); + struct ParsedMessage { bool ok = false; |
