flatulent 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/README +60 -16
  2. data/flatulent-0.0.2.gem +0 -0
  3. data/lib/flatulent/crypt/blowfish-tables.rb +190 -0
  4. data/lib/flatulent/crypt/blowfish.rb +109 -0
  5. data/lib/flatulent/crypt/cbc.rb +123 -0
  6. data/lib/flatulent/crypt/gost.rb +140 -0
  7. data/lib/flatulent/crypt/idea.rb +193 -0
  8. data/lib/flatulent/crypt/noise.rb +94 -0
  9. data/lib/flatulent/crypt/purerubystringio.rb +378 -0
  10. data/lib/flatulent/crypt/rijndael-tables.rb +117 -0
  11. data/lib/flatulent/crypt/rijndael.rb +269 -0
  12. data/lib/flatulent/crypt/stringxor.rb +27 -0
  13. data/lib/flatulent.rb +332 -121
  14. data/lib/flatulent.rb.bak +337 -0
  15. data/rails/app/controllers/flatulent_controller.rb +61 -6
  16. data/rails/lib/flatulent/attributes.rb +79 -0
  17. data/rails/lib/flatulent/crypt/blowfish-tables.rb +190 -0
  18. data/rails/lib/flatulent/crypt/blowfish.rb +109 -0
  19. data/rails/lib/flatulent/crypt/cbc.rb +123 -0
  20. data/rails/lib/flatulent/crypt/gost.rb +140 -0
  21. data/rails/lib/flatulent/crypt/idea.rb +193 -0
  22. data/rails/lib/flatulent/crypt/noise.rb +94 -0
  23. data/rails/lib/flatulent/crypt/purerubystringio.rb +378 -0
  24. data/rails/lib/flatulent/crypt/rijndael-tables.rb +117 -0
  25. data/rails/lib/flatulent/crypt/rijndael.rb +269 -0
  26. data/rails/lib/flatulent/fontfiles/banner.flf +2494 -0
  27. data/rails/lib/flatulent/fontfiles/big.flf +2204 -0
  28. data/rails/lib/flatulent/fontfiles/block.flf +1691 -0
  29. data/rails/lib/flatulent/fontfiles/bubble.flf +1630 -0
  30. data/rails/lib/flatulent/fontfiles/digital.flf +1286 -0
  31. data/rails/lib/flatulent/fontfiles/ivrit.flf +900 -0
  32. data/rails/lib/flatulent/fontfiles/lean.flf +1691 -0
  33. data/rails/lib/flatulent/fontfiles/mini.flf +899 -0
  34. data/rails/lib/flatulent/fontfiles/mnemonic.flf +3702 -0
  35. data/rails/lib/flatulent/fontfiles/script.flf +1493 -0
  36. data/rails/lib/flatulent/fontfiles/shadow.flf +1097 -0
  37. data/rails/lib/flatulent/fontfiles/slant.flf +1295 -0
  38. data/rails/lib/flatulent/fontfiles/small.flf +1097 -0
  39. data/rails/lib/flatulent/fontfiles/smscript.flf +1097 -0
  40. data/rails/lib/flatulent/fontfiles/smshadow.flf +899 -0
  41. data/rails/lib/flatulent/fontfiles/smslant.flf +1097 -0
  42. data/rails/lib/flatulent/fontfiles/standard.flf +2227 -0
  43. data/rails/lib/flatulent/fontfiles/term.flf +600 -0
  44. data/rails/lib/flatulent/pervasives.rb +32 -0
  45. data/rails/lib/flatulent/stringxor.rb +27 -0
  46. data/rails/lib/flatulent/text/double_metaphone.rb +356 -0
  47. data/rails/lib/flatulent/text/figlet/font.rb +117 -0
  48. data/rails/lib/flatulent/text/figlet/smusher.rb +64 -0
  49. data/rails/lib/flatulent/text/figlet/typesetter.rb +68 -0
  50. data/rails/lib/flatulent/text/figlet.rb +17 -0
  51. data/rails/lib/flatulent/text/levenshtein.rb +65 -0
  52. data/rails/lib/flatulent/text/metaphone.rb +97 -0
  53. data/rails/lib/flatulent/text/porter_stemming.rb +171 -0
  54. data/rails/lib/flatulent/text/soundex.rb +61 -0
  55. data/rails/lib/flatulent/text.rb +6 -0
  56. data/rails/lib/flatulent.rb +450 -0
  57. data/rails/log/development.log +14297 -0
  58. data/rails/log/fastcgi.crash.log +111 -0
  59. data/rails/log/lighttpd.access.log +3993 -0
  60. data/rails/log/lighttpd.error.log +111 -0
  61. data/rails/tmp/cache/javascripts/prototype.js-gzip-3275912-71260-1183440172 +0 -0
  62. data/rails/tmp/sessions/ruby_sess.32d68bc997054475 +0 -0
  63. data/rails/tmp/sessions/ruby_sess.4694a4b9bdf9bcf4 +0 -0
  64. data/rails/tmp/sessions/ruby_sess.99469fde69043a05 +0 -0
  65. data/rails/tmp/sessions/ruby_sess.a588c0a457345912 +0 -0
  66. data/rails/tmp/sessions/ruby_sess.b3344125a84a3efa +0 -0
  67. data/samples.rb +10 -0
  68. metadata +69 -3
  69. data/flatulent-0.0.0.gem +0 -0
