jpdfer 0.1.0

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