Search And Replace within A Binary Stream - vbscript

I am trying to change a value in a bytestream array. I am looking for the Null value, and I want to change it to a space. When I try to access the array I get an error message "Type Mismatch".
My VBS Code:
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Const adSaveCreateNotExist=1
'Create Stream object
Dim BinaryStream
Set BinaryStream = CreateObject("ADODB.Stream")
Dim InputFile
InputFile="C:\Users\oferbe\Documents\Tfachut\prepr\Testinput.txt"
'Specify stream type - we want To get binary data.
BinaryStream.Type = adTypeBinary
'Open the stream
BinaryStream.Open
'Load the file data from disk To stream object
BinaryStream.LoadFromFile InputFile
'Open the stream And get binary data from the object
ReadBinaryFile = BinaryStream.Read
BinaryStream.Close
For i = 0 to UBound(ReadBinaryFile)
If ReadBinaryFile(i)=00 Then ReadBinaryFile(i)=20
Next
BinaryStream.Open
'BinaryStream.Write ByteArray
BinaryStream.Write ReadBinaryFile
Dim OutPutFile
OutPutFile="C:\Users\oferbe\Documents\Tfachut\prepr\Ofer"
'Save binary data To disk
BinaryStream.SaveToFile OutPutFile, adSaveCreateOverWrite

The Read operation returns a byte array, which is basically a binary string having some of the properties of a VBScript array, but not all of them. You're better off reading the binary stream as a regular string:
inputFile = "C:\path\to\your\input.bin"
outputFile = "C:\path\to\your\output.bin"
Set stream = CreateObject("ADODB.Stream")
stream.Open
stream.Type = 2
stream.Charset = "Windows-1252"
stream.LoadFromFile inputFile
data = stream.ReadText
stream.Close
data = Replace(data, Chr(0), Chr(32))
stream.Open
stream.Type = 2
stream.Charset = "Windows-1252"
stream.WriteText data
stream.SaveToFile outputFile, 2
stream.Close
Set stream = Nothing

Related

Classic ASP Base64 Encoding and Line Breaks

I have been using the base64 encoding function from this answer (code is below)
https://stackoverflow.com/a/506992/510296
I noticed that it is wrapping lines of output after the 72nd character (which causes problems when I try to pass that encoded string to the eBay API).
I can remove the line breaks easily enough with replace(base64string, vblf, "") but wanted to ask if there is a proper way to prevent line breaks in the output.
Function Base64Encode(sText)
Dim oXML, oNode
Set oXML = CreateObject("Msxml2.DOMDocument.3.0")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.nodeTypedValue =Stream_StringToBinary(sText)
Base64Encode = oNode.text
Set oNode = Nothing
Set oXML = Nothing
End Function
Function Stream_StringToBinary(Text)
Const adTypeText = 2
Const adTypeBinary = 1
'Create Stream object
Dim BinaryStream 'As New Stream
Set BinaryStream = CreateObject("ADODB.Stream")
'Specify stream type - we want To save text/string data.
BinaryStream.Type = adTypeText
'Specify charset For the source text (unicode) data.
BinaryStream.CharSet = "us-ascii"
'Open the stream And write text/string data To the object
BinaryStream.Open
BinaryStream.WriteText Text
'Change stream type To binary
BinaryStream.Position = 0
BinaryStream.Type = adTypeBinary
'Ignore first two bytes - sign of
BinaryStream.Position = 0
'Open the stream And get binary data from the object
Stream_StringToBinary = BinaryStream.Read
Set BinaryStream = Nothing
End Function

How to create UTF-16 file in VBScript?

