drbservice 1.0.4

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,58 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ require 'digest/sha2'
5
+ require 'drbservice'
6
+
7
+ # An authentication strategy for DRbService -- set a password via a
8
+ # class method.
9
+ module DRbService::PasswordAuthentication
10
+
11
+ ### Methods added to including classes when PasswordAuthentication is
12
+ ### mixed in.
13
+ module ClassMethods
14
+
15
+ # The SHA2 digest of the service password
16
+ attr_accessor :password_digest
17
+
18
+ ### Set a password for the service. If you don't specify a password, even guarded
19
+ ### methods can be accessed. With a password set, the remote side can still call
20
+ ### unguarded methods, but all other methods will be hidden.
21
+ def service_password( password )
22
+ self.password_digest = Digest::SHA2.hexdigest( password )
23
+ DRbService.log.debug "Setting encrypted password for %p to "
24
+ end
25
+
26
+ end # module ClassMethods
27
+
28
+
29
+ ### Overridden mixin callback -- add the ClassMethods to the including class
30
+ def self::included( klass )
31
+ super
32
+ klass.extend( ClassMethods )
33
+ end
34
+
35
+
36
+ ### Authenticate using the specified +password+, calling the provided block if
37
+ ### authentication succeeds. Raises a SecurityError if authentication fails. If
38
+ ### no password is set, the block is called regardless of what the +password+ is.
39
+ def authenticate( password )
40
+ if digest = self.class.password_digest
41
+ if Digest::SHA2.hexdigest( password ) == digest
42
+ self.log.info "authentication successful"
43
+ @authenticated = true
44
+ yield
45
+ else
46
+ super
47
+ end
48
+ else
49
+ self.log.error "no password set -- authentication will always fail"
50
+ super
51
+ end
52
+ ensure
53
+ @authenticated = false
54
+ end
55
+
56
+ end # DRbService::PasswordAuthentication
57
+
58
+
@@ -0,0 +1,426 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'logger'
4
+ require 'erb'
5
+ require 'bigdecimal'
6
+ require 'date'
7
+
8
+ require 'drbservice'
9
+
10
+
11
+ class DRbService
12
+
13
+ ### A collection of ANSI color utility functions
14
+ module ANSIColorUtilities
15
+
16
+ # Set some ANSI escape code constants (Shamelessly stolen from Perl's
17
+ # Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
18
+ ANSI_ATTRIBUTES = {
19
+ 'clear' => 0,
20
+ 'reset' => 0,
21
+ 'bold' => 1,
22
+ 'dark' => 2,
23
+ 'underline' => 4,
24
+ 'underscore' => 4,
25
+ 'blink' => 5,
26
+ 'reverse' => 7,
27
+ 'concealed' => 8,
28
+
29
+ 'black' => 30, 'on_black' => 40,
30
+ 'red' => 31, 'on_red' => 41,
31
+ 'green' => 32, 'on_green' => 42,
32
+ 'yellow' => 33, 'on_yellow' => 43,
33
+ 'blue' => 34, 'on_blue' => 44,
34
+ 'magenta' => 35, 'on_magenta' => 45,
35
+ 'cyan' => 36, 'on_cyan' => 46,
36
+ 'white' => 37, 'on_white' => 47
37
+ }
38
+
39
+ ###############
40
+ module_function
41
+ ###############
42
+
43
+ ### Create a string that contains the ANSI codes specified and return it
44
+ def ansi_code( *attributes )
45
+ attributes.flatten!
46
+ attributes.collect! {|at| at.to_s }
47
+ return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
48
+ attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
49
+
50
+ if attributes.empty?
51
+ return ''
52
+ else
53
+ return "\e[%sm" % attributes
54
+ end
55
+ end
56
+
57
+
58
+ ### Colorize the given +string+ with the specified +attributes+ and return it, handling
59
+ ### line-endings, color reset, etc.
60
+ def colorize( *args )
61
+ string = ''
62
+
63
+ if block_given?
64
+ string = yield
65
+ else
66
+ string = args.shift
67
+ end
68
+
69
+ ending = string[/(\s)$/] || ''
70
+ string = string.rstrip
71
+
72
+ return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
73
+ end
74
+
75
+ end # module ANSIColorUtilities
76
+
77
+
78
+ #
79
+ # A alternate formatter for Logger instances.
80
+ #
81
+ # == Usage
82
+ #
83
+ # require 'drbservice/utils'
84
+ # DRbService.logger.formatter = DRbService::LogFormatter.new( DRbService.logger )
85
+ #
86
+ # == Version
87
+ #
88
+ # $Id: utils.rb,v 87bc5aa9e2be 2011/08/29 21:05:42 ged $
89
+ #
90
+ # == Authors
91
+ #
92
+ # * Michael Granger <ged@FaerieMUD.org>
93
+ #
94
+ # :include: LICENSE
95
+ #
96
+ #--
97
+ #
98
+ # Please see the file LICENSE in the 'docs' directory for licensing details.
99
+ #
100
+ class LogFormatter < Logger::Formatter
101
+
102
+ # The format to output unless debugging is turned on
103
+ DEFAULT_FORMAT = "[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"
104
+
105
+ # The format to output if debugging is turned on
106
+ DEFAULT_DEBUG_FORMAT = "[%1$s.%2$06d %3$d/%4$s] %5$5s {%6$s} -- %7$s\n"
107
+
108
+
109
+ ### Initialize the formatter with a reference to the logger so it can check for log level.
110
+ def initialize( logger, format=DEFAULT_FORMAT, debug=DEFAULT_DEBUG_FORMAT ) # :notnew:
111
+ @logger = logger
112
+ @format = format
113
+ @debug_format = debug
114
+
115
+ super()
116
+ end
117
+
118
+ ######
119
+ public
120
+ ######
121
+
122
+ # The Logger object associated with the formatter
123
+ attr_accessor :logger
124
+
125
+ # The logging format string
126
+ attr_accessor :format
127
+
128
+ # The logging format string that's used when outputting in debug mode
129
+ attr_accessor :debug_format
130
+
131
+
132
+ ### Log using either the DEBUG_FORMAT if the associated logger is at ::DEBUG level or
133
+ ### using FORMAT if it's anything less verbose.
134
+ def call( severity, time, progname, msg )
135
+ args = [
136
+ time.strftime( '%Y-%m-%d %H:%M:%S' ), # %1$s
137
+ time.usec, # %2$d
138
+ Process.pid, # %3$d
139
+ Thread.current == Thread.main ? 'main' : Thread.object_id, # %4$s
140
+ severity, # %5$s
141
+ progname, # %6$s
142
+ msg # %7$s
143
+ ]
144
+
145
+ if @logger.level == Logger::DEBUG
146
+ return self.debug_format % args
147
+ else
148
+ return self.format % args
149
+ end
150
+ end
151
+ end # class LogFormatter
152
+
153
+
154
+ #
155
+ # A ANSI-colorized formatter for Logger instances.
156
+ #
157
+ # == Usage
158
+ #
159
+ # require 'drbservice/utils'
160
+ # DRbService.logger.formatter = DRbService::ColorLogFormatter.new( DRbService.logger )
161
+ #
162
+ # == Version
163
+ #
164
+ # $Id: utils.rb,v 87bc5aa9e2be 2011/08/29 21:05:42 ged $
165
+ #
166
+ # == Authors
167
+ #
168
+ # * Michael Granger <ged@FaerieMUD.org>
169
+ #
170
+ # :include: LICENSE
171
+ #
172
+ #--
173
+ #
174
+ # Please see the file LICENSE in the 'docs' directory for licensing details.
175
+ #
176
+ class ColorLogFormatter < Logger::Formatter
177
+ extend DRbService::ANSIColorUtilities
178
+
179
+ # Color settings
180
+ LEVEL_FORMATS = {
181
+ :debug => colorize( :bold, :black ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s {%6$s} -- %7$s\n"},
182
+ :info => colorize( :normal ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"},
183
+ :warn => colorize( :bold, :yellow ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"},
184
+ :error => colorize( :red ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"},
185
+ :fatal => colorize( :bold, :red, :on_white ) {"[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"},
186
+ }
187
+
188
+
189
+ ### Initialize the formatter with a reference to the logger so it can check for log level.
190
+ def initialize( logger, settings={} ) # :notnew:
191
+ settings = LEVEL_FORMATS.merge( settings )
192
+
193
+ @logger = logger
194
+ @settings = settings
195
+
196
+ super()
197
+ end
198
+
199
+ ######
200
+ public
201
+ ######
202
+
203
+ # The Logger object associated with the formatter
204
+ attr_accessor :logger
205
+
206
+ # The formats, by level
207
+ attr_accessor :settings
208
+
209
+
210
+ ### Log using the format associated with the severity
211
+ def call( severity, time, progname, msg )
212
+ args = [
213
+ time.strftime( '%Y-%m-%d %H:%M:%S' ), # %1$s
214
+ time.usec, # %2$d
215
+ Process.pid, # %3$d
216
+ Thread.current == Thread.main ? 'main' : Thread.object_id, # %4$s
217
+ severity, # %5$s
218
+ progname, # %6$s
219
+ msg # %7$s
220
+ ]
221
+
222
+ return self.settings[ severity.downcase.to_sym ] % args
223
+ end
224
+ end # class LogFormatter
225
+
226
+
227
+ #
228
+ # An alternate formatter for Logger instances that outputs +div+ HTML
229
+ # fragments.
230
+ #
231
+ # == Usage
232
+ #
233
+ # require 'drbservice/utils'
234
+ # DRbService.logger.formatter = DRbService::HtmlLogFormatter.new( DRbService.logger )
235
+ #
236
+ # == Version
237
+ #
238
+ # $Id: utils.rb,v 87bc5aa9e2be 2011/08/29 21:05:42 ged $
239
+ #
240
+ # == Authors
241
+ #
242
+ # * Michael Granger <ged@FaerieMUD.org>
243
+ #
244
+ # :include: LICENSE
245
+ #
246
+ #--
247
+ #
248
+ # Please see the file LICENSE in the 'docs' directory for licensing details.
249
+ #
250
+ class HtmlLogFormatter < Logger::Formatter
251
+ include ERB::Util # for html_escape()
252
+
253
+ # The default HTML fragment that'll be used as the template for each log message.
254
+ HTML_LOG_FORMAT = %q{
255
+ <div class="log-message %5$s">
256
+ <span class="log-time">%1$s.%2$06d</span>
257
+ [
258
+ <span class="log-pid">%3$d</span>
259
+ /
260
+ <span class="log-tid">%4$s</span>
261
+ ]
262
+ <span class="log-level">%5$s</span>
263
+ :
264
+ <span class="log-name">%6$s</span>
265
+ <span class="log-message-text">%7$s</span>
266
+ </div>
267
+ }
268
+
269
+ ### Override the logging formats with ones that generate HTML fragments
270
+ def initialize( logger, format=HTML_LOG_FORMAT ) # :notnew:
271
+ @logger = logger
272
+ @format = format
273
+ super()
274
+ end
275
+
276
+
277
+ ######
278
+ public
279
+ ######
280
+
281
+ # The HTML fragment that will be used as a format() string for the log
282
+ attr_accessor :format
283
+
284
+
285
+ ### Return a log message composed out of the arguments formatted using the
286
+ ### formatter's format string
287
+ def call( severity, time, progname, msg )
288
+ args = [
289
+ time.strftime( '%Y-%m-%d %H:%M:%S' ), # %1$s
290
+ time.usec, # %2$d
291
+ Process.pid, # %3$d
292
+ Thread.current == Thread.main ? 'main' : Thread.object_id, # %4$s
293
+ severity.downcase, # %5$s
294
+ progname, # %6$s
295
+ html_escape( msg ).gsub(/\n/, '<br />') # %7$s
296
+ ]
297
+
298
+ return self.format % args
299
+ end
300
+
301
+ end # class HtmlLogFormatter
302
+
303
+
304
+ ### DRbService logging methods and data.
305
+ module Logging
306
+
307
+ # Mapping of symbols to logging levels
308
+ LEVEL = {
309
+ :debug => Logger::DEBUG,
310
+ :info => Logger::INFO,
311
+ :warn => Logger::WARN,
312
+ :error => Logger::ERROR,
313
+ :fatal => Logger::FATAL,
314
+ }
315
+
316
+
317
+ ### Inclusion callback: Add logging methods and instance variables to
318
+ ### the Module +mod+.
319
+ def self::included( mod )
320
+
321
+ # Logging class instance variables
322
+ default_logger = Logger.new( $stderr )
323
+ default_logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
324
+ formatter = DRbService::LogFormatter.new( default_logger )
325
+ default_logger.formatter = formatter
326
+
327
+ mod.instance_variable_set( :@default_logger, default_logger )
328
+ mod.instance_variable_set( :@default_log_formatter, formatter )
329
+ mod.instance_variable_set( :@logger, default_logger )
330
+
331
+ # Accessors
332
+ class << mod
333
+ include DRbService::Logging::ClassMethods
334
+
335
+ # The log formatter that will be used when the logging subsystem is reset
336
+ attr_accessor :default_log_formatter
337
+
338
+ # The logger that will be used when the logging subsystem is reset
339
+ attr_accessor :default_logger
340
+
341
+ # The logger that's currently in effect
342
+ attr_accessor :logger
343
+ alias_method :log, :logger
344
+ alias_method :log=, :logger=
345
+ end
346
+
347
+ end
348
+
349
+
350
+ ### A collection of class methods that will get added as class method to anything that
351
+ ### includes Logging.
352
+ module ClassMethods
353
+
354
+ ### Reset the global logger object to the default
355
+ def reset_logger
356
+ self.logger = self.default_logger
357
+ self.logger.level = Logger::WARN
358
+ self.logger.formatter = self.default_log_formatter
359
+ end
360
+
361
+
362
+ ### Returns +true+ if the global logger has not been set to something other than
363
+ ### the default one.
364
+ def using_default_logger?
365
+ return self.logger == self.default_logger
366
+ end
367
+
368
+
369
+ ### Return the library's version string
370
+ def version_string( include_buildnum=false )
371
+ vstring = "%s %s" % [ self.name, self.const_get(:VERSION) ]
372
+ if include_buildnum
373
+ rev = self.const_get(:REVISION)[/: ([[:xdigit:]]+)/, 1] rescue '0'
374
+ vstring << " (build %s)" % [ rev ]
375
+ end
376
+ return vstring
377
+ end
378
+
379
+ end # module ClassMethods
380
+
381
+
382
+ ### A logging proxy class that wraps calls to the logger into calls that include
383
+ ### the name of the calling class.
384
+ class ClassNameProxy # :nodoc:
385
+
386
+ ### Create a new proxy for the given +klass+.
387
+ def initialize( klass, force_debug=false )
388
+ @classname = klass.name
389
+ @force_debug = force_debug
390
+ end
391
+
392
+ ### Delegate calls the global logger with the class name as the 'progname'
393
+ ### argument.
394
+ def method_missing( sym, msg=nil, &block )
395
+ return super unless LEVEL.key?( sym )
396
+ sym = :debug if @force_debug
397
+ DRbService.logger.add( LEVEL[sym], msg, @classname, &block )
398
+ end
399
+ end # ClassNameProxy
400
+
401
+
402
+ ### Copy constructor -- clear the original's log proxy.
403
+ def initialize_copy( original )
404
+ @log_proxy = @log_debug_proxy = nil
405
+ super
406
+ end
407
+
408
+
409
+ ### Return the proxied logger.
410
+ def log
411
+ @log_proxy ||= ClassNameProxy.new( self.class )
412
+ end
413
+
414
+
415
+ ### Return a proxied "debug" logger that ignores other level specification.
416
+ def log_debug
417
+ @log_debug_proxy ||= ClassNameProxy.new( self.class, true )
418
+ end
419
+
420
+ end # module Logging
421
+
422
+
423
+ end # class DRbService
424
+
425
+ # vim: set nosta noet ts=4 sw=4:
426
+