rUtilAnts 0.2.1.20101110 → 0.2.2.20101125

Sign up to get free protection for your applications and to get access to all the features.
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.