PARTIAL update zig 0.10.0 -> 0.13.0 (Linux only)
This commit is contained in:
		
							parent
							
								
									c29716cc5e
								
							
						
					
					
						commit
						b57611439f
					
				
					 8 changed files with 104 additions and 393 deletions
				
			
		
							
								
								
									
										206
									
								
								GitRepoStep.zig
									
										
									
									
									
								
							
							
						
						
									
										206
									
								
								GitRepoStep.zig
									
										
									
									
									
								
							|  | @ -1,206 +0,0 @@ | |||
| //! Publish Date: 2021_10_17 | ||||
| //! This file is hosted at github.com/marler8997/zig-build-repos and is meant to be copied | ||||
| //! to projects that use it. | ||||
| const std = @import("std"); | ||||
| const GitRepoStep = @This(); | ||||
| 
 | ||||
| pub const ShaCheck = enum { | ||||
|     none, | ||||
|     warn, | ||||
|     err, | ||||
| 
 | ||||
|     pub fn reportFail(self: ShaCheck, comptime fmt: []const u8, args: anytype) void { | ||||
|         switch (self) { | ||||
|             .none => unreachable, | ||||
|             .warn => std.log.warn(fmt, args), | ||||
|             .err => { | ||||
|                 std.log.err(fmt, args); | ||||
|                 std.os.exit(0xff); | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| step: std.build.Step, | ||||
| builder: *std.build.Builder, | ||||
| url: []const u8, | ||||
| name: []const u8, | ||||
| branch: ?[]const u8 = null, | ||||
| sha: []const u8, | ||||
| path: []const u8 = null, | ||||
| sha_check: ShaCheck = .warn, | ||||
| fetch_enabled: bool, | ||||
| 
 | ||||
| var cached_default_fetch_option: ?bool = null; | ||||
| pub fn defaultFetchOption(b: *std.build.Builder) bool { | ||||
|     if (cached_default_fetch_option) |_| {} else { | ||||
|         cached_default_fetch_option = if (b.option(bool, "fetch", "automatically fetch network resources")) |o| o else false; | ||||
|     } | ||||
|     return cached_default_fetch_option.?; | ||||
| } | ||||
| 
 | ||||
| pub fn create(b: *std.build.Builder, opt: struct { | ||||
|     url: []const u8, | ||||
|     branch: ?[]const u8 = null, | ||||
|     sha: []const u8, | ||||
|     path: ?[]const u8 = null, | ||||
|     sha_check: ShaCheck = .warn, | ||||
|     fetch_enabled: ?bool = null, | ||||
| }) *GitRepoStep { | ||||
|     var result = b.allocator.create(GitRepoStep) catch @panic("memory"); | ||||
|     const name = std.fs.path.basename(opt.url); | ||||
|     result.* = GitRepoStep{ | ||||
|         .step = std.build.Step.init(.custom, "clone a git repository", b.allocator, make), | ||||
|         .builder = b, | ||||
|         .url = opt.url, | ||||
|         .name = name, | ||||
|         .branch = opt.branch, | ||||
|         .sha = opt.sha, | ||||
|         .path = if (opt.path) |p| (b.allocator.dupe(u8, p) catch @panic("memory")) else (std.fs.path.resolve(b.allocator, &[_][]const u8{ | ||||
|             b.build_root, | ||||
|             "libs", | ||||
|             name, | ||||
|         })) catch @panic("memory"), | ||||
|         .sha_check = opt.sha_check, | ||||
|         .fetch_enabled = if (opt.fetch_enabled) |fe| fe else defaultFetchOption(b), | ||||
|     }; | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| // TODO: this should be included in std.build, it helps find bugs in build files | ||||
| fn hasDependency(step: *const std.build.Step, dep_candidate: *const std.build.Step) bool { | ||||
|     for (step.dependencies.items) |dep| { | ||||
|         // TODO: should probably use step.loop_flag to prevent infinite recursion | ||||
|         //       when a circular reference is encountered, or maybe keep track of | ||||
|         //       the steps encounterd with a hash set | ||||
|         if (dep == dep_candidate or hasDependency(dep, dep_candidate)) | ||||
|             return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| fn make(step: *std.build.Step) !void { | ||||
|     const self = @fieldParentPtr(GitRepoStep, "step", step); | ||||
| 
 | ||||
|     std.fs.accessAbsolute(self.path, std.fs.File.OpenFlags{ .read = true }) catch { | ||||
|         const branch_args = if (self.branch) |b| &[2][]const u8{ " -b ", b } else &[2][]const u8{ "", "" }; | ||||
|         if (!self.fetch_enabled) { | ||||
|             std.debug.print("Error: git repository '{s}' does not exist\n", .{self.path}); | ||||
|             std.debug.print("       Use -Dfetch to download it automatically, or run the following to clone it:\n", .{}); | ||||
|             std.debug.print("       git clone {s}{s}{s} {s} && git -C {3s} checkout {s} -b for_ziget\n", .{ self.url, branch_args[0], branch_args[1], self.path, self.sha }); | ||||
|             std.os.exit(1); | ||||
|         } | ||||
| 
 | ||||
|         { | ||||
|             var args = std.ArrayList([]const u8).init(self.builder.allocator); | ||||
|             defer args.deinit(); | ||||
|             try args.append("git"); | ||||
|             try args.append("clone"); | ||||
|             try args.append("--recurse-submodules"); | ||||
|             try args.append(self.url); | ||||
|             // TODO: clone it to a temporary location in case of failure | ||||
|             //       also, remove that temporary location before running | ||||
|             try args.append(self.path); | ||||
|             if (self.branch) |branch| { | ||||
|                 try args.append("-b"); | ||||
|                 try args.append(branch); | ||||
|             } | ||||
|             try run(self.builder, args.items); | ||||
|         } | ||||
|         try run(self.builder, &[_][]const u8{ | ||||
|             "git", | ||||
|             "-C", | ||||
|             self.path, | ||||
|             "checkout", | ||||
|             self.sha, | ||||
|             "-b", | ||||
|             "fordep", | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     try self.checkSha(); | ||||
| } | ||||
| 
 | ||||
| fn checkSha(self: GitRepoStep) !void { | ||||
|     if (self.sha_check == .none) | ||||
|         return; | ||||
| 
 | ||||
|     const result: union(enum) { failed: anyerror, output: []const u8 } = blk: { | ||||
|         const result = std.ChildProcess.exec(.{ | ||||
|             .allocator = self.builder.allocator, | ||||
|             .argv = &[_][]const u8{ | ||||
|                 "git", | ||||
|                 "-C", | ||||
|                 self.path, | ||||
|                 "rev-parse", | ||||
|                 "HEAD", | ||||
|             }, | ||||
|             .cwd = self.builder.build_root, | ||||
|             .env_map = self.builder.env_map, | ||||
|         }) catch |e| break :blk .{ .failed = e }; | ||||
|         try std.io.getStdErr().writer().writeAll(result.stderr); | ||||
|         switch (result.term) { | ||||
|             .Exited => |code| { | ||||
|                 if (code == 0) break :blk .{ .output = result.stdout }; | ||||
|                 break :blk .{ .failed = error.GitProcessNonZeroExit }; | ||||
|             }, | ||||
|             .Signal => break :blk .{ .failed = error.GitProcessFailedWithSignal }, | ||||
|             .Stopped => break :blk .{ .failed = error.GitProcessWasStopped }, | ||||
|             .Unknown => break :blk .{ .failed = error.GitProcessFailed }, | ||||
|         } | ||||
|     }; | ||||
|     switch (result) { | ||||
|         .failed => |err| { | ||||
|             return self.sha_check.reportFail("failed to retreive sha for repository '{s}': {s}", .{ self.name, @errorName(err) }); | ||||
|         }, | ||||
|         .output => |output| { | ||||
|             if (!std.mem.eql(u8, std.mem.trimRight(u8, output, "\n\r"), self.sha)) { | ||||
|                 return self.sha_check.reportFail("repository '{s}' sha does not match\nexpected: {s}\nactual  : {s}\n", .{ self.name, self.sha, output }); | ||||
|             } | ||||
|         }, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn run(builder: *std.build.Builder, argv: []const []const u8) !void { | ||||
|     { | ||||
|         var msg = std.ArrayList(u8).init(builder.allocator); | ||||
|         defer msg.deinit(); | ||||
|         const writer = msg.writer(); | ||||
|         var prefix: []const u8 = ""; | ||||
|         for (argv) |arg| { | ||||
|             try writer.print("{s}\"{s}\"", .{ prefix, arg }); | ||||
|             prefix = " "; | ||||
|         } | ||||
|         std.log.info("[RUN] {s}", .{msg.items}); | ||||
|     } | ||||
| 
 | ||||
|     const child = try std.ChildProcess.init(argv, builder.allocator); | ||||
|     defer child.deinit(); | ||||
| 
 | ||||
|     child.stdin_behavior = .Ignore; | ||||
|     child.stdout_behavior = .Inherit; | ||||
|     child.stderr_behavior = .Inherit; | ||||
|     child.cwd = builder.build_root; | ||||
|     child.env_map = builder.env_map; | ||||
| 
 | ||||
|     try child.spawn(); | ||||
|     const result = try child.wait(); | ||||
|     switch (result) { | ||||
|         .Exited => |code| if (code != 0) { | ||||
|             std.log.err("git clone failed with exit code {}", .{code}); | ||||
|             std.os.exit(0xff); | ||||
|         }, | ||||
|         else => { | ||||
|             std.log.err("git clone failed with: {}", .{result}); | ||||
|             std.os.exit(0xff); | ||||
|         }, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Get's the repository path and also verifies that the step requesting the path | ||||
| // is dependent on this step. | ||||
| pub fn getPath(self: *const GitRepoStep, who_wants_to_know: *const std.build.Step) []const u8 { | ||||
|     if (!hasDependency(who_wants_to_know, &self.step)) | ||||
|         @panic("a step called GitRepoStep.getPath but has not added it as a dependency"); | ||||
|     return self.path; | ||||
| } | ||||
							
								
								
									
										136
									
								
								build.zig
									
										
									
									
									
								
							
							
						
						
									
										136
									
								
								build.zig
									
										
									
									
									
								
							|  | @ -1,12 +1,6 @@ | |||
| const std = @import("std"); | ||||
| const GitRepoStep = @import("GitRepoStep.zig"); | ||||
| 
 | ||||
| pub fn build(b: *std.build.Builder) void { | ||||
|     const zfetch_repo = GitRepoStep.create(b, .{ | ||||
|         .url = "https://github.com/truemedian/zfetch", | ||||
|         // .branch = "0.1.10", // branch also takes tags. Tag 0.1.10 isn't quite new enough | ||||
|         .sha = "271cab5da4d12c8f08e67aa0cd5268da100e52f1", | ||||
|     }); | ||||
| pub fn build(b: *std.Build) void { | ||||
|     // Standard target options allows the person running `zig build` to choose | ||||
|     // what target to build for. Here we do not override the defaults, which | ||||
|     // means any target is allowed, and the default is native. Other options | ||||
|  | @ -15,12 +9,12 @@ pub fn build(b: *std.build.Builder) void { | |||
| 
 | ||||
|     // Standard release options allow the person running `zig build` to select | ||||
|     // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. | ||||
|     const mode = b.standardReleaseOptions(); | ||||
|     const optimize = b.standardOptimizeOption(.{}); | ||||
| 
 | ||||
|     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), | ||||
|     const uploadexe = switch (target.result.os.tag) { | ||||
|         .linux => b.addExecutable(.{ .name = "clipboard-upload", .root_source_file = b.path("src/main-linux.zig"), .target = target }), | ||||
|         .windows => b.addExecutable(.{ .name = "clipboard-upload", .root_source_file = b.path("src/main-windows.zig"), .target = target }), | ||||
|         else => std.process.exit(1), | ||||
|     }; | ||||
| 
 | ||||
|     const path = if (b.option(bool, "curl", "use external curl command") orelse false) | ||||
|  | @ -30,19 +24,22 @@ pub fn build(b: *std.build.Builder) void { | |||
| 
 | ||||
|     const enc_path = blk: { | ||||
|         if (b.option(bool, "seperate-encryption", "use external encryption command") orelse false) { | ||||
|             const encryptionexe = b.addExecutable("encrypt", "src/encrypt.zig"); | ||||
|             encryptionexe.setTarget(target); | ||||
|             encryptionexe.setBuildMode(mode); | ||||
|             encryptionexe.install(); | ||||
|             const encryptionexe = b.addExecutable(.{ | ||||
|                 .name = "encrypt", | ||||
|                 .root_source_file = b.path("src/encrypt.zig"), | ||||
|                 .target = target, | ||||
|                 .optimize = optimize, | ||||
|             }); | ||||
|             b.getInstallStep().dependOn(&b.addInstallArtifact(encryptionexe, .{}).step); | ||||
|             break :blk "config/external_encryption.zig"; | ||||
|         } else { | ||||
|             break :blk "config/sane_encryption.zig"; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     configureExe(uploadexe, b, target, mode, zfetch_repo, path, enc_path); | ||||
|     configureExe(uploadexe, b, target, optimize, path, enc_path); | ||||
| 
 | ||||
|     const run_cmd = uploadexe.run(); | ||||
|     const run_cmd = b.addRunArtifact(uploadexe); | ||||
|     run_cmd.step.dependOn(b.getInstallStep()); | ||||
|     if (b.args) |args| { | ||||
|         run_cmd.addArgs(args); | ||||
|  | @ -51,11 +48,11 @@ pub fn build(b: *std.build.Builder) void { | |||
|     const run_step = b.step("run", "Run the app (uplaods clipboard contents)"); | ||||
|     run_step.dependOn(&run_cmd.step); | ||||
| 
 | ||||
|     const downloadexe = b.addExecutable("clipboard-download", "src/download.zig"); | ||||
|     const downloadexe = b.addExecutable(.{ .name = "clipboard-download", .root_source_file = b.path("src/download.zig"), .target = target }); | ||||
| 
 | ||||
|     configureExe(downloadexe, b, target, mode, zfetch_repo, path, enc_path); | ||||
|     configureExe(downloadexe, b, target, optimize, path, enc_path); | ||||
| 
 | ||||
|     const run_download_cmd = downloadexe.run(); | ||||
|     const run_download_cmd = b.addRunArtifact(downloadexe); | ||||
|     run_download_cmd.step.dependOn(b.getInstallStep()); | ||||
|     if (b.args) |args| { | ||||
|         run_download_cmd.addArgs(args); | ||||
|  | @ -65,10 +62,9 @@ pub fn build(b: *std.build.Builder) void { | |||
|     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, config_path: []const u8, enc_config_path: []const u8) void { | ||||
|     exe.setTarget(target); | ||||
|     exe.setBuildMode(mode); | ||||
|     if (target.getOs().tag == .linux) { | ||||
| fn configureExe(exe: *std.Build.Step.Compile, b: *std.Build, target: std.Build.ResolvedTarget, mode: std.builtin.OptimizeMode, config_path: []const u8, enc_config_path: []const u8) void { | ||||
|     exe.root_module.optimize = mode; | ||||
|     if (target.result.os.tag == .linux) { | ||||
|         exe.linkLibC(); | ||||
|         // LibX11 1.7.2: https://gitlab.freedesktop.org/xorg/lib/libx11/-/archive/libX11-1.7.2/libx11-libX11-1.7.2.tar.gz | ||||
|         // LibXfixes 5.0.3: https://gitlab.freedesktop.org/xorg/lib/libxfixes/-/archive/libXfixes-5.0.3/libxfixes-libXfixes-5.0.3.tar.gz | ||||
|  | @ -76,93 +72,39 @@ fn configureExe(exe: *std.build.LibExeObjStep, b: *std.build.Builder, target: st | |||
|         // We can download the above by taking each url and processing in a | ||||
|         // command e.g.: | ||||
|         // curl <url> | tar xz --wildcards '*.h' | ||||
|         exe.addIncludeDir("libx11-libX11-1.7.2/include"); | ||||
|         exe.addIncludeDir("libxfixes-libXfixes-5.0.3/include"); | ||||
|         exe.addIncludeDir("xorgproto-xorgproto-2021.5/include"); | ||||
|         exe.addIncludePath(b.path("libx11-libX11-1.7.2/include")); | ||||
|         exe.addIncludePath(b.path("libxfixes-libXfixes-5.0.3/include")); | ||||
|         exe.addIncludePath(b.path("xorgproto-xorgproto-2021.5/include")); | ||||
| 
 | ||||
|         // More than a little messy. We're grabbing libX11 and libXfixes from | ||||
|         // the host, while using downloaded headers. This assumes debian | ||||
|         // bullseye host, and also means you can't cross-compile from Windows. | ||||
|         // TODO: Make this better | ||||
|         // const dependent_objects = .{ | ||||
|         //     "/usr/lib/x86_64-linux-gnu/libX11.so.6", | ||||
|         //     "/usr/lib/x86_64-linux-gnu/libXfixes.so.3", | ||||
|         // }; | ||||
|         const dependent_objects = .{ | ||||
|             "/usr/lib/x86_64-linux-gnu/libX11.so.6", | ||||
|             "/usr/lib/x86_64-linux-gnu/libXfixes.so.3", | ||||
|             "/nix/store/wd7b3f9sqgs0flgicx213iiyzjb4jxqm-libXfixes-6.0.1/lib/libXfixes.so.3", | ||||
|         }; | ||||
|         inline for (dependent_objects) |obj| | ||||
|             exe.addObjectFile(obj); | ||||
|             exe.addObjectFile(.{ .cwd_relative = obj }); | ||||
|         // exe.addObjectFile(b.path(obj)); | ||||
|     } | ||||
|     if (target.getOs().tag == .windows) { | ||||
|     if (target.result.os.tag == .windows) { | ||||
|         // woah...we don't actually need libc! | ||||
|         exe.linkSystemLibrary("user32"); | ||||
|         exe.linkSystemLibrary("kernel32"); | ||||
|         exe.linkSystemLibrary("shell32"); | ||||
|     } | ||||
|     const copy_deps = std.build.RunStep.create(b, "copy zfetch deps"); | ||||
|     copy_deps.addArgs(&[_][]const u8{ | ||||
|         "cp", | ||||
|         "zfetch_deps.zig", | ||||
|         "libs/zfetch/deps.zig", | ||||
|     }); | ||||
|     copy_deps.step.dependOn(&zfetch_repo.step); | ||||
| 
 | ||||
|     // exe.step.dependOn(&zfetch_repo.step); | ||||
|     exe.step.dependOn(©_deps.step); | ||||
|     exe.root_module.addImport("config", b.createModule(.{ | ||||
|         .root_source_file = b.path(config_path), | ||||
|     })); | ||||
|     exe.root_module.addImport("encryptionconfig", b.createModule(.{ | ||||
|         .root_source_file = b.path(enc_config_path), | ||||
|     })); | ||||
| 
 | ||||
|     // This import won't work unless we're already cloned. The way around | ||||
|     // this is to have a multi-stage build process, but that's a lot of work. | ||||
|     // Instead, I've copied the addPackage and tweaked it for the build prefix | ||||
|     // so we'll have to keep that in sync with upstream | ||||
|     // const zfetch = @import("libs/zfetch/build.zig"); | ||||
|     const zpkg = getZfetchPackage(b, "libs/zfetch") catch unreachable; | ||||
|     exe.addPackage(zpkg); | ||||
|     exe.addPackage(.{ | ||||
|         .name = "iguanaTLS", | ||||
|         .path = .{ .path = "libs/zfetch/libs/iguanaTLS/src/main.zig" }, | ||||
|     }); | ||||
| 
 | ||||
|     exe.addPackage(.{ | ||||
|         .name = "config", | ||||
|         .path = .{ .path = config_path }, | ||||
|     }); | ||||
|     exe.addPackage(.{ | ||||
|         .name = "encryptionconfig", | ||||
|         .path = .{ .path = enc_config_path }, | ||||
|     }); | ||||
| 
 | ||||
|     exe.install(); | ||||
| } | ||||
| 
 | ||||
| fn getDependency(comptime lib_prefix: []const u8, comptime name: []const u8, comptime root: []const u8) !std.build.Pkg { | ||||
|     const path = lib_prefix ++ "/libs/" ++ name ++ "/" ++ root; | ||||
| 
 | ||||
|     // We don't actually care if the dependency has been checked out, as | ||||
|     // GitRepoStep will handle that for us | ||||
|     // Make sure that the dependency has been checked out. | ||||
|     // std.fs.cwd().access(path, .{}) catch |err| switch (err) { | ||||
|     //     error.FileNotFound => { | ||||
|     //         std.log.err("zfetch: dependency '{s}' not checked out", .{name}); | ||||
|     // | ||||
|     //         return err; | ||||
|     //     }, | ||||
|     //     else => return err, | ||||
|     // }; | ||||
| 
 | ||||
|     return std.build.Pkg{ | ||||
|         .name = name, | ||||
|         .path = .{ .path = path }, | ||||
|     }; | ||||
| } | ||||
| pub fn getZfetchPackage(b: *std.build.Builder, comptime lib_prefix: []const u8) !std.build.Pkg { | ||||
|     var dependencies = b.allocator.alloc(std.build.Pkg, 4) catch unreachable; | ||||
| 
 | ||||
|     dependencies[0] = try getDependency(lib_prefix, "iguanaTLS", "src/main.zig"); | ||||
|     dependencies[1] = try getDependency(lib_prefix, "network", "network.zig"); | ||||
|     dependencies[2] = try getDependency(lib_prefix, "uri", "uri.zig"); | ||||
|     dependencies[3] = try getDependency(lib_prefix, "hzzp", "src/main.zig"); | ||||
| 
 | ||||
|     return std.build.Pkg{ | ||||
|         .name = "zfetch", | ||||
|         .path = .{ .path = lib_prefix ++ "/src/main.zig" }, | ||||
|         .dependencies = dependencies, | ||||
|     }; | ||||
|     b.getInstallStep().dependOn(&b.addInstallArtifact(exe, .{}).step); | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| const builtin = @import("builtin"); | ||||
| const std = @import("std"); | ||||
| const zfetch = @import("zfetch"); | ||||
| const crypt = @import("crypt.zig"); | ||||
| const config = @import("config"); | ||||
| const encryptionconfig = @import("encryptionconfig"); | ||||
|  | @ -13,7 +12,7 @@ const encryptionconfig = @import("encryptionconfig"); | |||
| // iguanaTLS to support tls 1.3 | ||||
| // iguanaTLS to support something else, like ECDHE-ECDSA-CHACHA20-POLY1305 | ||||
| // In the meantime, I've allowed use of http, since we're encrypting anyway | ||||
| const clipboard_url = "http://clippy.lerch.org/work2"; | ||||
| const clipboard_url = "https://clippy.lerch.org/work2"; | ||||
| // const clipboard_url = "https://httpbin.org/post"; | ||||
| 
 | ||||
| const Self = @This(); | ||||
|  | @ -59,9 +58,8 @@ pub fn clipboardChanged(self: *Self, contents: []const u8) !void { | |||
|     defer aa.free(clip_contents); | ||||
| 
 | ||||
|     // Ugh - it's the encryption that Crowdstrike doesn't like.. :( | ||||
|     var buf: []u8 = try aa.alloc(u8, contents.len); | ||||
|     const buf: []u8 = try aa.dupe(u8, contents); | ||||
|     defer aa.free(buf); | ||||
|     std.mem.copy(u8, buf, contents); | ||||
|     const encrypted = encrypt(aa, self.key.*, buf) catch |e| { | ||||
|         std.log.err("Could not encrypt clipboard contents: {}", .{e}); | ||||
|         if (@errorReturnTrace()) |trace| { | ||||
|  | @ -127,19 +125,20 @@ fn get(allocator: std.mem.Allocator) ![]const u8 { | |||
|     //     @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(); | ||||
|     var data = std.ArrayList(u8).init(allocator); | ||||
|     defer data.deinit(); | ||||
|     var client = std.http.Client{ .allocator = allocator }; | ||||
|     defer client.deinit(); | ||||
| 
 | ||||
|     try req.do(.GET, headers, null); | ||||
|     const res = try client.fetch(.{ | ||||
|         .location = .{ .url = clipboard_url }, | ||||
|         .response_storage = .{ .dynamic = &data }, | ||||
|     }); | ||||
|     _ = res; // TODO: Check res.status | ||||
| 
 | ||||
|     // Printf debugging | ||||
|     // const stdout = std.io.getStdOut().writer(); | ||||
|  | @ -150,18 +149,6 @@ fn get(allocator: std.mem.Allocator) ![]const u8 { | |||
|     // } | ||||
|     // 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(); | ||||
| } | ||||
| 
 | ||||
|  | @ -270,42 +257,20 @@ fn put(allocator: std.mem.Allocator, data: []const u8) !void { | |||
|     //     @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 client = std.http.Client{ .allocator = allocator }; | ||||
|     defer client.deinit(); | ||||
| 
 | ||||
|     var headers = zfetch.Headers.init(allocator); | ||||
|     defer headers.deinit(); | ||||
|     const res = try client.fetch(.{ | ||||
|         .location = .{ .url = clipboard_url }, | ||||
|         .method = .PUT, | ||||
|         .payload = data, | ||||
|     }); | ||||
|     _ = res; // TODO: check status | ||||
| 
 | ||||
|     // 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(.PUT, headers, data); | ||||
| 
 | ||||
|     // 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 buf: [1024]u8 = undefined; | ||||
|     // while (true) { | ||||
|     //     const read = try reader.read(&buf); | ||||
|     //     if (read == 0) break; | ||||
|     // | ||||
|     //     try stdout.writeAll(buf[0..read]); | ||||
|     // } | ||||
| } | ||||
| 
 | ||||
| test "full integration" { | ||||
|     var allocator = std.testing.allocator; | ||||
|     const allocator = std.testing.allocator; | ||||
|     var watcher = init(allocator); | ||||
|     defer watcher.deinit(); | ||||
|     try watcher.clipboardChanged("hello world"); | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ pub fn encryptWithKey(allocator: std.mem.Allocator, key: [key_size]u8, data: []u | |||
|     var encrypted = try std.ArrayList(u8).initCapacity(allocator, block_size * (total_blocks + 1)); | ||||
|     defer encrypted.deinit(); | ||||
|     while (current_block < total_blocks) { | ||||
|         in = @ptrCast(*[block_size]u8, data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]); | ||||
|         in = @ptrCast(data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]); | ||||
|         ctx.encrypt(out[0..], in.*[0..]); | ||||
|         encrypted.appendSliceAssumeCapacity(out[0..]); | ||||
|         current_block += 1; | ||||
|  | @ -56,7 +56,7 @@ pub fn encryptWithKey(allocator: std.mem.Allocator, key: [key_size]u8, data: []u | |||
|         // We can't just ptrcast into data as we are likely to run over the end | ||||
|         // of the data memory. We'll declare a new input buffer | ||||
|         var in_last: [block_size]u8 = undefined; | ||||
|         const padding: u8 = @intCast(u8, block_size - (data.len % block_size)); | ||||
|         const padding: u8 = @intCast(block_size - (data.len % block_size)); | ||||
|         var inx: u8 = 0; | ||||
|         for (data[(total_blocks * block_size)..]) |b| { | ||||
|             in_last[inx] = b; | ||||
|  | @ -99,14 +99,14 @@ pub fn decryptWithKey(allocator: std.mem.Allocator, key: [key_size]u8, data: []c | |||
|     var decrypted = try std.ArrayList(u8).initCapacity(allocator, block_size * (total_blocks - 1)); | ||||
|     defer decrypted.deinit(); | ||||
|     while (current_block < total_blocks - 1) { | ||||
|         in = @ptrCast(*const [block_size]u8, data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]); | ||||
|         in = @ptrCast(data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]); | ||||
|         ctx.decrypt(out[0..], in.*[0..]); | ||||
|         decrypted.appendSliceAssumeCapacity(out[0..]); | ||||
|         current_block += 1; | ||||
|     } | ||||
| 
 | ||||
|     // deal with final block, PKCS#7 padding | ||||
|     in = @ptrCast(*const [block_size]u8, data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]); | ||||
|     in = @ptrCast(data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]); | ||||
|     ctx.decrypt(out[0..], in.*[0..]); | ||||
|     // Assertion was triggering when data was plain text | ||||
|     if (out[block_size - 1] > block_size) { | ||||
|  | @ -131,7 +131,7 @@ test "correct size, even block" { | |||
|     const str = "0123456789ABCDEF"; | ||||
|     var allocator = std.testing.allocator; | ||||
|     var buf: [str.len]u8 = undefined; | ||||
|     var data = try std.fmt.bufPrint(&buf, str, .{}); | ||||
|     const data = try std.fmt.bufPrint(&buf, str, .{}); | ||||
|     const encrypted = try encryptWithKey(allocator, test_key, data); | ||||
|     defer allocator.free(encrypted); | ||||
|     const size: usize = 32; | ||||
|  | @ -142,7 +142,7 @@ test "round trip, even block" { | |||
|     const str = "0123456789ABCDEF"; | ||||
|     var allocator = std.testing.allocator; | ||||
|     var buf: [str.len]u8 = undefined; | ||||
|     var data = try std.fmt.bufPrint(&buf, str, .{}); | ||||
|     const data = try std.fmt.bufPrint(&buf, str, .{}); | ||||
|     const encrypted = try encryptWithKey(allocator, test_key, data); | ||||
|     defer allocator.free(encrypted); | ||||
|     const decrypted = try decryptWithKey(allocator, test_key, encrypted); | ||||
|  | @ -155,7 +155,7 @@ test "round trip, uneven block" { | |||
|     const str = "0123456789ABCDEFG"; | ||||
|     var allocator = std.testing.allocator; | ||||
|     var buf: [str.len]u8 = undefined; | ||||
|     var data = try std.fmt.bufPrint(&buf, str, .{}); | ||||
|     const data = try std.fmt.bufPrint(&buf, str, .{}); | ||||
|     const encrypted = try encryptWithKey(allocator, test_key, data); | ||||
|     defer allocator.free(encrypted); | ||||
|     const decrypted = try decryptWithKey(allocator, test_key, encrypted); | ||||
|  | @ -167,8 +167,8 @@ test "round trip, uneven block, using password" { | |||
|     const str = "0123456789ABCDEFG"; | ||||
|     var allocator = std.testing.allocator; | ||||
|     var buf: [str.len]u8 = undefined; | ||||
|     var data = try std.fmt.bufPrint(&buf, str, .{}); | ||||
|     var key = try keyFromPassword(allocator, "foo", ""); | ||||
|     const data = try std.fmt.bufPrint(&buf, str, .{}); | ||||
|     const key = try keyFromPassword(allocator, "foo", ""); | ||||
|     defer allocator.free(key); | ||||
|     const encrypted = try encryptWithKey(allocator, key.*, data); | ||||
|     defer allocator.free(encrypted); | ||||
|  |  | |||
|  | @ -42,11 +42,9 @@ pub fn main() !u8 { | |||
|     var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||||
|     defer _ = gpa.deinit(); | ||||
|     const allocator = gpa.allocator(); | ||||
|     var args = std.process.args(); | ||||
|     var args = try std.process.argsWithAllocator(allocator); | ||||
|     defer args.deinit(); | ||||
|     while (args.next(allocator)) |arg_or_err| { | ||||
|         const arg = try arg_or_err; | ||||
|         defer allocator.free(arg); | ||||
|     while (args.next()) |arg| { | ||||
|         if (std.mem.eql(u8, arg, "-w")) { | ||||
|             watch = true; | ||||
|             break; | ||||
|  | @ -101,7 +99,16 @@ fn addToClipboard(allocator: std.mem.Allocator, data: []const u8) !void { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| fn execLinux(allocator: std.mem.Allocator, data: []const u8) !std.ChildProcess.ExecResult { | ||||
| const Term = struct { | ||||
|     allocator: std.mem.Allocator, | ||||
|     stderr: []const u8, | ||||
|     term: std.process.Child.Term, | ||||
| 
 | ||||
|     pub fn deinit(self: *Term) void { | ||||
|         self.allocator.free(self.stderr); | ||||
|     } | ||||
| }; | ||||
| fn execLinux(allocator: std.mem.Allocator, data: []const u8) !Term { | ||||
|     // we need to do this (maybe) because there is no real way to close stdin cleanly, which is what will | ||||
|     // kill xclip. | ||||
|     // | ||||
|  | @ -114,15 +121,21 @@ fn execLinux(allocator: std.mem.Allocator, data: []const u8) !std.ChildProcess.E | |||
|     defer allocator.free(xclip_cmd); | ||||
|     std.log.debug("cmd: {s}", .{xclip_cmd}); | ||||
| 
 | ||||
|     return std.ChildProcess.exec(.{ | ||||
|         .allocator = allocator, | ||||
|         .argv = &[_][]const u8{ | ||||
|     var child = std.process.Child.init( | ||||
|         &[_][]const u8{ | ||||
|             "/usr/bin/env", | ||||
|             "sh", | ||||
|             "-c", | ||||
|             xclip_cmd, | ||||
|         }, | ||||
|     }); | ||||
|         allocator, | ||||
|     ); | ||||
|     const term = try std.process.Child.spawnAndWait(&child); | ||||
|     return .{ | ||||
|         .term = term, | ||||
|         .allocator = allocator, | ||||
|         .stderr = if (child.stderr) |e| try e.readToEndAlloc(allocator, 10 * 1024 * 1024) else try allocator.dupe(u8, ""), | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| fn execWindows(allocator: std.mem.Allocator, data: []const u8) !std.ChildProcess.ExecResult { | ||||
|  |  | |||
|  | @ -12,11 +12,9 @@ pub fn main() !u8 { | |||
|     var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||||
|     defer _ = gpa.deinit(); | ||||
|     const allocator = gpa.allocator(); | ||||
|     var args = std.process.args(); | ||||
|     var args = try std.process.argsWithAllocator(allocator); | ||||
|     defer args.deinit(); | ||||
|     while (args.next(allocator)) |arg_or_err| { | ||||
|         const arg = try arg_or_err; | ||||
|         defer allocator.free(arg); | ||||
|     while (args.next()) |arg| { | ||||
|         if (std.mem.eql(u8, arg, "-w")) { | ||||
|             watch = true; | ||||
|             break; | ||||
|  | @ -29,15 +27,15 @@ pub fn main() !u8 { | |||
| } | ||||
| 
 | ||||
| fn clipboardAction(allocator: std.mem.Allocator, watch: bool, clip: *Clipboard) !void { | ||||
|     var display: *c.Display = c.XOpenDisplay(null).?; | ||||
|     const display: *c.Display = c.XOpenDisplay(null).?; | ||||
|     defer _ = c.XCloseDisplay(display); | ||||
|     const default_screen = c.XDefaultScreen(display); | ||||
|     var color = c.XBlackPixel(display, default_screen); | ||||
|     var window = c.XCreateSimpleWindow(display, c.XDefaultRootWindow(display), 0, 0, 1, 1, 0, color, color); | ||||
|     const color = c.XBlackPixel(display, default_screen); | ||||
|     const window = c.XCreateSimpleWindow(display, c.XDefaultRootWindow(display), 0, 0, 1, 1, 0, color, color); | ||||
|     defer _ = c.XDestroyWindow(display, window); | ||||
|     // Watch will not return | ||||
|     if (watch) try watchClip(allocator, display, window, "CLIPBOARD", clip); | ||||
|     var result = (try printSelection(allocator, display, window, "CLIPBOARD", "UTF8_STRING", clip)) or | ||||
|     const result = (try printSelection(allocator, display, window, "CLIPBOARD", "UTF8_STRING", clip)) or | ||||
|         (try printSelection(allocator, display, window, "CLIPBOARD", "STRING", clip)); | ||||
|     if (!result) return error.ClipboardActionFailed; | ||||
| } | ||||
|  | @ -46,7 +44,7 @@ fn watchClip(allocator: std.mem.Allocator, display: *c.Display, window: c.Window | |||
|     var event_base: c_int = undefined; | ||||
|     var error_base: c_int = undefined; | ||||
|     var event: c.XEvent = undefined; | ||||
|     var bufid = c.XInternAtom(display, bufname, c.False); | ||||
|     const bufid = c.XInternAtom(display, bufname, c.False); | ||||
| 
 | ||||
|     _ = c.XFixesQueryExtension(display, &event_base, &error_base); | ||||
|     _ = c.XFixesSelectSelectionInput(display, c.XDefaultRootWindow(display), bufid, c.XFixesSetSelectionOwnerNotifyMask); | ||||
|  | @ -74,10 +72,10 @@ fn printSelection( | |||
|     var ressize: c_ulong = undefined; | ||||
|     var restail: c_ulong = undefined; | ||||
|     var resbits: c_int = undefined; | ||||
|     var bufid = c.XInternAtom(display, bufname, c.False); | ||||
|     const bufid = c.XInternAtom(display, bufname, c.False); | ||||
|     var fmtid = c.XInternAtom(display, fmtname, c.False); | ||||
|     var propid = c.XInternAtom(display, "XSEL_DATA", c.False); | ||||
|     var incrid = c.XInternAtom(display, "INCR", c.False); | ||||
|     const propid = c.XInternAtom(display, "XSEL_DATA", c.False); | ||||
|     const incrid = c.XInternAtom(display, "INCR", c.False); | ||||
|     var event: c.XEvent = undefined; | ||||
| 
 | ||||
|     _ = c.XSelectInput(display, window, c.PropertyChangeMask); | ||||
|  | @ -91,13 +89,13 @@ fn printSelection( | |||
|         _ = c.XGetWindowProperty(display, window, propid, 0, c.LONG_MAX / 4, c.True, c.AnyPropertyType, &fmtid, &resbits, &ressize, &restail, &result); | ||||
|         defer _ = c.XFree(result); | ||||
|         if (fmtid != incrid) | ||||
|             _ = async clip.clipboardChanged(std.mem.span(result)); // TODO: Ensure we don't start queueing these things up | ||||
|             _ = try clip.clipboardChanged(std.mem.span(result)); // TODO: Ensure we don't start queueing these things up | ||||
| 
 | ||||
|         if (fmtid == incrid) { | ||||
|             ressize = 1; | ||||
|             var arena_allocator = std.heap.ArenaAllocator.init(allocator); | ||||
|             defer arena_allocator.deinit(); | ||||
|             var local_allocator = arena_allocator.allocator(); | ||||
|             const local_allocator = arena_allocator.allocator(); | ||||
|             var buffer = std.ArrayList(u8).init(local_allocator); | ||||
|             defer buffer.deinit(); | ||||
|             while (ressize > 0) { | ||||
|  | @ -110,7 +108,7 @@ fn printSelection( | |||
|                 //defer _ = c.XFree(result); // Creates double free error, but not sure why | ||||
|                 try buffer.appendSlice(try std.fmt.allocPrint(local_allocator, "{s}", .{result})); | ||||
|             } | ||||
|             _ = async clip.clipboardChanged(buffer.items); | ||||
|             _ = try clip.clipboardChanged(buffer.items); | ||||
|         } | ||||
|         return true; | ||||
|     } else // request failed, e.g. owner can't convert to the target format | ||||
|  |  | |||
|  | @ -1191,7 +1191,7 @@ fn UpdateContents(hwnd: w.HWND) void { | |||
|     // Get a lock on the clipboard | ||||
|     if (OpenClipboard(hwnd) > 0) { | ||||
|         defer _ = CloseClipboard(); | ||||
|         var hglb = GetClipboardData(uFormat).?; | ||||
|         var hglb = GetClipboardData(uFormat) orelse return; | ||||
|         const hnd = @intCast(isize, @ptrToInt(hglb)); | ||||
|         var lpstr = GlobalLock(hnd).?; | ||||
|         defer _ = GlobalUnlock(hnd); | ||||
|  |  | |||
|  | @ -1 +0,0 @@ | |||
| const use_submodules = 1; | ||||
		Loading…
	
	Add table
		
		Reference in a new issue