authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-08-07 00:45:36 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-08-07 00:45:36 -07:00
log728e82a8626115567eaf898c66f767763c0e6cce
tree1a0b2411dece4c256ce00dcc6ad029d238ebb4b3
parenta135ca3268d90709492056b008b20238da4dccc0

add html entity filtering to prevent tag injection


4 files changed, 25 insertions(+), 1 deletions(-)

src/lib.zig+21-1
......@@ -24,6 +24,7 @@
2424
2525const std = @import("std");
2626const range = @import("range").range;
27const htmlentities = @import("htmlentities");
2728
2829const tokenize = @import("./tokenize.zig");
2930const astgen = @import("./astgen.zig");
......@@ -75,7 +76,14 @@ fn do(writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype
7576 const TO = @TypeOf(x);
7677
7778 if (comptime std.meta.trait.isZigString(TO)) {
78 try writer.print("{s}", .{x});
79 const s: []const u8 = x;
80 for (s) |c| {
81 if (entityLookupBefore(&[_]u8{c})) |ent| {
82 try writer.writeAll(ent.entity);
83 } else {
84 try writer.writeAll(&[_]u8{c});
85 }
86 }
7987 return;
8088 }
8189 @compileError("pek: compile: unsupported type: " ++ @typeName(TO));
......@@ -101,3 +109,15 @@ fn do(writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype
101109fn search(comptime T: anytype, comptime args: []const []const u8) @TypeOf(if (args.len == 1) @field(T, args[0]) else search(@field(T, args[0]), args[1..])) {
102110 return if (args.len == 1) @field(T, args[0]) else search(@field(T, args[0]), args[1..]);
103111}
112
113fn entityLookupBefore(in: []const u8) ?htmlentities.Entity {
114 for (htmlentities.ENTITIES) |e| {
115 if (!std.mem.endsWith(u8, e.entity, ";")) {
116 continue;
117 }
118 if (std.mem.eql(u8, e.characters, in)) {
119 return e;
120 }
121 }
122 return null;
123}
src/main.zig+2
......@@ -21,6 +21,7 @@ const example_document =
2121 \\ li({this.name}", "{this.state.code})
2222 \\ /each/
2323 \\ )
24 \\ p("Spooky text: "{spooky})
2425 \\ )
2526 \\)
2627;
......@@ -39,5 +40,6 @@ pub fn main() !void {
3940 .{ .name = "Houston", .state = .{ .code = "TX" } },
4041 .{ .name = "Phoenix", .state = .{ .code = "AZ" } },
4142 },
43 .spooky = "<strong>I better not be in bold.</strong>",
4244 });
4345}
zig.mod+1
......@@ -5,3 +5,4 @@ license: AGPL-3.0
55description: An HTML preprocessor with a builtin template engine.
66dependencies:
77 - src: git https://github.com/nektro/zig-range
8 - src: git https://github.com/kivikakk/htmlentities.zig
zigmod.lock+1
......@@ -1,2 +1,3 @@
112
22git https://github.com/nektro/zig-range commit-890ca308fe09b3d5c866d5cfb3b3d7a95dbf939f
3git https://github.com/kivikakk/htmlentities.zig commit-c3cbe4cb3a9a9bd60e7c9fedcf9b97e087b98d6c