Class: HexaPDF::CLI::Modify

Inherits:
CmdParse::Command
  • Object
show all
Defined in:
lib/hexapdf/cli/modify.rb

Overview

Modifies a PDF file:

  • Decrypts or encrypts the PDF file.

  • Generates or deletes object and cross-reference streams.

  • Optimizes a PDF by merging the revisions of a PDF file and removes unused entries.

See: HexaPDF::Task::Optimize

Instance Method Summary collapse

Constructor Details

#initializeModify

:nodoc:



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/hexapdf/cli/modify.rb', line 49

def initialize #:nodoc:
  super('modify', takes_commands: false)
  short_desc("Modify a PDF file")
  long_desc("    This command modifies a PDF file. It can be used to encrypt/decrypt a file, to optimize it\n    and remove unused entries and to generate or delete object and cross-reference streams.\n  EOF\n\n  options.on(\"--password PASSWORD\", \"-p\", String,\n             \"The password for decryption. Use - for reading from standard input.\") do |pwd|\n    @password = (pwd == '-' ? command_parser.read_password(\"Input file password\") : pwd)\n  end\n  options.on(\"--pages PAGES\", \"The pages to be used in the output file\") do |pages|\n    @pages = pages\n  end\n  options.on(\"--embed FILE\", String, \"Embed the file into the output file (can be used \" \\\n             \"multiple times)\") do |file|\n    @embed_files << file\n  end\n  options.on(\"--[no-]compact\", \"Delete unnecessary PDF objects (default: yes)\") do |c|\n    @compact = c\n  end\n  options.on(\"--object-streams MODE\", [:generate, :preserve, :delete],\n             \"Handling of object streams (either generate, preserve or delete; \" \\\n             \"default: preserve)\") do |os|\n    @object_streams = os\n  end\n  options.on(\"--xref-streams MODE\", [:generate, :preserve, :delete],\n             \"Handling of cross-reference streams (either generate, preserve or delete; \" \\\n             \"default: preserve)\") do |x|\n    @xref_streams = x\n  end\n  options.on(\"--streams MODE\", [:compress, :preserve, :uncompress],\n             \"Handling of stream data (either compress, preserve or uncompress; default: \" \\\n             \"preserve)\") do |streams|\n    @streams = streams\n  end\n\n  options.separator(\"\")\n  options.separator(\"Encryption related options\")\n  options.on(\"--decrypt\", \"Remove any encryption\") do\n    @encryption = :remove\n  end\n  options.on(\"--encrypt\", \"Encrypt the output file\") do\n    @encryption = :add\n  end\n  options.on(\"--owner-password PASSWORD\", String, \"The owner password to be set on the \" \\\n             \"output file. Use - for reading from standard input.\") do |pwd|\n    @encryption = :add\n    @enc_owner_pwd = (pwd == '-' ? command_parser.read_password(\"Owner password\") : pwd)\n  end\n  options.on(\"--user-password PASSWORD\", String, \"The user password to be set on the \" \\\n             \"output file. Use - for reading from standard input.\") do |pwd|\n    @encryption = :add\n    @enc_user_pwd = (pwd == '-' ? command_parser.read_password(\"User password\") : pwd)\n  end\n  options.on(\"--algorithm ALGORITHM\", [:aes, :arc4],\n             \"The encryption algorithm: aes or arc4 (default: aes)\") do |a|\n    @encryption = :add\n    @enc_algorithm = a\n  end\n  options.on(\"--key-length BITS\", Integer,\n             \"The encryption key length in bits (default: 128)\") do |i|\n    @encryption = :add\n    @enc_key_length = i\n  end\n  options.on(\"--force-V4\",\n             \"Force the use of encryption version 4 if key length=128 and algorithm=arc4\") do\n    @encryption = :add\n    @enc_force_v4 = true\n  end\n  syms = HexaPDF::Encryption::StandardSecurityHandler::Permissions::SYMBOL_TO_PERMISSION.keys\n  options.on(\"--permissions PERMS\", Array,\n             \"Comma separated list of permissions to be set on the output file. Possible \" \\\n             \"values: \#{syms.join(', ')}\") do |perms|\n    perms.each do |perm|\n      unless syms.include?(perm)\n        raise OptionParser::InvalidArgument, \"\#{perm} (invalid permission name)\"\n      end\n    end\n    @encryption = :add\n    @enc_permissions = perms\n  end\n\n  @password = nil\n  @pages = '1-e'\n  @embed_files = []\n  @compact = true\n  @object_streams = :preserve\n  @xref_streams = :preserve\n  @streams = :preserve\n\n  @encryption = :preserve\n  @enc_user_pwd = @enc_owner_pwd = nil\n  @enc_key_length = 128\n  @enc_algorithm = :aes\n  @enc_force_v4 = false\n  @enc_permissions = []\nend\n".gsub!(/^ */, ''))

Instance Method Details

#execute(input_file, output_file) ⇒ Object

:nodoc:



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/hexapdf/cli/modify.rb', line 149

def execute(input_file, output_file) #:nodoc:
  @compact = true unless @pages == '1-e'
  if @enc_user_pwd && !@enc_user_pwd.empty? && (!@enc_owner_pwd || @enc_owner_pwd.empty?)
    @enc_owner_pwd = @enc_user_pwd
  end

  HexaPDF::Document.open(input_file, decryption_opts: {password: @password}) do |doc|
    arrange_pages(doc) unless @pages == '1-e'
    @embed_files.each {|file|  doc.utils.add_file(file, embed: true)}

    doc.task(:optimize, compact: @compact, object_streams: @object_streams,
             xref_streams: @xref_streams)

    handle_streams(doc) if @streams != :preserve

    if @encryption == :add
      doc.encrypt(algorithm: @enc_algorithm, key_length: @enc_key_length,
                  force_V4: @enc_force_v4, permissions: @enc_permissions,
                  owner_password: @enc_owner_pwd, user_password: @enc_user_pwd)
    elsif @encryption == :remove
      doc.encrypt(name: nil)
    end

    doc.write(output_file)
  end
rescue HexaPDF::Error => e
  $stderr.puts "Error while processing the PDF file: #{e.message}"
  exit(1)
end