rUtilAnts 0.2.1.20101110 → 0.2.2.20101125

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/ChangeLog CHANGED
@@ -1,5 +1,10 @@
1
1
  = rUtilAnts Release History
2
2
 
3
+ == 0.2.2.20101125 (Beta)
4
+
5
+ * Archive: Implemented a new module that provides archiving strings, objects and files with compression and encryption
6
+ * Platforms: Added support for i386-mingw32 (current Ruby installations on Windows use this platform)
7
+
3
8
  == 0.2.1.20101110 (Beta)
4
9
 
5
10
  * Changed copyright mentions.
data/ReleaseInfo CHANGED
@@ -2,7 +2,7 @@
2
2
  # This file has been generated by RubyPackager during a delivery.
3
3
  # More info about RubyPackager: http://rubypackager.sourceforge.net
4
4
  {
5
- :Version => '0.2.1.20101110',
5
+ :Version => '0.2.2.20101125',
6
6
  :Tags => [ 'Beta' ],
7
7
  :DevStatus => 'Beta'
8
8
  }
@@ -0,0 +1,356 @@
1
+ #--
2
+ # Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
3
+ # Licensed under the terms specified in LICENSE file. No warranty is provided.
4
+ #++
5
+
6
+ require 'ezcrypto'
7
+ require 'zlib'
8
+ require 'fileutils'
9
+
10
+ module RUtilAnts
11
+
12
+ module Archive
13
+
14
+ # Class used to give the encoders a streaming interface
15
+ class StringWriter
16
+
17
+ # Buffer size used in bytes
18
+ BUFFER_SIZE = 8388608
19
+
20
+ # Constructor
21
+ #
22
+ # Parameters:
23
+ # * *iPassword* (_String_): Password encrypting data
24
+ # * *iSalt* (_String_): Salt encoding data
25
+ # * *oFile* (_IO_): The IO that will receive encrypted data
26
+ def initialize(iPassword, iSalt, oFile)
27
+ @Password, @Salt, @File = iPassword, iSalt, oFile
28
+ @Buffer = ''
29
+ end
30
+
31
+ # Add a string to write
32
+ #
33
+ # Parameters:
34
+ # * *iData* (_String_): The data to encrypt and write
35
+ def <<(iData)
36
+ # Add to the buffer
37
+ if (@Buffer.size + iData.size < BUFFER_SIZE)
38
+ @Buffer.concat(iData)
39
+ else
40
+ # Flush the completed buffer
41
+ lIdxData = BUFFER_SIZE-@Buffer.size
42
+ @Buffer.concat(iData[0..lIdxData-1])
43
+ flush
44
+ # And now flush new data buffers
45
+ @Buffer = iData[lIdxData..lIdxData+BUFFER_SIZE-1]
46
+ while (@Buffer.size == BUFFER_SIZE)
47
+ flush
48
+ lIdxData += BUFFER_SIZE
49
+ @Buffer = iData[lIdxData..lIdxData+BUFFER_SIZE-1]
50
+ end
51
+ end
52
+ end
53
+
54
+ # Flush current data in the file
55
+ def flush
56
+ if (!@Buffer.empty?)
57
+ # Compress
58
+ lZippedData = Zlib::Deflate.new.deflate(@Buffer, Zlib::FINISH)
59
+ # Encrypt
60
+ lEncryptedData = EzCrypto::Key.encrypt_with_password(@Password, @Salt, lZippedData)
61
+ # Write
62
+ @File.write([lEncryptedData.size].pack('l'))
63
+ @File.write(lEncryptedData)
64
+ @Buffer = ''
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ # Class used to give the decoders a streaming interface
71
+ class StringReader
72
+
73
+ # Constructor
74
+ #
75
+ # Parameters:
76
+ # * *iPassword* (_String_): Password encrypting data
77
+ # * *iSalt* (_String_): Salt encoding data
78
+ # * *iFile* (_IO_): The IO that will send encrypted data
79
+ def initialize(iPassword, iSalt, iFile)
80
+ @Password, @Salt, @File = iPassword, iSalt, iFile
81
+ end
82
+
83
+ # Get the next string encrypted
84
+ #
85
+ # Return:
86
+ # * _String_: The next string encrypted (or nil if none)
87
+ def get
88
+ rObject = nil
89
+
90
+ # Read
91
+ lStrChunkSize = @File.read(4)
92
+ if (lStrChunkSize != nil)
93
+ lChunkSize = lStrChunkSize.unpack('l')[0]
94
+ lData = @File.read(lChunkSize)
95
+ # Decrypt
96
+ lDecryptedData = EzCrypto::Key.decrypt_with_password(@Password, @Salt, lData)
97
+ # Uncompress
98
+ rObject = Zlib::Inflate.new.inflate(lDecryptedData)
99
+ end
100
+
101
+ return rObject
102
+ end
103
+
104
+ end
105
+
106
+ TYPE_OBJECT = 'O'
107
+ TYPE_STRING = 'S'
108
+
109
+ # Class used to write a Ruby object
110
+ class ObjectWriter
111
+
112
+ # Constructor
113
+ #
114
+ # Parameters:
115
+ # * *iPassword* (_String_): Password encrypting data
116
+ # * *iSalt* (_String_): Salt encoding data
117
+ # * *oFile* (_IO_): The IO that will receive encrypted data
118
+ def initialize(iPassword, iSalt, oFile)
119
+ @StringWriter = StringWriter.new(iPassword, iSalt, oFile)
120
+ end
121
+
122
+ # Add an object to write
123
+ #
124
+ # Parameters:
125
+ # * *iObject* (_Object_): The object to write
126
+ def <<(iObject)
127
+ lStrType = nil
128
+ lStrObject = nil
129
+ if (iObject.is_a?(String))
130
+ lStrType = TYPE_STRING
131
+ lStrObject = iObject
132
+ else
133
+ lStrType = TYPE_OBJECT
134
+ lStrObject = Marshal.dump(iObject)
135
+ end
136
+ # Write it along with its length
137
+ @StringWriter << (lStrType + [lStrObject.size].pack('l') + lStrObject)
138
+ end
139
+
140
+ # Flush
141
+ def flush
142
+ @StringWriter.flush
143
+ end
144
+
145
+ end
146
+
147
+ # Class used to read a Ruby object
148
+ class ObjectReader
149
+
150
+ # Size of the object header
151
+ OBJECT_HEADER_SIZE = 5
152
+
153
+ # Constructor
154
+ #
155
+ # Parameters:
156
+ # * *iPassword* (_String_): Password encrypting data
157
+ # * *iSalt* (_String_): Salt encoding data
158
+ # * *iFile* (_IO_): The IO that will send encrypted data
159
+ def initialize(iPassword, iSalt, iFile)
160
+ @StringReader = StringReader.new(iPassword, iSalt, iFile)
161
+ @BufferRead = ''
162
+ end
163
+
164
+ # Get the next object encrypted
165
+ #
166
+ # Return:
167
+ # * _Object_: The next object encrypted (or nil if none)
168
+ def get
169
+ rObject = nil
170
+
171
+ # Read the size first
172
+ while (@BufferRead.size < OBJECT_HEADER_SIZE)
173
+ @BufferRead.concat(@StringReader.get)
174
+ end
175
+ lObjectType = @BufferRead[0..0]
176
+ lObjectSize = @BufferRead[1..OBJECT_HEADER_SIZE-1].unpack('l')[0]
177
+ # Then read the data
178
+ while (@BufferRead.size < OBJECT_HEADER_SIZE+lObjectSize)
179
+ @BufferRead.concat(@StringReader.get)
180
+ end
181
+ case lObjectType
182
+ when TYPE_OBJECT
183
+ rObject = Marshal.load(@BufferRead[OBJECT_HEADER_SIZE..OBJECT_HEADER_SIZE+lObjectSize-1])
184
+ when TYPE_STRING
185
+ rObject = @BufferRead[OBJECT_HEADER_SIZE..OBJECT_HEADER_SIZE+lObjectSize-1]
186
+ else
187
+ raise RuntimeError.new("Unknown object type: #{lObjectType}")
188
+ end
189
+ @BufferRead = @BufferRead[OBJECT_HEADER_SIZE+lObjectSize..-1]
190
+
191
+ return rObject
192
+ end
193
+
194
+ end
195
+
196
+ # Class used to write files and directories
197
+ class FilesWriter
198
+
199
+ # Size of the buffer used to write files contents
200
+ FILE_BUFFER_SIZE = 8388608
201
+
202
+ # Constructor
203
+ #
204
+ # Parameters:
205
+ # * *iPassword* (_String_): Password encrypting data
206
+ # * *iSalt* (_String_): Salt encoding data
207
+ # * *oFile* (_IO_): The IO that will receive encrypted data
208
+ def initialize(iPassword, iSalt, oFile)
209
+ @ObjectWriter = ObjectWriter.new(iPassword, iSalt, oFile)
210
+ # The list of empty directories
211
+ # list< String >
212
+ @EmptyDirs = []
213
+ # The list of files, along with their size
214
+ # list< [ String, Integer ] >
215
+ @LstFiles = []
216
+ # The total size of bytes
217
+ # Integer
218
+ @TotalSize = 0
219
+ end
220
+
221
+ # Add a single file to write
222
+ #
223
+ # Parameters:
224
+ # * *iFileName* (_String_): File to add
225
+ def addFile(iFileName)
226
+ lFileSize = File.size(iFileName)
227
+ @LstFiles << [ iFileName, lFileSize ]
228
+ @TotalSize += lFileSize
229
+ end
230
+
231
+ # Add a directory with all its recursive content
232
+ #
233
+ # Parameters:
234
+ # * *iDirName* (_String_): Name of the directory
235
+ def addDir(iDirName)
236
+ lEmpty = true
237
+ lRealDir = iDirName
238
+ if (iDirName == '')
239
+ lRealDir = '.'
240
+ end
241
+ Dir.foreach(lRealDir) do |iFileName|
242
+ if ((iFileName != '.') and
243
+ (iFileName != '..'))
244
+ lEmpty = false
245
+ lCompleteFileName = "#{iDirName}/#{iFileName}"
246
+ if (iDirName == '')
247
+ lCompleteFileName = iFileName
248
+ end
249
+ if (File.directory?(lCompleteFileName))
250
+ addDir(lCompleteFileName)
251
+ else
252
+ addFile(lCompleteFileName)
253
+ end
254
+ end
255
+ end
256
+ if (lEmpty)
257
+ @EmptyDirs << iDirName
258
+ end
259
+ end
260
+
261
+ # Add a files filter
262
+ #
263
+ # Parameters:
264
+ # * *iFilesFilter* (_String_): The files filter, to be used with glob
265
+ def addFiles(iFilesFilter)
266
+ Dir.glob(iFilesFilter).each do |iFileName|
267
+ if (!File.directory?(iFileName))
268
+ addFile(iFileName)
269
+ end
270
+ end
271
+ end
272
+
273
+ # Dump files to write on screen
274
+ def dump
275
+ logMsg "#{@EmptyDirs.size} empty directories:"
276
+ @EmptyDirs.each_with_index do |iDirName, iIdxDir|
277
+ logMsg "* [#{iIdxdir}]: #{iDirName}"
278
+ end
279
+ logMsg "#{@LstFiles.size} files (#{@TotalSize} bytes):"
280
+ @LstFiles.each_with_index do |iFileInfo, iIdxFile|
281
+ iFileName, iFileSize = iFileInfo
282
+ logMsg "* [#{iIdxFile}]: #{iFileName} (#{iFileSize} bytes)"
283
+ end
284
+ end
285
+
286
+ # Write everything in the file
287
+ def write
288
+ # First, the list of empty directories and the header
289
+ @ObjectWriter << [ @EmptyDirs, @LstFiles.size, @TotalSize ]
290
+ # Then each file
291
+ lEncodedSize = 0
292
+ @LstFiles.each do |iFileInfo|
293
+ iFileName, iFileSize = iFileInfo
294
+ lNbrChunks = iFileSize/FILE_BUFFER_SIZE
295
+ if (iFileSize % FILE_BUFFER_SIZE != 0)
296
+ lNbrChunks += 1
297
+ end
298
+ logDebug "Writing file #{iFileName} (#{iFileSize} bytes, #{lNbrChunks} chunks) ..."
299
+ @ObjectWriter << [ iFileName, lNbrChunks ]
300
+ File.open(iFileName, 'rb') do |iFile|
301
+ lNbrChunks.times do |iIdxChunk|
302
+ lFileDataChunk = iFile.read(FILE_BUFFER_SIZE)
303
+ @ObjectWriter << lFileDataChunk
304
+ lEncodedSize += lFileDataChunk.size
305
+ $stdout.write("#{(lEncodedSize*100)/@TotalSize} %\015")
306
+ end
307
+ end
308
+ end
309
+ @ObjectWriter.flush
310
+ end
311
+
312
+ end
313
+
314
+ # Class used to read files and directories
315
+ class FilesReader
316
+
317
+ # Constructor
318
+ #
319
+ # Parameters:
320
+ # * *iPassword* (_String_): Password encrypting data
321
+ # * *iSalt* (_String_): Salt encoding data
322
+ # * *iFile* (_IO_): The IO that will send encrypted data
323
+ def initialize(iPassword, iSalt, iFile)
324
+ @ObjectReader = ObjectReader.new(iPassword, iSalt, iFile)
325
+ end
326
+
327
+ # Read the files and write them in the current directory
328
+ def read
329
+ # First, read the archive header
330
+ lEmptyDirs, lNbrFiles, lTotalSize = @ObjectReader.get
331
+ # Create the empty directories
332
+ lEmptyDirs.each do |iDirName|
333
+ FileUtils::mkdir_p(iDirName)
334
+ end
335
+ # Read each file
336
+ lDecodedSize = 0
337
+ lNbrFiles.times do |iIdxFile|
338
+ lFileName, lNbrChunks = @ObjectReader.get
339
+ logDebug "Reading file #{lFileName} (#{lNbrChunks} chunks) ..."
340
+ FileUtils::mkdir_p(File.dirname(lFileName))
341
+ File.open(lFileName, 'wb') do |oFile|
342
+ lNbrChunks.times do |iIdxChunk|
343
+ lFileDataChunk = @ObjectReader.get
344
+ oFile.write(lFileDataChunk)
345
+ lDecodedSize += lFileDataChunk.size
346
+ $stdout.write("#{(lDecodedSize*100)/lTotalSize} %\015")
347
+ end
348
+ end
349
+ end
350
+ end
351
+
352
+ end
353
+
354
+ end
355
+
356
+ end
@@ -0,0 +1,149 @@
1
+ #--
2
+ # Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
3
+ # Licensed under the terms specified in LICENSE file. No warranty is provided.
4
+ #++
5
+
6
+ module RUtilAnts
7
+
8
+ module Platform
9
+
10
+ class PlatformInfo
11
+
12
+ # Return the ID of the OS
13
+ # Applications may adapt their behavior based on it.
14
+ #
15
+ # Return:
16
+ # * _Integer_: OS ID
17
+ def os
18
+ return OS_WINDOWS
19
+ end
20
+
21
+ # Return the list of directories where we look for executables
22
+ #
23
+ # Return:
24
+ # * <em>list<String></em>: List of directories
25
+ def getSystemExePath
26
+ return ENV['PATH'].split(';')
27
+ end
28
+
29
+ # Set the list of directories where we look for executables
30
+ #
31
+ # Parameters:
32
+ # * *iNewDirsList* (<em>list<String></em>): List of directories
33
+ def setSystemExePath(iNewDirsList)
34
+ ENV['PATH'] = iNewDirsList.join(';')
35
+ end
36
+
37
+ # Return the list of file extensions that might be discretely happened to executable files.
38
+ # This is the optional extensions that can be happened when invoked from a terminal.
39
+ #
40
+ # Return:
41
+ # * <em>list<String></em>: List of extensions (including .)
42
+ def getDiscreteExeExtensions
43
+ rExtList = []
44
+
45
+ ENV['PATHEXT'].split(';').each do |iExt|
46
+ rExtList << iExt.downcase
47
+ end
48
+
49
+ return rExtList
50
+ end
51
+
52
+ # Return the list of directories where we look for libraries
53
+ #
54
+ # Return:
55
+ # * <em>list<String></em>: List of directories
56
+ def getSystemLibsPath
57
+ return ENV['PATH'].split(';')
58
+ end
59
+
60
+ # Set the list of directories where we look for libraries
61
+ #
62
+ # Parameters:
63
+ # * *iNewDirsList* (<em>list<String></em>): List of directories
64
+ def setSystemLibsPath(iNewDirsList)
65
+ ENV['PATH'] = iNewDirsList.join(';')
66
+ end
67
+
68
+ # This method sends a message (platform dependent) to the user, without the use of wxruby
69
+ #
70
+ # Parameters:
71
+ # * *iMsg* (_String_): The message to display
72
+ def sendMsg(iMsg)
73
+ # iMsg must not be longer than 255 characters
74
+ # \n must be escaped.
75
+ if (iMsg.size > 255)
76
+ system("msg \"#{ENV['USERNAME']}\" /W \"#{iMsg[0..254]}\"")
77
+ else
78
+ system("msg \"#{ENV['USERNAME']}\" /W \"#{iMsg}\"")
79
+ end
80
+ end
81
+
82
+ # Execute a Shell command.
83
+ # Do not wait for its termination.
84
+ #
85
+ # Parameters:
86
+ # * *iCmd* (_String_): The command to execute
87
+ # * *iInTerminal* (_Boolean_): Do we execute this command in a separate terminal ?
88
+ # Return:
89
+ # * _Exception_: Error, or nil if success
90
+ def execShellCmdNoWait(iCmd, iInTerminal)
91
+ rException = nil
92
+
93
+ if (iInTerminal)
94
+ if (!system("start cmd /c #{iCmd}"))
95
+ rException = RuntimeError.new
96
+ end
97
+ else
98
+ begin
99
+ IO.popen(iCmd)
100
+ rescue Exception
101
+ rException = $!
102
+ end
103
+ end
104
+
105
+ return rException
106
+ end
107
+
108
+ # Execute a given URL to be launched in a browser
109
+ #
110
+ # Parameters:
111
+ # * *iURL* (_String_): The URL to launch
112
+ # Return:
113
+ # * _String_: Error message, or nil if success
114
+ def launchURL(iURL)
115
+ rError = nil
116
+
117
+ # We must put " around the URL after the http:// prefix, as otherwise & symbol will not be recognized
118
+ lMatch = iURL.match(/^(http|https|ftp|ftps):\/\/(.*)$/)
119
+ if (lMatch == nil)
120
+ rError = "URL #{iURL} is not one of http://, https://, ftp:// or ftps://. Can't invoke it."
121
+ else
122
+ IO.popen("start #{lMatch[1]}://\"#{lMatch[2]}\"")
123
+ end
124
+
125
+ return rError
126
+ end
127
+
128
+ # Get file extensions specifics to executable files
129
+ #
130
+ # Return:
131
+ # * <em>list<String></em>: List of extensions (including . character). It can be empty.
132
+ def getExecutableExtensions
133
+ # TODO: Use PATHEXT environment variable if possible
134
+ return [ '.exe', '.com', '.bat' ]
135
+ end
136
+
137
+ # Get prohibited characters from file names
138
+ #
139
+ # Return:
140
+ # * _String_: String of prohibited characters in file names
141
+ def getProhibitedFileNamesCharacters
142
+ return '\\/:*?"<>|'
143
+ end
144
+
145
+ end
146
+
147
+ end
148
+
149
+ end
@@ -130,6 +130,7 @@ module RUtilAnts
130
130
  # Return:
