pdfmd 1.9.1 → 2.0.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.
@@ -0,0 +1,125 @@
1
+ # == Module: pdfmdmethods
2
+ #
3
+ # Method to extend functionalities
4
+ module Pdfmdmethods
5
+
6
+ #
7
+ # Determine the valid setting
8
+ # 1. Priority: manual setting
9
+ # 2. Priority: Hiera setting
10
+ #
11
+ # If there is no manual setting, the value of 'manualSetting'
12
+ # should be set to 'nil'
13
+ #
14
+ def determineValidSetting(manualSetting,key)
15
+
16
+ if !@hieradata.nil?
17
+ hieraKey = '@hieradata'
18
+ hieraValue = ''
19
+
20
+ key.split(':').each do |keyname|
21
+
22
+ hieraKeyCheck = eval(hieraKey)
23
+ if !hieraKeyCheck.nil? and hieraKeyCheck.has_key?(keyname)
24
+ hieraKey = hieraKey + "['#{keyname}']"
25
+ else
26
+ # Key has not been found
27
+ hieraKey = ''
28
+ break
29
+ end
30
+ end
31
+
32
+ hieraValue = eval(hieraKey)
33
+
34
+ else
35
+ hieraValue = nil
36
+ end
37
+
38
+ if !manualSetting.nil?
39
+ self.log('debug', "Chosing manual setting '#{key} = #{manualSetting}'.")
40
+ manualSetting
41
+ elsif !hieraValue.nil? or
42
+ !hieraValue == ''
43
+
44
+ self.log('debug', "Chosing hiera setting '#{key} = #{hieraValue}'.")
45
+ hieraValue
46
+
47
+ else
48
+ self.log('debug', "No setting chosen for '#{key}' in hiera.")
49
+ false
50
+ end
51
+
52
+ end
53
+
54
+
55
+ #
56
+ # Logging stuff
57
+ def log(status = 'info', message)
58
+
59
+ # Setting the loglevel
60
+ case @loglevel
61
+ when /info/i
62
+ level = 'Logger::INFO'
63
+ when /warn/i
64
+ level = 'Logger::WARN'
65
+ when /error/i
66
+ level = 'Logger::ERROR'
67
+ when /debug/i
68
+ level = 'Logger::DEBUG'
69
+ else
70
+ level = 'Logger::INFO'
71
+ end
72
+ logger = Logger.new(@logfile)
73
+ logger.level = eval level
74
+ logger.send(status, message)
75
+ logger.close
76
+
77
+ end
78
+
79
+
80
+
81
+ #
82
+ # Query hiera for settings if available
83
+ def queryHiera(keyword, facts = 'UNSET')
84
+
85
+ pathHieraConfig = [
86
+ '/etc/hiera.yaml',
87
+ '/etc/puppet/hiera.yaml',
88
+ '/etc/puppetlabs/puppet/hiera.yaml',
89
+ ]
90
+ hieraConfig = ''
91
+ pathHieraConfig.each do |path|
92
+ if File.exist? path
93
+ hieraConfig = path
94
+ break
95
+ end
96
+ end
97
+
98
+ # Set default facts
99
+ facts == 'UNSET' ? facts = "fqdn=#{`hostname`}".chomp : ''.chomp
100
+
101
+ # If Hiera is not found (damn cat, get of my keyboard!), return false,
102
+ # otherwise return the hash from Hiera
103
+ if !system('which hiera > /dev/null 2>&1')
104
+ self.log('warn','Cannot find hiera command in $path.')
105
+ puts 'Cannot find "hiera" command in $path.'
106
+ return eval('{}')
107
+ else
108
+
109
+ self.log('debug', 'Reading hiera values for pdfmd::config.')
110
+ commandreturn = ''
111
+ commandreturn = `hiera -c #{hieraConfig} #{keyword} #{facts} 2>/dev/null`
112
+
113
+ if $?.exitstatus == 1
114
+ self.log('warn', 'Could not retrieve configuration from with hiera.')
115
+ eval('{}')
116
+ else
117
+ self.log('debug', 'Could retrieve configuration from hiera.')
118
+ eval(commandreturn)
119
+ end
120
+
121
+ end
122
+
123
+ end # End of queryHiera
124
+
125
+ end
@@ -0,0 +1,243 @@
1
+ # == Class: pdfmdrename
2
+ #
3
+ # Class for renaming the file according to the metadata
4
+ #
5
+ class Pdfmdrename < Pdfmd
6
+
7
+ attr_accessor :filename, :dryrun, :allkeywords, :outputdir, :nrkeywords, :copy
8
+
9
+ # document key mappings to determine the document type based on the
10
+ # string in the meta field 'title'
11
+ @@keymapping = {
12
+ 'cno' => ['Customer','Customernumber'],
13
+ 'con' => ['Contract'],
14
+ 'inf' => ['Information'],
15
+ 'inv' => ['Invoice', 'Invoicenumber'],
16
+ 'man' => ['Manual'],
17
+ 'off' => ['Offer', 'Offernumber'],
18
+ 'ord' => ['Order', 'Ordernumber'],
19
+ 'rec' => ['Receipt', 'Receiptnumber'],
20
+ 'tic' => ['Ticket'],
21
+ }
22
+
23
+ def initialize(filename)
24
+ super(filename)
25
+ @nrkeywords ||= 3
26
+
27
+ # Find the valid keymapping
28
+ # Use @@keymapping as default and only overwrite when provided by hiera.
29
+ hierakeymapping = self.determineValidSetting(nil, 'rename:keys')
30
+ hierakeymapping ? @@keymapping = hierakeymapping : ''
31
+
32
+ # FIXME: this default doctype assignment might need to be rewritten as the keymapping above.
33
+ @defaultDoctype = self.determineValidSetting('doc', 'rename:defaultdoctype')
34
+ @fileextension = 'pdf'
35
+ end
36
+
37
+ def rename
38
+
39
+ # Build new filename elements
40
+ newFilename = Hash.new
41
+ newFilename[:date] = @@metadata['createdate'].gsub(/\ \d{2}\:\d{2}\:\d{2}.*$/,'').gsub(/\:/,'')
42
+ newFilename[:author] = get_author()
43
+ newFilename[:doctype] = get_doctype()
44
+ newFilename[:title] = @@metadata['title'].downcase
45
+ newFilename[:subject] = @@metadata['subject'].downcase.gsub(/(\s|\-|\.|\&|\%)/,'_')
46
+ newFilename[:keywords] = get_keywords(get_keywordsPreface(newFilename))
47
+ newFilename[:extension] = @fileextension
48
+ newFilename[:outputdir] = get_outputdir(@outputdir)
49
+
50
+ command = @copy ? 'cp' : 'mv'
51
+
52
+ filetarget = get_filename(newFilename)
53
+ if @dryrun # Do nothing on dryrun
54
+ if @filename == filetarget
55
+ self.log('info', "Dryrun: File '#{@filename}' already has the correct name. Doing nothing.")
56
+ else
57
+ self.log('info',"Dryrun: Renaming '#{@filename}' to '#{get_filename(newFilename)}'.")
58
+ end
59
+ elsif @filename == filetarget # Do nothing when name is already correct.
60
+ self.log('info',"File '#{@filename}' already has the correct name. Doing nothing.")
61
+ else
62
+ self.log('info',"Renaming '#{@filename}' to '#{filetarget}'.")
63
+ command = command + " '#{@filename}' #{filetarget} 2>/dev/null"
64
+ system(command)
65
+ if !$?.exitstatus
66
+ log('error', "Error renaming '#{@filename}' to '#{filetarget}'.")
67
+ abort
68
+ else
69
+ log('info', "Successfully renamed file to '#{filetarget}'.")
70
+ end
71
+
72
+ end
73
+ end
74
+
75
+ #
76
+ # Return the filename from the available filedata
77
+ def get_filename(filedata = {})
78
+
79
+ if filedata.size > 0
80
+
81
+ # Create the filename out of all with some exceptions
82
+ #
83
+ # If the doctype is the default one, the first keywords are the
84
+ # title and the subject
85
+ if filedata[:doctype] == @defaultDoctype
86
+
87
+ # The subject and title is part of the keywords and handled there.
88
+ filedata[:outputdir] + '/' +
89
+ filedata[:date] + '-' +
90
+ filedata[:author] + '-' +
91
+ filedata[:doctype] + '-' +
92
+ filedata[:keywords] + '.' +
93
+ filedata[:extension]
94
+ else
95
+ filedata[:outputdir] + '/' + filedata.except(:extension, :title, :subject, :outputdir).values.join('-') + '.' + filedata[:extension]
96
+ end
97
+
98
+ else
99
+
100
+ false
101
+
102
+ end
103
+
104
+ end
105
+
106
+ # Validate the output directory
107
+ def get_outputdir(outputdir = '')
108
+
109
+ if !outputdir # outputdir is set to false, assume pwd
110
+ self.log('debug','No outputdir specified. Taking current pwd of file.')
111
+ outputdir = File.dirname(@filename)
112
+ elsif outputdir and !File.exist?(outputdir)
113
+ puts "Error: output directory '#{outputdir}' not found. Abort."
114
+ self.log('error',"Output directory '#{outputdir}' not accessible. Abort.")
115
+ exit 1
116
+ elsif outputdir and File.exist?(outputdir)
117
+ outputdir
118
+ else
119
+ false
120
+ end
121
+
122
+ end
123
+
124
+ # Get the keywords
125
+ def get_keywords(preface = '')
126
+
127
+ if !@@metadata['keywords'].empty?
128
+
129
+ keywordsarray = @@metadata['keywords'].split(',')
130
+ # Replace leading spaces and strings from the keymappings
131
+ # if the value is identical it will be placed at the beginning
132
+ # of the array (and therefore be right after the preface in the filename)
133
+ keywordsarraySorted = Array.new
134
+ keywordsarray.each_with_index do |value,index|
135
+ value = value.lstrip.chomp
136
+
137
+ @@keymapping.each do |abbreviation,keyvaluearray|
138
+ if keyvaluearray.kind_of?(String)
139
+ keyvaluearray = keyvaluearray.split(',')
140
+ end
141
+ keyvaluearray = keyvaluearray.sort_by{|size| -size.length}
142
+ keyvaluearray.each do |keystring|
143
+ value = value.gsub(/#{keystring.lstrip.chomp}\s?/i, abbreviation.to_s)
144
+ end
145
+ end
146
+
147
+ # Remove special characters from string
148
+ keywordsarray[index] = value.gsub(/\s|\/|\-|\./,'_')
149
+
150
+ # If the current value matches some of the replacement abbreviations,
151
+ # put the value at index 0 in the array. It will then be listed earlier in the filename.
152
+ if value.match(/^#{@@keymapping.keys.join('|')} /i)
153
+ keywordsarraySorted.insert(0, keywordsarray[index])
154
+ else
155
+ keywordsarraySorted.push(keywordsarray[index])
156
+ end
157
+
158
+ end
159
+
160
+ # Insert the preface if it is not empty
161
+ if !preface.to_s.empty?
162
+ keywordsarraySorted.insert(0, preface)
163
+ end
164
+
165
+ # Convert the keywordarray to a string an limit the number
166
+ # of keywords according to @nrkeywords or the parameter 'all'
167
+ if @@metadata['keywords'] = !@allkeywords
168
+ keywords = keywordsarraySorted.values_at(*(0..@nrkeywords-1)).join('-')
169
+ else
170
+ keywords = keywordsarraySorted.join('-')
171
+ end
172
+
173
+ # Normalize all keywords and return value
174
+ I18n.enforce_available_locales = false
175
+ I18n.transliterate(keywords).downcase.chomp('-')
176
+
177
+ else # Keywords metafield is empty :(
178
+ # So we return nothing or the preface (if available)
179
+
180
+ !preface.empty? ? preface : ''
181
+
182
+ end
183
+
184
+ end
185
+
186
+
187
+
188
+ # Get the preface for the keywords
189
+ # If the title is meaningful, then the
190
+ # subject will become the preface ( = first keyword)
191
+ # If the subject matches number/character combination and contains no spaces,
192
+ # the preface will be combined with the doctype.
193
+ # If not: The preface will contain the whole subject with dots and spaces being
194
+ # replaced with underscores.
195
+ def get_keywordsPreface(filedata = {})
196
+
197
+ I18n.enforce_available_locales = false
198
+ if filedata[:doctype].nil? or filedata[:doctype].empty?
199
+ filedata[:doctype] = @defaultDoctype
200
+ end
201
+
202
+ if !filedata[:subject].nil? and !filedata[:subject].empty? and
203
+ !filedata[:doctype] == @defaultDoctype
204
+
205
+ I18n.transliterate(filedata[:subject])
206
+
207
+ else
208
+
209
+ # Document matches standard document type.
210
+ # title and subject are being returned.
211
+
212
+ # Normalize special characters
213
+ title = @@metadata['title'].downcase
214
+ subject = !filedata[:subject].empty? ? '_' + filedata[:subject].downcase : ''
215
+ subject = subject.gsub(/\s|\-|\&/, '_')
216
+ I18n.transliterate(title + subject)
217
+
218
+ end
219
+
220
+ end
221
+
222
+ # Get the doctype from the title
223
+ #
224
+ def get_doctype()
225
+ doctype = @defaultDoctype
226
+ @@keymapping.each do |key,value|
227
+ value.kind_of?(String) ? value = value.split : ''
228
+ value.each do |keyword|
229
+ @@metadata['title'].match(/#{keyword}/i) ? doctype = key : ''
230
+ end
231
+ end
232
+ doctype.downcase
233
+ end
234
+
235
+ # Get the author from the metatags and
236
+ # normalize the string
237
+ def get_author()
238
+ author = @@metadata['author'].gsub(/\./,'_').gsub(/\&/,'').gsub(/\-/,'').gsub(/\s|\//,'_').gsub(/\,/,'_').gsub(/\_\_/,'_')
239
+ I18n.enforce_available_locales = false
240
+ I18n.transliterate(author).downcase # Normalising
241
+ end
242
+
243
+ end
@@ -0,0 +1,88 @@
1
+ # == Class: pdfmd.show
2
+ #
3
+ class Pdfmdshow < Pdfmd
4
+ attr_accessor :filename
5
+
6
+ @@show_filename = false
7
+ @@outputformat = ''
8
+ @@default_tags = ['createdate', 'author', 'title', 'subject', 'keywords']
9
+
10
+ def initialize(filename)
11
+ super(filename)
12
+ @filename = filename
13
+ end
14
+
15
+
16
+ # Define if the filename should be visible in the output
17
+ def show_filename( enable = nil)
18
+ @@show_filename = enable ? true : false
19
+ end
20
+
21
+
22
+ # Define the output format for showing the metadata
23
+ def set_outputformat( format = 'yaml' )
24
+ format.nil? ? format = 'yaml' : ''
25
+ self.log('debug',"Output format set to '#{format}'.")
26
+ @@outputformat = format
27
+ end
28
+
29
+ # Overvwrite the tags
30
+ def set_tags( tags = @@default_tags)
31
+
32
+ if tags
33
+
34
+ # Tags can be specified as array or string
35
+ #
36
+ case tags.class.to_s
37
+ when /array/i
38
+ @@default_tags = tags
39
+ when /string/i
40
+ @@default_tags = tags.split(/,\s+/)
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ # Return the provided metatags
48
+ def show_metatags( tags = @@default_tags, format = @@outputformat, show_filename = @@show_filename )
49
+
50
+ # Build the output hash from the tags matching the values in @@default_tags
51
+ metadataOutputHash = Hash.new
52
+ tags.each do |tagname|
53
+ if @@metadata.has_key?(tagname)
54
+ metadataOutputHash[tagname] = @@metadata[tagname]
55
+ elsif tagname.downcase == 'all' # Exception when for keyword 'all'
56
+ metadataOutputHash = @@metadata
57
+ end
58
+ end
59
+
60
+ if show_filename
61
+ metadataOutputHash['filename'] = @filename
62
+ end
63
+
64
+ # Return output well formatted
65
+ case format
66
+ when /hash/i
67
+ self.log('info',"Showing metatags for '#{@filename}' in format 'hash'.")
68
+ metadataOutputHash
69
+ when /csv/i
70
+ csvData = Hash.new
71
+ metadataOutputHash.keys.each do |tagname|
72
+ csvData[tagname] = '"' + metadataOutputHash[tagname.downcase].to_s.gsub(/"/,'""') + '"'
73
+ end
74
+ self.log('info',"Showing metatags for '#{@filename}' in format 'csv'.")
75
+ csvData.values.join(',')
76
+ when /json/i
77
+ require 'json'
78
+ self.log('info',"Showing metatags for '#{@filename}' in format 'json'.")
79
+ metadataOutputHash.to_json
80
+ else
81
+ require 'yaml'
82
+ self.log('info',"Showing metatags for '#{@filename}' in format 'yaml'.")
83
+ metadataOutputHash.to_yaml
84
+ end
85
+
86
+ end
87
+
88
+ end