jpdfer 0.1.0

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.
data/README.rdoc ADDED
@@ -0,0 +1,14 @@
1
+ = jpdfer
2
+
3
+ JRuby gem to wrap iText, the PDF manipulation java libraries. Allows
4
+ you to:
5
+
6
+
7
+ * Inspect PDF forms
8
+ * Write to form fields
9
+ * Flatten PDF forms
10
+
11
+
12
+ = TODO
13
+
14
+ * Add checkbox field to simple_form.pdf
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,23 @@
1
+ module Jpdfer
2
+
3
+ class KeyStore
4
+ JavaFileInputStream = java.io.FileInputStream
5
+ JavaKeyStore = java.security.KeyStore
6
+ JavaString = java.lang.String
7
+
8
+ def initialize(keystore_path, _alias, password)
9
+ @alias, @password = _alias, password
10
+ @keystore = JavaKeyStore::getInstance(JavaKeyStore::getDefaultType())
11
+ @keystore.load(JavaFileInputStream.new(keystore_path), JavaString.new(@password).toCharArray)
12
+ end
13
+
14
+ def private_key
15
+ @keystore.getKey(@alias, java.lang.String.new(@password).toCharArray)
16
+ end
17
+
18
+ def certificate_chain
19
+ @keystore.getCertificateChain(@alias)
20
+ end
21
+ end
22
+
23
+ end
data/lib/jpdfer/pdf.rb ADDED
@@ -0,0 +1,217 @@
1
+ # High-level/convenience wrapper class for a PDF document.
2
+
3
+ module Jpdfer
4
+
5
+ # PDF Document with a form that can be read, filled, and saved.
6
+ class Pdf
7
+ class NonexistentFieldError < Exception; end
8
+ class ReadOnlyError < Exception; end
9
+ include_package "com.itextpdf.text.pdf"
10
+ include_package "com.itextpdf.text.xml.xmp"
11
+
12
+ def self.create_flatten_fields_xml(fields)
13
+ schema = DublinCoreSchema.new
14
+ schema.addDescription(JSON({'jpdfer_flattened_fields' => fields}))
15
+ metaout = StringIO.new
16
+ xmpwriter = XmpWriter.new(metaout.to_outputstream)
17
+ xmpwriter.addRdfDescription(schema)
18
+ xmpwriter.close
19
+ metaout.string
20
+ end
21
+
22
+ def self.description_from_metadata_xml(metadata_string)
23
+ metadata_string.gsub!(/<\?.*?\?>/, '')
24
+ namespaces = {
25
+ "xmlns:x" => "adobe:ns:meta/",
26
+ "xmlns:rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
27
+ "xmlns:dc" => "http://purl.org/dc/elements/1.1/"
28
+ }
29
+ root_node = Nokogiri::XML.parse(metadata_string)
30
+ descriptions = root_node.xpath('.//dc:description//rdf:li/text()', namespaces)
31
+ descriptions.count > 0 ? descriptions.first.text : ""
32
+ end
33
+
34
+ def self.open(pdf_path, save_path, options={})
35
+ flatten = options.delete(:flatten)
36
+ pdf = self.new(pdf_path, options)
37
+ if block_given?
38
+ yield pdf
39
+ pdf.save_as(save_path, flatten)
40
+ else
41
+ pdf
42
+ end
43
+ end
44
+
45
+ # Currently the only option is :keystore
46
+ def initialize(path, options = {})
47
+ @data = File.read(path)
48
+ @output_buffer = StringIO.new
49
+ reader = PdfReader.new(@data.to_java_bytes)
50
+ @stamper = create_stamper(reader, options[:keystore])
51
+ @saved = false
52
+ end
53
+
54
+ # helper method for initialize not ment to be used publicly
55
+ def create_stamper(reader, keystore = nil)
56
+ if keystore
57
+ stamper = PdfStamper.createSignature(reader, @output_buffer.to_outputstream, 0)
58
+ key, certificate_chain = keystore.private_key, keystore.certificate_chain
59
+ # TODO: Should not always be self-signed
60
+ signature_type = Pdf::PdfSignatureAppearance::SELF_SIGNED
61
+ stamper.getSignatureAppearance.setCrypto(key, certificate_chain, nil, signature_type)
62
+ else
63
+ stamper = PdfStamper.new(reader, @output_buffer.to_outputstream)
64
+ end
65
+ stamper
66
+ end
67
+
68
+ # Writes PDF to +path+. If +flatten+ is true, also flattens the form
69
+ # so that the form is printed on the PDF document but the form is no
70
+ # longer editable.
71
+ #
72
+ # Once a this has been called the PDF becomes read-only and any
73
+ # subsequent calls to +save_as+, +set_field+, or +set_fields+
74
+ # will raise an ReadOnlyError.
75
+ #
76
+ # save_as returns *UNTESTED* if the PDF form is not valid
77
+ def save_as(path, flatten=false)
78
+ raise ReadOnlyError.new("Cannot save a previously saved pdf") if @saved
79
+ @saved = true
80
+ if flatten
81
+ metadata = self.class.create_flatten_fields_xml(fields)
82
+ @stamper.setXmpMetadata metadata.to_java_bytes
83
+ end
84
+ @stamper.setFormFlattening(flatten)
85
+ @stamper.close
86
+ File.open(path, 'wb') do |file|
87
+ file.write(@output_buffer.string)
88
+ end
89
+ end
90
+
91
+ # Returns fields defined in this PDF form and their values, if any.
92
+ # fields returns an empty hash if PDF document does not contain a form
93
+ def fields
94
+ form = @stamper.getAcroFields
95
+ h = {}
96
+ form.getFields.each_pair do |name, value|
97
+ h[name.to_sym] = form.getField(name)
98
+ end
99
+ h
100
+ end
101
+
102
+ # Returns value of named field.
103
+ #
104
+ # Raises Pdf::NonexistentFieldError if field does not exist.
105
+ # +name+:: Symbol name of field to retrieve
106
+ def get_field(name)
107
+ raise NonexistentFieldError.new("'#{name}' field does not exist in form") unless has_field?(name)
108
+ @stamper.getAcroFields.getField(name.to_s)
109
+ end
110
+
111
+ # Sets named field. set_field returns value set.
112
+ #
113
+ # Raises Pdf::NonexistentFieldError if field does not exist.
114
+ # +name+: Symbol naming the field to write
115
+ def set_field(name, value)
116
+ raise ReadOnlyError.new('Previously saved pdfs are read-only') if @saved
117
+ name = name.to_sym
118
+ raise NonexistentFieldError.new("'#{name}' field does not exist in form") unless has_field?(name)
119
+ @stamper.getAcroFields.setField(name.to_s, value.to_s)
120
+ value
121
+ end
122
+
123
+ # Sets many fields at once. Returns the hash of fields set (should
124
+ # always be equal to given set of fields).
125
+ #
126
+ # Raises Pdf::NonexistentFieldError if any field does not exist.
127
+ # +fields+:: A hash of :key => "value" pairs.
128
+ def set_fields(fields)
129
+ fields.each_pair do |name, value|
130
+ set_field(name, value)
131
+ end
132
+ fields
133
+ end
134
+
135
+ # true if field +name+ exists in form
136
+ #
137
+ # +name+:: Field name as Symbol (or String)
138
+ def has_field?(name)
139
+ fields.key?(name.to_sym)
140
+ end
141
+
142
+ # true if the receiving Pdf instance has a form
143
+ def has_form?
144
+ @stamper.getAcroFields.getFields.size > 0
145
+ end
146
+
147
+ # Returns field names and values that were written to a
148
+ # form in this pdf before flattening.
149
+ # Returns an empty hash if there are not any.
150
+ def flattened_fields
151
+ reader = @stamper.reader
152
+ metadata_string = String.from_java_bytes reader.getMetadata
153
+ description_text = self.class.description_from_metadata_xml(metadata_string)
154
+ begin
155
+ metadata = JSON(description_text)
156
+ _flattened_fields = metadata.key?('jpdfer_flattened_fields') ? metadata['jpdfer_flattened_fields'] : {}
157
+ rescue JSON::ParserError
158
+ _flattened_fields = {}
159
+ end
160
+ h = {}
161
+ _flattened_fields.each_pair do |name, value|
162
+ h[name.to_sym] = value
163
+ end
164
+ h
165
+ end
166
+
167
+ # true if the receiving Pdf instance was previously flattened with jpdfer
168
+ def has_flattened_fields?
169
+ flattened_fields.size > 0 ? true : false
170
+ end
171
+
172
+ # Returns the certification level of the pdf
173
+ def certification_level
174
+ case @stamper.reader.getCertificationLevel
175
+ when PdfSignatureAppearance::CERTIFIED_FORM_FILLING
176
+ level = :form_filling
177
+ when PdfSignatureAppearance::CERTIFIED_FORM_FILLING_AND_ANNOTATIONS
178
+ level = :form_filling_and_annotations
179
+ when PdfSignatureAppearance::CERTIFIED_NO_CHANGES_ALLOWED
180
+ level = :no_changes_allowed
181
+ when PdfSignatureAppearance::NOT_CERTIFIED
182
+ level = :not_certified
183
+ end
184
+ level
185
+ end
186
+
187
+ # Set the certification level on a pdf initialized with an optional keystore
188
+ #
189
+ # *level* must be one of :form_filling, :form_filling_and_annotations,
190
+ # :no_changes_allowed, :not_certified
191
+ def set_certification_level(level)
192
+ case level
193
+ when :form_filling
194
+ certification_level = PdfSignatureAppearance::CERTIFIED_FORM_FILLING
195
+ when :form_filling_and_annotations
196
+ certification_level = PdfSignatureAppearance::CERTIFIED_FORM_FILLING_AND_ANNOTATIONS
197
+ when :no_changes_allowed
198
+ certification_level = PdfSignatureAppearance::CERTIFIED_NO_CHANGES_ALLOWED
199
+ when :not_certified
200
+ level = PdfSignatureAppearance::NOT_CERTIFIED
201
+ end
202
+ @stamper.getSignatureAppearance.setCertificationLevel(certification_level)
203
+ end
204
+
205
+ # Sets the reason for the signature on the pdf
206
+ def set_signature_reason(reason)
207
+ @stamper.getSignatureAppearance.setReason(reason)
208
+ end
209
+
210
+ # Sets the location of the signature on the pdf
211
+ def set_signature_location(location)
212
+ @stamper.getSignatureAppearance.setLocation(location)
213
+ end
214
+
215
+ end
216
+
217
+ end
@@ -0,0 +1,3 @@
1
+ module Jpdfer
2
+ VERSION = "0.1.0"
3
+ end
data/lib/jpdfer.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'java'
2
+ require 'stringio'
3
+ require 'json'
4
+ require 'nokogiri'
5
+
6
+ module Jpdfer
7
+ ROOT = File.expand_path('..', File.dirname(__FILE__))
8
+ end
9
+
10
+ require File.expand_path('jars/itextpdf-5.1.1.jar', Jpdfer::ROOT)
11
+ require File.expand_path('jars/bcprov-jdk16-146.jar', Jpdfer::ROOT)
12
+ require File.expand_path('jars/bctsp-jdk16-146.jar', Jpdfer::ROOT)
13
+ require File.expand_path('jars/bcmail-jdk16-146.jar', Jpdfer::ROOT)
14
+
15
+ require 'jpdfer/pdf'
16
+ require 'jpdfer/key_store'
17
+ require 'jpdfer/version'
@@ -0,0 +1,375 @@
1
+ require 'spec_helper'
2
+
3
+ module Jpdfer
4
+
5
+ describe "Pdf Acceptance" do
6
+ before(:each) do
7
+ @data_path = File.join(ROOT, 'spec', 'data')
8
+ @pdf_path = File.join(@data_path, 'simple_form.pdf')
9
+ @pdf = Pdf.new(@pdf_path)
10
+ @unfilled_fields = {
11
+ :important_field => '',
12
+ :unimportant_field => '',
13
+ :semiimportant_field => '',
14
+ :tuesday_field => '',
15
+ :must_not_be_left_blank_field => ''
16
+ }
17
+ @filled_fields = {
18
+ :important_field => "I am important",
19
+ :unimportant_field => 'I am unimportant',
20
+ :semiimportant_field => 'I am confused',
21
+ :tuesday_field => 'Is it Tuesday already?',
22
+ :must_not_be_left_blank_field => 'NOT BLANK'
23
+ }
24
+ end
25
+
26
+ describe '.new' do
27
+ it 'should create new pdf' do
28
+ @pdf.should_not be_nil
29
+ end
30
+
31
+ describe 'given missing file' do
32
+ it 'should raise Errno::ENOENT (File Not Found)' do
33
+ lambda { Pdf.new('derp.pdf') }.should raise_error(Errno::ENOENT)
34
+ end
35
+ end
36
+
37
+ describe 'given an optional keystore' do
38
+ describe 'when Pdf is configured' do
39
+ before(:each) do
40
+ @keystore = KeyStore.new(
41
+ File.join(@data_path, 'keystore.ks'),
42
+ 'jpdfer',
43
+ 'durrderp'
44
+ )
45
+ @pdf = Pdf.new(@pdf_path, :keystore => @keystore)
46
+ @signed_pdf_path = File.join(@data_path, 'new_signed.pdf')
47
+ end
48
+
49
+ after(:each) do
50
+ FileUtils.rm_f(@signed_pdf_path)
51
+ end
52
+
53
+ it 'should create a signed pdf if saved' do
54
+ @pdf.save_as(@signed_pdf_path)
55
+ File.open(@signed_pdf_path) do |file|
56
+ data = file.read
57
+ data['Scott Nielsen'].should == 'Scott Nielsen'
58
+ data['Saxton Horne'].should == 'Saxton Horne'
59
+ end
60
+ end
61
+
62
+ describe '#set_certification_level' do
63
+ it 'should have the given certification level when saved' do
64
+ @pdf.set_certification_level(:no_changes_allowed)
65
+ @pdf.save_as(@signed_pdf_path)
66
+ @pdf = Pdf.new(@signed_pdf_path)
67
+ @pdf.certification_level.should == :no_changes_allowed
68
+ end
69
+ end
70
+
71
+ # TODO: I would like to add this functionality but havn't researched the java
72
+ # KeyStore and encryption classes enough yet
73
+ #
74
+ # describe 'given a pdf signed with the private_key and certificate' do
75
+ # before(:each) do
76
+ # pdf_path = File.join(@data_path, 'simple_form_flattened_signed.pdf')
77
+ # @pdf = Pdf.new(pdf_path, :keystore => @keystore)
78
+ # end
79
+
80
+ # describe '#signed?' do
81
+ # it 'should be true' do
82
+ # @pdf.should be_signed
83
+ # end
84
+ # end
85
+ # end
86
+
87
+ # describe 'given a pdf not signed with the private_key and certificate' do
88
+ # before(:each) do
89
+ # pdf_path = File.join(@data_path, 'simple_form_signed_by_someone_else.pdf')
90
+ # @pdf = Pdf.new(pdf_path, :keystore => @keystore)
91
+ # end
92
+
93
+ # describe '#signed?' do
94
+ # it 'should be false' do
95
+ # @pdf.should_not be_signed
96
+ # end
97
+ # end
98
+ # end
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '.open' do
104
+ before(:each) do
105
+ @save_path = File.join(@data_path, 'new_pdf.pdf')
106
+ end
107
+
108
+ after(:each) do
109
+ FileUtils.rm_f(@save_path)
110
+ end
111
+
112
+ it 'should instaniate a new pdf a pass it to the block and then save it' do
113
+ Pdf.open(@pdf_path, @save_path) do |pdf|
114
+ pdf.set_fields(@filled_fields)
115
+ end
116
+ new_pdf = Pdf.new(@save_path)
117
+ new_pdf.fields.should == @filled_fields
118
+ end
119
+
120
+ describe 'given the flatten option' do
121
+ it 'should be saved with the flatten option' do
122
+ Pdf.open(@pdf_path, @save_path, :flatten => true) do |pdf|
123
+ pdf.set_fields(@filled_fields)
124
+ end
125
+ new_pdf = Pdf.new(@save_path)
126
+ new_pdf.flattened_fields.should == @filled_fields
127
+ end
128
+ end
129
+ end
130
+
131
+ describe '#certification_level' do
132
+ it 'should return nil for an unsigned pdf' do
133
+ @pdf.certification_level.should == :not_certified
134
+ end
135
+
136
+ describe 'called on a signed pdf' do
137
+ before(:each) do
138
+ @pdf = Pdf.new(File.join(@data_path, 'simple_form_flattened_signed.pdf'))
139
+ end
140
+
141
+ it 'it should return the certification level' do
142
+ @pdf.certification_level.should == :no_changes_allowed
143
+ end
144
+ end
145
+ end
146
+
147
+ describe '#fields' do
148
+ it 'should return a hash of field name value pairs' do
149
+ @pdf.fields.should == @unfilled_fields
150
+ end
151
+ end
152
+
153
+ describe '#get_field' do
154
+ it 'should return the field value' do
155
+ @pdf.get_field(:important_field).should == ""
156
+ end
157
+
158
+ describe "with nonexistent field name" do
159
+ it "should raise Pdf::NonexistentFieldError" do
160
+ lambda { @pdf.get_field(:monkey) }.should raise_error(Pdf::NonexistentFieldError, /'monkey' field does not exist in form/)
161
+ end
162
+ end
163
+ end
164
+
165
+ describe '#set_field' do
166
+ it 'should fill the field with given name with given value' do
167
+ @pdf.set_field(:important_field, "I am important")
168
+ @pdf.get_field(:important_field).should == "I am important"
169
+ end
170
+
171
+ it 'should return the value written to the field' do
172
+ @pdf.set_field(:important_field, "I am important").should == 'I am important'
173
+ end
174
+
175
+ it 'should update fields' do
176
+ @pdf.set_field(:important_field, "I am important")
177
+ @pdf.fields.should == {
178
+ :important_field => 'I am important',
179
+ :unimportant_field => '',
180
+ :semiimportant_field => '',
181
+ :tuesday_field => '',
182
+ :must_not_be_left_blank_field => ''
183
+ }
184
+ end
185
+
186
+ describe "with existing field name" do
187
+ it "should not raise an error" do
188
+ lambda { @pdf.set_field(:important_field, 'I am important') }.should_not raise_error(Pdf::NonexistentFieldError)
189
+ end
190
+ end
191
+
192
+ describe "with nonexistent field name" do
193
+ it "should raise Pdf::NonexistentFieldError" do
194
+ lambda { @pdf.set_field(:monkey, 'Spider') }.should raise_error(Pdf::NonexistentFieldError, /'monkey' field does not exist in form/)
195
+ end
196
+ end
197
+ end
198
+
199
+ describe '#set_fields' do
200
+ it 'should fill the fields with given names with given values' do
201
+ @pdf.set_fields(@filled_fields)
202
+ @pdf.get_field(:important_field).should == "I am important"
203
+ @pdf.get_field(:unimportant_field).should == 'I am unimportant'
204
+ @pdf.get_field(:semiimportant_field).should == 'I am confused'
205
+ @pdf.get_field(:tuesday_field).should == 'Is it Tuesday already?'
206
+ @pdf.get_field(:must_not_be_left_blank_field).should == 'NOT BLANK'
207
+ end
208
+
209
+ it 'should update fields' do
210
+ @pdf.set_fields(@filled_fields)
211
+ @pdf.fields.should == @filled_fields
212
+ end
213
+
214
+ it 'should return the set fields' do
215
+ @pdf.set_fields(@filled_fields).should == @filled_fields
216
+ end
217
+
218
+ describe "with nonexistent field name" do
219
+ it "should raise Pdf::NonexistentFieldError" do
220
+ @filled_fields[:monkey] = "spider"
221
+ lambda { @pdf.set_fields(@filled_fields) }.should raise_error(Pdf::NonexistentFieldError, /'monkey' field does not exist in form/)
222
+ end
223
+ end
224
+ end
225
+
226
+ describe '#save_as' do
227
+ before(:each) do
228
+ @new_path = File.join(@data_path, 'simple_form_new.pdf')
229
+ FileUtils.rm_f(@new_path)
230
+ end
231
+
232
+ after(:each) do
233
+ FileUtils.rm_f(@new_path)
234
+ end
235
+
236
+ it 'should write the pdf to a new path' do
237
+ @pdf.save_as(@new_path)
238
+
239
+ new_pdf = Pdf.new(@new_path)
240
+ new_pdf.fields.should == {
241
+ :important_field => '',
242
+ :unimportant_field => '',
243
+ :semiimportant_field => '',
244
+ :tuesday_field => '',
245
+ :must_not_be_left_blank_field => ''
246
+ }
247
+ end
248
+
249
+ it 'should save updated fields to the new file' do
250
+ @pdf.set_field(:important_field, "I am important")
251
+ @pdf.save_as(@new_path)
252
+
253
+ new_pdf = Pdf.new(@new_path)
254
+ new_pdf.get_field(:important_field).should == "I am important"
255
+ end
256
+
257
+ describe 'given flatten=true' do
258
+ it 'should save the pdf without a form' do
259
+ @pdf.save_as(@new_path, true)
260
+
261
+ new_pdf = Pdf.new(@new_path)
262
+ new_pdf.should_not have_form
263
+ end
264
+ end
265
+
266
+ describe 'with a saved PDF' do
267
+ before(:each) do
268
+ @pdf.save_as(@new_path)
269
+ end
270
+
271
+ describe 'saving again' do
272
+ it "should raise Pdf::ReadOnlyError" do
273
+ lambda { @pdf.save_as(@new_path) }.should raise_error(Pdf::ReadOnlyError, /Cannot save a previously saved pdf/)
274
+ end
275
+ end
276
+
277
+ describe "#set_field" do
278
+ it "should raise Pdf:ReadOnlyError" do
279
+ lambda { @pdf.set_field(:important_field, 'I am important') }.should raise_error(Pdf::ReadOnlyError, /Previously saved pdfs are read-only/)
280
+ end
281
+ end
282
+
283
+ describe "#set_fields" do
284
+ it "should raise Pdf::ReadOnlyError" do
285
+ lambda { @pdf.set_fields(@filled_fields) }.should raise_error(Pdf::ReadOnlyError, /Previously saved pdfs are read-only/)
286
+ end
287
+ end
288
+ end
289
+ end
290
+
291
+ describe '#has_field?' do
292
+ describe "with field name as symbol" do
293
+ it 'should return true if the field exists' do
294
+ @pdf.has_field?(:important_field).should be(true)
295
+ end
296
+
297
+ it 'should return false if the field does not' do
298
+ @pdf.has_field?(:monkey).should be(false)
299
+ end
300
+ end
301
+
302
+ describe "with field name as string" do
303
+ it 'should return true if the field exists' do
304
+ @pdf.has_field?("important_field").should be(true)
305
+ end
306
+
307
+ it 'should return false if the field does not' do
308
+ @pdf.has_field?("monkey").should be(false)
309
+ end
310
+ end
311
+ end
312
+
313
+ describe '#has_form?' do
314
+ describe 'given a pdf with a form' do
315
+ it 'should return true' do
316
+ @pdf.should have_form
317
+ end
318
+ end
319
+
320
+ describe 'given a pdf without a form' do
321
+ it 'should return false' do
322
+ pdf = Pdf.new(File.join(@data_path, 'simple_form_flattened.pdf'))
323
+ pdf.should_not have_form
324
+ end
325
+ end
326
+ end
327
+
328
+ describe 'given a pdf that we have flattened' do
329
+ before(:each) do
330
+ @new_pdf_path = File.join(@data_path, 'we_flattened.pdf')
331
+ @pdf.set_fields(@filled_fields)
332
+ @pdf.save_as(@new_pdf_path, true)
333
+ @pdf = Pdf.new(@new_pdf_path)
334
+ end
335
+
336
+ after(:each) do
337
+ FileUtils.rm_f(@new_pdf_path)
338
+ end
339
+
340
+ describe '#flattened_fields' do
341
+ it 'returns a hash of field name value pairs of previous form fields' do
342
+ @pdf.flattened_fields.should == @filled_fields
343
+ end
344
+ end
345
+
346
+ describe '#has_flattened_fields?' do
347
+ it 'should return true' do
348
+ @pdf.should have_flattened_fields
349
+ end
350
+ end
351
+ end
352
+
353
+ describe 'given a pdf that is not flattened, or we did not flatten' do
354
+ before(:each) do
355
+ @pdf = Pdf.new(File.join(@data_path, 'simple_form_flattened.pdf'))
356
+ end
357
+
358
+ describe '#flattened_fields' do
359
+ it 'should return an empty hash' do
360
+ @pdf.flattened_fields.should == {}
361
+ end
362
+ end
363
+
364
+ describe '#has_flattened_fields' do
365
+ it 'should be false' do
366
+ @pdf.should_not have_flattened_fields
367
+ end
368
+ end
369
+ end
370
+
371
+ # set_field returns some error if the form field is incorrect (e.g. setting a checkbox with something silly like 'monkey' or 'true' instead of 'Yes'
372
+ # save_as returns *UNTESTED* if the PDF form is not valid
373
+ end
374
+
375
+ end
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ module Jpdfer
5
+ # IMPORTANT: These are model/unit specs! Test in isolation as much as possible!
6
+ describe Pdf do
7
+ before(:each) do
8
+ @data_path = File.join(ROOT, 'spec', 'data')
9
+ @pdf_path = File.join(@data_path, 'simple_form.pdf')
10
+ @pdf = Pdf.new(@pdf_path)
11
+ end
12
+
13
+ describe '.new' do
14
+ it 'should create new pdf' do
15
+ @pdf.should_not be_nil
16
+ end
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,3 @@
1
+ # spec_helper.rb
2
+ require 'jpdfer'
3
+ require 'fileutils'
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jpdfer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Scott Nielsen
9
+ - David Brady
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2012-01-25 00:00:00 -07:00
15
+ default_executable:
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: nokogiri
19
+ prerelease: false
20
+ requirement: &id001 !ruby/object:Gem::Requirement
21
+ none: false
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: "0"
26
+ type: :runtime
27
+ version_requirements: *id001
28
+ - !ruby/object:Gem::Dependency
29
+ name: json-jruby
30
+ prerelease: false
31
+ requirement: &id002 !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: "0"
37
+ type: :runtime
38
+ version_requirements: *id002
39
+ - !ruby/object:Gem::Dependency
40
+ name: rspec
41
+ prerelease: false
42
+ requirement: &id003 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ type: :development
49
+ version_requirements: *id003
50
+ description: Ruby-style wrapper in JRuby for reading and writing PDF forms
51
+ email: scottnielsen5@gmail.com
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - README.rdoc
60
+ - jars/bcmail-jdk16-146.jar
61
+ - jars/bcprov-jdk16-146.jar
62
+ - jars/bctsp-jdk16-146.jar
63
+ - jars/itextpdf-5.1.1.jar
64
+ - lib/jpdfer.rb
65
+ - lib/jpdfer/key_store.rb
66
+ - lib/jpdfer/pdf.rb
67
+ - lib/jpdfer/version.rb
68
+ - spec/acceptance/jpdfer/pdf_acceptance_spec.rb
69
+ - spec/data/flattened.pdf
70
+ - spec/data/keystore.ks
71
+ - spec/data/simple_form.pdf
72
+ - spec/data/simple_form_flattened.pdf
73
+ - spec/data/simple_form_flattened_signed.pdf
74
+ - spec/data/simple_form_signed_by_someone_else.pdf
75
+ - spec/lib/jpdfer/pdf_spec.rb
76
+ - spec/spec_helper.rb
77
+ has_rdoc: true
78
+ homepage: http://github.com/scizo/jpdfer
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options:
83
+ - --main
84
+ - README.rdoc
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: "0"
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.5.1
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Read and write PDF forms in JRuby
106
+ test_files:
107
+ - spec/acceptance/jpdfer/pdf_acceptance_spec.rb
108
+ - spec/data/flattened.pdf
109
+ - spec/data/keystore.ks
110
+ - spec/data/simple_form.pdf
111
+ - spec/data/simple_form_flattened.pdf
112
+ - spec/data/simple_form_flattened_signed.pdf
113
+ - spec/data/simple_form_signed_by_someone_else.pdf
114
+ - spec/lib/jpdfer/pdf_spec.rb
115
+ - spec/spec_helper.rb