srctree

Gregory Mullen parent f42e3a0d ef63443d
gist submission works

but that's about it :D
inlinesplit
src/context.zig added: 229, removed: 24, total 205
@@ -97,12 +97,6 @@ pub fn sendPage(ctx: *Context, page: anytype) Error!void {
else => unreachable,
};
const loggedin = if (ctx.request.auth.valid()) "<a href=\"#\">Logged In</a>" else "Public";
try ctx.putContext("NavAuth", .{ .slice = loggedin });
if (ctx.request.auth.user(ctx.alloc)) |usr| {
try ctx.putContext("Current_username", .{ .slice = usr.username });
} else |_| {}
//
 
page.data.body_header.?.nav.?.nav_auth = loggedin;
const page_compiled = try page.build(ctx.alloc);
@@ -97,12 +97,6 @@ pub fn sendPage(ctx: *Context, page: anytype) Error!void {
else => unreachable,
};
const loggedin = if (ctx.request.auth.valid()) "<a href=\"#\">Logged In</a>" else "Public";
 
 
 
 
 
 
page.data.body_header.?.nav.?.nav_auth = loggedin;
const page_compiled = try page.build(ctx.alloc);
src/endpoints/gist.zig added: 229, removed: 24, total 205
@@ -1,30 +1,71 @@
 
const Context = @import("../context.zig");
const Template = @import("../template.zig");
 
 
 
const Route = @import("../routes.zig");
const Error = Route.Error;
const POST = Route.POST;
const GET = Route.GET;
 
 
 
const endpoints = [_]Route.Match{
GET("", view),
GET("gist", view),
 
 
POST("post", post),
};
pub fn router(ctx: *Context) Error!Route.Callable {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
return Route.router(ctx, &endpoints);
}
 
 
 
 
 
