use arena allocator, because this is a short lived cli tool
This commit is contained in:
76
src/main.zig
76
src/main.zig
@@ -16,15 +16,13 @@ const Base32Error = @import("base32.zig").Base32Error;
|
|||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
mainInternal() catch |err| {
|
mainInternal() catch |err| {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
Base32Error.InvalidCharacter => {
|
Base32Error.InvalidCharacter, Base32Error.InvalidPadding => {
|
||||||
try std.io.getStdErr().writer().print("The secret is invalid.\n", .{});
|
|
||||||
},
|
|
||||||
Base32Error.InvalidPadding => {
|
|
||||||
try std.io.getStdErr().writer().print("The secret is invalid.\n", .{});
|
try std.io.getStdErr().writer().print("The secret is invalid.\n", .{});
|
||||||
},
|
},
|
||||||
ArgumentError.UnknownParameter => {
|
ArgumentError.UnknownParameter => {
|
||||||
try std.io.getStdErr().writer().print("Unknown argument\n", .{});
|
// do nothing, error message is already written (because the message contains the name of the unknown parameter)
|
||||||
},
|
},
|
||||||
|
ArgumentError.InvalidOtpAuthUrl => {},
|
||||||
else => |leftover_err| {
|
else => |leftover_err| {
|
||||||
try std.io.getStdErr().writer().print("{?}\n", .{leftover_err});
|
try std.io.getStdErr().writer().print("{?}\n", .{leftover_err});
|
||||||
},
|
},
|
||||||
@@ -34,8 +32,9 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn mainInternal() !void {
|
fn mainInternal() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
const allocator = gpa.allocator();
|
defer arena.deinit();
|
||||||
|
const allocator = arena.allocator();
|
||||||
|
|
||||||
const args = try std.process.argsAlloc(allocator);
|
const args = try std.process.argsAlloc(allocator);
|
||||||
|
|
||||||
@@ -171,15 +170,14 @@ fn parseArgs(allocator: Allocator, args: []const []const u8) !Args {
|
|||||||
}
|
}
|
||||||
result.show = args[i];
|
result.show = args[i];
|
||||||
} else {
|
} else {
|
||||||
std.debug.print("unknown parameter: {s}\n", .{arg});
|
std.debug.print("unknown argument: {s}\n", .{arg});
|
||||||
return ArgumentError.UnknownParameter;
|
return ArgumentError.UnknownParameter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo use a real url parser
|
fn parseOtpAuthUrl(allocator: Allocator, url: []const u8) !OtpAuthUrl {
|
||||||
fn parseOtpAuthUrl(url: []const u8) !OtpAuthUrl {
|
|
||||||
const uri = try std.Uri.parse(url);
|
const uri = try std.Uri.parse(url);
|
||||||
|
|
||||||
if (!eql(u8, uri.scheme, "otpauth")) {
|
if (!eql(u8, uri.scheme, "otpauth")) {
|
||||||
@@ -190,9 +188,6 @@ fn parseOtpAuthUrl(url: []const u8) !OtpAuthUrl {
|
|||||||
return error.InvalidOtpAuthUrl;
|
return error.InvalidOtpAuthUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
||||||
const allocator = gpa.allocator();
|
|
||||||
|
|
||||||
var name = try uri.path.toRawMaybeAlloc(allocator);
|
var name = try uri.path.toRawMaybeAlloc(allocator);
|
||||||
name = std.mem.trimLeft(u8, name, "/");
|
name = std.mem.trimLeft(u8, name, "/");
|
||||||
|
|
||||||
@@ -259,12 +254,26 @@ fn read_config(allocator: Allocator, config_location: []const u8) !ArrayList(Otp
|
|||||||
|
|
||||||
var authenticators = std.ArrayList(OtpAuthUrl).init(allocator);
|
var authenticators = std.ArrayList(OtpAuthUrl).init(allocator);
|
||||||
|
|
||||||
|
var line_no: usize = 1;
|
||||||
while (try in_stream.readUntilDelimiterOrEofAlloc(allocator, '\n', 1024 * 1024)) |line| {
|
while (try in_stream.readUntilDelimiterOrEofAlloc(allocator, '\n', 1024 * 1024)) |line| {
|
||||||
|
//defer allocator.free(line);
|
||||||
if (line.len > 0 and std.mem.trim(u8, line, " \r").len > 0) {
|
if (line.len > 0 and std.mem.trim(u8, line, " \r").len > 0) {
|
||||||
const authenticator = try parseOtpAuthUrl(line);
|
const authenticatorResult = parseOtpAuthUrl(allocator, line);
|
||||||
|
if (authenticatorResult) |authenticator| {
|
||||||
try authenticators.append(authenticator);
|
try authenticators.append(authenticator);
|
||||||
|
} else |err| {
|
||||||
|
switch (err) {
|
||||||
|
error.InvalidOtpAuthUrl => {
|
||||||
|
try std.io.getStdErr().writer().print("invalid otpauth url in line {d}\n", .{line_no});
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
return err;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
line_no += 1;
|
||||||
|
}
|
||||||
return authenticators;
|
return authenticators;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,16 +303,18 @@ fn getAuthenticator(allocator: Allocator, name: []const u8, config_location: []c
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "parse command line parameter: 'list'" {
|
test "parse command line parameter: 'list'" {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||||
const allocator = gpa.allocator();
|
defer arena.deinit();
|
||||||
|
const allocator = arena.allocator();
|
||||||
|
|
||||||
const arg = try parseArgs(allocator, &[_][]const u8{ "path/of/executable", "list" });
|
const arg = try parseArgs(allocator, &[_][]const u8{ "path/of/executable", "list" });
|
||||||
try expect(arg.list);
|
try expect(arg.list);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "read list of entries" {
|
test "read list of entries" {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||||
const allocator = gpa.allocator();
|
defer arena.deinit();
|
||||||
|
const allocator = arena.allocator();
|
||||||
|
|
||||||
std.fs.cwd().deleteTree("test-tmp") catch unreachable;
|
std.fs.cwd().deleteTree("test-tmp") catch unreachable;
|
||||||
try std.fs.cwd().makeDir("test-tmp");
|
try std.fs.cwd().makeDir("test-tmp");
|
||||||
@@ -313,7 +324,7 @@ test "read list of entries" {
|
|||||||
std.fs.cwd().deleteTree("test-tmp") catch unreachable;
|
std.fs.cwd().deleteTree("test-tmp") catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = try file.write("otpauth://totp/token1?secret=c2VjcmV0Cg==\notpauth://totp/token2?secret=c2VjcmV0Cg==\n");
|
_ = try file.write("otpauth://totp/token1?secret=c2VjcmV0Cg==\notpauth://totp/token2?secret=c2VjcmV0Cg==");
|
||||||
|
|
||||||
const list: std.ArrayList([]const u8) = try executeGetList(allocator, "test-tmp/zig-totp");
|
const list: std.ArrayList([]const u8) = try executeGetList(allocator, "test-tmp/zig-totp");
|
||||||
try std.testing.expectEqualStrings("token1", list.items[0]);
|
try std.testing.expectEqualStrings("token1", list.items[0]);
|
||||||
@@ -321,8 +332,33 @@ test "read list of entries" {
|
|||||||
try std.testing.expectEqual(2, list.items.len);
|
try std.testing.expectEqual(2, list.items.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "read list of entries, ignoring invalid otpauth urls" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const allocator = arena.allocator();
|
||||||
|
|
||||||
|
std.fs.cwd().deleteTree("test-tmp") catch unreachable;
|
||||||
|
try std.fs.cwd().makeDir("test-tmp");
|
||||||
|
const file = try std.fs.cwd().createFile("test-tmp/zig-totp", .{ .read = true });
|
||||||
|
defer {
|
||||||
|
file.close();
|
||||||
|
std.fs.cwd().deleteTree("test-tmp") catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = try file.write("otpauth://totp/token1?secret=c2VjcmV0Cg==\notpauth://invalid\n");
|
||||||
|
|
||||||
|
const list: std.ArrayList([]const u8) = try executeGetList(allocator, "test-tmp/zig-totp");
|
||||||
|
|
||||||
|
try std.testing.expectEqualStrings("token1", list.items[0]);
|
||||||
|
try std.testing.expectEqual(1, list.items.len);
|
||||||
|
}
|
||||||
|
|
||||||
test "parse oth pauth url" {
|
test "parse oth pauth url" {
|
||||||
const actual: OtpAuthUrl = try parseOtpAuthUrl("otpauth://totp/foo?secret=MFQQ&period=31&digits=7");
|
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const allocator = arena.allocator();
|
||||||
|
|
||||||
|
const actual: OtpAuthUrl = try parseOtpAuthUrl(allocator, "otpauth://totp/foo?secret=MFQQ&period=31&digits=7");
|
||||||
|
|
||||||
try std.testing.expectEqualStrings("MFQQ", actual.secretEncoded);
|
try std.testing.expectEqualStrings("MFQQ", actual.secretEncoded);
|
||||||
try std.testing.expectEqualStrings("foo", actual.name);
|
try std.testing.expectEqualStrings("foo", actual.name);
|
||||||
|
|||||||
Reference in New Issue
Block a user