rstyx 0.4.0 → 0.4.1

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.
data/lib/rstyx/server.rb CHANGED
@@ -1,42 +1,40 @@
1
1
  #!/usr/bin/ruby
2
2
  #
3
+ # Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
4
+ # Copyright:: Copyright (c) 2005-2007 Rafael R. Sevilla
5
+ # Homepage:: http://rstyx.rubyforge.org/
6
+ # License:: GNU Lesser General Public License / Ruby License
7
+ #
8
+ # $Id: server.rb 278 2007-09-19 07:22:37Z dido $
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
3
12
  # Copyright (C) 2005-2007 Rafael Sevilla
4
13
  # This file is part of RStyx
5
14
  #
6
- # RStyx is free software; you can redistribute it and/or modify
7
- # it under the terms of the GNU Lesser General Public License as
8
- # published by the Free Software Foundation; either version 2.1
9
- # of the License, or (at your option) any later version.
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either 1) the GNU Lesser General Public License
17
+ # as published by the Free Software Foundation; either version 3 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's license.
10
19
  #
11
- # RStyx is distributed in the hope that it will be useful, but
12
- # WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- # GNU Lesser General Public License for more details.
20
+ # See the file COPYING for complete licensing information
15
21
  #
16
- # You should have received a copy of the GNU Lesser General Public
17
- # License along with RStyx; if not, write to the Free Software
18
- # Foundation, Inc., 51 Franklin St., Fifth Floor, Boston, MA
19
- # 02110-1301 USA.
22
+ #----------------------------------------------------------------------------
20
23
  #
21
24
  # Styx Server
22
25
  #
23
26
  # To create a Styx server, one has to create an SDirectory object that
24
27
  # acts as the server root, e.g.:
25
28
  #
26
- # sd = RStyx::Server::SDirectory.new("/")
27
- # sf = RStyx::Server::InMemoryFile.new("test.file")
28
- # sf.contents = "hello"
29
- # sd << sf
30
- # serv = RStyx::Server::TCPServer.new(:bindaddr => "0.0.0.0",
31
- # :port => 9876,
32
- # :root => sd)
33
- # serv.run.join
29
+ # sd = RStyx::Server::SDirectory.new("/")
30
+ # sf = RStyx::Server::InMemoryFile.new("test.file")
31
+ # sf.contents = "hello"
32
+ # sd << sf
33
+ # serv = RStyx::Server::TCPServer.new(:bindaddr => "0.0.0.0",
34
+ # :port => 9876,
35
+ # :root => sd)
36
+ # serv.run.join
34
37
  #
35
- # Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
36
- # Copyright:: Copyright (c) 2005-2007 Rafael R. Sevilla
37
- # License:: GNU Lesser General Public License
38
- #
39
- # $Id: server.rb 249 2007-09-14 04:21:18Z dido $
40
38
  #
41
39
  require 'thread'
42
40
  require 'monitor'
@@ -59,7 +57,31 @@ module RStyx
59
57
  # assemble all inbound messages
60
58
  #
61
59
  module StyxServerProtocol
62
- attr_accessor :sentmessages, :msize, :log, :root
60
+ ##
61
+ # maximum message size supported
62
+ attr_accessor :msize
63
+ ##
64
+ # Logger object used for logging server events
65
+ attr_accessor :log
66
+ ##
67
+ # The root of the file tree for this server
68
+ attr_accessor :root
69
+ ##
70
+ # An authenticator which is sent messages received from the client.
71
+ # Used when doing Inferno authentication.
72
+ attr_accessor :authenticator
73
+ ##
74
+ # The session object corresponding to this connection
75
+ attr_accessor :session
76
+ ##
77
+ # Server's authentication information
78
+ attr_accessor :myauth
79
+ ##
80
+ # Connected peer's authentication information
81
+ attr_accessor :userauth
82
+ ##
83
+ # Shared secret obtained during Inferno authentication
84
+ attr_accessor :secret
63
85
 