My system is Window 10 English-US.
I need to write some non-printable ASCII characters to a text file. So for eg for the ASCII value of 28, I want to write \u001Cw to the file. I don't have to do anything special when coded in Java. Below is my code in VBS
Dim objStream
Set objStream = CreateObject("ADODB.Stream")
objStream.Open
objStream.Type = 2
objStream.Position = 0
objStream.CharSet = "utf-16"
objStream.WriteText ChrW(28) 'Need this to appear as \u001Cw in the output file
objStream.SaveToFile "C:\temp\test.txt", 2
objStream.Close
You need a read-write stream so that writing to it and saving it to file both work.
Const adModeReadWrite = 3
Const adTypeText = 2
Const adSaveCreateOverWrite = 2
Sub SaveToFile(text, filename)
With CreateObject("ADODB.Stream")
.Mode = adModeReadWrite
.Type = adTypeText
.Charset = "UTF-16"
.Open
.WriteText text
.SaveToFile filename, adSaveCreateOverWrite
.Close
End With
End Sub
text = Chr(28) & "Hello" & Chr(28)
SaveToFile text, "C:\temp\test.txt"
Other notes:
I like to explicitly define with Const all the constants in the code. Makes reading so much easier.
A With block save quite some typing here.
Setting the stream type to adTypeText is not really necessary, that's the default anyway. But explicit is better than implicit, I guess.
Setting the Position to 0 on a new stream is superfluous.
It's unnecessary to use ChrW() for ASCII-range characters. The stream's Charset decides the byte width when you save the stream to file. In RAM, everything is Unicode anyway (yes, even in VBScript).
There are two UTF-16 encodings supported by ADODB.Stream: little-endian UTF-16LE (which is the default and synonymous with UTF-16) and big-endian UTF-16BE, with the byte order reversed.
You can achieve the same result with the FileSystemObject and its CreateTextFile() method:
Set FSO = CreateObject("Scripting.FileSystemObject")
Sub SaveToFile(text, filename)
' CreateTextFile(filename [, Overwrite [, Unicode]])
With FSO.CreateTextFile(filename, True, True)
.Write text
.Close
End With
End Sub
text = Chr(28) & "Hello" & Chr(28)
SaveToFile text, "C:\temp\test.txt"
This is a little bit simpler, but it only offers a Boolean Unicode parameter, which switches between UTF-16 and ANSI (not ASCII, as the documentation incorrectly claims!). The solution with ADODB.Stream gives you fine-grained encoding choices, for example UTF-8, which is impossible with the FileSystemObject.
For the record, there are two ways to create an UTF-8-encoded text file:
The way Microsoft likes to do it, with a 3-byte long Byte Order Mark (BOM) at the start of the file. Most, if not all Microsoft tools do that when they offer "UTF-8" as an option, ADODB.Stream is no exception.
The way everyone else does it - without a BOM. This is correct for most uses.
To create an UTF-8 file with BOM, the first code sample above can be used. To create an UTF-8 file without BOM, we can use two stream objects:
Const adModeReadWrite = 3
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateOverWrite = 2
Sub SaveToFile(text, filename)
Dim iStr: Set iStr = CreateObject("ADODB.Stream")
Dim oStr: Set oStr = CreateObject("ADODB.Stream")
' one stream for converting the text to UTF-8 bytes
iStr.Mode = adModeReadWrite
iStr.Type = adTypeText
iStr.Charset = "UTF-8"
iStr.Open
iStr.WriteText text
' one steam to write bytes to a file
oStr.Mode = adModeReadWrite
oStr.Type = adTypeBinary
oStr.Open
' switch first stream to binary mode and skip UTF-8 BOM
iStr.Position = 0
iStr.Type = adTypeBinary
iStr.Position = 3
' write remaining bytes to file and clean up
oStr.Write iStr.Read
oStr.SaveToFile filename, adSaveCreateOverWrite
oStr.Close
iStr.Close
End Sub

Convert current charset to windows-1252

