I'm running a Windows service that checks a hardware instrument approximately fifteen times a second, 24/7, on COM4. When the instrument receives a command it responds accordingly, ending its response with >CRLF to indicate round trip completion.
The following code is giving me some trouble:
01 Public Async Function SendAsync() As Task(Of Response)
02 Dim oResponse As Response
03 Dim sData As String
04
05 Do
06 Me.Port.WriteLine(Me.Instruction)
07
08 sData = Await ReadResponseAsync()
09 oResponse = New Response(Me.Instruction, sData)
10 Loop While oResponse.Status = Response.States.SyntaxError
11
12 Return oResponse
13 End Function
14
15 Private Async Function ReadResponseAsync() As Task(Of String)
16 Dim iSize As Integer
17 Dim sData As String
18 Dim aData As Byte()
19
20 aData = New Byte(255) {}
21 sData = String.Empty
22
23 Do
24 iSize = Await Me.Port.BaseStream.ReadAsync(aData, 0, aData.Length)
25 sData &= Encoding.ASCII.GetString(aData, 0, iSize)
26 Loop While Not sData.EndsWith($">{vbCrLf}")
27
28 Return sData
29 End Function
I'm getting a rare IOException on line 24:
System.IO.IOException: The I/O operation has been aborted because Of either a thread Exit Or an application request.
This has occurred twice in the past 144 hours, giving it a ratio of 1 in roughly 3.8mm challenge/response cycles. It doesn't correspond with any service stop actions.
Does this mean the data for that cycle is forever lost to me?
If I were to wrap the ReadAsync() call in a Try/Catch, like so, would the next loop pick up the waiting response?
Do
Try
iSize = Await Me.Port.BaseStream.ReadAsync(aData, 0, aData.Length)
sData &= Encoding.ASCII.GetString(aData, 0, iSize)
Catch ex As IOException
Main.Logger.Warn("IOException was skipped. Data will be retrieved on next attempt.")
aData = New Byte(255) {}
sData = String.Empty
End Try
Loop While Not sData.EndsWith($">{vbCrLf}")
I would like to spin up a quick test for this, but I'm unable to reproduce the IOException in context.
Related
Edit: Here is a .NET fiddle of the issue
I am currently trying to write a process which encrypts files sent in as streams of Byte. The AES library does not seem to be applying padding correctly.
When I try to do an encryption I get cipher bytes like this:
... 50 57 243 226 18 0 0 0 0 0 0 0 0 0 ... (about 30,000 0s appended to the end)
When i think I should be getting cipher bytes like this (using PKCS7) :
... 50 57 243 226 18 9 9 9 9 9 9 9 9 9
How do I get the actual padding method to be recognised and return padding like the PKCS7?
Public Function Encrypt(InputStream As Stream) As Byte()
Dim outputStream = New MemoryStream()
Dim EncryptionKey As String = "MAKV2SPBNI99212"
Using encryptor As Aes = Aes.Create()
Dim pdb As New Rfc2898DeriveBytes(EncryptionKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
encryptor.Key = pdb.GetBytes(32)
encryptor.IV = pdb.GetBytes(16)
Using cs As New CryptoStream(outputStream, encryptor.CreateEncryptor(), CryptoStreamMode.Write)
Dim data As Integer
While (Assign(data, InputStream.ReadByte())) <> -1
cs.WriteByte(CByte(data))
End While
End Using
End Using
Return outputStream.GetBuffer()
End Function
Public Function Decrypt(InputStream As Stream) As Byte()
Dim outputStream = New MemoryStream()
Dim EncryptionKey As String = "MAKV2SPBNI99212"
Using encryptor As Aes = Aes.Create()
Dim pdb As New Rfc2898DeriveBytes(EncryptionKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
encryptor.Key = pdb.GetBytes(32)
encryptor.IV = pdb.GetBytes(16)
Using cs As New CryptoStream(InputStream, encryptor.CreateDecryptor(), CryptoStreamMode.Read)
Dim data As Integer
While (Assign(data, cs.ReadByte())) <> -1
outputStream.WriteByte(CByte(data))
End While
End Using
End Using
Return outputStream.GetBuffer
End Function
Private Function Assign(Of T)(ByRef source As T, ByVal value As T) As T
source = value
Return value
End Function
You shouldn't be using the .GetBuffer method on the returned MemoryStreams. .GetBuffer returns the underlying array which is typically larger than the amount of data in the Stream. That's why you are seeing the extra 0's at the end, and why the padding is failing to be read properly. See the remarks section in the documentation for the MemoryStream.GetBuffer Method
What you should be doing instead is calling outputStream.ToArray which will return a Byte array containing only the relevant data contained in the Stream, without all the trailing 0's.
I tried getting properties from WorkflowTask Object but not getting comment property. Currently referring to this API documentation: https://dev.alfresco.com/resource/AlfrescoOne/5.1/PublicAPI/org/alfresco/service/cmr/workflow/WorkflowTask.html
List<WorkflowTask> allTasks;
allTasks = workflowService.queryTasks(taskQuery,true);
for(int i=0; i<allTasks.size(); i++)
{
HashMap<String, Object> taskInfo = new HashMap<String, Object>();
task = allTasks.get(i);
Map<QName,Serializable> taskProperties = task.getProperties();
}
I ran debugging mode and checked taskProperties contents.
It seems that you are trying to retrieve the comment of active task, tasks which are not completed yet.For those task you user needs to write comment and save it.
Once it is saved you will be able to see it.
If its not the active tasks which you are getting then,comment should not be null.
Below is output when i tried same code for retrieving the active task and printed properties.
{http://www.alfresco.org/model/content/1.0}created = Fri Mar 16 12:56:26 IST 2018
{http://www.alfresco.org/model/bpm/1.0}percentComplete = 0
{http://www.alfresco.org/model/bpm/1.0}pooledActors = []
{http://www.alfresco.org/model/content/1.0}name = Task
{http://www.alfresco.org/model/bpm/1.0}packageActionGroup =
{http://www.alfresco.org/model/bpm/1.0}reassignable = true
{http://www.alfresco.org/model/bpm/1.0}outcomePropertyName = {http://www.alfresco.org/model/workflow/1.0}reviewOutcome
{http://www.alfresco.org/model/content/1.0}owner = test
{http://www.alfresco.org/model/workflow/1.0}reviewOutcome = Reject
{http://www.alfresco.org/model/bpm/1.0}taskId = 1889
{http://www.alfresco.org/model/bpm/1.0}packageItemActionGroup = edit_package_item_actions
{http://www.alfresco.org/model/bpm/1.0}dueDate = null
{http://www.alfresco.org/model/bpm/1.0}completionDate = null
{http://www.alfresco.org/model/bpm/1.0}description = asd
{http://www.alfresco.org/model/bpm/1.0}priority = 2
{http://www.alfresco.org/model/bpm/1.0}status = Not Yet Started
{http://www.alfresco.org/model/bpm/1.0}package = workspace://SpacesStore/ee203aff-9842-4d7b-b7e9-0f40b0b8a3b3
{http://www.alfresco.org/model/bpm/1.0}startDate = Fri Mar 16 12:56:26 IST 2018
{http://www.alfresco.org/model/bpm/1.0}comment = sdadasdasdasd
{http://www.alfresco.org/model/bpm/1.0}hiddenTransitions =
This is a common problem but the solutions suggested here and here don't work for me, also they don't involve a database.
I'd like the code sample 'Failing code (WITH database)' to work.
This is my encrypt/decrypt code (copied from here: https://msdn.microsoft.com/en-us/library/system.security.cryptography.aes.aspx?cs-save-lang=1&cs-lang=vb&f=255&MSPPError=-2147217396#code-snippet-2):
Shared Function EncryptStringToBytes_Aes(ByVal plainText As String, ByVal Key() As Byte, ByVal IV() As Byte) As Byte()
' Check arguments.
If plainText Is Nothing OrElse plainText.Length <= 0 Then
Throw New ArgumentNullException("plainText")
End If
If Key Is Nothing OrElse Key.Length <= 0 Then
Throw New ArgumentNullException("Key")
End If
If IV Is Nothing OrElse IV.Length <= 0 Then
Throw New ArgumentNullException("Key")
End If
Dim encrypted() As Byte
' Create an Aes object
' with the specified key and IV.
Using aesAlg As Aes = Aes.Create()
aesAlg.Key = Key
aesAlg.IV = IV
' Create a decrytor to perform the stream transform.
Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)
' Create the streams used for encryption.
Using msEncrypt As New MemoryStream()
Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
Using swEncrypt As New StreamWriter(csEncrypt)
'Write all data to the stream.
swEncrypt.Write(plainText)
End Using
encrypted = msEncrypt.ToArray()
End Using
End Using
End Using
' Return the encrypted bytes from the memory stream.
Return encrypted
End Function 'EncryptStringToBytes_Aes
Shared Function DecryptStringFromBytes_Aes(ByVal cipherText() As Byte, ByVal Key() As Byte, ByVal IV() As Byte) As String
' Check arguments.
If cipherText Is Nothing OrElse cipherText.Length <= 0 Then
Throw New ArgumentNullException("cipherText")
End If
If Key Is Nothing OrElse Key.Length <= 0 Then
Throw New ArgumentNullException("Key")
End If
If IV Is Nothing OrElse IV.Length <= 0 Then
Throw New ArgumentNullException("Key")
End If
' Declare the string used to hold
' the decrypted text.
Dim plaintext As String = Nothing
' Create an Aes object
' with the specified key and IV.
Using aesAlg As Aes = Aes.Create()
aesAlg.Key = Key
aesAlg.IV = IV
' Create a decrytor to perform the stream transform.
Dim decryptor As ICryptoTransform = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)
' Create the streams used for decryption.
Using msDecrypt As New MemoryStream(cipherText)
Using csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
Using srDecrypt As New StreamReader(csDecrypt)
' Read the decrypted bytes from the decrypting stream
' and place them in a string.
plaintext = srDecrypt.ReadToEnd()
End Using <= PADDING ERROR THROWN HERE
End Using
'cipherText = msDecrypt.ToArray() 'added by me
End Using
End Using
Return plaintext
End Function 'DecryptStringFromBytes_Aes
Working sample (without database)
Dim original As String = "Here is some data to encrypt!"
Dim key As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(_sharedSecret, _salt)
Try
' Create a new instance of the Aes
' class. This generates a new key and initialization
' vector (IV).
Using myAes As Aes = Aes.Create()
myAes.Key = key.GetBytes(myAes.KeySize / 8)
myAes.IV = key.GetBytes(myAes.BlockSize / 8)
' Encrypt the string to an array of bytes.
Dim encrypted As Byte() = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV)
' Decrypt the bytes to a string.
Dim roundtrip As String = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV)
'Display the original data and the decrypted data.
ltStatus.Text = String.Format("Original: {0}", original)
ltStatus.Text += String.Format("Round Trip: {0}", roundtrip)
End Using
Catch ex As Exception
Console.WriteLine("Error: {0}", ex.Message)
End Try
Failing code (WITH database)
Dim _salt As Byte() = Encoding.ASCII.GetBytes("o6806642kbM7c5")
Dim _sharedSecret As String = "abcd"
Dim original As String = "Here is some data to encrypt!"
Dim key As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(_sharedSecret, _salt)
Dim encrypted As Byte()
Try
Using myAes As Aes = Aes.Create()
myAes.Key = key.GetBytes(myAes.KeySize / 8)
myAes.IV = key.GetBytes(myAes.BlockSize / 8)
myAes.Padding = PaddingMode.PKCS7
encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV)
End Using
Catch ex As Exception
Console.WriteLine("Error: {0}", ex.Message)
End Try
'save to DB
Dim myConnection As SqlConnection = GetConnection()
Dim cmd As New SqlCommand("UPDATE banks set bank_name=#bankname WHERE id=1", myConnection)
cmd.Parameters.Add(New SqlParameter("#bankname", encrypted))
Try
myConnection.Open()
cmd.ExecuteScalar()
Catch ex As Exception
GlobalFunctions.LogError("banks:INSERT encrypted", ex.Message, LogLevel.Normal)
Finally
myConnection.Close()
End Try
'retreive from db
Dim decrypted As String = ""
myConnection = GetConnection()
cmd = New SqlCommand("SELECT bank_name FROM banks where id=1", myConnection)
Dim reader As SqlDataReader
Try
myConnection.Open()
reader = cmd.ExecuteReader
If reader.Read Then
Using myAes As Aes = Aes.Create()
myAes.Key = key.GetBytes(myAes.KeySize / 8)
myAes.IV = key.GetBytes(myAes.BlockSize / 8)
myAes.Padding = PaddingMode.PKCS7
decrypted = DecryptStringFromBytes_Aes(reader("bank_name"), myAes.Key, myAes.IV)
End Using
Else
GlobalFunctions.LogError("banks:nothing to be read?!?", LogLevel.Normal)
End If
Catch ex As Exception
GlobalFunctions.LogError("banks:SELECT encrypted.", ex.Message, LogLevel.Normal)
Finally
myConnection.Close()
End Try
But something goes wrong here:
A binary value is succesfully added in my MSSQL database in field bank_name of type varbinary(MAX). (I also tried smaller fields, e.g. varbinary(50))
But when I try to decrypt this field after retreival from the database I get the error Padding is invalid and cannot be removed. See the codeline with the comment '<= PADDING ERROR THROWN HERE' in the above code 'Failing code (WITH database)'.
I checked here and here. And I'm not passing an empty string
Also I tried adding cipherText = msDecrypt.ToArray(), but the error already occurs before this line is hit.
UPDATE 2
My dumped values are:
ReportError stores the values in a textfield in the DB, the reported values are:
myAes.Key in
00000000 95 0C 95 EA 1D 40 0C FB 1D 3F B7 FB 73 FB 3F EA ����������������
00000010 40 62 51 62 51 EA 62 73 B7 2E 1D C8 1D 51 51 95 ����������������
myAes.IV in
00000000 51 A6 84 73 95 C8 2E 62 84 C8 0C 62 C8 2E 1D 84 ����������������
encrypted in
00000000 FB FB B7 73 D9 51 A6 2E 95 73 62 73 3F 84 A6 40 ����������������
00000010 B7 62 84 2E 51 95 EA 1D 51 A6 EA 2E 51 A6 51 95 ����������������
myAes.Key out
00000000 51 1D 73 40 EA A6 73 EA FB 73 73 A6 0C A6 D9 1D ����������������
00000010 2E 3F FB 2E 73 A6 A6 0C A6 C8 95 0C D9 1D B7 73 ����������������
myAes.IV out
00000000 B7 95 51 73 B7 D9 95 EA 0C C8 95 95 0C 84 40 62 ����������������
encrypted out
00000000 FB FB B7 73 D9 51 A6 2E 95 73 62 73 3F 84 A6 40 ����������������
00000010 B7 62 84 2E 51 95 EA 1D 51 A6 EA 2E 51 A6 51 95 ����������������
banks:SELECT encrypted. Padding is invalid and cannot be removed.
Here's the full code I use now:
Imports System.Security.Cryptography
Imports System.Data.SqlClient
Imports System.Text
Namespace HexDump
Class Utils
Public Shared Function HexDump(bytes As Byte(), Optional bytesPerLine As Integer = 16) As String
If bytes Is Nothing Then
Return "<null>"
End If
Dim bytesLength As Integer = bytes.Length
Dim HexChars As Char() = "0123456789ABCDEF".ToCharArray()
' 8 characters for the address
Dim firstHexColumn As Integer = 8 + 3
' 3 spaces
' - 2 digit for the hexadecimal value and 1 space
' - 1 extra space every 8 characters from the 9th
Dim firstCharColumn As Integer = firstHexColumn + bytesPerLine * 3 + (bytesPerLine - 1) / 8 + 2
' 2 spaces
' - characters to show the ascii value
Dim lineLength As Integer = firstCharColumn + bytesPerLine + Environment.NewLine.Length
' Carriage return and line feed (should normally be 2)
Dim line As Char() = (New [String](" "c, lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray()
Dim expectedLines As Integer = (bytesLength + bytesPerLine - 1) / bytesPerLine
Dim result As New StringBuilder(expectedLines * lineLength)
Dim i As Integer = 0
While i < bytesLength
line(0) = HexChars((i >> 28) And &HF)
line(1) = HexChars((i >> 24) And &HF)
line(2) = HexChars((i >> 20) And &HF)
line(3) = HexChars((i >> 16) And &HF)
line(4) = HexChars((i >> 12) And &HF)
line(5) = HexChars((i >> 8) And &HF)
line(6) = HexChars((i >> 4) And &HF)
line(7) = HexChars((i >> 0) And &HF)
Dim hexColumn As Integer = firstHexColumn
Dim charColumn As Integer = firstCharColumn
For j As Integer = 0 To bytesPerLine - 1
If j > 0 AndAlso (j And 7) = 0 Then
hexColumn += 1
End If
If i + j >= bytesLength Then
line(hexColumn) = " "c
line(hexColumn + 1) = " "c
line(charColumn) = " "c
Else
'Dim b As Byte = bytes(i + j)
'line(hexColumn) = HexChars((b >> 4) And &HF)
'line(hexColumn + 1) = HexChars(b And &HF)
'line(charColumn) = (If(b < 32, "·"c, CChar(b)))
Dim b As Byte = bytes((i + j))
line(hexColumn) = HexChars(((b + 4) _
And 15))
line((hexColumn + 1)) = HexChars((b And 15))
line(charColumn) = Microsoft.VisualBasic.ChrW(65533)
End If
hexColumn += 3
charColumn += 1
Next
result.Append(line)
i += bytesPerLine
End While
Return result.ToString()
End Function
End Class
End Namespace
Public Class banks_financial
Inherits System.Web.UI.Page
Private _lang As String
Private _registryId As Integer
Private _salt As Byte() = Encoding.ASCII.GetBytes("o6806642kbM7c5")
Private _sharedSecret As String = "abcd"
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim original As String = "Here is some data to encrypt!"
Dim key As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(_sharedSecret, _salt)
Dim encrypted As Byte()
Try
Using myAes As Aes = Aes.Create()
myAes.Key = key.GetBytes(myAes.KeySize / 8)
myAes.IV = key.GetBytes(myAes.BlockSize / 8)
myAes.Padding = PaddingMode.PKCS7
encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV)
ReportError("myAes.Key in", HexDump.Utils.HexDump(myAes.Key))
ReportError("myAes.IV in", HexDump.Utils.HexDump(myAes.IV))
ReportError("encrypted in", HexDump.Utils.HexDump(encrypted))
End Using
Catch ex As Exception
Console.WriteLine("Error: {0}", ex.Message)
End Try
'save to DB
Dim myConnection As SqlConnection = GetConnection()
Dim cmd As New SqlCommand("UPDATE banks set bank_name=#bankname WHERE id=1", myConnection)
cmd.Parameters.Add(New SqlParameter("#bankname", encrypted))
Try
myConnection.Open()
cmd.ExecuteScalar()
Catch ex As Exception
GlobalFunctions.ReportError("banks:INSERT encrypted", ex.Message, LogLevel.Normal)
Finally
myConnection.Close()
End Try
'retreive from db
Dim decrypted As String = ""
myConnection = GetConnection()
cmd = New SqlCommand("SELECT bank_name FROM banks where id=1", myConnection)
Dim reader As SqlDataReader
Try
myConnection.Open()
reader = cmd.ExecuteReader
If reader.Read Then
Using myAes As Aes = Aes.Create()
myAes.Key = key.GetBytes(myAes.KeySize / 8)
myAes.IV = key.GetBytes(myAes.BlockSize / 8)
myAes.Padding = PaddingMode.PKCS7
ReportError("myAes.Key out", HexDump.Utils.HexDump(myAes.Key))
ReportError("myAes.IV out", HexDump.Utils.HexDump(myAes.IV))
ReportError("encrypted out", HexDump.Utils.HexDump(reader("bank_name")))
decrypted = DecryptStringFromBytes_Aes(reader("bank_name"), myAes.Key, myAes.IV)
ReportError("decrypted", decrypted)
End Using
Else
GlobalFunctions.ReportError("banks:nothing to be read?!?", LogLevel.Normal)
End If
Catch ex As Exception
GlobalFunctions.ReportError("banks:SELECT encrypted.", ex.Message, LogLevel.Normal)
Finally
myConnection.Close()
End Try
ltStatus.Text = GetMessageStatus(decrypted, MsgType.ok)
End Class
The immediate problem is that your test code is misusing Rfc2898DeriveBytes/ PBKDF. It has nothing to do with the database. Each time you call GetBytes() on a given instance, it returns a different set of bytes (by design!). This is apparent with a bit of code like this:
Dim salt = CryptoTools.GetRandomBytes(16)
Dim PBKDF = New Rfc2898DeriveBytes("secret", salt, 10000)
Dim a = PBKDF.GetBytes(32)
Dim b = PBKDF.GetBytes(32)
Dim c = PBKDF.GetBytes(32)
If a.SequenceEqual(b) = False Then
Console.WriteLine("A != B")
End If
...
It's very clear with Intellisense:
The arrays are not at all alike. From the Remarks section on MSDN for GetBytes:
The Rfc2898DeriveBytes class takes a password, a salt, and an iteration count, and then generates keys through calls to the GetBytes method. Repeated calls to this method will not generate the same key; ...
The emphasis is mine, but is intended to point out that it is a key generator not just a hasher. So, in your "Fails with Database" code you have this block:
Dim key As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(_sharedSecret, _salt)
...
Using myAes As Aes = Aes.Create()
...
myAes.Key = key.GetBytes(myAes.KeySize / 8)
myAes.IV = key.GetBytes(myAes.BlockSize / 8)
...
End Using
The Key and IV generated will not be the same. This is good, but probably not what you intended. The same block is used later to decrypt what was read back from the db. The Key and IV used to decrypt will also be different from each other, but more importantly they will not be the same Key and IV used to encrypt!
This is a fatal flaw, and causes the error. It seems like a misleading error message, but it is simple to reproduce/fix. You need a new PBKDF to 'start over' in the decryption part, or Reset the existing one:
' after this line...
Dim decrypted As String = ""
' ...add this:
key As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(_sharedSecret, _salt)
' or
'key.Reset()
It is more likely that the real code would not be doing a roundtrip in the same method, and using a new Rfc2898DeriveByteswould be created.
Finally, note that the IV and Salt should be unique and random for effective encryption. There really isn't much point in encrypting each row with the same password, key, salt and IV beyond the illusion of security. Someone only has to crack the PW for one row to get the data for all the rows.
Because Rfc2898DeriveBytes is deterministic, it can play a role in generating the IV and Salt (for the data to be encrypted) without having to save them or use static ones.
Generally a padding error really means that the key, encrypted data or options are incorrect, not the padding, per se.
Make sure the key is exactly the correct length, if not the implementation will use unspecified bytes. Make the key exactly a correct key size: 128, 192 or 256 bits (16, 24 or 32 bytes).
Make sure the key, data and IV do not have an incorrect encoding, encryption is based on 8-bit bytes with no encoding. Some libraries will accept and produce other encodings such as Base64 and hexadecimal, check the documentation carefully.
Hex dump the key, IV, encrypted data and decrypted data and add samples of these to the question.
Encryption function calls are actually simple, if you supply the correct (and full) inputs the output will be correct. If the results check the inputs carefully.
UPDATE:
The IV and key are not the same for both encryption and decryption, they must be the same.
One way to ensure the IV is the same is to pre-pend it to the encrypted data on encryption and on decryption recover it from the encrypted data and skip it when decryption the encrypted data.
The key must be pre-shared between the encryption and decryption code in some manner prior to the decryption.
I have a function (see below) and it works perfectly. I recently moved my code to another server and i did not change anything in it. It fails to run on new server.
Microsoft VBScript runtime error '800a0005'
Invalid procedure call or argument: 'Mid'
/calculate.asp, line 416
When i checked the line 416, i got this:
Dim result3: result3 = Mid(o3.responseText, Basla3, Bitir3)
and this is the complete function:
<%
Function xyz()
Dim o3: Set o3 = Server.CreateObject("MSXML2.ServerXMLHTTP")
Dim o_date3: o_date3 = split(EndingDate, ".")
Dim s_date3
If (Len(o_date3(2)) = 4) Then
s_date3 = o_date3(2)
Else
s_date3 = "20" & o_date3(2)
End If
If (Len(o_date3(1)) = 2) Then
s_date3 = s_date3 & o_date3(1)
Else
s_date3 = s_date3 & "0" & o_date3(1)
End If
If (Len(o_date3(0)) = 2) Then
s_date3 = s_date3 & o_date3(0)
Else
s_date3 = s_date3 & "0" & o_date3(0)
End If
Dim s3: s3 = "<soapenv:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:urn=""urn:AntTransferWSIntf-IAntTransferWS""><soapenv:Header/><soapenv:Body><urn:EURCurrency soapenv:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/""><DateStr xsi:type=""xsd:string"">" + s_date3 + "</DateStr></urn:EURCurrency></soapenv:Body></soapenv:Envelope>"
o3.Open "POST", serviceUrl, False
o3.setRequestHeader "Content-Type", "text/xml"
o3.setRequestHeader "Connection", "close"
o3.setRequestHeader "SOAPAction", " "
o3.send s3
Dim hataVarMiBasla3: hataVarMiBasla3 = (InStr(1, o3.responseText, "<faultstring>", vbTextCompare)) + 13
If (hataVarMiBasla3 > 13) Then
Dim hataVarMiBitir3: hataVarMiBitir3 = (InStr(1, o3.responseText, "</faultstring>", vbTextCompare)) - hataVarMiBasla3
Dim hata3: hata3 = Mid(o3.responseText, hataVarMiBasla3, hataVarMiBitir3)
KurGetir = hata3
Else
Dim Basla3: Basla3 = (InStr(1, o3.responseText, """xsd:double"">", vbTextCompare)) + 13
Dim Bitir3: Bitir3 = (InStr(1, o3.responseText, "</return>", vbTextCompare)) - Basla3
Dim result3: result3 = Mid(o3.responseText, Basla3, Bitir3)
xyz = CDbl(Replace(result3, ".", mstrComma))
End If
Set o3 = Nothing
End Function
%>
Why am i receiving this error?
Mid struct from MSDN
Mid(string, start[, length])
Not official reference but according to my experience, you get that error if
start is less than or equal to zero.
length is less than zero (if it is not missed in the Mid call)
Have a look at the error line and related ones.
Dim Basla3: Basla3 = (InStr(1, o3.responseText, """xsd:double"">", vbTextCompare)) + 13
Dim Bitir3: Bitir3 = (InStr(1, o3.responseText, "</return>", vbTextCompare)) - Basla3
Dim result3: result3 = Mid(o3.responseText, Basla3, Bitir3)
Lets suppose o3.responseText is empty because your code does not check whether the response is empty.
Basla3 can not be less than 13 according to InStr() + 13, so it's not the problem.
However it seems like Bitir3 can be less then zero according to InStr() - Basla3 (Basla3 evaluated as 13).
Continuing with the assumption, (InStr(1, o3.responseText, "</return>", vbTextCompare)) evaluated as 0, then with - Basla3 it will be evaluated as -13. Tada! rule 2 violated, length cannot be less than zero.
The problem with your code is, there is no check response length nor response status.
If the response is empty, consider the following:
Your new server may have connectivity problems unlike the old one.
The API which you have is authorized for the old server's IP address only.
In a nutshell, you should optimize the code and be sure that there is an xml response.
At least use something like that:
o3.Send
If o3.readyState = 4 And o3.status = 200 Then
If Len(o3.responseText) > 0 Then
'response is ready to parse
Else
'response status is ok but empty
End If
Else
'request failed
End If
BTW, due to your request is a soap call, I'd highly recommend done the job by parsing xml response using DomDocument etc.
Replacing decimal points, using Mid & InStr pair to check node existence are just trouble and bad practice also.
If I were to take a guess.
VBScript gives strange errors when your "MID" function has to deal with special characters, or what it thinks are non-string values.
So, o3.responseText probably contains text that it doesn't like.
Hi Below is my code of ASPClassic, in which csvData is a very large string containing variable.Now in this At line where Mid function is call error 'Invalid Procedure Call or argument : Mid' occur why this happens...
Dim dataLen
Dim fromLen
Dim toLen
Dim slab
Dim totalPass
dataLen =len(csvData)
fromLen =0
toLen =100000
slab =100000
totalPass =(dataLen/slab)
if (dataLen Mod slab)>0 then
totalPass=totalPass+1
end if
Dim i
For i = 0 To dataLen
i=toLen
if toLen > dataLen then
toLen=dataLen
end if
Response.Write Mid(csvData,fromLen,toLen)
fromLen=toLen
toLen=toLen+slab
Next
I think that your fromLen is 0, when you call Mid() for the first time:
>> m = Mid("x", 0, 1)
>>
Error Number: 5
Error Description: Invalid procedure call or argument
Try to initialize with:
fromLen = 1
mid start position can not be 0 it should always be from 1
It should be noted that the Mid() function's END position ALSO cannot be zero (0).