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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c353a570a0806dfe590c8f5f2f13397a065030b0
4
- data.tar.gz: 9e09d7118c9006868b586ddce96738ea88a51af1
3
+ metadata.gz: 8de9b34e6b07e216baf33dd87f483e41edf284c1
4
+ data.tar.gz: 20f286868afbde83b138c3a780d626f7b15e2c8b
5
5
  SHA512:
6
- metadata.gz: 777a7cd47cea0d6ebc9d077d5dd3c32f7e89e28de7d11b321d686b1491a04d5c47e5488c14816dd631513d979cb429076c1cb99506a2e356352e6922af5e3ff2
7
- data.tar.gz: 13b389f1cdbf9fafab32c811b80faefc7003315e3cb13f5faeb2463decc1bcd4350faf80647afbc2c31698a361d53d73f0d865aca4d0c14d776998586124692d
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
- NOTE: This gem is only intended to provide quick access to the metadata returned by the pdfinfo command without flags
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
@@ -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
- if opts[:owner_password]
24
- flags << ['-opw', opts[:owner_password]]
25
- elsif opts[:user_password]
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
- stdout, stderr, status = Open3.capture2e("#{pdfinfo_command} #{flags.join(" ")} #{file_path}")
30
- stdout.chomp
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'].empty? ? nil : info_hash['Title']
45
- @subject = info_hash['Subject'].empty? ? nil : info_hash['Subject']
46
- @keywords = info_hash['Keywords'].empty? ? [] : info_hash['Keywords'].split(/\s/)
47
- @author = info_hash['Author'].empty? ? nil : info_hash['Author']
48
- @creator = info_hash['Creator'].empty? ? nil : info_hash['Creator']
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
@@ -1,3 +1,3 @@
1
1
  class Pdfinfo
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.3'
3
3
  end
@@ -12,13 +12,15 @@ RSpec.describe Pdfinfo do
12
12
  response.sub(/(?<=#{key}:)(.+)$/, new_value)
13
13
  end
14
14
 
15
- specify "mock responses match" do
16
- expect(`pdfinfo -upw foo #{fixture_path('pdfs/encrypted.pdf')}`.chomp).to eq(encrypted_response)
17
- expect(`pdfinfo #{fixture_path('pdfs/test.pdf')}`.chomp).to eq(unencrypted_response)
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
- before(:each) do
21
- allow(Open3).to receive(:capture2e).and_return([mock_response, nil, nil])
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(:capture2e).with("pdfinfo path/to/file.pdf")
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(:capture2e).with("pdfinfo -upw foo path/to/file.pdf")
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(:capture2e).with("pdfinfo -opw bar path/to/file.pdf")
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 title is not present' do
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdfinfo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Venegas