Hello I have a script in vbs that will send emails to desired destination
the problem is the output text is corrupted
Current output : ils n’ont
Desired output : ils n'ont etc...
After research I found that I need to convert the text to windows 1252 in order to accept french characters
So I implemented the conversion functions :
Const adTypeBinary = 1
Const adTypeText = 2
//accept a string and convert it to Bytes array in the selected Charset
Function StringToBytes(Str,Charset)
Dim Stream : Set Stream = CreateObject("ADODB.Stream")
Stream.Type = adTypeText
Stream.Charset = Charset
Stream.Open
Stream.WriteText Str
Stream.Flush
Stream.Position = 0
// rewind stream and read Bytes
Stream.Type = adTypeBinary
StringToBytes= Stream.Read
Stream.Close
Set Stream = Nothing
End Function
//accept Bytes array and convert it to a string using the selected charset
Function BytesToString(Bytes, Charset)
Dim Stream : Set Stream = CreateObject("ADODB.Stream")
Stream.Charset = Charset
Stream.Type = adTypeBinary
Stream.Open
Stream.Write Bytes
Stream.Flush
Stream.Position = 0
// rewind stream and read text
Stream.Type = adTypeText
BytesToString= Stream.ReadText
Stream.Close
Set Stream = Nothing
End Function
' This will alter charset of a string from 1-byte charset(as windows-1252)
' to another 1-byte charset(as windows-1251)
Function AlterCharset(Str, FromCharset, ToCharset)
Dim Bytes
Bytes = StringToBytes(Str, FromCharset)
AlterCharset = BytesToString(Bytes, ToCharset)
End Function
but how to detect the current encoding charest in order to convert them to windows-1252?
how should I call my function below properly?
objEmail.Subject = eSubject
objEmail.Textbody = AlterCharset(eTextBody , "How to detect the current charset? ", "windows-1252") <--- how to write it properly here?
EDIT :
Doing this line of code did solve my char issues :
objEmail.Textbody = AlterCharset(eTextBody , "windows-1252 ", "UTF-8")
but the script will work on different PC , so I need to dynamically get the current charset in order to convert it to UTF-8

Hashing of text from memory instead from file

I want to hash the passwort 'HelloWorld' to MD5. Following code is an excerpt from Generating the hash value of a file. The problem is that with the presented code, I need to save the password to a file before hashing it. How can I pass it in memory? I am feeling very uncomfortable with vbs, please excuse me. I do not know what kind of type binary is in vbs.
Option Explicit
MsgBox("Md5 Hash for 'HelloWorld': " & GenerateMD5("HelloWorld"))
Public Function GenerateMD5(ByRef hashInput)
'hashInput is the plain text hash algorithm input
Dim oMD5 : Set oMD5 = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
oMD5.Initialize()
Dim baHash : baHash = oMD5.ComputeHash_2(GetBinaryFile("D:/HASHINPUT.txt"))
GenerateMD5 = ByteArrayToHexStr(baHash)
End Function
Private Function ByteArrayToHexStr(ByVal fByteArray)
Dim k
ByteArrayToHexStr = ""
For k = 1 To Lenb(fByteArray)
ByteArrayToHexStr = ByteArrayToHexStr & Right("0" & Hex(Ascb(Midb(fByteArray, k, 1))), 2)
Next
End Function
Private Function GetBinaryFile(filename)
Dim oStream: Set oStream = CreateObject("ADODB.Stream")
oStream.Type = 1 'adTypeBinary
oStream.Open
oStream.LoadFromFile filename
GetBinaryFile = oStream.Read
oStream.Close
Set oStream = Nothing
End Function
I suspect you need input of data type Byte() for ComputeHash_2(). VBScript can't create that data type by itself, but you should be able to use the ADODB.Stream object for converting a string to a byte array without writing it to a file first. Something like this:
pwd = "foobar"
Set stream = CreateObject("ADODB.Stream")
stream.Mode = 3 'read/write
stream.Type = 2 'text
stream.Charset = "ascii"
stream.Open
stream.WriteText pwd
stream.Position = 0 'rewind
stream.Type = 1 'binary
bytearray = stream.Read
stream.Close

Read and write binary file in VBscript

