pdfinfo 1.0.0 → 1.0.3
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 +4 -4
- data/README.md +7 -4
- data/lib/pdfinfo.rb +22 -18
- data/lib/pdfinfo/version.rb +1 -1
- data/spec/pdfinfo_spec.rb +38 -11
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8de9b34e6b07e216baf33dd87f483e41edf284c1
|
4
|
+
data.tar.gz: 20f286868afbde83b138c3a780d626f7b15e2c8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1649532afbe24edf37248f94afe1c57724f0ac4f4a1aa187cff31bb4ce73b7d2ffea93f1360e4c1112fca35b328d445f1e6ac4017c6310bc3b1acb92d22cf08d
|
7
|
+
data.tar.gz: 3d667764447ec721ac6444b83fd4632340a0201f72b5f2dde5441520f4e77753cd5fcc2327f6ab6f6ff81699eb453cec2c083a3e07189ba4fcb99ac0104e2516
|
data/README.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# Pdfinfo
|
2
2
|
|
3
|
-
Simple ruby wrapper around the pdfinfo command
|
4
|
-
|
3
|
+
Simple ruby wrapper around the pdfinfo command.
|
4
|
+
This gem was written and tested around xpdf version 3.04.
|
5
|
+
|
5
6
|
|
6
7
|
## Depdendecies
|
7
8
|
|
8
|
-
usage of this gem assumes that you have xpdf installed. The fastest way to install xpdf:
|
9
|
+
usage of this gem assumes that you have xpdf installed (which gives us access to the pdfinfo command). The fastest way to install xpdf:
|
9
10
|
|
10
11
|
$ brew install xpdf
|
11
12
|
|
@@ -13,7 +14,7 @@ usage of this gem assumes that you have xpdf installed. The fastest way to inst
|
|
13
14
|
|
14
15
|
Add this line to your application's Gemfile:
|
15
16
|
|
16
|
-
gem 'pdfinfo'
|
17
|
+
gem 'pdfinfo', '~> 1.0.0'
|
17
18
|
|
18
19
|
And then execute:
|
19
20
|
|
@@ -27,6 +28,8 @@ Or install it yourself as:
|
|
27
28
|
|
28
29
|
|
29
30
|
```ruby
|
31
|
+
pdfinfo = Pdfinfo.new("path/to/file.pdf")
|
32
|
+
|
30
33
|
pdfinfo.title #=> "Title" # or nil
|
31
34
|
pdfinfo.subject #=> "Subject" # or nil
|
32
35
|
pdfinfo.keywords #=> ["Keyword1", "Keyword2"] # or nil
|
data/lib/pdfinfo.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'open3'
|
2
|
+
require 'shellwords'
|
2
3
|
|
3
4
|
class Pdfinfo
|
4
5
|
DIMENSIONS_REGEXP = /([\d\.]+) x ([\d\.]+)/
|
@@ -20,14 +21,13 @@ class Pdfinfo
|
|
20
21
|
|
21
22
|
def self.exec(file_path, opts = {})
|
22
23
|
flags = []
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
flags << ['-upw', opts[:user_password]]
|
27
|
-
end
|
24
|
+
flags.concat(['-enc', opts.fetch(:encoding, 'UTF-8')])
|
25
|
+
flags.concat(['-opw', opts[:owner_password]]) if opts[:owner_password]
|
26
|
+
flags.concat(['-upw', opts[:user_password]]) if opts[:user_password]
|
28
27
|
|
29
|
-
|
30
|
-
stdout.
|
28
|
+
command = Shellwords.join([pdfinfo_command, *flags, file_path])
|
29
|
+
stdout, status = Open3.capture2(command)
|
30
|
+
stdout.encode('UTF-8', invalid: :replace, replace: '')
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.pdfinfo_command
|
@@ -41,17 +41,20 @@ class Pdfinfo
|
|
41
41
|
def initialize(source_path, opts = {})
|
42
42
|
info_hash = parse_shell_response(Pdfinfo.exec(source_path, opts))
|
43
43
|
|
44
|
-
@title = info_hash['Title']
|
45
|
-
@subject = info_hash['Subject']
|
46
|
-
@
|
47
|
-
@
|
48
|
-
@
|
49
|
-
@producer = info_hash['Producer'].empty? ? nil : info_hash['Producer']
|
50
|
-
@creation_date = info_hash['CreationDate'].empty? ? nil : Time.parse(info_hash['CreationDate'])
|
44
|
+
@title = presence(info_hash['Title'])
|
45
|
+
@subject = presence(info_hash['Subject'])
|
46
|
+
@author = presence(info_hash['Author'])
|
47
|
+
@creator = presence(info_hash['Creator'])
|
48
|
+
@producer = presence(info_hash['Producer'])
|
51
49
|
@tagged = !!(info_hash['Tagged'] =~ /yes/)
|
52
|
-
@form = info_hash['Form']
|
53
|
-
@page_count = info_hash['Pages'].to_i
|
54
50
|
@encrypted = !!(info_hash['Encrypted'] =~ /yes/)
|
51
|
+
@page_count = info_hash['Pages'].to_i
|
52
|
+
@file_size = info_hash['File size'].to_i
|
53
|
+
@form = info_hash['Form']
|
54
|
+
@pdf_version = info_hash['PDF version']
|
55
|
+
|
56
|
+
@keywords = (info_hash['Keywords'] || "").split(/\s/)
|
57
|
+
@creation_date = presence(info_hash['CreationDate']) ? Time.parse(info_hash['CreationDate']) : nil
|
55
58
|
|
56
59
|
raw_usage_rights = Hash[info_hash['Encrypted'].scan(/(\w+):(\w+)/)]
|
57
60
|
booleanize_usage_right = lambda {|val| !(raw_usage_rights[val] == 'no') }
|
@@ -64,8 +67,6 @@ class Pdfinfo
|
|
64
67
|
end
|
65
68
|
|
66
69
|
@width, @height = extract_page_dimensions(info_hash['Page size'])
|
67
|
-
@file_size = info_hash['File size'].to_i
|
68
|
-
@pdf_version = info_hash['PDF version']
|
69
70
|
end
|
70
71
|
|
71
72
|
def tagged?
|
@@ -94,6 +95,9 @@ class Pdfinfo
|
|
94
95
|
end
|
95
96
|
|
96
97
|
private
|
98
|
+
def presence(val)
|
99
|
+
(val.nil? || val.empty?) ? nil : val
|
100
|
+
end
|
97
101
|
def parse_shell_response(response_str)
|
98
102
|
Hash[response_str.split(/\n/).map {|kv| kv.split(/:/, 2).map(&:strip) }]
|
99
103
|
end
|
data/lib/pdfinfo/version.rb
CHANGED
data/spec/pdfinfo_spec.rb
CHANGED
@@ -12,13 +12,15 @@ RSpec.describe Pdfinfo do
|
|
12
12
|
response.sub(/(?<=#{key}:)(.+)$/, new_value)
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
before(:each) do |ex|
|
16
|
+
unless ex.metadata[:skip_mock_response]
|
17
|
+
allow(Open3).to receive(:capture2).and_return([mock_response, nil])
|
18
|
+
end
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
specify "mock responses match", :skip_mock_response do
|
22
|
+
expect(`pdfinfo -upw foo #{fixture_path('pdfs/encrypted.pdf')}`.chomp).to eq(encrypted_response)
|
23
|
+
expect(`pdfinfo #{fixture_path('pdfs/test.pdf')}`.chomp).to eq(unencrypted_response)
|
22
24
|
end
|
23
25
|
|
24
26
|
describe '.pdfinfo_command' do
|
@@ -36,23 +38,30 @@ RSpec.describe Pdfinfo do
|
|
36
38
|
describe '.exec' do
|
37
39
|
context 'with no options given' do
|
38
40
|
it 'runs the pdfinfo command without flags' do
|
39
|
-
expect(Open3).to receive(:
|
41
|
+
expect(Open3).to receive(:capture2).with("pdfinfo -enc UTF-8 path/to/file.pdf")
|
40
42
|
Pdfinfo.new("path/to/file.pdf")
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
44
46
|
context "passing in :user_password" do
|
45
47
|
it 'runs the pdfinfo command passing the user password flag' do
|
46
|
-
expect(Open3).to receive(:
|
48
|
+
expect(Open3).to receive(:capture2).with("pdfinfo -enc UTF-8 -upw foo path/to/file.pdf")
|
47
49
|
Pdfinfo.new("path/to/file.pdf", user_password: 'foo')
|
48
50
|
end
|
49
51
|
end
|
50
52
|
context 'passing in :owner_password' do
|
51
53
|
it 'runs the pdfinfo command passing the user password flag' do
|
52
|
-
expect(Open3).to receive(:
|
54
|
+
expect(Open3).to receive(:capture2).with("pdfinfo -enc UTF-8 -opw bar path/to/file.pdf")
|
53
55
|
Pdfinfo.new("path/to/file.pdf", owner_password: 'bar')
|
54
56
|
end
|
55
57
|
end
|
58
|
+
|
59
|
+
context "when passed a path with spaces" do
|
60
|
+
it 'should escape the file path' do
|
61
|
+
expect(Open3).to receive(:capture2).with("pdfinfo -enc UTF-8 path/to/file\\ with\\ spaces.pdf")
|
62
|
+
Pdfinfo.new("path/to/file with spaces.pdf")
|
63
|
+
end
|
64
|
+
end
|
56
65
|
end
|
57
66
|
|
58
67
|
describe '#title' do
|
@@ -75,12 +84,18 @@ RSpec.describe Pdfinfo do
|
|
75
84
|
expect(pdfinfo.subject).to eq('Pdfinfo Subject')
|
76
85
|
end
|
77
86
|
end
|
78
|
-
context 'when
|
87
|
+
context 'when subject value is not present' do
|
79
88
|
let(:mock_response) { modified_response(unencrypted_response, 'Subject', '') }
|
80
89
|
it 'returns nil' do
|
81
90
|
expect(pdfinfo.subject).to be_nil
|
82
91
|
end
|
83
92
|
end
|
93
|
+
context 'when subject key is not present' do
|
94
|
+
let(:mock_response) { unencrypted_response.sub(/^Subject.*\n/, '') }
|
95
|
+
it 'returns nil' do
|
96
|
+
expect(pdfinfo.subject).to be_nil
|
97
|
+
end
|
98
|
+
end
|
84
99
|
end
|
85
100
|
|
86
101
|
describe '#keywords' do
|
@@ -89,12 +104,18 @@ RSpec.describe Pdfinfo do
|
|
89
104
|
expect(pdfinfo.keywords).to eq(['Keyword1', 'Keyword2'])
|
90
105
|
end
|
91
106
|
end
|
92
|
-
context 'when keywords is not present' do
|
107
|
+
context 'when keywords value is not present' do
|
93
108
|
let(:mock_response) { modified_response(unencrypted_response, 'Keywords', '') }
|
94
109
|
it 'returns an empty array' do
|
95
110
|
expect(pdfinfo.keywords).to eq([])
|
96
111
|
end
|
97
112
|
end
|
113
|
+
context 'when keywords key is not present' do
|
114
|
+
let(:mock_response) { unencrypted_response.sub(/^Keywords.*\n/, '') }
|
115
|
+
it 'returns an empty array' do
|
116
|
+
expect(pdfinfo.keywords).to eq([])
|
117
|
+
end
|
118
|
+
end
|
98
119
|
end
|
99
120
|
|
100
121
|
describe '#author' do
|
@@ -120,12 +141,18 @@ RSpec.describe Pdfinfo do
|
|
120
141
|
expect(pdfinfo.creation_date).to eq(Time.parse("2014-10-26 18:23:25 -0700"))
|
121
142
|
end
|
122
143
|
end
|
123
|
-
context 'when creation date is not present' do
|
144
|
+
context 'when creation date value is not present' do
|
124
145
|
let(:mock_response) { modified_response(unencrypted_response, 'CreationDate', '') }
|
125
146
|
it 'returns nil' do
|
126
147
|
expect(pdfinfo.creation_date).to be_nil
|
127
148
|
end
|
128
149
|
end
|
150
|
+
context 'when creation date key is not present' do
|
151
|
+
let(:mock_response) { unencrypted_response.sub(/^CreationDate.*\n/, '') }
|
152
|
+
it 'returns nil' do
|
153
|
+
expect(pdfinfo.creation_date).to be_nil
|
154
|
+
end
|
155
|
+
end
|
129
156
|
end
|
130
157
|
|
131
158
|
describe '#creator' do
|