64
86
  DEFAULT_MSIZE = 8216
65
87
 
@@ -95,11 +117,11 @@ module RStyx
95
117
  # negotiation results in the protocol_negotiated flag in the
96
118
  # current session becoming true, and all other outstanding I/O
97
119
  # on the session (e.g. opened fids and the like) all removed.
98
- #
120
+ #--
99
121
  # External methods used:
100
122
  #
101
123
  # Session#reset_session *
102
- #
124
+ #++
103
125
  def tversion(msg)
104
126
  @cversion = msg.version
105
127
  @cmsize = msg.msize
@@ -123,7 +145,7 @@ module RStyx
123
145
  # depending on the auth methods that we decide to support.
124
146
  #
125
147
  def tauth(msg)
126
- return(Message::Rerror.new(:ename => "Authentication methods through auth messages are not used."))
148
+ return(Message::Rerror.new(:ename => "Authentication methods through auth messages are not supported."))
127
149
  end
128
150
 
129
151
  ##
@@ -134,14 +156,14 @@ module RStyx
134
156
  # 1. The client has not done a version negotiation yet.
135
157
  # 2. The client has provided a fid which it is already using
136
158
  # for something else.
137
- #
159
+ #--
138
160
  # External methods used:
139
161
  #
140
162
  # Session#version_negotiated? *
141
163
  # Session#has_fid? *
142
164
  # Session#[]= *
143
165
  # SFile#qid (root) *
144
- #
166
+ #++
145
167
  def tattach(msg)
146
168
  # Do not allow attaches without version negotiation
147
169
  unless @session.version_negotiated?
@@ -175,11 +197,11 @@ module RStyx
175
197
  # flushed transaction). Some means, possibly a session-wide
176
198
  # global transaction lock on server internal state changes
177
199
  # may be necessary to allow flushes of this kind to work.
178
- #
200
+ #--
179
201
  # External methods used:
180
202
  #
181
203
  # Session#flush_tag *
182
- #
204
+ #++
183
205
  def tflush(msg)
184
206
  @session.flush_tag(msg.oldtag)
185
207
  return(Message::Rflush.new)
@@ -205,7 +227,7 @@ module RStyx
205
227
  # Note that if several parts of the walk managed to succeed, this
206
228
  # method will still return an Rwalk response, but it will NOT
207
229
  # associate newfid with anything.
208
- #
230
+ #--
209
231
  # External methods used:
210
232
  #
211
233
  # Session#[] *
@@ -218,7 +240,7 @@ module RStyx
218
240
  # SFile#atime=
219
241
  # SFile#[]
220
242
  # SFile#qid
221
- #
243
+ #++
222
244
  #
223
245
  def twalk(msg)
224
246
  if msg.wnames.length > MAXWELEM
@@ -232,13 +254,12 @@ module RStyx
232
254
  raise StyxException.new("cannot walk to an open fid")
233
255
  end
234
256
  nfid = msg.newfid
235
- if nfid != fid
236
- # if the original and new fids are different, check that
237
- # the new fid isn't already in use.
238
- if (@session.has_fid?(nfid))
239
- raise StyxException.new("fid already in use")
240
- end
257
+ # if the original and new fids are different, check that
258
+ # the new fid isn't already in use.
259
+ if nfid != fid && @session.has_fid?(nfid)
260
+ raise StyxException.new("fid already in use")
241
261
  end
262
+
242
263
  rwalk = Message::Rwalk.new(:qids => [])
243
264
  num = 0
244
265
  msg.wnames.each do |n|
@@ -258,6 +279,7 @@ module RStyx
258
279
  end
259
280
  break
260
281
  end
282
+ sf.atime = Time.now
261
283
  # This allows a client to get a fid representing the directory
262
284
  # at the end of the walk, even if the client does not have
263
285
  # execute permissions on that directory. Therefore, in Inferno,
@@ -279,7 +301,7 @@ module RStyx
279
301
 