131
131
  # * <em>list<String></em>: List of extensions (including . character). It can be empty.
132
132
  def getExecutableExtensions
133
+ # TODO: Use PATHEXT environment variable if possible
133
134
  return [ '.exe', '.com', '.bat' ]
134
135
  end
135
136
 
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 1
9
- - 20101110
10
- version: 0.2.1.20101110
8
+ - 2
9
+ - 20101125
10
+ version: 0.2.2.20101125
11
11
  platform: ruby
12
12
  authors:
13
13
  - Muriel Salvan
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-10 00:00:00 +01:00
18
+ date: 2010-11-25 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -28,31 +28,33 @@ extensions: []
28
28
  extra_rdoc_files: []
29
29
 
30
30
  files:
31
- - lib/rUtilAnts/URLHandlers/HTTP.rb
32
- - lib/rUtilAnts/URLHandlers/FTP.rb
33
- - lib/rUtilAnts/URLHandlers/LocalFile.rb
34
- - lib/rUtilAnts/URLHandlers/DataImage.rb
31
+ - AUTHORS
32
+ - ChangeLog
33
+ - Credits
34
+ - lib/rUtilAnts/Archive.rb
35
+ - lib/rUtilAnts/ForeignProcess.rb
35
36
  - lib/rUtilAnts/GUI/Bug.png
