╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ web.zig ──────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
593 } 594 } 595 return null; 596 } 597 598 fn parseFormField(allocator: std.mem.Allocator, body: []const u8, key: []const u8) !?[]u8 { 599 var iter = std.mem.splitScalar(u8, body, '&'); 600 while (iter.next()) |pair| { 601 const eq = std.mem.indexOfScalar(u8, pair, '=') orelse continue; 602 if (std.mem.eql(u8, pair[0..eq], key)) { 603 return try decodeFormValue(allocator, pair[eq + 1 ..]); 604 } 605 } 606 return null; 607 } 608 609 fn decodeFormValue(allocator: std.mem.Allocator, encoded: []const u8) ![]u8 { 610 var out: std.ArrayList(u8) = .empty; 611 errdefer out.deinit(allocator); 612 var i: usize = 0; 613 while (i < encoded.len) : (i += 1) { 614 switch (encoded[i]) { 615 '+' => try out.append(allocator, ' '), 616 '%' => { 617 if (i + 2 >= encoded.len) return error.InvalidPercentEncoding; 618 const hi = std.fmt.charToDigit(encoded[i + 1], 16) catch return error.InvalidPercentEncoding; 619 const lo = std.fmt.charToDigit(encoded[i + 2], 16) catch return error.InvalidPercentEncoding; 620 try out.append(allocator, hi * 16 + lo); 621 i += 2; 622 }, 623 else => try out.append(allocator, encoded[i]), 624 } 625 } 626 return try out.toOwnedSlice(allocator); 627 } 628