add initial download for linux

This commit is contained in:
Emil Lerch 2022-01-05 11:29:14 -08:00
parent b6a03c8634
commit 1cbc4a846c
Signed by: lobo
GPG Key ID: A7B62D657EF764F8
3 changed files with 161 additions and 10 deletions

View File

@ -17,12 +17,42 @@ pub fn build(b: *std.build.Builder) void {
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions();
const exe = switch (target.getOs().tag) {
const uploadexe = switch (target.getOs().tag) {
.linux => b.addExecutable("clipboard-upload", "src/main-linux.zig"),
.windows => b.addExecutable("clipboard-upload", "src/main-windows.zig"),
else => std.os.exit(1),
};
configureExe(uploadexe, b, target, mode, zfetch_repo);
const run_cmd = uploadexe.run();
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app (uplaods clipboard contents)");
run_step.dependOn(&run_cmd.step);
const downloadexe = switch (target.getOs().tag) {
.linux => b.addExecutable("clipboard-download", "src/download-linux.zig"),
.windows => b.addExecutable("clipboard-download", "src/download-windows.zig"),
else => std.os.exit(1),
};
configureExe(downloadexe, b, target, mode, zfetch_repo);
const run_download_cmd = downloadexe.run();
run_download_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_download_cmd.addArgs(args);
}
const run_download_step = b.step("run-down", "Run the app (downloads clipboard contents)");
run_download_step.dependOn(&run_download_cmd.step);
}
fn configureExe(exe: *std.build.LibExeObjStep, b: *std.build.Builder, target: std.zig.CrossTarget, mode: std.builtin.Mode, zfetch_repo: anytype) void {
exe.setTarget(target);
exe.setBuildMode(mode);
if (target.getOs().tag == .linux) {
@ -77,15 +107,6 @@ pub fn build(b: *std.build.Builder) void {
.path = .{ .path = "libs/zfetch/libs/iguanaTLS/src/main.zig" },
});
exe.install();
const run_cmd = exe.run();
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
fn getDependency(comptime lib_prefix: []const u8, comptime name: []const u8, comptime root: []const u8) !std.build.Pkg {

View File

@ -30,6 +30,24 @@ pub fn deinit(self: *Self) void {
self.allocator.free(self.key);
}
pub fn download(self: *Self) ?[]const u8 {
const encrypted = get(self.allocator) catch |e| {
std.log.err("Could not download remote clipboard contents: {}", .{e});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
return null;
};
defer self.allocator.free(encrypted);
return crypt.decryptWithKey(self.allocator, self.key.*, encrypted) catch |e| {
std.log.err("Could not decrypt remote clipboard contents: {}", .{e});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
return null;
};
}
pub fn clipboardChanged(self: *Self, contents: []const u8) !void {
var arena_allocator = std.heap.ArenaAllocator.init(self.allocator);
defer arena_allocator.deinit();
@ -72,6 +90,50 @@ fn getKey(allocator: std.mem.Allocator) !*[crypt.key_size]u8 {
return tmp_key;
}
fn get(allocator: std.mem.Allocator) ![]const u8 {
// TODO: Windows
// var cert_reader = std.io.fixedBufferStream(
// @embedFile("/etc/ssl/certs/ca-certificates.crt"),
// ).reader();
// const trust = try tls.x509.CertificateChain.from_pem(allocator, cert_reader);
try zfetch.init();
defer zfetch.deinit();
var headers = zfetch.Headers.init(allocator);
defer headers.deinit();
// try headers.appendValue("Accept", "application/json");
// try headers.appendValue("Content-Type", "text/plain");
var req = try zfetch.Request.init(allocator, clipboard_url, null);
defer req.deinit();
try req.do(.GET, headers, null);
// Printf debugging
// const stdout = std.io.getStdOut().writer();
// try stdout.print("status: {d} {s}\n", .{ req.status.code, req.status.reason });
// try stdout.print("headers:\n", .{});
// for (req.headers.list.items) |header| {
// try stdout.print(" {s}: {s}\n", .{ header.name, header.value });
// }
// try stdout.print("body:\n", .{});
//
const reader = req.reader();
var data = std.ArrayList(u8).init(allocator);
defer data.deinit();
const data_writer = data.writer();
var buf: [1024]u8 = undefined;
while (true) {
const read = try reader.read(&buf);
if (read == 0) break;
try data_writer.writeAll(buf[0..read]);
}
return data.toOwnedSlice();
}
fn post(allocator: std.mem.Allocator, data: []const u8) !void {
// TODO: Windows
// var cert_reader = std.io.fixedBufferStream(

68
src/download-linux.zig Normal file
View File

@ -0,0 +1,68 @@
const std = @import("std");
const Clipboard = @import("clipboard.zig");
pub fn main() !u8 {
var watch = false;
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var args = std.process.args();
defer args.deinit();
while (args.next(allocator)) |arg_or_err| {
const arg = try arg_or_err;
defer allocator.free(arg);
if (std.mem.eql(u8, arg, "-w")) {
watch = true;
break;
}
}
var clip = try Clipboard.init(allocator);
defer clip.deinit();
if (watch) {
while (clip.download()) |text| {
std.log.debug("Got remote clipboard: {s}", .{text});
addToClipboardNoError(allocator, text);
allocator.free(text);
}
} else {
if (clip.download()) |text| {
std.log.debug("Got remote clipboard: {s}", .{text});
addToClipboardNoError(allocator, text);
allocator.free(text);
}
}
return 0;
}
fn addToClipboardNoError(allocator: std.mem.Allocator, data: []const u8) void {
addToClipboard(allocator, data) catch |e| {
std.log.err("Could not add data to clipboard: {}", .{e});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
};
}
fn addToClipboard(allocator: std.mem.Allocator, data: []const u8) !void {
// We're going to cheat here and just run xclip
const xclip_cmd = try std.fmt.allocPrint(allocator, "echo '{s}' | xclip -selection c", .{data});
defer allocator.free(xclip_cmd);
const result = try std.ChildProcess.exec(.{
.allocator = allocator,
.argv = &[_][]const u8{
"/usr/bin/env",
"sh",
"-c",
xclip_cmd,
},
});
try std.io.getStdErr().writer().writeAll(result.stderr);
switch (result.term) {
.Exited => |code| if (code != 0) return error.NonZeroExit,
.Signal => return error.FailedWithSignal,
.Stopped => return error.WasStopped,
.Unknown => return error.Failed,
}
}