I used earlier ADODB.Stream to read and to write binary file here is the link for that
How to concatenate binary file using ADODB.stream in VBscript
it works fine the only problem is ADODB.stream is disabled on windows 2003 server,
Is there another way i can read 3 files in binary mode and concatenate them or store them in one file in VBscript
thank you
Jp
Based on Luc125 and Alberto answers here are the 2 reworked and simplified functions:
The Read function
Function readBinary(strPath)
Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")
Dim oFile: Set oFile = oFSO.GetFile(strPath)
If IsNull(oFile) Then MsgBox("File not found: " & strPath) : Exit Function
With oFile.OpenAsTextStream()
readBinary = .Read(oFile.Size)
.Close
End With
End Function
The Write function
Function writeBinary(strBinary, strPath)
Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")
' below lines pupose: checks that write access is possible!
Dim oTxtStream
On Error Resume Next
Set oTxtStream = oFSO.createTextFile(strPath)
If Err.number <> 0 Then MsgBox(Err.message) : Exit Function
On Error GoTo 0
Set oTxtStream = Nothing
' end check of write access
With oFSO.createTextFile(strPath)
.Write(strBinary)
.Close
End With
End Function
I had a similar problem a year ago. We know that the TextStream objects are intended for ANSI or Unicode text data, not binary data; their .readAll() method produces a corrupted output if the stream is binary. But there is workaround. Reading the characters one by one into an array works fine. This should allow you to read binary data into VB strings, and write it back to disk. When further manipulating such binary strings do not forget that certain operations may result into broken strings because they are intended for text only. I for one always convert binary strings into integer arrays before working with them.Function readBinary(path)
Dim a
Dim fso
Dim file
Dim i
Dim ts
Set fso = CreateObject("Scripting.FileSystemObject")
Set file = fso.getFile(path)
If isNull(file) Then
MsgBox("File not found: " & path)
Exit Function
End If
Set ts = file.OpenAsTextStream()
a = makeArray(file.size)
i = 0
' Do not replace the following block by readBinary = by ts.readAll(), it would result in broken output, because that method is not intended for binary data
While Not ts.atEndOfStream
a(i) = ts.read(1)
i = i + 1
Wend
ts.close
readBinary = Join(a,"")
End Function
Sub writeBinary(bstr, path)
Dim fso
Dim ts
Set fso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set ts = fso.createTextFile(path)
If Err.number <> 0 Then
MsgBox(Err.message)
Exit Sub
End If
On Error GoTo 0
ts.Write(bstr)
ts.Close
End Sub
Function makeArray(n) ' Small utility function
Dim s
s = Space(n)
makeArray = Split(s," ")
End Function
The ADODB stream object is VBScript's only native method of reading binary streams. If ADODB is disabled, you will need to install some other third-party component to provide the same functionality.
It is possible to read all bytes together:
Set FS = CreateObject("Scripting.FileSystemObject")
Set fil = FS.GetFile(filename)
fpga = fil.OpenAsTextStream().Read(file.Size)
ADODB stream object is VBScript's only native method of reading binary streams
Const TypeBinary = 1
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Function readBytes(file)
Dim inStream: Set inStream = WScript.CreateObject("ADODB.Stream") ' ADODB stream object used
inStream.Open ' open with no arguments makes the stream an empty container
inStream.type= TypeBinary
inStream.LoadFromFile(file)
readBytes = inStream.Read()
End Function
Sub writeBytes(file, bytes)
Dim binaryStream: Set binaryStream = CreateObject("ADODB.Stream")
binaryStream.Type = TypeBinary
binaryStream.Open 'Open the stream and write binary data
binaryStream.Write bytes
binaryStream.SaveToFile file, ForWriting 'Save binary data to disk
End Sub
Read 3 files & join to one file (without ADODB):
Dim oFSO : Set oFSO = CreateObject("Scripting.FileSystemObject")
If oFSO.FileExists("out.bin") Then oFSO.DeleteFile("out.bin")
Dim outFile : Set outFile = oFSO.OpenTextFile("out.bin", 8, true)
' 3 input files to concatenate
Dim oFS1 : Set oFS1 = oFSO.GetFile("in1.bin")
Dim oFS2 : Set oFS2 = oFSO.GetFile("in2.bin")
Dim oFS3 : Set oFS3 = oFSO.GetFile("in3.bin")
Dim read1 : Set read1 = oFS1.OpenAsTextStream()
Dim read2 : Set read2 = oFS2.OpenAsTextStream()
Dim read3 : Set read3 = oFS3.OpenAsTextStream()
Dim write1 : write1 = read1.Read(oFS1.Size)
read1.Close
outFile.write(write1)
Dim write2 : write2 = read2.Read(oFS2.Size)
read2.Close
outFile.write(write2)
Dim write3 : write3 = read3.Read(oFS3.Size)
read3.Close
outFile.write(write3)
outFile.Close
Tested on audio, video, image, zip archives & pdf (binaries) on Win 10 for binary file copy, edit, split, join, patching & (byte level) encryption, encoding & compression.
See example (answer) here for binary file patching.

Resources