pdfmd 1.9.1 → 2.0.0

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