pdfinfo 1.0.0 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|