pngcheck 0.2.8-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 023bb81d1b08ce9cf0e71e5c479dfc2ddd62ad5277a2b520043f7f652624f876
4
+ data.tar.gz: 6a193863d47d5f0c335fe1558a32404d37010fcad10d8d1853befb18f4a531ee
5
+ SHA512:
6
+ metadata.gz: 4c361c999a9b5296509f275bdd28870f591a28caadf1154eb363d117dcd7163ae4f2acd7d27bf3c6d1471263f3b755e64cabed105ff31be916607de8a3e60ddb
7
+ data.tar.gz: f5ac6e88842e83e1b9240dfb3f7e3ca89e4177e47ac7be8ca57e755c8de59c351c59a94d04cffc5e2fc730da88d52ff35e86144d618a003c50ddc7300290d4ba
data/.cross_rubies ADDED
@@ -0,0 +1,8 @@
1
+ x64-mingw32
2
+ x86_64-linux
3
+ x86_64-linux-musl
4
+ aarch64-linux
5
+ aarch64-linux-musl
6
+ x86_64-darwin
7
+ arm64-darwin
8
+ x64-mingw-ucrt
data/.hound.yml ADDED
@@ -0,0 +1,3 @@
1
+ ruby:
2
+ enabled: true
3
+ config_file: .rubocop.yml
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,9 @@
1
+ inherit_from:
2
+ - 'https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml'
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.7
6
+ SuggestExtensions: false
7
+
8
+ Gemspec/RequireMFA:
9
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in pngcheck.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,53 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2022, Ribose Inc.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+
27
+
28
+ This module includes original pngcheck software [http://www.libpng.org/pub/png/apps/pngcheck.html]
29
+ that is distributed under the follwoing license:
30
+
31
+ Copyright 1995-2020 by Alexander Lehmann <lehmann@usa.net>,
32
+ Andreas Dilger <adilger@enel.ucalgary.ca>,
33
+ Glenn Randers-Pehrson <randeg@alum.rpi.edu>,
34
+ Greg Roelofs <newt@pobox.com>,
35
+ John Bowler <jbowler@acm.org>,
36
+ Tom Lane <tgl@sss.pgh.pa.us>
37
+
38
+ Permission to use, copy, modify, and distribute this software and its
39
+ documentation for any purpose and without fee is hereby granted, provided
40
+ that the above copyright notice appear in all copies and that both that
41
+ copyright notice and this permission notice appear in supporting
42
+ documentation. This software is provided "as is" without express or
43
+ implied warranty.
44
+
45
+
46
+ [This license applies to pngcheck.c and its associated makefiles and
47
+ documentation in the main directory. The files in the "gpl" subdirectory--
48
+ specifically, pngsplit.c and png-fix-IDAT-windowsize.c--are licensed under the
49
+ GNU General Public License. The files in "amiga" subdirectory are Copyright
50
+ 2003 Simon Goodwin and were contributed without an explicit license statement,
51
+ but insofar as the "gpl" subdirectory didn't exist at the time, it's safe to
52
+ assume their intended license was similar to pngcheck's, just with Simon's
53
+ copyright replacing the one above.]
data/README.adoc ADDED
@@ -0,0 +1,161 @@
1
+ image:https://github.com/metanorma/pngcheck-ruby/actions/workflows/test-and-release.yml/badge.svg["test-and-release", link="https://github.com/metanorma/pngcheck-ruby/actions/workflows/test-and-release.yml"]
2
+
3
+ == PngCheck: PNG, JNG and MNG integrity checks
4
+
5
+ The `pngcheck` gem provides the `PngCheck` Ruby library, used to
6
+
7
+ * verify the integrity of PNG, JNG and MNG files, through
8
+
9
+ ** checking the internal 32-bit CRCs ("checksums");
10
+ ** decompressing the image data;
11
+
12
+ * dump *almost* all of the chunk-level information in the image in
13
+ human-readable form, including:
14
+
15
+ ** print the basic statistics about an image (dimensions, bit depth, etc.);
16
+ ** list the color and transparency info in its palette (assuming it has one); or
17
+ ** to extract the embedded text annotations.
18
+
19
+ The `PngCheck` Ruby library is a wrapper around the original
20
+ http://www.libpng.org/pub/png/apps/pngcheck.html[`pngcheck`] tool
21
+ from the http://www.libpng.org/pub/png/libpng.html[`libpng`] project.
22
+
23
+ NOTE: `PngCheck` incorporates
24
+ http://www.libpng.org/pub/png/apps/pngcheck.html[`pngcheck`] version 3.0.3, as
25
+ provided on the official website:
26
+ http://www.libpng.org/pub/png/apps/pngcheck.html
27
+
28
+ NOTE: The `PngCheck` Ruby library does not distribute nor modify the `pngcheck`
29
+ GPL executables `pngsplit` and `png-fix-IDAT-windowsize`, and hence is not bound
30
+ under the GPL license.
31
+
32
+ === Installation
33
+
34
+ Add this line to your application's Gemfile:
35
+
36
+ [source,ruby]
37
+ ----
38
+ gem 'pngcheck'
39
+ ----
40
+
41
+ And then execute:
42
+
43
+ [source,sh]
44
+ ----
45
+ $ bundle install
46
+ ----
47
+
48
+ Or install it yourself as:
49
+ [source,sh]
50
+ ----
51
+ $ gem install pngcheck
52
+ ----
53
+
54
+ === Usage
55
+
56
+ ==== PngCheck status codes
57
+
58
+ [source,ruby]
59
+ ----
60
+ PngCheck::STATUS_OK = 0
61
+ PngCheck::STATUS_WARNING = 1 # an error in some circumstances but not in all
62
+ PngCheck::STATUS_MINOR_ERROR = 3 # minor spec errors (e.g., out-of-range values)
63
+ PngCheck::STATUS_MAJOR_ERROR = 4 # file corruption, invalid chunk length/layout, etc.
64
+ PngCheck::STATUS_CRITICAL_ERROR = 5 # unexpected EOF or other file(system) error
65
+ ----
66
+
67
+ ==== File processing
68
+
69
+ [source,ruby]
70
+ ----
71
+ status, info = PngCheck.analyze_file("spec/examples/correct.png")
72
+ ----
73
+
74
+ Where:
75
+
76
+ * `status` is file status code
77
+ * `info` is either file content information for correct files, or error message for corrupt files
78
+
79
+ [source,ruby]
80
+ ----
81
+ valid = PngCheck.check_file("spec/examples/correct.png")
82
+ ----
83
+
84
+ Where:
85
+
86
+ * `valid` is `true` if the file is correct
87
+ * otherwise an exception is raised. Possible exception types are `PngCheck::EmptyPngError`, `PngCheck::CorruptPngError`
88
+
89
+
90
+ ==== Memory buffer processing
91
+
92
+ [source,ruby]
93
+ ----
94
+ data = File.binread("spec/examples/correct.png")
95
+ status, info = PngCheck.analyze_buffer(data)
96
+ ----
97
+
98
+ Where:
99
+
100
+ * `status` is the PngCheck status code
101
+ * `info` is either file content information for correct files, or the error
102
+ message for corrupt files
103
+
104
+
105
+ [source,ruby]
106
+ ----
107
+ data = File.binread("spec/examples/correct.png")
108
+ valid = PngCheck.check_buffer(data)
109
+ ----
110
+
111
+ Where:
112
+
113
+ * `valid` is `true` if the buffer is correct image
114
+ * otherwise an exception is raised. Possible exception types are `PngCheck::EmptyPngError`, `PngCheck::CorruptPngError`
115
+
116
+
117
+ ==== Pre-validation with libpng-ruby
118
+
119
+ `libpng-ruby` is the Ruby wrapper library around `libpng`, commonly used to
120
+ process PNG files in Ruby.
121
+
122
+ To prevent crashing libpng-ruby with corrupt PNG files, you may wish to
123
+ pre-verify integrity of the PNG file before loading it with `libpng-ruby`.
124
+ Any errors in the PNG will cause a `PngCheck::CorruptPngError` to be raised,
125
+ hence skipping the `libpng` code.
126
+
127
+ The mechanism to do so is demonstrated below:
128
+
129
+ [source,ruby]
130
+ ----
131
+ require 'png'
132
+ encoded = File.binread("spec/examples/correct.png")
133
+
134
+ begin
135
+ PngCheck.check_buffer(encoded)
136
+ dec = PNG::Decoder.new
137
+ raw = dec << encoded
138
+ rescue PngCheck::CorruptPngError => e
139
+ puts "Exception #{e.message}"
140
+ end
141
+ ----
142
+
143
+
144
+ === Contributing
145
+
146
+ Bug reports and pull requests are welcome on GitHub at https://github.com/metanorma/pngcheck-ruby.
147
+
148
+ === License
149
+
150
+ Open-sourced under the link:LICENSE.txt[Ribose BSD-2 clause license].
151
+ Copyright Ribose for all code excluding the `pngcheck` library.
152
+
153
+ The `pngcheck` library is provided under its original license as unmodified
154
+ code, its license is located
155
+ http://www.libpng.org/pub/png/src/pngcheck-3.0.3.LICENSE[here].
156
+
157
+ NOTE: The core code of the `pngcheck` library is licensed under the
158
+ http://www.libpng.org/pub/png/src/libpng-LICENSE.txt[libpng 3-clause BSD license],
159
+ while two additional executables `pngsplit` and `png-fix-IDAT-windowsize` are
160
+ offered under GPL. Since the `PngCheck` Ruby library does not offer the GPL
161
+ executables, the gem itself is offered under a BSD license instead of GPL.
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
6
+ require_relative "ext/layout"
7
+
8
+ RSpec::Core::RakeTask.new(:spec)
9
+ RuboCop::RakeTask.new
10
+
11
+ task default: %i[spec rubocop]
12
+
13
+ task :compile do
14
+ require_relative "ext/extconf"
15
+ end
16
+
17
+ task spec: :compile
18
+
19
+ desc "Build install-compilation gem"
20
+ task "gem:native:any" do
21
+ sh "rake platform:any gem"
22
+ end
23
+
24
+ desc "Download pngcheck source"
25
+ task :pngcheck do
26
+ test_cmd = "test -f #{PNGCHECK_LOCAL}"
27
+ wget_cmd = "wget -nc -nv -O #{PNGCHECK_LOCAL} #{PNGCHECK_URI}"
28
+ sh "#{test_cmd} || #{wget_cmd}"
29
+ end
30
+ task compile: :pngcheck
31
+
32
+ require "rubygems/package_task"
33
+
34
+ desc "Define the gem task to build on any platform (compile on install)"
35
+ task "platform:any" do
36
+ spec = Gem::Specification::load("pngcheck.gemspec").dup
37
+ spec.files << PNGCHECK_LOCAL
38
+ task = Gem::PackageTask.new(spec)
39
+ task.define
40
+ end
41
+ task "gem:native:any": :pngcheck
42
+
43
+ File.readlines(".cross_rubies", chomp: true).each do |platform|
44
+ desc "Build pre-compiled gem for the #{platform} platform"
45
+ task "gem:native:#{platform}" do
46
+ sh "rake compile platform:#{platform} gem target_platform=#{platform}"
47
+ end
48
+
49
+ desc "Define the gem task to build on the #{platform} platform (binary gem)"
50
+ task "platform:#{platform}" do
51
+ spec = Gem::Specification::load("pngcheck.gemspec").dup
52
+ spec.platform = Gem::Platform.new(platform)
53
+ spec.files += Dir.glob("lib/pngcheck/*.{dll,so,dylib}")
54
+ spec.extensions = []
55
+ spec.dependencies.reject! { |d| d.name == "mini_portile2" }
56
+
57
+ task = Gem::PackageTask.new(spec)
58
+ task.define
59
+ end
60
+ end
61
+
62
+ require "rake/clean"
63
+
64
+ CLOBBER.include("pkg")
65
+ CLEAN.include("ports",
66
+ "tmp",
67
+ PNGCHECK_LOCAL,
68
+ "lib/pngcheck/*.dll",
69
+ "lib/pngcheck/*.dylib",
70
+ "lib/pngcheck/*.so")
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "pngcheck"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/rspec ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("bundle", __dir__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/ext/Makefile ADDED
@@ -0,0 +1,4 @@
1
+ # dummy Makefile, it is required to build an extension
2
+ all:
3
+ clean:
4
+ install:
data/ext/extconf.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "../lib"))
4
+ require "pngcheck/recipe"
5
+
6
+ recipe = PngCheck::Recipe.new
7
+ recipe.cook
data/ext/layout.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ PNGCHECK_ARCH = "pngcheck-3.0.3.tar.gz"
4
+ PNGCHECK_URI = "http://www.libpng.org/pub/png/src/#{PNGCHECK_ARCH}"
5
+ PNGCHECK_LOCAL = "ext/#{PNGCHECK_ARCH}"
data/ext/wrapper.c ADDED
@@ -0,0 +1,106 @@
1
+ #ifdef _WIN32
2
+ # include <windows.h>
3
+ # include <share.h>
4
+ # include <io.h>
5
+ # include <stdio.h>
6
+ #endif
7
+
8
+ #include <sys/stat.h>
9
+ #include <fcntl.h>
10
+ #include <errno.h>
11
+
12
+ #ifdef _WIN32
13
+ /* https://github.com/Arryboom/fmemopen_windows */
14
+
15
+ FILE *fmemopen(void *buf, size_t len, char *type) {
16
+ int fd;
17
+ FILE *fp;
18
+ char tp[MAX_PATH - 13];
19
+ char fn[MAX_PATH + 1];
20
+ int * pfd = &fd;
21
+ int retner = -1;
22
+ char tfname[] = "MemTF_";
23
+ if (!GetTempPathA(sizeof(tp), tp)) return NULL;
24
+ if (!GetTempFileNameA(tp, tfname, 0, fn)) return NULL;
25
+ retner = _sopen_s(pfd, fn, _O_CREAT | _O_SHORT_LIVED | _O_TEMPORARY | _O_RDWR | _O_BINARY | _O_NOINHERIT, _SH_DENYRW, _S_IREAD | _S_IWRITE);
26
+ if (retner != 0) return NULL;
27
+ if (fd == -1) return NULL;
28
+ fp = _fdopen(fd, "wb+");
29
+ if (!fp) {
30
+ _close(fd);
31
+ return NULL;
32
+ }
33
+ fwrite(buf, len, 1, fp);
34
+ rewind(fp);
35
+ return fp;
36
+ }
37
+ #endif
38
+
39
+ #include "pngcheck.c"
40
+
41
+ #define EXTRA_MESSAGE_SIZE 1024
42
+
43
+ void failed_to_open(char *extra_msg, char *fname) {
44
+ snprintf(extra_msg, EXTRA_MESSAGE_SIZE, "Failed to open %s: %s\n", fname, strerror(errno));
45
+ extra_msg[EXTRA_MESSAGE_SIZE-1] = 0;
46
+ }
47
+
48
+ void failed_to_dup(char *extra_msg, char *fmt) {
49
+ snprintf(extra_msg, EXTRA_MESSAGE_SIZE, fmt, strerror(errno));
50
+ extra_msg[EXTRA_MESSAGE_SIZE-1] = 0;
51
+ }
52
+
53
+ int pngcheck_inner(FILE* fp, char *fname, char *cname, char *extra_msg) {
54
+ int rc = kCriticalError;
55
+ int fd = open(cname, O_WRONLY);
56
+ if (fd == -1) {
57
+ failed_to_open(extra_msg, cname);
58
+ }
59
+ else {
60
+ int stdout_copy = dup(STDOUT_FILENO);
61
+ if (stdout_copy == -1) {
62
+ failed_to_dup(extra_msg, "Failed to save stdout: %s\n");
63
+ }
64
+ else {
65
+ if (dup2(fd, STDOUT_FILENO) == -1) {
66
+ failed_to_dup(extra_msg, "Failed to reassign stdout: %s\n");
67
+ }
68
+ else {
69
+ rc = pngcheck(fp, fname, 0, NULL);
70
+ fflush(stdout);
71
+ }
72
+ dup2(stdout_copy, STDOUT_FILENO);
73
+ }
74
+ close(fd);
75
+ }
76
+ return rc;
77
+ }
78
+
79
+ int pngcheck_file(char *fname, char *cname, char *extra_msg) {
80
+ int rc = kCriticalError;
81
+ extra_msg[0] = 0;
82
+ FILE* fp = fopen(fname, "rb");
83
+ if (fp == NULL) {
84
+ failed_to_open(extra_msg, fname);
85
+ }
86
+ else {
87
+ rc = pngcheck_inner(fp, fname, cname, extra_msg);
88
+ fclose(fp);
89
+ }
90
+ return rc;
91
+ }
92
+
93
+ int pngcheck_buffer(char *data, int size, char *cname, char *extra_msg) {
94
+ int rc = kCriticalError;
95
+ extra_msg[0] = 0;
96
+ char* fname = "[memory buffer]";
97
+ FILE* fp = fmemopen(data, size, "rb");
98
+ if (fp == NULL) {
99
+ failed_to_open(extra_msg, fname);
100
+ }
101
+ else {
102
+ rc = pngcheck_inner(fp, fname, cname, extra_msg);
103
+ fclose(fp);
104
+ }
105
+ return rc;
106
+ }
Binary file
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rbconfig"
4
+ require "mini_portile2"
5
+ require "pathname"
6
+ require "tmpdir"
7
+ require "shellwords"
8
+ require "open3"
9
+ require_relative "version"
10
+
11
+ ROOT = Pathname.new(File.expand_path("../..", __dir__))
12
+ require "#{ROOT}/ext/layout.rb"
13
+
14
+ module PngCheck
15
+ class Recipe < MiniPortile
16
+ COMMON_FLAGS = "-shared -fPIC -Wall -O -DUSE_ZLIB"
17
+
18
+ def files_to_load_all
19
+ @files << {
20
+ url: "file:#{ROOT}/#{PNGCHECK_LOCAL}", # "http://www.libpng.org/pub/png/src/pngcheck-3.0.3.tar.gz"
21
+ sha256: "c36a4491634af751f7798ea421321642f9590faa032eccb0dd5fb4533609dee6", # rubocop:disable Layout/LineLength
22
+ }
23
+ end
24
+
25
+ def files_to_load_cross
26
+ if target_platform.eql?("aarch64-linux") &&
27
+ !host_platform.eql?("aarch64-linux")
28
+ @files << {
29
+ url: "http://ports.ubuntu.com/pool/main/z/zlib/zlib1g-dev_1.2.11.dfsg-2ubuntu1.3_arm64.deb", # rubocop:disable Layout/LineLength
30
+ sha256: "0ebadc1ff2a70f0958d4e8e21ffa97d9fa4da23555eaae87782e963044a26fcf", # rubocop:disable Layout/LineLength
31
+ }
32
+ end
33
+ end
34
+
35
+ def initialize
36
+ super("pngcheck", "3.0.3")
37
+ files_to_load_all
38
+ files_to_load_cross
39
+ @target = ROOT.join(@target).to_s
40
+ @printed = {}
41
+ end
42
+
43
+ def lib_filename
44
+ @lib_filename ||=
45
+ if MiniPortile.windows?
46
+ "pngcheck.dll"
47
+ else
48
+ "pngcheck.so"
49
+ end
50
+ end
51
+
52
+ def lib_workpath
53
+ @lib_workpath ||= File.join(work_path, lib_filename)
54
+ end
55
+
56
+ def make_cmd
57
+ "#{cc} #{cflags} #{COMMON_FLAGS} -o #{lib_filename} wrapper.c -lz"
58
+ end
59
+
60
+ def cook_if_not
61
+ cook unless File.exist?(checkpoint)
62
+ end
63
+
64
+ def cook
65
+ super
66
+ FileUtils.touch(checkpoint)
67
+ end
68
+
69
+ def download_file_file(uri, full_path)
70
+ if MiniPortile.windows?
71
+ FileUtils.mkdir_p File.dirname(full_path)
72
+ FileUtils.cp uri.to_s.delete_prefix("file:"), full_path
73
+ else
74
+ super
75
+ end
76
+ end
77
+
78
+ def tmp_path
79
+ "tmp/#{@host}/ports"
80
+ end
81
+
82
+ def checkpoint
83
+ File.join(@target, "#{name}-#{version}-#{host}.installed")
84
+ end
85
+
86
+ def configure
87
+ FileUtils.cp(ROOT.join("ext", "wrapper.c"), work_path, verbose: false)
88
+ if target_platform.eql?("aarch64-linux") &&
89
+ !host_platform.eql?("aarch64-linux")
90
+ extract_file("#{work_path}/../data.tar.xz", work_path.to_s)
91
+ end
92
+ end
93
+
94
+ def verify_lib
95
+ begin
96
+ out, = Open3.capture2("file #{lib_workpath}")
97
+ rescue StandardError
98
+ message("Failed to call file, skipped library verification ...\n")
99
+ return
100
+ end
101
+
102
+ unless out.include?(target_format)
103
+ raise "Invalid file format '#{out.strip}', '#{@target_format}' expected"
104
+ end
105
+
106
+ message("Verifying #{lib_workpath} ... OK\n")
107
+ end
108
+
109
+ def install
110
+ libs = Dir.glob(File.join(work_path, "*"))
111
+ .grep(%r{/(?:lib)?[a-zA-Z0-9\-]+\.(?:so|dylib|dll)$})
112
+
113
+ FileUtils.cp_r(libs, ROOT.join("lib", "pngcheck"), verbose: false)
114
+ verify_lib
115
+ end
116
+
117
+ def execute(action, command, command_opts = {})
118
+ super(action, command, command_opts.merge(debug: false))
119
+ end
120
+
121
+ def message(text)
122
+ return super unless text.start_with?("\rDownloading")
123
+
124
+ match = text.match(/(\rDownloading .*)\(\s*\d+%\)/)
125
+ pattern = match ? match[1] : text
126
+ return if @printed[pattern]
127
+
128
+ @printed[pattern] = true
129
+ super
130
+ end
131
+
132
+ # rubocop:disable Metrics/MethodLength
133
+ # rubocop:disable Metrics/CyclomaticComplexity
134
+ def host_platform
135
+ @host_platform ||=
136
+ case @host
137
+ when /\Ax86_64-w64-mingw32/
138
+ "x64-mingw32"
139
+ when /\Ax86_64-w64-mingw-ucrt/
140
+ "x64-mingw-ucrt"
141
+ when /\A(arm64|aarch64).*linux/
142
+ "aarch64-linux"
143
+ when /\Ax86_64.*(darwin|macos|osx)/
144
+ "x86_64-darwin"
145
+ when /\A(arm64|aarch64).*(darwin|macos|osx)/
146
+ "arm64-darwin"
147
+ else
148
+ @host
149
+ end
150
+ end
151
+
152
+ def target_platform
153
+ @target_platform ||=
154
+ case ENV.fetch("target_platform", nil)
155
+ when /\A(arm64|aarch64).*(darwin|macos|osx)/
156
+ "arm64-darwin"
157
+ when /\Ax86_64.*(darwin|macos|osx)/
158
+ "x86_64-darwin"
159
+ when /\A(arm64|aarch64).*linux/
160
+ "aarch64-linux"
161
+ else
162
+ ENV.fetch("target_platform", host_platform)
163
+ end
164
+ end
165
+
166
+ def target_format
167
+ @target_format ||=
168
+ case target_platform
169
+ when "arm64-darwin"
170
+ "Mach-O 64-bit dynamically linked shared library arm64"
171
+ when "x86_64-darwin"
172
+ "Mach-O 64-bit dynamically linked shared library x86_64"
173
+ when "aarch64-linux"
174
+ "ELF 64-bit LSB shared object, ARM aarch64"
175
+ when /\Ax86_64.*linux.*/
176
+ "ELF 64-bit LSB shared object, x86-64"
177
+ when /\Ax64-mingw(32|-ucrt)/
178
+ "PE32+ executable (DLL) (console) x86-64, for MS Windows"
179
+ else
180
+ "skip"
181
+ end
182
+ end
183
+
184
+ def cc
185
+ @cc ||=
186
+ if target_platform.eql?(host_platform)
187
+ "gcc"
188
+ else
189
+ case target_platform
190
+ when "aarch64-linux"
191
+ "aarch64-linux-gnu-gcc"
192
+ when "arm64-darwin"
193
+ "gcc -target arm64-apple-macos11"
194
+ else
195
+ "gcc"
196
+ end
197
+ end
198
+ end
199
+
200
+ def cflags
201
+ @cflags ||=
202
+ if target_platform.eql?("aarch64-linux") &&
203
+ !host_platform.eql?("aarch64-linux")
204
+ "-I./usr/include -L./usr/lib/#{target_platform}-gnu"
205
+ else
206
+ ""
207
+ end
208
+ end
209
+ # rubocop:enable Metrics/CyclomaticComplexity
210
+ # rubocop:enable Metrics/MethodLength
211
+ end
212
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PngCheck
4
+ VERSION = "0.2.8"
5
+ end
data/lib/pngcheck.rb ADDED
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi"
4
+ require "tempfile"
5
+ require_relative "pngcheck/version"
6
+
7
+ module PngCheck
8
+ EMPTY_IMAGE = "Image is empty"
9
+
10
+ class CorruptPngError < StandardError; end
11
+
12
+ class EmptyPngError < StandardError
13
+ def initialize(msg = EMPTY_IMAGE)
14
+ super
15
+ end
16
+ end
17
+
18
+ STATUS_OK = 0
19
+ STATUS_WARNING = 1 # an error in some circumstances but not in all
20
+ STATUS_MINOR_ERROR = 3 # minor spec errors (e.g., out-of-range values)
21
+ STATUS_MAJOR_ERROR = 4 # file corruption, invalid chunk length/layout, etc.
22
+ STATUS_CRITICAL_ERROR = 5 # unexpected EOF or other file(system) error
23
+
24
+ EXTRA_MESSAGE_SIZE = 1024
25
+
26
+ extend FFI::Library
27
+
28
+ lib_filename = FFI::Platform.windows? ? "pngcheck.dll" : "pngcheck.so"
29
+ ffi_lib File.expand_path("pngcheck/#{lib_filename}", __dir__)
30
+ .gsub("/", File::ALT_SEPARATOR || File::SEPARATOR)
31
+
32
+ # int pngcheck_file(char *fname, char *cname, char *extra_message)
33
+ typedef :string, :file_path
34
+ typedef :pointer, :extra_message
35
+ typedef :int, :status
36
+ attach_function :pngcheck_file, %i[file_path file_path extra_message],
37
+ :status
38
+ # int pngcheck_string(char *data, int size, char *cname, char *extra_message)
39
+ typedef :pointer, :data
40
+ typedef :int, :size
41
+ attach_function :pngcheck_buffer, %i[data size file_path extra_message],
42
+ :status
43
+
44
+ @@semaphore = Mutex.new
45
+
46
+ class << self
47
+ def analyze_file(path)
48
+ return [STATUS_CRITICAL_ERROR, EMPTY_IMAGE] if File.zero? path
49
+
50
+ do_analyze_file(path)
51
+ end
52
+
53
+ def check_file(path)
54
+ status, info = analyze_file(path)
55
+ raise EmptyPngError.new if info.eql? EMPTY_IMAGE
56
+ raise CorruptPngError.new info unless status == STATUS_OK
57
+
58
+ true
59
+ end
60
+
61
+ def analyze_buffer(data)
62
+ return [STATUS_CRITICAL_ERROR, EMPTY_IMAGE] if data.empty?
63
+
64
+ do_analyze_buffer(data)
65
+ end
66
+
67
+ def check_buffer(data)
68
+ status, info = analyze_buffer(data)
69
+ raise EmptyPngError.new if info.eql? EMPTY_IMAGE
70
+ raise CorruptPngError.new info unless status == STATUS_OK
71
+
72
+ true
73
+ end
74
+
75
+ private
76
+
77
+ def do_analyze_file(path)
78
+ Tempfile.open("captured-stream-") do |captured_stream|
79
+ extra_msg = FFI::Buffer.alloc_out(EXTRA_MESSAGE_SIZE, 1, false)
80
+ @@semaphore.lock
81
+ status = pngcheck_file(path, captured_stream.path, extra_msg)
82
+ @@semaphore.unlock
83
+ # we assume that pngcheck_file returns either captured_stream
84
+ # or extra message but not both
85
+
86
+ [status, captured_stream.read + extra_msg.get_string(0)]
87
+ end
88
+ end
89
+
90
+ def do_analyze_buffer(data)
91
+ Tempfile.open("captured-stream-") do |captured_stream|
92
+ extra_msg = FFI::Buffer.alloc_out(EXTRA_MESSAGE_SIZE, 1, false)
93
+ mem_buf = FFI::MemoryPointer.new(:char, data.bytesize)
94
+ mem_buf.put_bytes(0, data)
95
+ @@semaphore.lock
96
+ status = pngcheck_buffer(mem_buf, data.bytesize, captured_stream.path,
97
+ extra_msg)
98
+ @@semaphore.unlock
99
+ [status, captured_stream.read + extra_msg.get_string(0)]
100
+ end
101
+ end
102
+ end
103
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pngcheck
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.8
5
+ platform: x86_64-linux
6
+ authors:
7
+ - Ribose Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.3.22
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.3.22
33
+ - !ruby/object:Gem::Dependency
34
+ name: ffi
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '13.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '13.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: libpng-ruby
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.6'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.6'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rubocop
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1.4'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.4'
103
+ description:
104
+ email:
105
+ - open.source@ribose.com
106
+ executables:
107
+ - console
108
+ - rspec
109
+ - setup
110
+ extensions: []
111
+ extra_rdoc_files: []
112
+ files:
113
+ - ".cross_rubies"
114
+ - ".hound.yml"
115
+ - ".rspec"
116
+ - ".rubocop.yml"
117
+ - Gemfile
118
+ - LICENSE.txt
119
+ - README.adoc
120
+ - Rakefile
121
+ - bin/console
122
+ - bin/rspec
123
+ - bin/setup
124
+ - ext/Makefile
125
+ - ext/extconf.rb
126
+ - ext/layout.rb
127
+ - ext/wrapper.c
128
+ - lib/pngcheck.rb
129
+ - lib/pngcheck/pngcheck.so
130
+ - lib/pngcheck/recipe.rb
131
+ - lib/pngcheck/version.rb
132
+ homepage: https://github.com/metanorma/pngcheck-ruby
133
+ licenses:
134
+ - BSD-2-Clause
135
+ metadata:
136
+ homepage_uri: https://github.com/metanorma/pngcheck-ruby
137
+ source_code_uri: https://github.com/metanorma/pngcheck-ruby
138
+ changelog_uri: https://github.com/metanorma/pngcheck-ruby
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: 2.7.0
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubygems_version: 3.1.6
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: Ruby interface to pngcheck.
158
+ test_files: []