pngcheck 0.2.8-x86_64-linux-musl
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 +7 -0
- data/.cross_rubies +8 -0
- data/.hound.yml +3 -0
- data/.rspec +1 -0
- data/.rubocop.yml +9 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +53 -0
- data/README.adoc +161 -0
- data/Rakefile +70 -0
- data/bin/console +15 -0
- data/bin/rspec +29 -0
- data/bin/setup +8 -0
- data/ext/Makefile +4 -0
- data/ext/extconf.rb +7 -0
- data/ext/layout.rb +5 -0
- data/ext/wrapper.c +106 -0
- data/lib/pngcheck/pngcheck.so +0 -0
- data/lib/pngcheck/recipe.rb +212 -0
- data/lib/pngcheck/version.rb +5 -0
- data/lib/pngcheck.rb +103 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 99b15c73419c0c64c81007716c57888bf46f685d4346b00d7d8fef14dc783124
|
4
|
+
data.tar.gz: be2d20075c6839497f8defbd8a35c5a36077e8c6950c03bfcfa72e7db31acd71
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 10be40e02108840529bcec19ea80063db0a7074a0791e60bc6337acb6844f5c21cbc8a2ad792669edd546d0fe62ae82a7e4fe8d7c949a7e6f386545ad842f57b
|
7
|
+
data.tar.gz: 3aca24064a31cc004dd186cd55aa464d459e6d520a4d4ccfbd7c56865f521d811fa15112e2f21a24542f777da8ad177113fae1803cbabeab2a75a41f99ac2c3a
|
data/.cross_rubies
ADDED
data/.hound.yml
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
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
data/ext/Makefile
ADDED
data/ext/extconf.rb
ADDED
data/ext/layout.rb
ADDED
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
|
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-musl
|
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.3.7
|
155
|
+
signing_key:
|
156
|
+
specification_version: 4
|
157
|
+
summary: Ruby interface to pngcheck.
|
158
|
+
test_files: []
|