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 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