How to get the MD5 of a FolderItem

I see that Xojo has a built in Crypto function to find the MD5 digest from a MemoryBlock. Given a FolderItem, how would I find the file’s MD5 digest? I’m not sure how to convert a file to a MemoryBlock.

This is one of the reasons I like the old framework. Strings can be used as memory blocks without much work.
Depending on the size of your FolderItem, you can ReadAll into a string, then use the string for MD5.

Alternatively, if it’s Mac only, you can use Shell to md5 a file.

I would test to be sure you get the same result between Terminal.app and my ReadAll into a string method though.

Or read the file in chunks. This is how I did it in Kaju…

Protected Function HashOfFile(f As FolderItem) as String
  if f is nil or not f.IsReadable then
    return ""
  end if
  
  dim bs as BinaryStream = BinaryStream.Open( f )
  
  const kBlock = 1000000
  
  dim hasher as new MD5Digest
  
  while not bs.EOF
    dim chunk as string = bs.Read( kBlock )
    hasher.Process( chunk )
  wend
  
  return EncodeHex( hasher.Value )
  
  Exception err as RuntimeException
    return ""
End Function

The files vary in size from about 1Mb to 100Mb. Guessing that’s maybe too big for a String? Needs to work on Windows too I’m afraid.

If I go the new framework route, do I need to read the whole file in as a BinaryStream then convert that to a MemoryBlock then Hash it? Seems like a lot of effort…

@Kem Tekinay What’s the advantage of chunking the read?

You don’t have to load the entire file into memory, instead just loading manageable blocks.

Any way of doing this new framework only (so it works on iOS)?

Mac? Win? Linux?

MD5DigestMBS.HashFile function is fast and uses preemptive threading, so if used in a Xojo thread, it can do the work in background.

I don’t see an MD5Digest equivalent in the new framework yet so you’d have to do it with OS calls. (I haven’t researched to see what might be available.)

Meaning MBS isn’t an option

for iOS and Mac you could use my Encryption Kit:
http://www.monkeybreadsoftware.de/xojo/EncryptionKit/

Well, most times not all options are available for all cases.
So we use a lot of #if in our code.

Plugin is available for Mac+Win+Linux and supports preemptive threading.
The Kit is available for Mac+IOS and supports various hashes including MD5.

But as Xojo on iOS is limited in multithreading, he may need to use a Xojo thread and a binary stream and feed the digest engine chunk by chunk.

http://developer.xojo.com/xojo-crypto$MD5
It’s at least possible to MD5 in the new framework. I’m not sure about chunking it though.

Edit: Added quote for reference, and extra details.

Sorry for my posts.
I though the point was how to quickly process MD5 of file.
I wrote the plugin functions once to process that with 8 cores busy in a threaded app myself.

If you don’t need threading on desktop, the built in function is fine of course.

I was supplementing Kem’s post, I probably should have quoted it.

It’s good to know that MBS on Desktop can handle the harder stuff in threads.
Thank you for your additions :slight_smile:

These are all good points. Sadly they highlight the difficulties that the new framework brings.

It looks like the new Xojo.Crypto.Hash() method will calculate a MD5 digest on a Xojo.Core.MemoryBlock (which you can get from a Xojo.IO.FolderItem by reading it as a Xojo.IO.BinaryStream) but I can’t for the life of me find an equivalent of the classic framework EncodeHex() to convert the Xojo.Core.MemoryBlock returned by the new framework Hash() method into a Hex value I could display to the user.

Here’s what I have so far:

[code]Public Function FileToMD5(file as Xojo.IO.FolderItem) as Text
’ Returns the MD5 hash value for this file.
’ Returns “” if there’s an error.

using xojo.Core
using xojo.Crypto

dim data as xojo.Core.MemoryBlock
dim bs as xojo.IO.BinaryStream
dim result as xojo.Core.MemoryBlock

’ Sanity check
if file is Nil or file.IsFolder or not file.IsReadable then
return “”
end if

’ Open the file and read it into a MemoryBlock
bs = Xojo.IO.BinaryStream.Open(file, xojo.IO.BinaryStream.LockModes.Read)
data = bs.Read(bs.Length)
bs.Close()

result = Hash(data, xojo.Crypto.HashAlgorithms.MD5) ’ <— Convert to Hex???

exception err as RuntimeException
return “”
End Function[/code]

Any ideas how to get the hash as a user-readable Text object?

You could write your own EncodeHex function.
I don’t see one in the new framework.

iterate each uint8, use toHex on each one & concatenate them together

  result = Hash(data, xojo.Crypto.HashAlgorithms.MD5) ' <--- Convert to Hex????
  
   dim strResult as text

 For i As Integer = 0 To result.size()-1
  strResult = strResult + if(result.UInt8Value(i)<10, "0" + result.UInt8Value(i).toHex, result.UInt8Value(i).toHex)
Next

return strResult

Also search the forum for alternatives. I remember that we covered EncodeHex once upon a time.