buzzware-buzzcore 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,188 @@
1
+ require 'net/ftp'
2
+
3
+ this_path = File.dirname(__FILE__)
4
+ require this_path+'/misc_utils'
5
+
6
+ String.class_eval do
7
+ def bite!(aValue=$/,aString=self)
8
+ if aString[0,aValue.length] == aValue
9
+ aString[0,aValue.length] = ''
10
+ return aString
11
+ else
12
+ return aString
13
+ end
14
+ end
15
+
16
+ def bite(aValue=$/)
17
+ bite!(aValue,self.clone)
18
+ end
19
+ end
20
+
21
+
22
+ module Net
23
+ class FTP
24
+ def FTP.with_connect(aHost,aUsername,aPassword,aDir=nil)
25
+ open(aHost,aUsername,aPassword) do |f|
26
+ f.passive = true
27
+ f.chdir(aDir) if aDir
28
+ yield f
29
+ end
30
+ end
31
+
32
+ def self.crack_file_line(aString)
33
+ values = aString.scan(/(.{10}).{28}(.{13})(.*)$/).flatten
34
+ {
35
+ :bits => values[0],
36
+ :date => values[1],
37
+ :name => values[2]
38
+ }
39
+ end
40
+
41
+ # BEGIN BUGFIXES
42
+
43
+ #
44
+ # Returns the size of the given (remote) filename.
45
+ #
46
+ def size(filename)
47
+ voidcmd("TYPE I")
48
+ resp = sendcmd("SIZE " + filename)
49
+ code = resp[0, 3]
50
+ if code != "213" && code != "220"
51
+ raise FTPReplyError, resp
52
+ end
53
+ return resp[3..-1].strip.to_i
54
+ end
55
+
56
+ # END BUGFIXES
57
+
58
+ def subdirs(aPath)
59
+ list.delete_if {|line| line[0,1]=='d'}
60
+ return list
61
+ end
62
+
63
+ def files(aPath)
64
+ list.delete_if {|line| line[0,1]!='d'}
65
+ return list
66
+ end
67
+
68
+ def expand_dir(aPath,aBase=nil)
69
+ return aPath if aPath=='/'
70
+ return MiscUtils::path_relative?(aPath) ? File.expand_path(aPath,aBase || pwd()) : File.expand_path(aPath)
71
+ end
72
+
73
+ def dir_exists?(aPath)
74
+ aPath = expand_dir(aPath)
75
+ return true if aPath=='/'
76
+ dirname = File.basename(aPath)
77
+ parent = MiscUtils.path_parent(aPath)
78
+ dirname!='' && nlst(parent).include?(dirname)
79
+ end
80
+
81
+ def file_exists?(aPath)
82
+ aPath = expand_dir(aPath)
83
+ filename = File.basename(aPath)
84
+ parent = File.dirname(aPath)
85
+ filename!='' && nlst(parent).include?(filename)
86
+ end
87
+
88
+ def filelist_recurse(aPath=nil,aResult=nil,&block)
89
+ #puts "filelist_recurse: #{aPath.to_s} #{aResult.inspect}"
90
+ orig_dir = !aResult ? pwd : nil # assigned if called at top with aResult=nil
91
+ aResult ||= []
92
+ aPath ||= ''
93
+ chdir(aPath)
94
+ list('*').each do |f|
95
+ is_dir = f[0,1]=='d'
96
+ details = FTP::crack_file_line(f)
97
+ full = File.join(aPath,details[:name])
98
+ if !block_given? || yield(full)
99
+ if is_dir
100
+ filelist_recurse(full,aResult)
101
+ else
102
+ aResult << full
103
+ end
104
+ end
105
+ end
106
+ chdir(orig_dir) if orig_dir
107
+ return aResult
108
+ end
109
+
110
+ def get_files(aRemoteDir,aLocalDir,aFiles,aOptions=nil)
111
+ aOptions = {:overwrite => true}.merge(aOptions || {})
112
+ aFiles.each do |r|
113
+ relative = r.bite(MiscUtils::append_slash(aRemoteDir))
114
+ d = File.join(aLocalDir,relative)
115
+ puts "getting #{relative}"
116
+ getbinaryfile(r, d) unless !aOptions[:overwrite] && File.exists?(d)
117
+ end
118
+ end
119
+
120
+ def get_dir(aRemoteDir,aLocalDir,aOptions=nil,&block)
121
+ remote_files = block_given? ? filelist_recurse(aRemoteDir,nil,&block) : filelist_recurse(aRemoteDir)
122
+ get_files(aRemoteDir,aLocalDir,remote_files,aOptions)
123
+ end
124
+
125
+ def highest_existing(aPath)
126
+ sep = MiscUtils::sniff_seperator(aPath)
127
+ path = MiscUtils::path_parts(File.expand_path(aPath)) if aPath.is_a?(String)
128
+ # now assume path is an Array
129
+ depth = path.length-1
130
+ depth.downto(0) do |i| # from full path up to root
131
+ curr = (path[0]=='' && i==0) ? '/' : path[0..i].join(sep)
132
+ return curr if dir_exists?(curr)
133
+ end
134
+ return sep # root
135
+ end
136
+
137
+ def ensure_dir(aPath,aThorough=false)
138
+ if !aThorough
139
+ mkdir(aPath) unless dir_exists?(aPath)
140
+ else
141
+ return if dir_exists?(aPath)
142
+ path = expand_dir(aPath)
143
+ hi_existing = highest_existing(path)
144
+ # path to create under hi_existing
145
+ to_create = MiscUtils::path_debase(path,hi_existing)
146
+ parts = MiscUtils::path_parts(to_create)
147
+ curr_path = hi_existing
148
+
149
+ parts.each do |part|
150
+ curr_path = File.join(curr_path,part)
151
+ mkdir(curr_path)
152
+ end
153
+ end
154
+ end
155
+
156
+ def put_files(aLocalDir,aRemoteDir,aFiles,aOptions=nil)
157
+ aOptions = {:overwrite => true}.merge(aOptions || {})
158
+
159
+ # convert all files to relative to aLocalDir
160
+ aFiles = aFiles.map { |f| f.bite(MiscUtils::append_slash(aLocalDir)) }.sort
161
+
162
+ filelist = nil
163
+ this_dir = last_dir = nil
164
+ aFiles.each do |r|
165
+ d = File.expand_path(r,aRemoteDir)
166
+ this_dir = File.dirname(d)
167
+ if this_dir!=last_dir
168
+ ensure_dir(this_dir,true)
169
+ filelist = files(this_dir) - ['.','..','.svn']
170
+ end
171
+ if aOptions[:overwrite] || !filelist.member?(File.basename(r))
172
+ puts "Putting #{r}"
173
+ putbinaryfile(File.expand_path(r,aLocalDir), d)
174
+ else
175
+ puts "Skipping #{relative}"
176
+ end
177
+ last_dir = this_dir
178
+ end
179
+ end
180
+
181
+ def put_dir(aLocalDir,aRemoteDir,&block)
182
+ local_files = block_given? ? MiscUtils::recursive_file_list(aLocalDir,true,&block) : MiscUtils::recursive_file_list(aLocalDir)
183
+ put_files(aLocalDir,aRemoteDir,local_files)
184
+ end
185
+
186
+ end
187
+ end
188
+
@@ -0,0 +1,159 @@
1
+ require 'logger'
2
+ require 'buzzcore/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
+
@@ -0,0 +1,382 @@
1
+ require 'tmpdir'
2
+ require 'logger'
3
+ require 'pathname'
4
+
5
+ require 'buzzcore/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
+