yore 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,159 +0,0 @@
1
- require 'logger'
2
- require 'ihl_ruby/misc_utils'
3
-
4
- class Logger
5
- attr_reader :logdev
6
- end
7
-
8
- module LogUtils
9
-
10
- # eg.
11
- # {
12
- # 'destination' => 'STDERR|STDOUT|FILE',
13
- # 'filename' => '/path/to/file.ext',
14
- # 'level' => 'DEBUG|INFO|...',
15
- #
16
- # 'age' = 'daily|weekly|monthly',
17
- # OR
18
- # 'max_files' => 3,
19
- # 'max_bytes' => 1024000
20
- # }
21
- def self.create_logger_from_config(aConfigHash)
22
- if not aConfigHash
23
- result = Logger.new(STDERR)
24
- result.level = Logger::INFO
25
- return result
26
- end
27
-
28
- result = nil
29
- case aConfigHash['destination']
30
- when 'STDERR' then
31
- result = Logger.new(STDERR)
32
- when 'STDOUT' then
33
- result = Logger.new(STDOUT)
34
- when 'FILE' then
35
- result = aConfigHash['age'] ?
36
- Logger.new(aConfigHash['filename'],aConfigHash['age']) :
37
- Logger.new(
38
- aConfigHash['filename'],
39
- (aConfigHash['max_files'] || 3).to_i,
40
- (aConfigHash['max_bytes'] || 1024000).to_i
41
- )
42
- else
43
- result = Logger.new(STDERR)
44
- end
45
- puts valstr = "Logger::#{(aConfigHash['level'] || 'INFO').upcase}"
46
- result.level = eval(valstr)
47
- return result
48
- end
49
-
50
- # use this to trunc a log file to 0 bytes
51
- def self.trunc(aFilename)
52
- f = File.open(aFilename, "w")
53
- f.close
54
- end
55
-
56
- class ReportFormatter < Logger::Formatter
57
- def call(severity, time, progname, msg)
58
- "|%s %1s %s\n" % [(time.strftime('%H%M%S.')<<"%03d" % (time.usec/1000)),severity[0..0],msg2str(msg)]
59
- end
60
- end
61
-
62
- class Reporter < Logger
63
- def initialize(logdev)
64
- super(logdev)
65
- end
66
-
67
- end
68
-
69
- def self.create_reporter(aFilename=nil)
70
- aFilename ||= MiscUtils::temp_file()
71
- result = Logger.new(aFilename)
72
- result.formatter = ReportFormatter.new
73
- result
74
- end
75
- end
76
-
77
-
78
-
79
- class MultiLogger < Logger
80
-
81
- attr_reader :loggers
82
-
83
- def initialize(aLoggers)
84
- @loggers = aLoggers.is_a?(Array) ? aLoggers : [aLoggers]
85
- end
86
-
87
- def add(severity, message = nil, progname = nil, &block)
88
- return true if !@loggers
89
- severity ||= UNKNOWN
90
- @loggers.each do |lr|
91
- block_given? ? lr.add(severity,message,progname,&block) : lr.add(severity,message,progname)
92
- end
93
- true
94
- end
95
- alias log add
96
-
97
- def <<(msg)
98
- @loggers.each do |lr|
99
- lr << msg
100
- end
101
- end
102
-
103
- def close
104
- @loggers.each do |lr|
105
- lr.close
106
- end
107
- end
108
-
109
- end
110
-
111
- #DEBUG D
112
- #INFO
113
- #WARN ?
114
- #ERROR !
115
- #FATAL F
116
- #UNKNOWN U
117
-
118
- # Logger that mostly works like a STDOUT logger, except that warnings and above get sent to STDERR instead
119
- class ConsoleLogger < Logger
120
-
121
- class ReportFormatter < Logger::Formatter
122
- def call(severity, time, progname, msg)
123
- msg2str(msg)+"\n"
124
- end
125
- end
126
-
127
- def initialize(aErrLevel = Severity::WARN)
128
- super(STDOUT)
129
- self.formatter = ReportFormatter.new
130
- self.level = Severity::INFO
131
- self << "\n"
132
- @err_logger = Logger.new(STDERR)
133
- @err_level = aErrLevel
134
- @err_logger.formatter = ReportFormatter.new
135
- end
136
-
137
- alias_method :orig_add, :add
138
- def add(severity, message = nil, progname = nil, &block)
139
- if severity >= @err_level
140
- block_given? ? @err_logger.add(severity,message,progname,&block) : @err_logger.add(severity,message,progname)
141
- else
142
- block_given? ? orig_add(severity,message,progname,&block) : orig_add(severity,message,progname)
143
- end
144
- end
145
- alias log add
146
-
147
- #
148
- # Close the logging device.
149
- #
150
- def close
151
- begin
152
- @logdev.close if @logdev
153
- ensure
154
- @err_logger.close
155
- end
156
- end
157
-
158
- end
159
-
@@ -1,382 +0,0 @@
1
- require 'tmpdir'
2
- require 'logger'
3
- require 'pathname'
4
-
5
- require 'ihl_ruby/logging'
6
-
7
- module MiscUtils
8
-
9
- def self.logger
10
- @logger || @logger = Logger.new(STDERR)
11
- end
12
-
13
- # applies the given block to key/value pairs included/excluded by the given parameters
14
- # aSource must be a hash, and may contain hashes which will be recursively processed.
15
- # aInclude/aExclude may be nil, an array of selected keys, or a hash containing arrays of keys for inner hashes of aSource
16
- # When aInclude/aExclude are a hash, non-hash source values may be selected by passing a value of true. Hash source values
17
- # will be selected as a whole (all keys) when true is passed.
18
- # input = { 'a' => 1, 'b' => {'x' => 9, 'y' => 8}, 'c' => 3 }
19
- # filter_multilevel_hash(input,['a','b'],{'b'=>['y']}) {|h,k,v| h[k] = true}
20
- # input now = { 'a' => true, 'b' => {'x' => true, 'y' => 8}, 'c' => 3 }
21
- def self.filter_multilevel_hash(aSource,aInclude=nil,aExclude=nil,&block)
22
- aSource.each do |key,value|
23
- next if aInclude.is_a?(Array) and !aInclude.include?(key) # skip if not in aInclude array
24
- next if aExclude.is_a?(Array) and aExclude.include?(key) # skip if in aExclude array
25
- next if aExclude.is_a?(Hash) and aExclude[key]==true # skip if in aExclude hash with value=true
26
- next if aInclude.is_a?(Hash) and !aInclude.include?(key) # skip if not in aInclude hash at all
27
- if value.is_a?(Hash) # value is hash so recursively apply filter
28
- filter_multilevel_hash(
29
- value,
30
- aInclude.is_a?(Hash) && (f = aInclude[key]) ? f : nil, # pass include array if provided for key
31
- aExclude.is_a?(Hash) && (f = aExclude[key]) ? f : nil, # pass exclude array if provided for key
32
- &block
33
- )
34
- else
35
- yield(aSource,key,value)
36
- end
37
- end
38
- end
39
-
40
- # returns output string if succesful, or integer return code if not, or nil
41
- def self.execute(aCommand,aWorkingDir=nil,aTimeout=nil,aTimeoutClass=nil)
42
- return nil unless !aWorkingDir || File.exists?(aWorkingDir)
43
- begin
44
- orig_wd = Dir.getwd
45
- pipe = nil
46
- result = nil
47
- Dir.chdir(aWorkingDir) if aWorkingDir
48
- Timeout.timeout(aTimeout,aTimeoutClass || Timeout::Error) do # nil aTimeout will not time out
49
- pipe = IO.popen(aCommand)
50
- logger.debug "command PID:"+pipe.pid.to_s
51
- result = pipe.read
52
- end
53
- ensure
54
- pipe.close if pipe
55
- Dir.chdir(orig_wd)
56
- end
57
- return result
58
- end
59
-
60
- def self.execute_string(aCmdString,aWorkingDir=nil)
61
- result = nil
62
- begin
63
- orig_dir = Dir.pwd
64
- Dir.chdir(aWorkingDir) if aWorkingDir
65
- result = `#{aCmdString}`
66
- ensure
67
- Dir.chdir(orig_dir) if aWorkingDir
68
- end
69
- return result
70
- end
71
-
72
- def self.temp_file(aExt=nil,aDir=nil)
73
- aExt ||= '.tmp'
74
- File.expand_path(("%08X" % rand(0x3FFFFFFF)) + aExt, aDir||Dir.tmpdir)
75
- end
76
-
77
- def self.make_temp_file(aName=nil,aDir=nil,aContent=nil)
78
- filename = aName ? File.expand_path(aName,aDir || Dir.tmpdir) : temp_file(nil,aDir)
79
- FileUtils.mkdir_p(File.dirname(filename))
80
- aContent ||= "content of "+filename
81
- string_to_file(aContent,filename)
82
- filename
83
- end
84
-
85
- def self.make_temp_dir(aPrefix='')
86
- new_dir = nil
87
- begin
88
- new_dir = File.join(Dir.tmpdir,aPrefix+("%08X" % rand(0x3FFFFFFF)))
89
- end until new_dir && !File.exists?(new_dir)
90
- Dir.mkdir new_dir
91
- return new_dir
92
- end
93
-
94
- def self.mkdir?(aPath,aPermissions)
95
- if File.exists?(aPath)
96
- File.chmod(aPermissions, aPath)
97
- else
98
- Dir.mkdir(aPath, aPermissions)
99
- end
100
- end
101
-
102
- def self.string_to_file(aString,aFilename)
103
- File.open(aFilename,'wb') {|file| file.puts aString }
104
- end
105
-
106
- def self.string_from_file(aFilename)
107
- result = nil
108
- File.open(aFilename, "rb") { |f| result = f.read }
109
- return result && result[0..-2] # quick hack to stop returning false \n at end
110
- end
111
-
112
- def self.sniff_seperator(aPath)
113
- result = 0.upto(aPath.length-1) do |i|
114
- char = aPath[i,1]
115
- break char if char=='\\' || char=='/'
116
- end
117
- result = File::SEPARATOR if result==0
118
- return result
119
- end
120
-
121
- def self.append_slash(aPath,aSep=nil)
122
- aSep = sniff_seperator(aPath) unless aSep
123
- last_char = aPath[-1,1]
124
- aPath += aSep unless last_char=='\\' || last_char=='/'
125
- return aPath
126
- end
127
-
128
- def self.remove_slash(aPath)
129
- last_char = aPath[-1,1]
130
- aPath = aPath[0..-2] if last_char=='\\' || last_char=='/'
131
- return aPath
132
- end
133
-
134
- # Remove base dir from given path. Result will be relative to base dir and not have a leading or trailing slash
135
- #'/a/b/c','/a' = 'b/c'
136
- #'/a/b/c','/' = 'a/b/c'
137
- #'/','/' = ''
138
- def self.path_debase(aPath,aBase)
139
- aBase = MiscUtils::append_slash(aBase)
140
- aPath = MiscUtils::remove_slash(aPath) unless aPath=='/'
141
- aPath[0,aBase.length]==aBase ? aPath[aBase.length,aPath.length-aBase.length] : aPath
142
- end
143
-
144
- def self.path_rebase(aPath,aOldBase,aNewBase)
145
- rel_path = path_debase(aPath,aOldBase)
146
- append_slash(aNewBase)+rel_path
147
- end
148
-
149
- def self.path_combine(aBasePath,aPath)
150
- return aBasePath if !aPath
151
- return aPath if !aBasePath
152
- return path_relative?(aPath) ? File.join(aBasePath,aPath) : aPath
153
- end
154
-
155
- def self.path_parent(aPath)
156
- MiscUtils.append_slash(File.dirname(MiscUtils.remove_slash(File.expand_path(aPath))))
157
- end
158
-
159
- def self.simple_dir_name(aPath)
160
- File.basename(remove_slash(aPath))
161
- end
162
-
163
- def self.path_parts(aPath)
164
- sep = sniff_seperator(aPath)
165
- aPath.split(sep)
166
- end
167
-
168
- def self.file_extension(aFile,aExtended=true)
169
- f = File.basename(aFile)
170
- dot = aExtended ? f.index('.') : f.rindex('.')
171
- return dot ? f[dot+1..-1] : f
172
- end
173
-
174
- def self.file_no_extension(aFile,aExtended=true)
175
- ext = file_extension(aFile,aExtended)
176
- return aFile.chomp('.'+ext)
177
- end
178
-
179
- def self.file_change_ext(aFile,aExt,aExtend=false)
180
- file_no_extension(aFile,false)+(aExtend ? '.'+aExt+'.'+file_extension(aFile,false) : '.'+aExt)
181
- end
182
-
183
- def self.platform
184
- RUBY_PLATFORM.scan(/-(.+)$/).flatten.first
185
- end
186
-
187
- def self.windows_path(aPath)
188
- aPath.gsub('/','\\')
189
- end
190
-
191
- def self.ruby_path(aPath)
192
- aPath.gsub('\\','/')
193
- end
194
-
195
- def self.is_uri?(aString)
196
- /^[a-zA-Z0-9+_]+\:\/\// =~ aString ? true : false
197
- end
198
-
199
- def self.native_path(aPath)
200
- is_windows? ? windows_path(aPath) : ruby_path(aPath)
201
- end
202
-
203
- def self.path_relative?(aPath)
204
- return false if aPath[0,1]=='/'
205
- return false if aPath =~ /^[a-zA-Z]:/
206
- return true
207
- end
208
-
209
- def self.path_absolute?(aPath)
210
- !path_relative(aPath)
211
- end
212
-
213
- def self.is_windows?
214
- platform=='mswin32'
215
- end
216
-
217
- # takes a path and combines it with a root path (which defaults to Dir.pwd) unless it is absolute
218
- # the final result is then expanded
219
- def self.canonize_path(aPath,aRootPath=nil)
220
- path = Pathname.new(aPath)
221
- path = Pathname.new(aRootPath || Dir.pwd)+path if path.relative?
222
- File.expand_path(path)
223
- end
224
-
225
- def self.get_files(aArray,aPath,aFullPath=true,aRootPath=nil,&block)
226
- #puts "get_files: aPath='#{aPath}'"
227
- if aRootPath
228
- abssrcpath = path_combine(aRootPath,aPath)
229
- else
230
- abssrcpath = aRootPath = aPath
231
- aPath = nil
232
- end
233
- return aArray if !File.exists?(abssrcpath)
234
- #abssrcpath is real path to query
235
- #aRootPath is highest level path
236
- #aPath is current path relative to aRootPath
237
- Dir.new(abssrcpath).to_a.each do |file|
238
- next if ['.','..'].include? file
239
- fullpath = File.join(abssrcpath,file)
240
- resultpath = aFullPath ? fullpath : path_combine(aPath,file)
241
- if !block_given? || yield(resultpath)
242
- if FileTest.directory?(fullpath)
243
- block_given? ? get_files(aArray,path_combine(aPath,file),aFullPath,aRootPath,&block) : get_files(aArray,path_combine(aPath,file),aFullPath,aRootPath)
244
- else
245
- aArray << resultpath
246
- end
247
- end
248
- end
249
- return aArray
250
- end
251
-
252
- def self.recursive_file_list(aPath,aFullPath=true,&block)
253
- block_given? ? get_files([],aPath,aFullPath,nil,&block) : get_files([],aPath,aFullPath)
254
- end
255
-
256
- # returns true if aPath1 and aPath2 are the same path (doesn't query file system)
257
- # both must be absolute or both relative
258
- def self.path_same(aPath1,aPath2)
259
- return nil unless path_relative?(aPath1) == path_relative?(aPath2)
260
- remove_slash(aPath1) == remove_slash(aPath2)
261
- end
262
-
263
- # returns true if aPath is under aPathParent
264
- # both must be absolute or both relative
265
- def self.path_ancestor(aPathParent,aPath)
266
- return nil unless path_relative?(aPathParent) == path_relative?(aPath)
267
- aPath.index(append_slash(aPathParent))==0
268
- end
269
-
270
- # returns the lowest path containing all files (assumes aFiles contains only absolute paths)
271
- def self.file_list_ancestor(aFiles)
272
- files = aFiles.is_a?(Hash) ? aFiles.keys : aFiles
273
- result = File.dirname(files.first)
274
- files.each do |fp|
275
- filedir = File.dirname(fp)
276
- while path_same(result,filedir)==false && path_ancestor(result,filedir)==false
277
- result = path_parent(result)
278
- end
279
- end
280
- result
281
- end
282
-
283
- def self.path_match(aPath,aPatterns)
284
- aPatterns = [aPatterns] unless aPatterns.is_a? Array
285
- aPatterns.any? do |pat|
286
- case pat
287
- when String then aPath[0,pat.length] == pat
288
- when Regexp then aPath =~ pat
289
- else false
290
- end
291
- end
292
- end
293
-
294
-
295
- # takes a hash and returns a single closed tag containing the hash pairs as attributes, correctly encoded
296
- def self.hash_to_xml_tag(aName,aHash)
297
- atts = ''
298
- aHash.each do |k,v|
299
- atts += ' ' + k.to_s + "=\"#{v.to_s.to_xs}\""
300
- end
301
- "<#{aName}#{atts}/>"
302
- end
303
-
304
- def self.filelist_from_patterns(aPatterns,aBasePath)
305
- return [] unless aPatterns
306
- aPatterns = [aPatterns] unless aPatterns.is_a? Array
307
-
308
- aPatterns.map do |fp|
309
- fp = File.expand_path(fp,aBasePath) # relative to rails root
310
- fp = FileList[fp] if fp['*'] || fp['?']
311
- fp
312
- end.flatten
313
- end
314
-
315
- #:host
316
- #:port
317
- #:helodomain
318
- #:user
319
- #:password
320
- #:from
321
- #:from_alias
322
- #:to
323
- #:to_alias
324
- #:subject
325
- #:message
326
- #:auth : 'plain', 'login', 'cram_md5'
327
-
328
- # send an email via an SMTP server
329
- def self.send_email(aArgs)
330
- msg = <<END_OF_MESSAGE
331
- From: #{aArgs[:from_alias]} <#{aArgs[:from]}>
332
- To: #{aArgs[:to_alias]} <#{aArgs[:to]}>
333
- Subject: #{aArgs[:subject]}
334
-
335
- #{aArgs[:message]}
336
- END_OF_MESSAGE
337
-
338
- Net::SMTP.start(
339
- aArgs[:host],
340
- aArgs[:port],
341
- aArgs[:helodomain],
342
- aArgs[:user],
343
- aArgs[:password],
344
- aArgs[:auth]
345
- ) do |smtp|
346
- smtp.send_message msg, aArgs[:from], aArgs[:to]
347
- end
348
- end
349
-
350
- end
351
-
352
- # include this at the top of a class to protect it from baddies.
353
- # eg.
354
- # + nearly all ancestor public_instance_methods will be hidden
355
- # + inspect will only return the class name
356
- # + methods will return public methods
357
- module SecureThisClass
358
- def self.hack(aClass,aOptions={})
359
- include_actions = (aOptions[:include] || aClass.public_instance_methods.clone)
360
- exclude_actions = ['class','public_methods'] | (aOptions[:exclude] || [])
361
- actions_to_hide = include_actions-exclude_actions
362
- aClass.class_eval do
363
- actions_to_hide.each { |m| protected m.to_sym }
364
-
365
- def inspect
366
- return self.class.name
367
- end
368
-
369
- def methods
370
- public_methods
371
- end
372
- end
373
- end
374
- end
375
-
376
-
377
- module ::Kernel
378
- def secure_class(aOptions={})
379
- SecureThisClass::hack(self,aOptions)
380
- end
381
- end
382
-
@@ -1,84 +0,0 @@
1
- require 'rubygems'
2
- gem 'RequirePaths'; require 'require_paths'
3
- require_paths '.','..'
4
-
5
- gem 'Platform'; require 'platform'
6
- gem 'shairontoledo-popen4'; require 'popen4'
7
-
8
- module POpen4
9
-
10
- class ExecuteError < StandardError
11
-
12
- attr_reader :result #,:stderr,:stdout,:exitcode,:pid
13
-
14
- def initialize(aArg)
15
- if aArg.is_a? Hash
16
- msg = ([aArg[:stderr],aArg[:stdout],"Error #{aArg[:exitcode].to_s}"].find {|i| i && !i.empty?})
17
- super(msg)
18
- @result = aArg
19
- else
20
- super(aArg)
21
- end
22
- end
23
-
24
- def inspect
25
- "#{self.class.to_s}: #{@result.inspect}"
26
- end
27
-
28
- end
29
-
30
- def self.pump_thread(aIn,aOut)
31
- Thread.new do
32
- loop { aOut.puts aIn.gets }
33
- end
34
- end
35
-
36
- # Usage :
37
- # result = POpen4::shell('somebinary') do |r| # block gives opportunity to adjust result, and avoid exception raised from non-zero exit codes
38
- # if r[:exitcode]==254 # eg. say this binary returns 254 to mean something special but not an error
39
- # r[:stdout] = 'some correct output'
40
- # r[:stderr] = ''
41
- # r[:exitcode] = 0
42
- # end
43
- # end
44
- #
45
- # OR
46
- #
47
- # result = POpen4::shell('somebinary');
48
- # puts result[:stdout]
49
- #
50
- # Giving aStdOut,aStdErr causes the command output to be connected to the given stream, and that stream to not be given in the result hash
51
- def self.shell(aCommand,aWorkingDir=nil,aTimeout=nil,aStdOut=nil,aStdErr=nil)
52
- raise ExecuteError.new('aWorkingDir doesnt exist') unless !aWorkingDir || File.exists?(aWorkingDir)
53
- orig_wd = Dir.getwd
54
- result = {:command => aCommand, :dir => (aWorkingDir || orig_wd)}
55
- status = nil
56
- begin
57
- Dir.chdir(aWorkingDir) if aWorkingDir
58
- Timeout.timeout(aTimeout,ExecuteError) do # nil aTimeout will not time out
59
- status = POpen4::popen4(aCommand) do |stdout, stderr, stdin, pid|
60
- thrOut = aStdOut ? Thread.new { aStdOut.puts stdout.read } : nil
61
- thrErr = aStdErr ? Thread.new { aStdErr.puts stderr.read } : nil
62
- thrOut.join if thrOut
63
- thrErr.join if thrErr
64
-
65
- result[:stdout] = stdout.read unless aStdOut
66
- result[:stderr] = stderr.read unless aStdErr
67
- result[:pid] = pid
68
- end
69
- end
70
- ensure
71
- Dir.chdir(orig_wd)
72
- end
73
- result[:exitcode] = (status && status.exitstatus) || 1
74
- yield(result) if block_given?
75
- raise ExecuteError.new(result) if result[:exitcode] != 0
76
- return result
77
- end
78
-
79
- def self.shell_out(aCommand,aWorkingDir=nil,aTimeout=nil,&block)
80
- block_given? ? POpen4::shell(aCommand,aWorkingDir,aTimeout,STDOUT,STDERR,&block) : POpen4::shell(aCommand,aWorkingDir,aTimeout,STDOUT,STDERR)
81
- end
82
-
83
- end
84
-
@@ -1,53 +0,0 @@
1
- module StringUtils
2
- def self.crop(aString,aLength,aEllipsis=true,aConvertNil=true)
3
- return aConvertNil ? ' '*aLength : nil if !aString
4
-
5
- increase = aLength-aString.length
6
- return aString+' '*increase if increase>=0
7
- return aEllipsis ? aString[0,aLength-3]+'...' : aString[0,aLength]
8
- end
9
-
10
- # aTemplate is a string containing tokens like ${SOME_TOKEN}
11
- # aValues is a hash of token names eg. 'SOME_TOKEN' and their values to substitute
12
- def self.render_template(aTemplate,aValues)
13
- # get positions of tokens
14
- result = aTemplate.gsub(/\$\{(.*?)\}/) do |s|
15
- key = s[2..-2]
16
- rep = (aValues[key] || s)
17
- #puts "replacing #{s} with #{rep}"
18
- rep
19
- end
20
- #puts "rendered :\n#{result}"
21
- return result
22
- end
23
-
24
- def self.clean_number(aString)
25
- aString.gsub(/[^0-9.-]/,'')
26
- end
27
-
28
- # supply a block with 2 parameters, and it will get called for each char as an integer
29
- def self.each_unicode_char(aString)
30
- len = 1
31
- index = 0
32
- char = 0
33
- aString.each_byte do |b|
34
- if index==0
35
- len = 1
36
- len = 2 if b & 0b11000000 != 0
37
- len = 3 if b & 0b11100000 != 0
38
- len = 4 if b & 0b11110000 != 0
39
- char = 0
40
- end
41
-
42
- char |= b << index*8
43
-
44
- yield(char,len) if index==len-1 # last byte; char is complete
45
-
46
- index += 1
47
- index = 0 if index >= len
48
- end
49
- end
50
-
51
-
52
- end
53
-