March 24th, 2005, 04:41 PM
I'm having trouble translating the following code.Hash = Mid
To Python. Because of the way Visual Basic's Mid() function works, I have no clue what's going on in this code. I got as far as this:
Hash = Mid(Mid(Data, 34), InStr(Mid(Data, 34), Chr(0)) + 1, InStr(Mid(Mid(Data, 34), InStr(Data, Chr(0)) + 1), Chr(0)))
I know that isn't very far at all. But I was becoming very confused, I wasn't sure where the first Mid() was doing around the second Mid(). I will appreciate any help.
hash = data[data[33:], data.find(data[33:]),
March 25th, 2005, 12:52 AM
I don't and probably never will know VB but you might want to stop trying to translate code and learn Python . I think you'll find things much easier if you do.
Anyway, what does the line do (or what is it surposed to do). If you give us some sample text and the value you want I'm sure we can work something out .
March 25th, 2005, 04:44 AM
I've said the same before, Mark, but to no avail. While your persistence is admirable, Yegg, I would think that you would eventually get tired of beating yourself agains this particular wall. As I've said a number of times, VB and Python are too different for a direct transliteration to be practical.
As for this particular problem, well, let me start by saying that the code-monkey who wrote that VB fragment should be shot. Unfortunately, it is all too typical of VB code, and of the particular program you are trying to duplicate. The fact that he makes the same function call three times in a single line is enough to make me weep. Do us all a favor and send the VB source code to The Daily WTF for proper excoriation, then bury your own copy at the crossroads at midnight with a stake through it's disk spindle.
If you insist on it, then I'd advise you to break up the expression into a number of sub-expressions, over perhaps a half dozen lines. Let's start by indenting this Lisp-fashion to show the individual function calls:
This shows a bit clearer what it's doing - it is taking the substring of Data beginning at character 34, then taking a substring of that that begins one char past the first null that appears in the first substring, and ending at (bear with me here) a position determined from the position of the first null following an offset into that first substring matching the location one char past the first null in the original string (I feel woozy).
Hash = Mid(Mid(Data, 34), _ ' initial substring
' final substring start point
InStr(Mid(Data, 34), Chr(0)) + 1, _
' final substring endpoint
InStr(Mid(Mid(Data, 34), _
InStr(Data, Chr(0)) + 1), _
Either the protocol designer was insane, or (more likely) the VB coder had no clue what he was doing. Let's break the VB code into separate lines nd see if it's any clearer.
Converting this to Python:
null_char = chr(0)
data_tail = mid(Data, 34) ' the substring to parse
' the starting point of the final substring
hash_start = InStr(data_tail, null_char) + 1
' the end point of the final substring
data_null_offset = InStr(Data, null_char) + 1
offset_substr = Mid(data_tail, data_null_offset)
hash_end = InStr(offset_substr, null_char)
' extract the final substring containing the hash (MD5 sig?)
hash = Mid(data_tail, hash_start, hash_end)
This is still execrable code, but it should come within earshot of working. I wish I knew more about just what it is trying to implement; I'm certain there has to be an easier way to do this, but I'm too tired right now to work it out.
null_char = '\0'
data_tail = Data[33:] # the substring to parse
# the starting point of the final substring
# doesn't need the '+ 1' offset because of
# how the slice operator works
hash_start = data_tail.find(null_char)
# the end point of the final substring
data_null_offset = Data.find(null_char)
offset_substr = data_tail[data_null_offset:]
hash_end = offset_substr.find(null_char)
# extract the final substring containing the hash (MD5 sig?)
hash = data_tail[hash_start:hash_end]
Comments and Corrections Welcome.
Comments on this post
Last edited by Schol-R-LEA; March 26th, 2005 at 07:36 PM.
March 26th, 2005, 06:58 AM
Yup ... it's ghastly. The bright side is there IS a better way of doing it:
Originally Posted by Schol-R-LEA
Understanding why it should work is left as an exercise for Yegg ;-)
hash = Data[33:].split('\0')
ps: "data" is a better name for a variable than "Data" since "Data" implies a class.
March 26th, 2005, 09:27 AM
Netytan, it's not so much learnign Python. Back in the day when Battle.net bot's first were being created, the early programmers obviously didn't know near as much then as they know now. That code is over 5 years old, that's probably why it's so horrible. This code which most people use or create a copy like it for their bots, is needed for having a hashed connection (using the game clients hash files) to a Battle.net game. This one works only for Starcraft. I'm pretty sure most of the code I can figure out how to translate, but it was just this line that seemed very confusing. There was two Mid() functions one over the other, and there were too many comma's to concentrate on, I kept forgetting where one Mid() began and the other ended. Thanks for all the help Schol-R-LEA.
March 26th, 2005, 07:16 PM
A pair of footnotes:
After I posted this, I remembered that VB 6 and earlier already had a named constant for the null character, not surprisingly named vbNullChar. I wonder if the person who wrote the original even knew it.
Netytan's solution (assuming it is correct, which it certainly appears to be) implies that the protocol in question (or at least this part of it) consists of a fixed 34-byte header followed by a series null-delimited fields, the second of which contains the hash code in question. If so, then the obvious VB solution would have been something like
Why didn't the original coder do that? Certainly not because it was easier; the original line shows a twisted sort of ingenuity, and must have taken hours to devise. Perhaps the coder didn't know about the split() function, but you'd think that if you were have so much trouble with a piece of code that the original line was the best you could come up with, you would crack open a reference book to try and find a better solution. Who knows?
DataTail = Mid(data, 34)
DataFields = split(DataTail, vbNullChar)
hash = DataFields(1)
Anyway, as a correctness test for this, perhaps Yegg can take this code (with the appropriate declarations) and insert it into the VB code as a replacement for the original. This should tell us conclusively if it works right or not.
Last edited by Schol-R-LEA; March 26th, 2005 at 07:32 PM.
March 26th, 2005, 08:34 PM
Hmm, I'm sure the original coder knew about the split() function. After all, this was one of the earliest forms of starcraft hashing. They must have known enough about what they were doing. When I get some time, I will try that code and see if it works correctly.