Friday, 24 June 2011

Downloading and Parsing Vendor IDS files to CSV in VB.Net

The following function will parse an ids file and produce an equivalent CSV file. It has been tested with the following two ids files:
  1. The PCI ven/dev list: http://pciids.sourceforge.net/v2.2/pci.ids
  2. The USB ven/dev list: http://www.linux-usb.org/usb.ids
Ids files seem to have two sections; The first section contains the list of hardware and vendor IDs, while the second section has a list of known device classes, subclasses and programming interfaces. This function will only parse the first section. In principle, the only thing that one needs to do to add support for another ids, is to add a line telling the function when to stop parsing (see the idsToCsv() function below, at the beginning of the "Do While objReader.Peek()" loop).

It takes two parameters: "FileInPath" is the location of the OUI file and "FileOutPath" is the path of the CSVyou want to save to. If no file is there, one will be created automatically.
Public Sub idsToCsv(ByVal FileInPath As String, ByVal FileOutPath As String)
 Log("* Converting " + FileInPath + " to csv...", COLOR_TEXT_NORMAL, True)

 Dim TextLine As String = ""
 Dim lineArr As String()
 Dim resArr(5) As String

 If Not IO.File.Exists(FileInPath) Then
  Log(SPACER + "File '" + FileInPath + "' does not exist.", COLOR_ERROR, True)
  Exit Sub
 End If

 Dim objReader As New System.IO.StreamReader(FileInPath)
 Dim objWriter As New System.IO.StreamWriter(FileOutPath)

 Dim char1 = "", char2 = ""

 Do While objReader.Peek() <> -1
  TextLine = objReader.ReadLine()

  If TextLine.Equals("# List of known device classes, subclasses and protocols") Then Exit Do
  If TextLine.Equals("# List of known device classes, subclasses and programming interfaces") Then Exit Do

  Try
   If TextLine.Length > 3 Then
    lineArr = IdsSplit(TextLine, Chr(32) & Chr(32))
    char1 = TextLine.Substring(0, 1)

    Select Case char1
     Case "#" ' this is a comment. do nothing
     Case Chr(9) ' We have intented once
      char2 = TextLine.Substring(1, 1)
      Select Case char2
       Case Chr(9) ' we have intented twice
        ' This should be a if_id, if_name
        resArr(4) = lineArr(0).ToString.Trim
        resArr(5) = lineArr(1).ToString.Trim

        Try
         objWriter.Write(CreateIdsLine(resArr))
        Catch
         Log(SPACER + "Could not write to '" + FileOutPath + "': " + Err.Description, COLOR_ERROR, True)
         CloseStreams(objReader, objWriter)
         Exit Sub
        End Try
       Case Else
        ' This should be a device_id, device_name line
        resArr(2) = lineArr(0).ToString.Trim
        resArr(3) = lineArr(1).ToString.Trim
        resArr(4) = ""
        resArr(5) = ""

        Try
         objWriter.Write(CreateIdsLine(resArr))
        Catch
         Log(SPACER + "Could not write to '" + FileOutPath + "': " + Err.Description, COLOR_ERROR, True)
         CloseStreams(objReader, objWriter)
         Exit Sub
        End Try
      End Select
     Case Else
      ' This should be a vendor_id, vendor_name line
      Array.Clear(resArr, 0, resArr.Length)
      resArr(0) = lineArr(0).ToString.Trim
      resArr(1) = lineArr(1).ToString.Trim
      Try
       objWriter.Write(CreateIdsLine(resArr))
      Catch
       Log(SPACER + "Could not write to '" + FileOutPath + "': " + Err.Description, COLOR_ERROR, True)
       CloseStreams(objReader, objWriter)
       Exit Sub
      End Try
    End Select
   End If
  Catch
   Log(SPACER + "Error: " + Err.Description, COLOR_ERROR, True)
   CloseStreams(objReader, objWriter)
   Exit Sub
  End Try
 Loop

 Log("* Finished conversion", COLOR_TEXT_NORMAL, True)
 CloseStreams(objReader, objWriter)
End Sub


Private Sub CloseStreams(ByRef SReader As IO.StreamReader, ByRef SWriter As IO.StreamWriter)
 Try
  SWriter.Flush()
  SWriter.Close()
  SWriter.Dispose()
 Catch
 End Try

 Try
  SReader.Close()
  SReader.Dispose()
 Catch
 End Try
End Sub

The "Log()" function is a function I use to add make entries in a RichTextBox. Feel free to remove it or replace it with a "Console.Writeline()".

The code above, will not download the ids files. To do that use the following function.

It takes up to four parameters, even though only two are needed in this case: "uri" is the online location of the file we want to download (http://standards.ieee.org/regauth/oui/oui.txt), "destFile" is the location we want the file downloaded to, "uname" and "pass" is the username and password to access the URI if needed.

The function will return nothing if it completed successfully or a description of the error if not.
   Public Function DownloadFile(ByVal uri As String, ByVal destFile As String, _  
   Optional ByVal uname As String = Nothing, Optional ByVal pass As String = Nothing) _  
   As String  
     Try  
       Dim wc As New System.Net.WebClient  
       If Not uname Is Nothing AndAlso Not pass Is Nothing Then  
         wc.Credentials = New System.Net.NetworkCredential(uname, pass)  
       End If  
       wc.DownloadFile(uri, destFile)  
     Catch  
       Return Err.Description  
     End Try  
     Return ""  
   End Function  

So to download and parse the file, you will need something like this:
Dim uri as string = "http://www.linux-usb.org/usb.ids"
Dim res = DownloadFile(uri, "C:\usb.ids")
if res.length>0 then
 Console.writeline("Error: " + res)
else 
 IdsToCsv("C:\usb.ids", "C:\usb.csv") 
End if
/code>

1 comment:

  1. This is a good logger:
    http://www.kellermansoftware.com/p-14-net-logging-library.aspx

    ReplyDelete