280
302
  ##
281
303
  # Handle open messages.
282
- #
304
+ #--
283
305
  # External methods used:
284
306
  #
285
307
  # Session#[]
@@ -289,7 +311,7 @@ module RStyx
289
311
  # SFile#qid
290
312
  # Session#iounit
291
313
  # Session#user
292
- #
314
+ #++
293
315
  def topen(msg)
294
316
  sf = @session[msg.fid]
295
317
  mode = msg.mode
@@ -312,11 +334,38 @@ module RStyx
312
334
  unless @session.writable?(dir)
313
335
  raise StyxException.new("permission denied, no write permissions to parent directory")
314
336
  end
337
+ # Check the file type
338
+ perm = msg.perm
339
+ isdir = (perm & DMDIR) != 0
340
+ isapponly = (perm & DMAPPEND) != 0
341
+ isexclusive = (perm & DMEXCL) != 0
342
+ isauth = (perm & DMAUTH) != 0
343
+
344
+ if isauth
345
+ # Auth files cannot be created by Styx messages
346
+ raise StyxException.new("can't create a file of type DMAUTH")
347
+ end
348
+
349
+ # Get the low 9 bits of the permission number (these low 9 bits
350
+ # are the rwxrwxrwx file permissions)
351
+ operm = msg.perm & 01777
352
+ # Get the real permissions of this file. This depends on the
353
+ # permissions of the parent directory
354
+ realperm = operm
355
+ if isdir
356
+ realperm = operm & (~0777 | (dir.permissions & 0777))
357
+ # directories must be opened with OREAD (no other bits set)
358
+ if msg.mode != OREAD
359
+ raise StyxException.new("when creating a directory must open with read permission only")
360
+ end
361
+ else
362
+ realperm = operm & (~0666 | (dir.permissions & 0666))
363
+ end
315
364
 
316
- # Create the file in the directory. Note that SDirectory#newfile
317
- # has to do all of the permission checking and all that.
318
- new_file = dir.newfile(msg.name, msg.perm)
319
- o dir << new_file
365
+ # Create the file in the directory, add it to the directory tree,
366
+ # and associate the new file with the given fid
367
+ new_file = dir.newfile(msg.name, realperm, isdir, isapponly, isexcl)
368
+ dir << new_file
320
369
  @session[msg.fid] = new_file
321
370
  new_file.add_client(SFileClient.new(@session, msg.fid, msg.mode))