@@ -0,0 +1,193 @@
1
+ # idea.rb Richard Kernahan <kernighan_rich@rubyforge.org>
2
+
3
+ # IDEA (International Data Encryption Algorithm) by
4
+ # Xuejia Lai and James Massey (1992). Refer to license info at end.
5
+ # Ported by Richard Kernahan 2005
6
+
7
+ module Crypt
8
+ class IDEA
9
+
10
+ require 'crypt/cbc'
11
+ include Crypt::CBC
12
+
13
+ require 'digest/md5'
14
+
15
+ ULONG = 0x100000000
16
+ USHORT = 0x10000
17
+
18
+ ENCRYPT = 0
19
+ DECRYPT = 1
20
+
21
+
22
+ def block_size
23
+ return(8)
24
+ end
25
+
26
+
27
+ def initialize(key128, mode)
28
+ # IDEA is subject to attack unless the key is sufficiently random, so we
29
+ # take an MD5 digest of a variable-length passphrase to ensure a solid key
30
+ if (key128.class == String)
31
+ digest = Digest::MD5.new(key128).digest
32
+ key128 = digest.unpack('n'*8)
33
+ end
34
+ raise "Key must be 128 bits (8 words)" unless (key128.class == Array) && (key128.length == 8)
35
+ raise "Mode must be IDEA::ENCRYPT or IDEA::DECRYPT" unless ((mode == ENCRYPT) | (mode == DECRYPT))
36
+ if (mode == ENCRYPT)
37
+ @subkeys = generate_encryption_subkeys(key128)
38
+ else (mode == DECRYPT)
39
+ @subkeys = generate_decryption_subkeys(key128)
40
+ end
41
+ end
42
+
43
+
44
+ def mul(a, b)
45
+ modulus = 0x10001
46
+ return((1 - b) % USHORT) if (a == 0)
47
+ return((1 - a) % USHORT) if (b == 0)
48
+ return((a * b) % modulus)
49
+ end
50
+
51
+
52
+ def mulInv(x)
53
+ modulus = 0x10001
54
+ x = x.to_i % USHORT
55
+ return(x) if (x <= 1)
56
+ t1 = USHORT / x
57
+ y = modulus % x
58
+ if (y == 1)
59
+ inv = (1 - t1) & 0xFFFF
60
+ return(inv)
61
+ end
62
+ t0 = 1
63
+ while (y != 1)
64
+ q = x / y
65
+ x = x % y
66
+ t0 = t0 + (q * t1)
67
+ return(t0) if (x == 1)
68
+ q = y / x
69
+ y = y % x
70
+ t1 = t1 + (q * t0)
71
+ end
72
+ inv = (1 - t1) & 0xFFFF
73
+ return(inv)
74
+ end
75
+
76
+
77
+ def generate_encryption_subkeys(key)
78
+ encrypt_keys = []
79
+ encrypt_keys[0..7] = key.dup
80
+ 8.upto(51) { |i|
81
+ a = ((i + 1) % 8 > 0) ? (i-7) : (i-15)
82
+ b = ((i + 2) % 8 < 2) ? (i-14) : (i-6)
83
+ encrypt_keys[i] = ((encrypt_keys[a] << 9) | (encrypt_keys[b] >> 7)) % USHORT
84
+ }
85
+ return(encrypt_keys)
86
+ end
87
+
88
+
89
+ def generate_decryption_subkeys(key)
90
+ encrypt_keys = generate_encryption_subkeys(key)
91
+ decrypt_keys = []
92
+ decrypt_keys[48] = mulInv(encrypt_keys.shift)
93
+ decrypt_keys[49] = (-encrypt_keys.shift) % USHORT
94
+ decrypt_keys[50] = (-encrypt_keys.shift) % USHORT
95
+ decrypt_keys[51] = mulInv(encrypt_keys.shift)
96
+ 42.step(0, -6) { |i|
97
+ decrypt_keys[i+4] = encrypt_keys.shift % USHORT
98
+ decrypt_keys[i+5] = encrypt_keys.shift % USHORT
99
+ decrypt_keys[i] = mulInv(encrypt_keys.shift)
100
+ if (i ==0)
101
+ decrypt_keys[1] = (-encrypt_keys.shift) % USHORT
102
+ decrypt_keys[2] = (-encrypt_keys.shift) % USHORT
103
+ else
104
+ decrypt_keys[i+2] = (-encrypt_keys.shift) % USHORT
105
+ decrypt_keys[i+1] = (-encrypt_keys.shift) % USHORT
106
+ end
107
+ decrypt_keys[i+3] = mulInv(encrypt_keys.shift)
108
+ }
109
+ return(decrypt_keys)
110
+ end
111
+
112
+
113
+ def crypt_pair(l, r)
114
+ word = [l, r].pack('NN').unpack('nnnn')
115
+ k = @subkeys[0..51]
116
+ 8.downto(1) { |i|
117
+ word[0] = mul(word[0], k.shift)
118
+ word[1] = (word[1] + k.shift) % USHORT
119
+ word[2] = (word[2] + k.shift) % USHORT
120
+ word[3] = mul(word[3], k.shift)
121
+ t2 = word[0] ^ word[2]
122
+ t2 = mul(t2, k.shift)
123
+ t1 = (t2 + (word[1] ^ word[3])) % USHORT
124
+ t1 = mul(t1, k.shift)
125
+ t2 = (t1 + t2) % USHORT
126
+ word[0] ^= t1
127
+ word[3] ^= t2
128
+ t2 ^= word[1]
129
+ word[1] = word[2] ^ t1
130
+ word[2] = t2
131
+ }
132
+ result = []
133
+ result << mul(word[0], k.shift)
134
+ result << (word[2] + k.shift) % USHORT
135
+ result << (word[1] + k.shift) % USHORT
136
+ result << mul(word[3], k.shift)
137
+ twoLongs = result.pack('nnnn').unpack('NN')
138
+ return(twoLongs)
139
+ end
140
+
141
+ def encrypt_block(block)
142
+ xl, xr = block.unpack('NN')
143
+ xl, xr = crypt_pair(xl, xr)
144
+ encrypted = [xl, xr].pack('NN')
145
+ return(encrypted)
146
+ end
147
+
148
+
149
+ def decrypt_block(block)
150
+ xl, xr = block.unpack('NN')
151
+ xl, xr = crypt_pair(xl, xr)
152
+ decrypted = [xl, xr].pack('NN')
153
+ return(decrypted)
154
+ end
155
+
156
+
157
+ end
158
+ end
159
+
160
+ # LICENSE INFORMATION
161
+ #
162
+ # This software product contains the IDEA algorithm as described and claimed in
163
+ # US patent 5,214,703, EPO patent 0482154 (covering Austria, France, Germany,
164
+ # Italy, the Netherlands, Spain, Sweden, Switzerland, and the UK), and Japanese
165
+ # patent application 508119/1991, "Device for the conversion of a digital block
166
+ # and use of same" (hereinafter referred to as "the algorithm"). Any use of
167
+ # the algorithm for commercial purposes is thus subject to a license from Ascom
168
+ # Systec Ltd. of CH-5506 Maegenwil (Switzerland), being the patentee and sole
169
+ # owner of all rights, including the trademark IDEA.
170
+ #
171
+ # Commercial purposes shall mean any revenue generating purpose including but
172
+ # not limited to:
173
+ #
174
+ # i) Using the algorithm for company internal purposes (subject to a site
175
+ # license).
176
+ #
177
+ # ii) Incorporating the algorithm into any software and distributing such
178
+ # software and/or providing services relating thereto to others (subject to
179
+ # a product license).
180
+ #
181
+ # iii) Using a product containing the algorithm not covered by an IDEA license
182
+ # (subject to an end user license).
183
+ #
184
+ # All such end user license agreements are available exclusively from Ascom
185
+ # Systec Ltd and may be requested via the WWW at http://www.ascom.ch/systec or
186
+ # by email to idea@ascom.ch.
187
+ #
188
+ # Use other than for commercial purposes is strictly limited to non-revenue
189
+ # generating data transfer between private individuals. The use by government
190
+ # agencies, non-profit organizations, etc is considered as use for commercial
191
+ # purposes but may be subject to special conditions. Any misuse will be
192
+ # prosecuted.
193
+
@@ -0,0 +1,94 @@
1
+ # crypt/rattle.rb Richard Kernahan <kernighan_rich@rubyforge.org>
2
+
3
+ # add_noise - take a message and intersperse noise to make a new noisy message of given byte-length
4
+ # remove_noise - take a noisy message and extract the message
5
+
6
+ module Crypt
7
+ module Noise
8
+
9
+ def add_noise(newLength)
10
+ message = self
11
+ usableNoisyMessageLength = newLength / 9 * 8
12
+ bitmapSize = newLength / 9
13
+ remainingBytes = newLength - usableNoisyMessageLength - bitmapSize
14
+ if (message.length > usableNoisyMessageLength)
15
+ minimumNewLength = (message.length / 8.0).ceil * 9
16
+ puts "For a clear text of #{message.length} bytes, the minimum obscured length"
17
+ puts "is #{minimumNewLength} bytes which allows for no noise in the message."
18
+ puts "You should choose an obscured length of at least double the clear text"
19
+ puts "length, such as #{message.length / 8 * 32} bytes"
20
+ raise "Insufficient length for noisy message"
21
+ end
22
+ bitmap = []
23
+ usableNoisyMessageLength.times { bitmap << false }
24
+ srand(Time.now.to_i)
25
+ positionsSelected = 0
26
+ while (positionsSelected < message.length)
27
+ positionTaken = rand(usableNoisyMessageLength)
28
+ if bitmap[positionTaken]
29
+ next
30
+ else
31
+ bitmap[positionTaken] = true
32
+ positionsSelected = positionsSelected.next
33
+ end
34
+ end
35
+
36
+ noisyMessage = ""
37
+ 0.upto(bitmapSize-1) { |byte|
38
+ c = 0
39
+ 0.upto(7) { |bit|
40
+ c = c + (1<<bit) if bitmap[byte * 8 + bit]
41
+ }
42
+ noisyMessage << c.chr
43
+ }
44
+ posInMessage = 0
45
+ 0.upto(usableNoisyMessageLength-1) { |pos|
46
+ if bitmap[pos]
47
+ meaningfulByte = message[posInMessage]
48
+ noisyMessage << meaningfulByte
49
+ posInMessage = posInMessage.next
50
+ else
51
+ noiseByte = rand(256).chr
52
+ noisyMessage << noiseByte
53
+ end
54
+ }
55
+ remainingBytes.times {
56
+ noiseByte = rand(256).chr
57
+ noisyMessage << noiseByte
58
+ }
59
+ return(noisyMessage)
60
+ end
61
+
62
+
63
+ def remove_noise
64
+ noisyMessage = self
65
+ bitmapSize = noisyMessage.length / 9
66
+ actualMessageLength = bitmapSize * 8
67
+
68
+ actualMessageStart = bitmapSize
69
+ actualMessageFinish = bitmapSize + actualMessageLength - 1
70
+ actualMessage = noisyMessage[actualMessageStart..actualMessageFinish]
71
+
72
+ bitmap = []
73
+ 0.upto(bitmapSize - 1) { |byte|
74
+ c = noisyMessage[byte]
75
+ 0.upto(7) { |bit|
76
+ bitmap[byte * 8 + bit] = (c[bit] == 1)
77
+ }
78
+ }
79
+ clearMessage = ""
80
+ 0.upto(actualMessageLength) { |pos|
81
+ meaningful = bitmap[pos]
82
+ if meaningful
83
+ clearMessage << actualMessage[pos]
84
+ end
85
+ }
86
+ return(clearMessage)
87
+ end
88
+
89
+ end
90
+ end
91
+
92
+ class String
93
+ include Crypt::Noise
94
+ end
@@ -0,0 +1,378 @@
1
+ # Thanks to Binky DaClown who wrote this pure-ruby implementation
2
+ # http://rubyforge.org/projects/prstringio/
3
+ # Apparently CBC does not work well with the C-based stringio
4
+
5
+ module Crypt
6
+ class PureRubyStringIO
7
+
8
+ include Enumerable
9
+
10
+ SEEK_CUR = IO::SEEK_CUR
11
+ SEEK_END = IO::SEEK_END
12
+ SEEK_SET = IO::SEEK_SET
13
+
14
+ @@relayMethods = [:<<, :all?, :any?, :binmode, :close, :close_read, :close_write, :closed?, :closed_read?,
15
+ :closed_write?, :collect, :detect, :each, :each_byte, :each_line, :each_with_index,
16
+ :entries, :eof, :eof?, :fcntl, :fileno, :find, :find_all, :flush, :fsync, :getc, :gets,
17
+ :grep, :include?, :inject, :isatty, :length, :lineno, :lineno=, :map, :max, :member?,
18
+ :min, :partition, :path, :pid, :pos, :pos=, :print, :printf, :putc, :puts, :read,
19
+ :readchar, :readline, :readlines, :reject, :rewind, :seek, :select, :size, :sort,
20
+ :sort_by, :string, :string=, :sync, :sync=, :sysread, :syswrite, :tell, :truncate, :tty?,
21
+ :ungetc, :write, :zip]
22
+
23
+ def self.open(string="", mode="r+")
24
+ if block_given? then
25
+ sio = new(string, mode)
26
+ rc = yield(sio)
27
+ sio.close
28
+ rc
29
+ else
30
+ new(string, mode)
31
+ end
32
+ end
33
+
34
+ def <<(obj)
35
+ requireWritable
36
+ write obj
37
+ self
38
+ end
39
+
40
+ def binmode
41
+ self
42
+ end
43
+
44
+ def close
45
+ requireOpen
46
+ @sio_closed_read = true
47
+ @sio_closed_write = true
48
+ self
49
+ end
50
+
51
+ def close_read
52
+ raise IOError, "closing non-duplex IO for reading", caller if closed_read?
53
+ @sio_closed_read = true
54
+ self
55
+ end
56
+
57
+ def close_write
58
+ raise IOError, "closing non-duplex IO for writing", caller if closed_write?
59
+ @sio_closed_read = true
60
+ self
61
+ end
62
+
63
+ def closed?
64
+ closed_read? && closed_write?
65
+ end
66
+
67
+ def closed_read?
68
+ @sio_closed_read
69
+ end
70
+
71
+ def closed_write?
72
+ @sio_closed_write
73
+ end
74
+
75
+ def each(sep_string=$/, &block)
76
+ requireReadable
77
+ @sio_string.each(sep_string, &block)
78
+ @sio_pos = @sio_string.length
79
+ end
80
+
81
+ def each_byte(&block)
82
+ requireReadable
83
+ @sio_string.each_byte(&block)
84
+ @sio_pos = @sio_string.length
85
+ end
86
+
87
+ def eof
88
+ requireReadable { @sio_pos >= @sio_string.length }
89
+ end
90
+
91
+ def fcntl(integer_cmd, arg)
92
+ raise NotImplementedError, "The fcntl() function is unimplemented on this machine", caller
93
+ end
94
+
95
+ def fileno
96
+ nil
97
+ end
98
+
99
+ def flush
100
+ self
101
+ end
102
+
103
+ def fsync
104
+ 0
105
+ end
106
+
107
+ def getc
108
+ requireReadable
109
+ char = @sio_string[@sio_pos]
110
+ @sio_pos += 1 unless char.nil?
111
+ char
112
+ end
113
+
114
+ def gets(sep_string=$/)
115
+ requireReadable
116
+ @sio_lineno += 1
117
+ pstart = @sio_pos
118
+ @sio_pos = @sio_string.index(sep_string, @sio_pos) || [@sio_string.length, @sio_pos].max
119
+ @sio_string[pstart..@sio_pos]
120
+ end
121
+
122
+ def initialize(string="", mode="r+")
123
+ @sio_string = string.to_s
124
+ @sio_lineno = 0
125
+ @mode = mode
126
+ @relay = nil
127
+ case mode.delete("b")
128
+ when "r"
129
+ @sio_closed_read = false
130
+ @sio_closed_write = true
131
+ @sio_pos = 0
132
+ when "r+"
133
+ @sio_closed_read = false
134
+ @sio_closed_write = false
135
+ @sio_pos = 0
136
+ when "w"
137
+ @sio_closed_read = true
138
+ @sio_closed_write = false
139
+ @sio_pos = 0
140
+ @sio_string.replace("")
141
+ when "w+"
142
+ @sio_closed_read = false
143
+ @sio_closed_write = false
144
+ @sio_pos = 0
145
+ @sio_string.replace("")
146
+ when "a"
147
+ @sio_closed_read = true
148
+ @sio_closed_write = false
149
+ @sio_pos = @sio_string.length
150
+ when "a+"
151
+ @sio_closed_read = false
152
+ @sio_closed_write = false
153
+ @sio_pos = @sio_string.length
154
+ else
155
+ raise ArgumentError, "illegal access mode #{mode}", caller
156
+ end
157
+ end
158
+
159
+ def isatty
160
+ flase
161
+ end
162
+
163
+ def length
164
+ @sio_string.length
165
+ end
166
+
167
+ def lineno
168
+ @sio_lineno
169
+ end
170
+
171
+ def lineno=(integer)
172
+ @sio_lineno = integer
173
+ end
174
+
175
+ def path
176
+ nil
177
+ end
178
+
179
+ def pid
180
+ nil
181
+ end
182
+
183
+ def pos
184
+ @sio_pos
185
+ end
186
+
187
+ def pos=(integer)
188
+ raise Errno::EINVAL, "Invalid argument", caller if integer < 0
189
+ @sio_pos = integer
190
+ end
191
+
192
+ def print(*args)
193
+ requireWritable
194
+ args.unshift($_) if args.empty
195
+ args.each { |obj| write(obj) }
196
+ write($\) unless $\.nil?
197
+ nil
198
+ end
199
+
200
+ def printf(format_string, *args)
201
+ requireWritable
202
+ write format(format_string, *args)
203
+ nil
204
+ end
205
+
206
+ def putc(obj)
207
+ requireWritable
208
+ write(obj.is_a?(Numeric) ? sprintf("%c", obj) : obj.to_s[0..0])
209
+ obj
210
+ end
211
+
212
+ def puts(*args)
213
+ requireWritable
214
+ args.unshift("") if args.empty?
215
+ args.each { |obj|
216
+ write obj
217
+ write $/
218
+ }
219
+ nil
220
+ end
221
+
222
+ def read(length=nil, buffer=nil)
223
+ requireReadable
224
+ len = length || [@sio_string.length - @sio_pos, 0].max
225
+ raise ArgumentError, "negative length #{len} given", caller if len < 0
226
+ buffer ||= ""
227
+ pstart = @sio_pos
228
+ @sio_pos += len
229
+ buffer.replace(@sio_string[pstart..@sio_pos])
230
+ buffer.empty? && !length.nil? ? nil : buffer
231
+ end
232
+
233
+ def readchar
234
+ requireReadable
235
+ raise EOFError, "End of file reached", caller if eof?
236
+ getc
237
+ end
238
+
239
+ def readline
240
+ requireReadable
241
+ raise EOFError, "End of file reached", caller if eof?
242
+ gets
243
+ end
244
+
245
+ def readlines(sep_string=$/)
246
+ requireReadable
247
+ raise EOFError, "End of file reached", caller if eof?
248
+ rc = []
249
+ until eof
250
+ rc << gets(sep_string)
251
+ end
252
+ rc
253
+ end
254
+
255
+ def reopen(string, mode=nil)
256
+ if string.is_a?(self.class) then
257
+ raise ArgumentError, "wrong number of arguments (2 for 1)", caller if !mode.nil?
258
+ @relay = string
259
+ instance_eval(%Q{
260
+ class << self
261
+ @@relayMethods.each { |name|
262
+ define_method(name, ObjectSpace._id2ref(#{@relay.object_id}).method(("original_" + name.to_s).to_sym).to_proc)
263
+ }
264
+ end
265
+ })
266
+ else
267
+ raise ArgumentError, "wrong number of arguments (1 for 2)", caller if mode.nil?
268
+ class << self
269
+ @@relayMethods.each { |name|
270
+ alias_method(name, "original_#{name}".to_sym)
271
+ public name
272
+ }
273
+ @relay = nil
274
+ end unless @relay.nil?
275
+ @sio_string = string.to_s
276
+ @mode = mode
277
+ end
278
+ end
279
+
280
+ def rewind
281
+ @sio_pos = 0
282
+ @sio_lineno = 0
283
+ end
284
+
285
+ def seek(amount, whence=SEEK_SET)
286
+ if whence == SEEK_CUR then
287
+ offset += @sio_pos
288
+ elsif whence == SEEK_END then
289
+ offset += size
290
+ end
291
+ @sio_pos = offset
292
+ end
293
+
294
+ def string
295
+ @sio_string
296
+ end
297
+
298
+ def string=(newstring)
299
+ @sio_string = newstring
300
+ end
301
+
302
+ def sync
303
+ true
304
+ end
305
+
306
+ def sync=(boolean)
307
+ boolean
308
+ end
309
+
310
+ def sysread(length=nil, buffer=nil)
311
+ requireReadable
312
+ raise EOFError, "End of file reached", caller if eof?
313
+ read(length, buffer)
314
+ end
315
+
316
+ def syswrite(string)
317
+ requireWritable
318
+ addition = "\000" * (@sio_string.length - @sio_pos) + string.to_s
319
+ @sio_string[@sio_pos..(addition.length - 1)] = addition
320
+ @sio_pos += addition.size
321
+ addition.size
322
+ end
323
+
324
+ #In ruby 1.8.4 truncate differs from the docs in two ways.
325
+ #First, if an integer greater that the length is given then the string is expanded to the new integer
326
+ #length. As this expansion seems to contain junk characters instead of nulls I suspect this may be a
327
+ #flaw in the C code which could cause a core dump if abused/used.
328
+ #Second, the documentation states that truncate returns 0. It returns the integer instead.
329
+ #This implementation follows the documentation in the first instance as I suspect this will be fixed
330
+ #in the C code. In the second instance, it follows the actions of the C code instead of the docs.
331
+ #This was decided as it causes no immedeate harm and this ruby implentation is to be as compatable
332
+ #as possible with the C version. Should the C version change to match the docs the ruby version
333
+ #will be simple to update as well.
334
+ def truncate(integer)
335
+ requireWritable
336
+ raise Errno::EINVAL, "Invalid argument - negative length", caller if integer < 0
337
+ @sio_string[[integer, @sio_string.length].max..-1] = ""
338
+ integer
339
+ end
340
+
341
+ def ungetc(integer)
342
+ requireWritable
343
+ if @sio_pos > 0 then
344
+ @sio_pos -= 1
345
+ putc(integer)
346
+ @sio_pos -= 1
347
+ end
348
+ end
349
+
350
+ alias :each_line :each
351
+ alias :eof? :eof
352
+ alias :size :length
353
+ alias :tty? :isatty
354
+ alias :tell :pos
355
+ alias :write :syswrite
356
+
357
+ protected
358
+ @@relayMethods.each { |name|
359
+ alias_method("original_#{name}".to_sym, name)
360
+ protected "original_#{name}".to_sym
361
+ }
362
+
363
+ private
364
+
365
+ def requireReadable
366
+ raise IOError, "not opened for reading", caller[1..-1] if @sio_closed_read
367
+ end
368
+
369
+ def requireWritable
370
+ raise IOError, "not opened for writing", caller[1..-1] if @sio_closed_write
371
+ end
372
+
373
+ def requireOpen
374
+ raise IOError, "closed stream", caller[1..-1] if @sio_closed_read && @sio_closed_write
375
+ end
376
+
377
+ end
378
+ end