fn post(ctx: *Context) Error!void {
var tmpl = Template.findTemplate("gist.html");
return ctx.sendTemplate(&tmpl);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
}
fn view(ctx: *Context) Error!void {
const tmpl = Template.findTemplate("gist.html");
const page_data = Template.PageData("gist.html");
 
// TODO move this back into context somehow
var btns = [1]Template.Structs.Navbuttons{
.{
@@ -33,7 +74,9 @@ fn view(ctx: *Context) Error!void {
},
};
var page = page_data.init(tmpl, .{
 
 
.meta_head = .{
.open_graph = .{
.title = "Create A New Gist",
@@ -45,8 +88,44 @@ fn view(ctx: *Context) Error!void {
.nav_buttons = &btns,
},
},
.gist_body = "ha, it worked",
});
return ctx.sendPage(&page);
}
@@ -1,30 +1,71 @@
const std = @import("std");
const Context = @import("../context.zig");
const Template = @import("../template.zig");
const UserData = @import("../request_data.zig").UserData;
 
const Gist = @import("../types.zig").Gist;
const Route = @import("../routes.zig");
const Error = Route.Error;
const POST = Route.POST;
const GET = Route.GET;
const GistPage = Template.PageData("gist.html");
const GistNewPage = Template.PageData("gist_new.html");
 
const endpoints = [_]Route.Match{
GET("", view),
GET("gist", view),
GET("new", new),
POST("new", post),
POST("post", post),
};
pub fn router(ctx: *Context) Error!Route.Callable {
if (!std.mem.eql(u8, ctx.uri.next() orelse "", "gist")) return error.Unrouteable;
 
if (ctx.uri.peek()) |peek| {
if (peek.len == 64) {
for (peek) |chr| {
switch (chr) {
'a'...'f', '0'...'9' => continue,
else => return error.Unrouteable,
}
} else {
return view;
}
}
}
 
return Route.router(ctx, &endpoints);
}
const GistPost = struct {
file_name: [][]const u8,
file_blob: [][]const u8,
};
 
fn post(ctx: *Context) Error!void {
try ctx.request.auth.validOrError();
 
const postd = ctx.req_data.post_data orelse return error.BadData;
const udata = UserData(GistPost).initMap(ctx.alloc, postd) catch return error.BadData;
// I assume this is still enforced in ReleaseFast but I want to control the
// error returned
if (udata.file_name.len != udata.file_blob.len) return error.BadData;
 
const username = if (ctx.auth.valid())
(ctx.auth.user(ctx.alloc) catch unreachable).username
else
"public";
 
const hash_str: [64]u8 = Gist.new(username, udata.file_name, udata.file_blob) catch return error.Unknown;
 
return ctx.response.redirect("/gist/" ++ hash_str, true) catch unreachable;
}
fn new(ctx: *Context) Error!void {
const tmpl = Template.findTemplate("gist_new.html");
 
 
// TODO move this back into context somehow
var btns = [1]Template.Structs.Navbuttons{
.{
@@ -33,7 +74,9 @@ fn view(ctx: *Context) Error!void {
},
};
var files = [1]Template.Structs.Gistfiles{.{}};
 
var page = GistNewPage.init(tmpl, .{
.meta_head = .{
.open_graph = .{
.title = "Create A New Gist",
@@ -45,8 +88,44 @@ fn view(ctx: *Context) Error!void {
.nav_buttons = &btns,
},
},
.gist_files = &files,
});
return ctx.sendPage(&page);
}
 
fn view(ctx: *Context) Error!void {
const tmpl = Template.findTemplate("gist.html");
 
// TODO move this back into context somehow
var btns = [1]Template.Structs.Navbuttons{
.{
.name = "inbox",
.url = "/inbox",
},
};
 
if (ctx.uri.next()) |hash| {
if (hash.len != 64) return error.BadData;
 
const gist = Gist.open(ctx.alloc, hash[0..64].*) catch return error.Unknown;
std.debug.assert(gist.files.len == 1);
 
var page = GistPage.init(tmpl, .{
.meta_head = .{
.open_graph = .{
.title = "Create A New Gist",
},
},
.body_header = .{
.nav = .{
.nav_auth = undefined,
.nav_buttons = &btns,
},
},
.gist_body = gist.files[0].blob,
});
 
return ctx.sendPage(&page);
} else return error.Unrouteable;
}
src/template.zig added: 229, removed: 24, total 205
@@ -690,8 +690,8 @@ pub fn findTemplate(comptime name: []const u8) Template {
pub fn PageData(comptime name: []const u8) type {
//const template = findTemplate(name);
const page_type = comptime findPageType(name);
return Page(page_type);
}
fn intToWord(in: u8) []const u8 {
@@ -690,8 +690,8 @@ pub fn findTemplate(comptime name: []const u8) Template {
pub fn PageData(comptime name: []const u8) type {
//const template = findTemplate(name);
const page_data = comptime findPageType(name);
return Page(page_data);
}
fn intToWord(in: u8) []const u8 {
src/types.zig added: 229, removed: 24, total 205
@@ -4,6 +4,7 @@ pub const Comment = @import("types/comment.zig");
pub const CommitMap = @import("types/commit-map.zig");
pub const Delta = @import("types/delta.zig");
pub const Diff = @import("types/diff.zig");
 
pub const Issue = @import("types/issue.zig");
pub const Network = @import("types/network.zig");
pub const Read = @import("types/read.zig");
@@ -22,6 +23,7 @@ pub fn init(dir: []const u8) !void {
CommitMap,
Delta,
Diff,
 
Issue,
Network,
Read,
@@ -4,6 +4,7 @@ pub const Comment = @import("types/comment.zig");
pub const CommitMap = @import("types/commit-map.zig");
pub const Delta = @import("types/delta.zig");
pub const Diff = @import("types/diff.zig");
pub const Gist = @import("types/gist.zig");
pub const Issue = @import("types/issue.zig");
pub const Network = @import("types/network.zig");
pub const Read = @import("types/read.zig");
@@ -22,6 +23,7 @@ pub fn init(dir: []const u8) !void {
CommitMap,
Delta,
Diff,
Gist,
Issue,
Network,
Read,
filename was Deleted added: 229, removed: 24, total 205
@@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
const std = @import("std");
const builtin = @import("builtin");
const Allocator = std.mem.Allocator;
const endian = builtin.cpu.arch.endian();
 
pub const Gist = @This();
 
pub const TYPE_PREFIX = "{s}/gist";
const GIST_VERSION: usize = 0;
pub var datad: std.fs.Dir = undefined;
 
pub const File = struct {
name: []const u8,
blob: []const u8,
};
 
hash: [32]u8,
owner: []const u8,
created: i64,
files: []File,
 
pub fn init(_: []const u8) !void {}
pub fn initType() !void {}
 
fn readVersioned(a: Allocator, hash: [32]u8, reader: std.io.AnyReader) !Gist {
const int: usize = try reader.readInt(usize, endian);
return switch (int) {
0 => {
const t = Gist{
.hash = hash,
.owner = try reader.readUntilDelimiterAlloc(a, 0x00, 0x100),
.created = try reader.readInt(i64, endian),
.files = try a.alloc(File, try reader.readInt(u8, endian)),
};
for (t.files) |*file| {
file.name = try reader.readUntilDelimiterAlloc(a, 0x00, 0xFFF);
file.blob = try reader.readUntilDelimiterAlloc(a, 0x00, 0xFFFF);
}
 
return t;
},
 
else => error.UnsupportedVersion,
};
}
 
pub fn writeOut(self: Gist, w: std.io.AnyWriter) !void {
try w.writeInt(usize, GIST_VERSION, endian);
try w.writeAll(self.owner);
try w.writeAll("\x00");
try w.writeInt(u8, @truncate(self.files.len), endian);
for (self.files) |file| {
try w.writeAll(file.name);
try w.writeAll("\x00");
try w.writeAll(file.blob);
try w.writeAll("\x00");
}
}
 
pub fn open(a: Allocator, hash: [64]u8) !Gist {
// TODO handle open errors
var file = try datad.openFile(hash ++ ".gist", .{});
defer file.close();
 
const reader = file.reader().any();
var buf: [32]u8 = undefined;
const hashbytes = try std.fmt.hexToBytes(&buf, &hash);
return readVersioned(a, hashbytes[0..32].*, reader);
}
 
pub fn new(owner: []const u8, names: [][]const u8, blobs: [][]const u8) ![64]u8 {
var hash: [32]u8 = undefined;
var hash_str: [64]u8 = undefined;
var sha = std.crypto.hash.sha2.Sha256.init(.{});
sha.update(owner);
 
std.debug.assert(names.len <= 20);
var files_buf: [20]File = undefined;
 
for (names, blobs, files_buf[0..names.len]) |name, blob, *fout| {
sha.update(name);
sha.update(blob);
fout.name = name;
fout.blob = blob;
}
sha.final(&hash);
 
const gist = Gist{
.hash = hash,
.owner = owner,
.created = std.time.timestamp(),
.files = files_buf[0..names.len],
};
_ = try std.fmt.bufPrint(&hash_str, "{}", .{std.fmt.fmtSliceHexLower(&hash)});
 
var buf: [2048]u8 = undefined;
const filename = try std.fmt.bufPrint(&buf, "{s}.gist", .{hash_str});
const file = try datad.createFile(filename, .{});
const writer = file.writer().any();
 
try gist.writeOut(writer);
 
return hash_str;
}
src/types/user.zig added: 229, removed: 24, total 205
@@ -30,7 +30,7 @@ pub fn readVersioned(a: Allocator, file: std.fs.File) !User {
}
mtls_fp: [40]u8 = .{0} ** 40,
username: []u8,
pub fn readFile(a: Allocator, file: std.fs.File) !User {
defer file.close();
@@ -30,7 +30,7 @@ pub fn readVersioned(a: Allocator, file: std.fs.File) !User {
}
mtls_fp: [40]u8 = .{0} ** 40,
username: []const u8,
pub fn readFile(a: Allocator, file: std.fs.File) !User {
defer file.close();
filename was Deleted added: 229, removed: 24, total 205
@@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>srctree</title>
<_meta_head.html>
</head>
<body>
<_body_header.html>
<content>
<form method="POST" class="gist pretty" action="/gist/post">
<For GistFiles>
<div class="block">
<label>File Name</label>
<input name="file_name" value="<Name ORNULL>"/>
<br>
<textarea name="file_blob" cols="100" rows="<Count ORELSE 10>"><Blob ORNULL></textarea>
</div>
 
</For>
<button type="submit" name="new_file">Add Another File</button>
<button type="submit" name="save">Save</button>
</form>
 
</content>
</body>
</html>