322
371
  return(Message::Rcreate.new(:qid => new_file.qid,
@@ -383,7 +432,7 @@ o dir << new_file
383
432
  # A remove is just like a clunk with the side effect of
384
433
  # removing the file if the permissions allow.
385
434
  sf = @session[msg.fid]
386
- sf.lock do
435
+ sf.synchronize do
387
436
  @session.clunk(msg.fid)
388
437
  parent = sf.parent
389
438
  if @session.writable?(parent)
@@ -394,8 +443,8 @@ o dir << new_file
394
443
  raise StyxException.new("directory not empty")
395
444
  end
396
445
  sf.remove
446
+ parent.set_mtime(Time.now, @session.user)
397
447
  end
398
- parent.set_mtime(Time.now, @session.user)
399
448
  return(Message::Rremove.new)
400
449
  end
401
450
 
@@ -414,7 +463,7 @@ o dir << new_file
414
463
  def twstat(msg)
415
464
  nstat = msg.stat
416
465
  sf = @session[msg.fid]
417
- sf.lock do
466
+ sf.synchronize do
418
467
  # Check if we are changing the file's name
419
468
  unless nstat.name.empty?
420
469
  dir = sf.parent
@@ -554,8 +603,10 @@ o dir << new_file
554
603
  @log.error("#{@peername} unknown fid in message #{msg.to_s}")
555
604
  reply(Message::Rerror.new(:ename => "Unknown fid #{e.fid}"), tag)
556
605
  rescue StyxException => e
557
- @log.error("#{@peername} styx exception #{e.message} in #{msg.to_s}")
606
+ @log.error("#{@peername} styx exception #{e.message} for #{msg.to_s}")
558
607
  reply(Message::Rerror.new(:ename => "Error: #{e.message}"), tag)
608
+ rescue Exception => e
609
+ @log.error("#{@peername} internal error #{e.message} for #{e.to_s} at #{e.backtrace}")
559
610
  end
560
611
 
561
612
  end
@@ -565,6 +616,12 @@ o dir << new_file
565
616
  # Receive data from the network connection, called by EventMachine.
566
617
  #
567
618
  def receive_data(data)
619
+ # If we are in keyring authentication mode, write any data received
620
+ # into the @auth's buffer, and simply return.
621
+ unless @authenticator.nil?
622
+ @authenticator << data
623
+ return
624
+ end
568
625
  @msgbuffer << data
569
626
  # self.class.log.debug(" << #{data.unpack("H*").inspect}")
570
627
  while @msgbuffer.length > 4
@@ -621,6 +678,10 @@ o dir << new_file
621
678
  # Active iounit for this connection
622
679
  #
623
680
  attr_accessor :iounit
681
+ ##
682
+ # Group table
683
+ #
684
+ attr_accessor :groups
624
685
 
625
686
  ##
626
687
  # Create a new session.
@@ -772,15 +833,17 @@ o dir << new_file
772
833
  end
773
834
  end
774
835
 
836
+ # These constants are used by Session#permission? and should NOT
837
+ # be changed. The algorithm used depends on it!
838
+ EXECUTE = 0
839
+ WRITE = 1
840
+ READ = 2
841
+
775
842
  ##
776
843
  # Check the permissions for a given mode
777
844
  #
778
- #--
779
- # FIXME: the permissions are only for anonymous access at the
780
- # moment, so only the world permissions are ever checked.
781
- #++
782
845
  # _sf_:: the file to check against
783
- # _mode_:: the mode to check (OEXEC, OWRITE, or OREAD)
846
+ # _mode_:: the mode to check (EXEC, WRITE, or READ)
784
847
  #
785
848
  def permission?(sf, mode)
786
849
  if mode < 0 || mode > 2
@@ -788,22 +851,42 @@ o dir << new_file
788
851
  end
789
852
  # We bit shift the permissions value so that the mode is
790
853
  # represented by the last bit (all) the fourth to last bit
791
- # (group), and the seventh-to-last bit (user).
854
+ # (group), and the seventh-to-last bit (user). For example,
855
+ # if we started with a mode of 0755 (binary 111101101,
856
+ # rwxrwxrwx), and we want to check write permissions, we
857
+ # shift by one bit so that the value of perms is 1110110, or
858
+ # (rwxrwxrw).
792
859
  perms = sf.permissions >> mode
793
860
  # Check permissions for 'all' -- the low-order bit
794
- if perms & 0b000_000_001 == 1
861
+ unless perms & 0b000_000_001 == 0
795
862
  return(true)
796
863
  end
797
864
 
798
- # XXX: this has to be something more useful!
799
- return(false)
865
+ # Group permissions
866
+ unless (perms & 0b000_001_000) == 0
867
+ # The group has the correct permissions; now we have to find if
868
+ # the user is a member of the group in question.
869
+ ug = @groups[@user]
870
+ unless ug.index(sf.gid).nil?
871
+ return(true)
872
+ end
873
+ end
874
+
875
+ # Owner permissions. This is the final fallback.
876
+ return(((perms & 0b001_000_000) != 0) && (@user == sf.uid))
800
877
  end
801
878
 
802
879
  ##
803
880
  # Check for executable permission for the SFile _sf_.
804
881
  #
805
882
  def execute?(sf)
806
- return(true)
883
+ return(permission?(sf, EXECUTE))
884
+ end
885
+
886
+ ##
887
+ # Check for write permission for the SFile _sf_.
888
+ def writable?(sf)
889
+ return(permission?(sf, WRITE))
807
890
  end
808
891
 
809
892
  ##
@@ -818,7 +901,59 @@ o dir << new_file
818
901
  raise StyxException.new("can't open locked file")
819
902
  end
820
903
  openmode = mode & 0x03
821
- # XXX: Needs to be filled out further...
904
+ case openmode
905
+ when OREAD
906
+ unless permission?(sf, READ)
907
+ raise StyxException.new("read permission denied")
908
+ end
909
+ when OWRITE
910
+ unless permission?(sf, WRITE)
911
+ raise StyxException.new("write permission denied")
912
+ end
913
+ when ORDWR
914
+ unless permission?(sf, READ)
915
+ raise StyxException.new("read permission denied")
916
+ end
917
+ unless permission?(sf, WRITE)
918
+ raise StyxException.new("write permission denied")
919
+ end
920
+ when OEXEC
921
+ unless permission?(sf, EXECUTE)
922
+ raise StyxException.new("execute permission denied")
923
+ end
924
+ else
925
+ # shouldn't happen
926
+ raise StyxException.new("internal Styx error openmode = #{openmode}: should be between 0 and 3")
927
+ end
928
+
929
+ # Execute permission is required for a directory in order to
930
+ # do anything with it
931
+ if sf.directory? && !execute?(sf)
932
+ raise StyxException("directory execute permission denied")
933
+ end
934
+
935
+ if (mode & OTRUNC) != 0
936
+ # can't truncate a directory
937
+ if sf.directory?
938
+ raise StyxException.new("cannot truncate a directory")
939
+ end
940
+ unless permission?(sf, WRITE)
941
+ raise StyxException.new("need write permissions to truncate a file")
942
+ end
943
+ end
944
+
945
+ if (mode & ORCLOSE) != 0
946
+ # can't delete a directory on closing
947
+ if sf.directory?
948
+ raise StyxException.new("cannot automatically delete a directory")
949
+ end
950
+ # we must have write permissions on the parent directory and the file
951
+ # itself to delete the file on clunking its fid
952
+ unless permission?(sf.parent, WRITE)
953
+ raise StyxException.new("need write permissions on the parent directory to delete the file when the fid is clunked")
954
+ end
955
+ # TODO: do we need write permissions on the file itself?
956
+ end
822
957
  end
823
958
 
824
959
  end # class Session
@@ -837,12 +972,27 @@ o dir << new_file
837
972
  # serve (typically an SDirectory instance)
838
973
  # _:log_:: A Logger object where server-generated log messages
839
974
  # are stored.
975
+ # _:auth_:: An authentication object. If this is a
976
+ # Keyring::Authinfo instance, it will use the Inferno
977
+ # authentication protocol to authenticate clients who
978
+ # connect, and only allow connections from clients with
979
+ # certificates signed by the same CA that signed its
980
+ # own certificate. If this is nil, no authentication
981
+ # will be required for connections.
982
+ # _:groups_:: A hash table, indexed by user names, that returns
983
+ # an array of groups of which a particular user is
984
+ # member of. If not specified, it defaults to an
985
+ # empty group table (which sets the group of everyone
986
+ # to 'nogroup')
840
987
  # _:debug_:: Debug level, which is assigned to the logger's level
841
988
  # Set this to Logger::DEBUG if you want full debugging
842
989
  # messages to appear.
843
990
  #
844
991
  def initialize(config)
845
992
  @root = config[:root]
993
+ @auth = config[:auth]
994
+ @groups = config[:groups]
995
+ @groups ||= Hash.new(["nogroup"])
846
996
  @log = config[:log] || Logger.new(STDERR)
847
997
  @log.level = config[:debug] || Logger::WARN
848
998
  end
@@ -898,6 +1048,51 @@ o dir << new_file
898
1048
  StyxServerProtocol) do |conn|
899
1049
  conn.root = @root
900
1050
  conn.log = @log
1051
+ if @auth.is_a?(Keyring::Authinfo)
1052
+ # Perform Inferno authentication protocol
1053
+ conn.myauth = @auth
1054
+ conn.authenticator = Keyring::FileWrapper.new(conn)
1055
+ Thread.new do
1056
+ begin
1057
+ conn.userauth, conn.secret = Keyring.auth(conn.authenticator,
1058
+ :server, @auth,
1059
+ ["none"])
1060
+ rescue Exception => e
1061
+ # You fail. Get outta my face!
1062
+ @log.info("client authentication error #{e.class.to_s}: #{e.message}")
1063
+ conn.close_connection
1064
+ else
1065
+ # Successful authentication. Set the session.auth flag to
1066
+ # true and the user to the owner of the public key that
1067
+ # was used to authenticate
1068
+ conn.session.user = conn.userauth.mypk.owner
1069
+ conn.session.auth = true
1070
+ @log.info("authenticated connection for #{conn.session.user}")
1071
+ # Stop using the authenticator after the protocol is done.
1072
+ # The authenticator might have received some data meant
1073
+ # to be Styx protocol messages so we do receive_data to
1074
+ # make sure that the data does get received.
1075
+ a = conn.authenticator
1076
+ conn.authenticator = nil
1077
+ if a.data.length > 0
1078
+ conn.receive_data(a.data)
1079
+ end
1080
+ end
1081
+ end
1082
+ else
1083
+ # Either we're using some other non-Inferno authentication
1084
+ # method, in which case auth files are used and the peer
1085
+ # authentication information is filled in later, or we're
1086
+ # not bothering to do any authentication. We fill in
1087
+ # userauth with nil (the connection is unauthenticated)
1088
+ # and we put "nobody" in the username (the anonymous user).
1089
+ conn.userauth = nil
1090
+ conn.session.user = "nobody"
1091
+ conn.session.auth = false
1092
+ conn.authenticator = nil
1093
+ @log.info("unauthenticated connection for #{conn.username}")
1094
+ end
1095
+ conn.session.groups = @groups
901
1096
  end
902
1097
  end
903
1098
  end
@@ -969,7 +1164,7 @@ o dir << new_file
969
1164
  # opened it with read access mode).
970
1165
  #
971
1166
  def readable?
972
- return(mode == OREAD || mode == ORDWR)
1167
+ return(@mode == OREAD || @mode == ORDWR)
973
1168
  end
974
1169
 
975
1170
  ##
@@ -977,7 +1172,7 @@ o dir << new_file
977
1172
  # opened it with write access).
978
1173
  #
979
1174
  def writable?
980
- return(mode == OWRITE || mode == ORDWR)
1175
+ return(@mode == OWRITE || @mode == ORDWR)
981
1176
  end
982
1177
 
983
1178
  end
@@ -1473,7 +1668,7 @@ o dir << new_file
1473
1668
  # implementation does nothing; subclasses must override this to
1474
1669
  # provide the correct functionality.
1475
1670
  #
1476
- def refresh
1671
+ def refresh(update_children)
1477
1672
  end
1478
1673
  end # class SFile
1479
1674
 
@@ -1608,10 +1803,17 @@ o dir << new_file
1608
1803
  # FIXME: make this method actually DO something!
1609
1804
  #++
1610
1805
  #
1611
- def newfile(name, perm)
1806
+ def newfile(name, perm, isdir, isapponly, isexcl)
1612
1807
  raise StyxException.new("cannot create files in this directory")
1613
1808
  end
1614
1809
 
1810
+ ##
1811
+ # Remove a file from the directory
1812
+ def remove_child(child)
1813
+ @children.delete(child)
1814
+ self.contents_changed
1815
+ end
1816
+
1615
1817
  end # class SDirectory
1616
1818
 
1617
1819
  ##
data/lib/rstyx/version.rb CHANGED
@@ -1,34 +1,35 @@
1
1
  #!/usr/bin/ruby
2
2
  #
3
- # Copyright (C) 2005 Rafael Sevilla
3
+ # Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
4
+ # Copyright:: Copyright (c) 2005-2007 Rafael R. Sevilla
5
+ # Homepage:: http://rstyx.rubyforge.org/
6
+ # License:: GNU Lesser General Public License / Ruby License
7
+ #
8
+ # $Id: version.rb 285 2007-09-19 07:32:56Z dido $
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2005-2007 Rafael Sevilla
4
13
  # This file is part of RStyx
5
14
  #
6
- # RStyx is free software; you can redistribute it and/or modify
7
- # it under the terms of the GNU Lesser General Public License as
8
- # published by the Free Software Foundation; either version 2.1
9
- # of the License, or (at your option) any later version.
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either 1) the GNU Lesser General Public License
17
+ # as published by the Free Software Foundation; either version 3 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's license.
10
19
  #
