talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit d3b38006cdb9ff7869f844c6b98f7c6073573df6
parent cab59c0fbb25e07921a546b510782a3496c84ced
Author: Oliver Lowe <o@olowe.co>
Date:   Sun,  7 Sep 2025 18:37:32 +1000

Filter temp outgoing mail file using zig

Diffstat:
Msrc/build.zig | 3+--
Dsrc/fence/build.zig | 21---------------------
Dsrc/fence/build.zig.zon | 86-------------------------------------------------------------------------------
Msrc/fence/src/fence.h | 1+
Msrc/fence/src/root.zig | 49+++++++++++++++++++++++++++++++++++++++----------
Msrc/procmime.c | 21---------------------
Msrc/procmsg.c | 50++++----------------------------------------------
Msrc/procmsg.h | 2--
8 files changed, 45 insertions(+), 188 deletions(-)

diff --git a/src/build.zig b/src/build.zig @@ -108,7 +108,6 @@ pub fn build(b: *std.Build) void { etpan.addIncludePath(b.path(".")); etpan.addIncludePath(b.path("common")); - // We will also create a module for our other entry point, 'main.zig'. const exe_mod = b.createModule(.{ .target = target, .optimize = optimize, @@ -135,7 +134,7 @@ pub fn build(b: *std.Build) void { "-DGTK_DISABLE_DEPRECATION_WARNINGS", "-DGDK_DISABLE_DEPRECATION_WARNINGS", "-g", - // "-std=c11", + "-std=c17", }, }); exe.addIncludePath(b.path("..")); diff --git a/src/fence/build.zig b/src/fence/build.zig @@ -1,21 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.Build) void { - const mod = b.createModule(.{ - .root_source_file = b.path("src/root.zig"), - .target = b.standardTargetOptions(.{}), - }); - - const lib = b.addLibrary(.{ - .linkage = .static, - .name = "fence", - .root_module = mod, - }); - // https://github.com/ziglang/zig/issues/6817 - lib.bundle_compiler_rt = true; - - b.installArtifact(lib); - - const header_file = b.addInstallHeaderFile(b.path("src/fence.h"), "fence.h"); - b.getInstallStep().dependOn(&header_file.step); -} diff --git a/src/fence/build.zig.zon b/src/fence/build.zig.zon @@ -1,86 +0,0 @@ -.{ - // This is the default name used by packages depending on this one. For - // example, when a user runs `zig fetch --save <url>`, this field is used - // as the key in the `dependencies` table. Although the user can choose a - // different name, most users will stick with this provided value. - // - // It is redundant to include "zig" in this name because it is already - // within the Zig package namespace. - .name = .chestertons_fence, - - // This is a [Semantic Version](https://semver.org/). - // In a future version of Zig it will be used for package deduplication. - .version = "0.0.0", - - // Together with name, this represents a globally unique package - // identifier. This field is generated by the Zig toolchain when the - // package is first created, and then *never changes*. This allows - // unambiguous detection of one package being an updated version of - // another. - // - // When forking a Zig project, this id should be regenerated (delete the - // field and run `zig build`) if the upstream project is still maintained. - // Otherwise, the fork is *hostile*, attempting to take control over the - // original project's identity. Thus it is recommended to leave the comment - // on the following line intact, so that it shows up in code reviews that - // modify the field. - .fingerprint = 0x9a0d03fed7adc588, // Changing this has security and trust implications. - - // Tracks the earliest Zig version that the package considers to be a - // supported use case. - .minimum_zig_version = "0.14.0+5ad91a646", - - // This field is optional. - // Each dependency must either provide a `url` and `hash`, or a `path`. - // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. - // Once all dependencies are fetched, `zig build` no longer requires - // internet connectivity. - .dependencies = .{ - // See `zig fetch --save <url>` for a command-line interface for adding dependencies. - //.example = .{ - // // When updating this field to a new URL, be sure to delete the corresponding - // // `hash`, otherwise you are communicating that you expect to find the old hash at - // // the new URL. If the contents of a URL change this will result in a hash mismatch - // // which will prevent zig from using it. - // .url = "https://example.com/foo.tar.gz", - // - // // This is computed from the file contents of the directory of files that is - // // obtained after fetching `url` and applying the inclusion rules given by - // // `paths`. - // // - // // This field is the source of truth; packages do not come from a `url`; they - // // come from a `hash`. `url` is just one of many possible mirrors for how to - // // obtain a package matching this `hash`. - // // - // // Uses the [multihash](https://multiformats.io/multihash/) format. - // .hash = "...", - // - // // When this is provided, the package is found in a directory relative to the - // // build root. In this case the package's hash is irrelevant and therefore not - // // computed. This field and `url` are mutually exclusive. - // .path = "foo", - // - // // When this is set to `true`, a package is declared to be lazily - // // fetched. This makes the dependency only get fetched if it is - // // actually used. - // .lazy = false, - //}, - }, - - // Specifies the set of files and directories that are included in this package. - // Only files and directories listed here are included in the `hash` that - // is computed for this package. Only files listed here will remain on disk - // when using the zig package manager. As a rule of thumb, one should list - // files required for compilation plus any license(s). - // Paths are relative to the build root. Use the empty string (`""`) to refer to - // the build root itself. - // A directory listed here means that all files within, recursively, are included. - .paths = .{ - "build.zig", - "build.zig.zon", - "src", - // For example... - //"LICENSE", - //"README.md", - }, -} diff --git a/src/fence/src/fence.h b/src/fence/src/fence.h @@ -1,2 +1,3 @@ char fence_is_top_level_domain(char *domain); int quote_depth(char *line); +size_t fence_copy_after_line(char *dst, char *src, char *line); diff --git a/src/fence/src/root.zig b/src/fence/src/root.zig @@ -29,7 +29,7 @@ fn quoteDepth(line: []const u8) u8 { var depth: u8 = 0; const last = std.mem.lastIndexOfScalar(u8, ln, '>') orelse return 1; - for (line[first..last+1]) |c| { + for (line[first .. last + 1]) |c| { if (c == '>') { if (depth == 0xff) return depth; depth += 1; @@ -46,16 +46,45 @@ export fn quote_depth(line: [*:0]const u8) c_int { return @as(c_int, n); } +fn copyAfterLine(dst: std.fs.File, src: std.fs.File, key: []const u8) !usize { + var buf: [8192]u8 = undefined; + var rd = std.io.bufferedReader(src.reader()); + var r = rd.reader(); + var wr = std.io.bufferedWriter(dst.writer()); + var w = wr.writer(); + var found = false; + var n: usize = 0; + while (try r.readUntilDelimiterOrEof(buf[0..], '\n')) |line| { + if (std.mem.startsWith(u8, line, key)) { + found = true; + continue; + } + if (!found) continue; + try w.print("{s}\n", .{line}); + n += (line.len + 1); // + 1 for newline + } + try wr.flush(); + return n; +} + +export fn fence_copy_after_line(dst: [*:0]const u8, src: [*:0]const u8, line: [*:0]const u8) usize { + const fdst = std.fs.cwd().createFile(std.mem.span(dst), .{}) catch return 0; + defer fdst.close(); + const fsrc = std.fs.cwd().openFile(std.mem.span(src), .{}) catch return 0; + defer fsrc.close(); + return copyAfterLine(fdst, fsrc, std.mem.span(line)) catch 0; +} + test "quote depth" { - const tests = [_]struct{[]const u8, u8}{ - .{">>> hello", 3}, - .{"> >> hello", 3}, - .{" > hello >", 1}, - .{"hello>>", 0}, - .{">> hello >>", 2}, - .{"> \t> hello", 2}, - .{">", 1}, - .{ "xxx > hello >>", 0}, + const tests = [_]struct { []const u8, u8 }{ + .{ ">>> hello", 3 }, + .{ "> >> hello", 3 }, + .{ " > hello >", 1 }, + .{ "hello>>", 0 }, + .{ ">> hello >>", 2 }, + .{ "> \t> hello", 2 }, + .{ ">", 1 }, + .{ "xxx > hello >>", 0 }, }; for (tests) |t| { const got = quoteDepth(t[0]); diff --git a/src/procmime.c b/src/procmime.c @@ -32,7 +32,6 @@ #include "procmime.h" #include "procheader.h" #include "quoted-printable.h" -#include "uuencode.h" #include "unmime.h" #include "html.h" #include "codeconv.h" @@ -426,26 +425,6 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo) if (tmpfp != outfp) { fclose(tmpfp); } - } else if (encoding == ENC_X_UUENCODE) { - gchar outbuf[BUFFSIZE]; - glong len; - gboolean flag = FALSE; - - while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) { - if (!flag && strncmp(buf,"begin ", 6)) continue; - - if (flag) { - len = fromuutobits(outbuf, buf); - if (len <= 0) { - if (len < 0) - g_warning("bad UUENCODE content (%ld)", len); - break; - } - if (fwrite(outbuf, sizeof(gchar), (size_t)len, outfp) < (size_t)len) - err = TRUE; - } else - flag = TRUE; - } } else { while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) { if (!flowed) { diff --git a/src/procmsg.c b/src/procmsg.c @@ -26,6 +26,7 @@ #include <ctype.h> #include <math.h> + #include "main.h" #include "utils.h" #include "procmsg.h" @@ -33,6 +34,7 @@ #include "send_message.h" #include "procmime.h" #include "statusbar.h" +#include "fence.h" #include "folder.h" #include "foldersel.h" #include "prefs_common.h" @@ -949,51 +951,6 @@ gboolean procmsg_queue_is_empty(FolderItem *queue) return res; } -gint procmsg_remove_special_headers(const gchar *in, const gchar *out) -{ - FILE *fp, *outfp; - gchar buf[BUFFSIZE]; - - if ((fp = g_fopen(in, "rb")) == NULL) { - FILE_OP_ERROR(in, "g_fopen"); - return -1; - } - if ((outfp = g_fopen(out, "wb")) == NULL) { - FILE_OP_ERROR(out, "g_fopen"); - fclose(fp); - return -1; - } - while (fgets(buf, sizeof(buf), fp) != NULL) { - /* new way */ - if ((!strncmp(buf, "X-Claws-End-Special-Headers: 1", - strlen("X-Claws-End-Special-Headers:"))) || - (!strncmp(buf, "X-Sylpheed-End-Special-Headers: 1", - strlen("X-Sylpheed-End-Special-Headers:")))) - break; - /* old way */ - if (buf[0] == '\r' || buf[0] == '\n') break; - /* from other mailers */ - if (!strncmp(buf, "Date: ", 6) - || !strncmp(buf, "To: ", 4) - || !strncmp(buf, "From: ", 6) - || !strncmp(buf, "Subject: ", 9)) { - rewind(fp); - break; - } - } - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (fputs(buf, outfp) == EOF) { - FILE_OP_ERROR(out, "fputs"); - fclose(outfp); - fclose(fp); - return -1; - } - } - safe_fclose(outfp); - fclose(fp); - return 0; -} - gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file) { gint num; @@ -1017,7 +974,8 @@ gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file) g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg.out.%08x", get_rc_dir(), G_DIR_SEPARATOR, (guint) rand()); - if (procmsg_remove_special_headers(file, tmp) !=0) + char *end = "X-Claws-End-Special-Headers:"; + if (fence_copy_after_line(tmp, file, end) == 0) return -1; while (folder_item_scan(outbox) < 0) { diff --git a/src/procmsg.h b/src/procmsg.h @@ -346,8 +346,6 @@ void procmsg_msginfo_change_flags (MsgInfo *msginfo, MsgTmpFlags add_tmp_flags, MsgPermFlags rem_perm_flags, MsgTmpFlags rem_tmp_flags); -gint procmsg_remove_special_headers (const gchar *in, - const gchar *out); gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file); gboolean procmsg_msg_has_flagged_parent (MsgInfo *info,