mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-30 15:41:48 +00:00
re-enable datauris
This commit is contained in:
52
src/browser/DataURI.zig
Normal file
52
src/browser/DataURI.zig
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
// Parses data:[<media-type>][;base64],<data>
|
||||||
|
pub fn parse(allocator: Allocator, src: []const u8) !?[]const u8 {
|
||||||
|
if (!std.mem.startsWith(u8, src, "data:")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uri = src[5..];
|
||||||
|
const data_starts = std.mem.indexOfScalar(u8, uri, ',') orelse return null;
|
||||||
|
|
||||||
|
var data = uri[data_starts + 1 ..];
|
||||||
|
|
||||||
|
// Extract the encoding.
|
||||||
|
const metadata = uri[0..data_starts];
|
||||||
|
if (std.mem.endsWith(u8, metadata, ";base64")) {
|
||||||
|
const decoder = std.base64.standard.Decoder;
|
||||||
|
const decoded_size = try decoder.calcSizeForSlice(data);
|
||||||
|
|
||||||
|
const buffer = try allocator.alloc(u8, decoded_size);
|
||||||
|
errdefer allocator.free(buffer);
|
||||||
|
|
||||||
|
try decoder.decode(buffer, data);
|
||||||
|
data = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const testing = @import("../testing.zig");
|
||||||
|
test "DataURI: parse valid" {
|
||||||
|
try test_valid("data:text/javascript; charset=utf-8;base64,Zm9v", "foo");
|
||||||
|
try test_valid("data:text/javascript; charset=utf-8;,foo", "foo");
|
||||||
|
try test_valid("data:,foo", "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
test "DataURI: parse invalid" {
|
||||||
|
try test_cannot_parse("atad:,foo");
|
||||||
|
try test_cannot_parse("data:foo");
|
||||||
|
try test_cannot_parse("data:");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_valid(uri: []const u8, expected: []const u8) !void {
|
||||||
|
defer testing.reset();
|
||||||
|
const data_uri = try parse(testing.arena_allocator, uri) orelse return error.TestFailed;
|
||||||
|
try testing.expectEqual(expected, data_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_cannot_parse(uri: []const u8) !void {
|
||||||
|
try testing.expectEqual(null, parse(undefined, uri));
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ const parser = @import("netsurf.zig");
|
|||||||
|
|
||||||
const Env = @import("env.zig").Env;
|
const Env = @import("env.zig").Env;
|
||||||
const Page = @import("page.zig").Page;
|
const Page = @import("page.zig").Page;
|
||||||
|
const DataURI = @import("DataURI.zig");
|
||||||
const Browser = @import("browser.zig").Browser;
|
const Browser = @import("browser.zig").Browser;
|
||||||
const HttpClient = @import("../http/Client.zig");
|
const HttpClient = @import("../http/Client.zig");
|
||||||
const URL = @import("../url.zig").URL;
|
const URL = @import("../url.zig").URL;
|
||||||
@@ -168,6 +169,9 @@ pub fn addFromElement(self: *ScriptManager, element: *parser.Element) !void {
|
|||||||
var source: Script.Source = undefined;
|
var source: Script.Source = undefined;
|
||||||
var remote_url: ?[:0]const u8 = null;
|
var remote_url: ?[:0]const u8 = null;
|
||||||
if (try parser.elementGetAttribute(element, "src")) |src| {
|
if (try parser.elementGetAttribute(element, "src")) |src| {
|
||||||
|
if (try DataURI.parse(page.arena, src)) |data_uri| {
|
||||||
|
source = .{ .@"inline" = data_uri };
|
||||||
|
}
|
||||||
remote_url = try URL.stitch(page.arena, src, page.url.raw, .{ .null_terminated = true });
|
remote_url = try URL.stitch(page.arena, src, page.url.raw, .{ .null_terminated = true });
|
||||||
source = .{ .remote = .{} };
|
source = .{ .remote = .{} };
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
// Represents https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/data
|
|
||||||
pub const DataURI = struct {
|
|
||||||
was_base64_encoded: bool,
|
|
||||||
// The contents in the uri. It will be base64 decoded but not prepared in
|
|
||||||
// any way for mime.charset.
|
|
||||||
data: []const u8,
|
|
||||||
|
|
||||||
// Parses data:[<media-type>][;base64],<data>
|
|
||||||
pub fn parse(allocator: Allocator, src: []const u8) !?DataURI {
|
|
||||||
if (!std.mem.startsWith(u8, src, "data:")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uri = src[5..];
|
|
||||||
const data_starts = std.mem.indexOfScalar(u8, uri, ',') orelse return null;
|
|
||||||
|
|
||||||
// Extract the encoding.
|
|
||||||
var metadata = uri[0..data_starts];
|
|
||||||
var base64_encoded = false;
|
|
||||||
if (std.mem.endsWith(u8, metadata, ";base64")) {
|
|
||||||
base64_encoded = true;
|
|
||||||
metadata = metadata[0 .. metadata.len - 7];
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Extract mime type. This not trivial because Mime.parse requires
|
|
||||||
// a []u8 and might mutate the src. And, the DataURI.parse references atm
|
|
||||||
// do not have deinit calls.
|
|
||||||
|
|
||||||
// Prepare the data.
|
|
||||||
var data = uri[data_starts + 1 ..];
|
|
||||||
if (base64_encoded) {
|
|
||||||
const decoder = std.base64.standard.Decoder;
|
|
||||||
const decoded_size = try decoder.calcSizeForSlice(data);
|
|
||||||
|
|
||||||
const buffer = try allocator.alloc(u8, decoded_size);
|
|
||||||
errdefer allocator.free(buffer);
|
|
||||||
|
|
||||||
try decoder.decode(buffer, data);
|
|
||||||
data = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.was_base64_encoded = base64_encoded,
|
|
||||||
.data = data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *const DataURI, allocator: Allocator) void {
|
|
||||||
if (self.was_base64_encoded) {
|
|
||||||
allocator.free(self.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const testing = std.testing;
|
|
||||||
test "DataURI: parse valid" {
|
|
||||||
try test_valid("data:text/javascript; charset=utf-8;base64,Zm9v", "foo");
|
|
||||||
try test_valid("data:text/javascript; charset=utf-8;,foo", "foo");
|
|
||||||
try test_valid("data:,foo", "foo");
|
|
||||||
}
|
|
||||||
|
|
||||||
test "DataURI: parse invalid" {
|
|
||||||
try test_cannot_parse("atad:,foo");
|
|
||||||
try test_cannot_parse("data:foo");
|
|
||||||
try test_cannot_parse("data:");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_valid(uri: []const u8, expected: []const u8) !void {
|
|
||||||
const data_uri = try DataURI.parse(std.testing.allocator, uri) orelse return error.TestFailed;
|
|
||||||
defer data_uri.deinit(testing.allocator);
|
|
||||||
try testing.expectEqualStrings(expected, data_uri.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_cannot_parse(uri: []const u8) !void {
|
|
||||||
try testing.expectEqual(null, DataURI.parse(std.testing.allocator, uri));
|
|
||||||
}
|
|
||||||
@@ -25,7 +25,6 @@ const Dump = @import("dump.zig");
|
|||||||
const State = @import("State.zig");
|
const State = @import("State.zig");
|
||||||
const Env = @import("env.zig").Env;
|
const Env = @import("env.zig").Env;
|
||||||
const Mime = @import("mime.zig").Mime;
|
const Mime = @import("mime.zig").Mime;
|
||||||
const DataURI = @import("datauri.zig").DataURI;
|
|
||||||
const Session = @import("session.zig").Session;
|
const Session = @import("session.zig").Session;
|
||||||
const Renderer = @import("renderer.zig").Renderer;
|
const Renderer = @import("renderer.zig").Renderer;
|
||||||
const Window = @import("html/window.zig").Window;
|
const Window = @import("html/window.zig").Window;
|
||||||
|
|||||||
Reference in New Issue
Block a user