11
- # RStyx is distributed in the hope that it will be useful, but
12
- # WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- # GNU Lesser General Public License for more details.
20
+ # See the file COPYING for complete licensing information
15
21
  #
16
- # You should have received a copy of the GNU Lesser General Public
17
- # License along with RStyx; if not, write to the Free Software
18
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19
- # 02111-1307 USA.
22
+ #----------------------------------------------------------------------------
20
23
  #
21
24
  # RStyx version code
22
25
  #
23
- # $Id: version.rb 261 2007-09-18 04:43:42Z dido $
24
- #
25
26
 
26
27
  module RStyx
27
28
  module Version
28
29
 
29
30
  MAJOR = 0
30
31
  MINOR = 4
31
- TINY = 0
32
+ TINY = 1
32
33
 
33
34
  # The version of RStyx in use.
34
35
  STRING = [ MAJOR, MINOR, TINY ].join(".")
data/lib/rstyx.rb CHANGED
@@ -1,31 +1,33 @@
1
1
  #!/usr/bin/ruby
2
2
  #
3
- # Copyright (C) 2005,2006 Rafael Sevilla
3
+ # Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
4
+ # Copyright:: Copyright (c) 2005-2007 Rafael R. Sevilla
5
+ # Homepage:: http://rstyx.rubyforge.org/
6
+ # License:: GNU Lesser General Public License / Ruby License
7
+ #
8
+ # $Id: rstyx.rb 294 2007-09-19 07:45:28Z dido $
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2005-2007 Rafael Sevilla
4
13
  # This file is part of RStyx
