fillable-pdf 1.1.3 → 1.1.4

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
  SHA256:
3
- metadata.gz: 2cdd748940498c34c3e4f19f91f83cfc47fcf34dda1d10eb07e05f7aef9c7d57
4
- data.tar.gz: a98954a86876c759716a8919a24f54c175ec97eb0eddd19bc2b9aaa844bdd6cb
3
+ metadata.gz: 9ef1adfa571c40a68f117e48e73917ef837207c8c2888a449672f2fa07664873
4
+ data.tar.gz: fb5c2c786c58b1635c37534381ae5ac106aaa0694e7839ec73acdaa331c863d5
5
5
  SHA512:
6
- metadata.gz: bb4104898a7feb6a16338aae323b3d1285f8fb5dd2458e48d5e936ca17ed27fc407289c68db0a466105bbe06fc1100cfd5a8cfa92873f6f6b731692ee385bfaf
7
- data.tar.gz: 07430fe63ccbbec3e4c7c5191d6831b767320b87ed6ea0bd0542c11d41e10fe8c7883ce7d396fe7cc31f029d425fb87e055e3af01bd44358cf8d3b99010e17ca
6
+ metadata.gz: 86ad2b2c634818d159e2f7b710d2d38c5e726eecf9c809e8b19466cc2f842f8af9633b0900004b0f98031741a2680f5aff2bbf40f4448161d0590a2141630192
7
+ data.tar.gz: e940b9d5908efb0fae7b7975b0ec7878b78876fccc07c5a08c9a7e1575fa38e4829ae0a41290a791ac6e8d0d21dd97024e14c65700baf3e1f01d14b0ba7f02c7
data/README.md CHANGED
@@ -12,8 +12,6 @@ FillablePDF is an extremely simple and lightweight utility that bridges iText an
12
12
 
13
13
  Supports **Ruby 2.4 → latest** and **JDK 8 → latest**, with the full Ruby/Java matrix tested daily in CI.
14
14
 
15
- [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/vkononov)
16
-
17
15
  ## Known Issues
18
16
 
19
17
  1. Phusion Passenger's [smart spawning](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#the-smart-spawning-method) is not supported. Please see [Deployment with Phusion Passenger + Nginx](#deployment-with-phusion-passenger--nginx) for more information.
@@ -1,3 +1,3 @@
1
1
  class FillablePDF
2
- VERSION = '1.1.3'
2
+ VERSION = '1.1.4'
3
3
  end
data/lib/fillable-pdf.rb CHANGED
@@ -5,6 +5,7 @@ require_relative 'fillable-pdf/errors'
5
5
  require 'base64'
6
6
  require 'securerandom'
7
7
  require 'tmpdir'
8
+ require 'tempfile'
8
9
 
9
10
  class FillablePDF # rubocop:disable Metrics/ClassLength
10
11
  include SuppressWarnings
@@ -295,15 +296,15 @@ class FillablePDF # rubocop:disable Metrics/ClassLength
295
296
  #
296
297
  def save(flatten: false)
297
298
  ensure_document_open
298
- tmp_file = "#{Dir.tmpdir}/#{SecureRandom.uuid}"
299
- save_as(tmp_file, flatten: flatten)
300
- FileUtils.mv tmp_file, @file_path
299
+ write_document(@file_path, flatten: flatten)
301
300
  self
301
+ rescue StandardError => e
302
+ raise FileOperationError, "Failed to save file `#{@file_path}`: #{e.message}"
302
303
  end
303
304
 
304
305
  ##
305
306
  # Saves the filled out PDF document in a given path and flattens it if requested.
306
- # If the path matches the current file path, it will call save() instead.
307
+ # The destination is replaced only after the document has been finalized.
307
308
  #
308
309
  # @param [String] file_path the name of the PDF file or file path
309
310
  # @param [Boolean] flatten true if PDF should be flattened, false otherwise
@@ -312,12 +313,7 @@ class FillablePDF # rubocop:disable Metrics/ClassLength
312
313
  #
313
314
  def save_as(file_path, flatten: false)
314
315
  ensure_document_open
315
- if @file_path == file_path
316
- save(flatten: flatten)
317
- return self
318
- end
319
-
320
- File.open(file_path, 'wb') { |f| f.write(finalize(flatten: flatten)) && f.close }
316
+ write_document(file_path, flatten: flatten)
321
317
  self
322
318
  rescue StandardError => e
323
319
  raise FileOperationError, "Failed to save file `#{file_path}`: #{e.message}"
@@ -335,9 +331,12 @@ class FillablePDF # rubocop:disable Metrics/ClassLength
335
331
  #
336
332
  def save_as!(file_path, flatten: false)
337
333
  ensure_document_open
338
- raise InvalidArgumentError, 'Cannot save_as! to the same file path. Use save() instead.' if @file_path == file_path
334
+ if same_source_file?(file_path)
335
+ raise InvalidArgumentError,
336
+ 'Cannot save_as! to the same file path. Use save() instead.'
337
+ end
339
338
 
340
- File.open(file_path, 'wb') { |f| f.write(finalize(flatten: flatten)) && f.close }
339
+ write_document(file_path, flatten: flatten)
341
340
  self
342
341
  rescue InvalidArgumentError
343
342
  raise
@@ -369,6 +368,29 @@ class FillablePDF # rubocop:disable Metrics/ClassLength
369
368
 
370
369
  private
371
370
 
371
+ def same_source_file?(file_path)
372
+ File.expand_path(@file_path.to_s) == File.expand_path(file_path.to_s) ||
373
+ (File.exist?(file_path) && File.identical?(@file_path, file_path))
374
+ end
375
+
376
+ # Keep the existing destination intact until finalization and writing succeed.
377
+ # Resolve symlinks so saving through one preserves the link itself.
378
+ def write_document(file_path, flatten:) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
379
+ destination = File.expand_path(file_path.to_s)
380
+ destination = File.realpath(destination) if File.symlink?(destination)
381
+ mode = File.stat(destination).mode & 0o777 if File.exist?(destination)
382
+ temporary = Tempfile.new(['.fillable-pdf-', '.pdf'], File.dirname(destination))
383
+ temporary.binmode
384
+ temporary.write(finalize(flatten: flatten))
385
+ temporary.flush
386
+ temporary.fsync
387
+ temporary.chmod(mode) if mode
388
+ temporary.close
389
+ File.rename(temporary.path, destination)
390
+ ensure
391
+ temporary&.close!
392
+ end
393
+
372
394
  ##
373
395
  # Writes the contents of the modified fields to the previously opened PDF file.
374
396
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fillable-pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vadim Kononov
@@ -96,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
96
  version: '0'
97
97
  requirements:
98
98
  - JDK >= 8
99
- rubygems_version: 4.0.10
99
+ rubygems_version: 4.0.20
100
100
  specification_version: 4
101
101
  summary: Fill, read, flatten and edit PDF form fields in Ruby with the iText engine
102
102
  test_files: []