36
37
  - lib/rUtilAnts/GUI/BugReportDialog.rb
38
+ - lib/rUtilAnts/GUI.rb
39
+ - lib/rUtilAnts/Logging.rb
40
+ - lib/rUtilAnts/Misc.rb
41
+ - lib/rUtilAnts/Platform.rb
42
+ - lib/rUtilAnts/Platforms/i386-cygwin/PlatformInfo.rb
37
43
  - lib/rUtilAnts/Platforms/i386-linux/PlatformInfo.rb
44
+ - lib/rUtilAnts/Platforms/i386-mingw32/PlatformInfo.rb
38
45
  - lib/rUtilAnts/Platforms/i386-mswin32/PlatformInfo.rb
39
46
  - lib/rUtilAnts/Platforms/x86_64-linux/PlatformInfo.rb
40
- - lib/rUtilAnts/Platforms/i386-cygwin/PlatformInfo.rb
41
47
  - lib/rUtilAnts/Plugins.rb
42
- - lib/rUtilAnts/GUI.rb
43
- - lib/rUtilAnts/Platform.rb
44
48
  - lib/rUtilAnts/URLAccess.rb
45
- - lib/rUtilAnts/Logging.rb
46
49
  - lib/rUtilAnts/URLCache.rb
47
- - lib/rUtilAnts/Misc.rb
48
- - lib/rUtilAnts/ForeignProcess.rb
49
- - ReleaseInfo
50
- - README
50
+ - lib/rUtilAnts/URLHandlers/DataImage.rb
51
+ - lib/rUtilAnts/URLHandlers/FTP.rb
52
+ - lib/rUtilAnts/URLHandlers/HTTP.rb
53
+ - lib/rUtilAnts/URLHandlers/LocalFile.rb
51
54
  - LICENSE
52
- - AUTHORS
53
- - Credits
55
+ - README
56
+ - ReleaseInfo
54
57
  - TODO
55
- - ChangeLog
56
58
  has_rdoc: true
57
59
  homepage: http://rutilants.sourceforge.net/
58
60
  licenses: []
@@ -63,6 +65,7 @@ rdoc_options: []
63
65
  require_paths:
64
66
  - lib
65
67
  required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
66
69
  requirements:
67
70
  - - ">="
68
71
  - !ruby/object:Gem::Version
@@ -70,6 +73,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
73
  - 0
71
74
  version: "0"
72
75
  required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
73
77
  requirements:
74
78
  - - ">="
75
79
  - !ruby/object:Gem::Version
@@ -79,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
83
  requirements: []
80
84
 
81
85
  rubyforge_project: rutilants
82
- rubygems_version: 1.3.6
86
+ rubygems_version: 1.3.7
83
87
  signing_key:
84
88
  specification_version: 3
85
89
  summary: A collection of various utility libraries.