5
14
  #
6
- # RStyx is free software; you can redistribute it and/or modify
7
- # it under the terms of the GNU Lesser General Public License as
8
- # published by the Free Software Foundation; either version 2.1
9
- # of the License, or (at your option) any later version.
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either 1) the GNU Lesser General Public License
17
+ # as published by the Free Software Foundation; either version 3 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's license.
10
19
  #
11
- # RStyx is distributed in the hope that it will be useful, but
12
- # WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- # GNU Lesser General Public License for more details.
20
+ # See the file COPYING for complete licensing information
15
21
  #
16
- # You should have received a copy of the GNU Lesser General Public
17
- # License along with RStyx; if not, write to the Free Software
18
- # Foundation, Inc., 51 Franklin St., Fifth Floor, Boston, MA
19
- # 02110-1301 USA.
22
+ #----------------------------------------------------------------------------
20
23
  #
21
24
  # Main require -- should get everything ready for the user of the lib.
22
25
  #
23
- # $Id: rstyx.rb 260 2007-09-18 04:43:12Z dido $
24
26
  #
25
27
  require 'rstyx/common'
26
28
  require 'rstyx/messages'
27
29
  require 'rstyx/errors'
28
30
  require 'rstyx/keyring'
29
31
  require 'rstyx/client'
30
- require 'rstyx/authmodules'
32
+ require 'rstyx/server'
31
33