/*
*
* Autopsy Forensic Browser
*
* Copyright 2012-2014 Basis Technology Corp.
*
* Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com
* Project Contact/Architect: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* In order to update the USB database you must first copy it from
* http://www.linux-usb.org/usb.ids into a text file named "USB_DATA".
*/
package org.sleuthkit.autopsy.recentactivity;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Scanner;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
/**
* Loads a file that maps USB IDs to names of makes and models. Uses Linux USB
* info.
*/
class UsbDeviceIdMapper {
private static final Logger logger = Logger.getLogger(UsbDeviceIdMapper.class.getName());
private HashMap<String, USBInfo> devices;
private static final String DataFile = "USB_DATA.txt"; //NON-NLS
public UsbDeviceIdMapper() {
try {
loadDeviceMap();
} catch (FileNotFoundException ex) {
logger.log(Level.SEVERE, "Could not find file " + DataFile + ".", ex); //NON-NLS
devices = null;
} catch (IOException ex) {
logger.log(Level.SEVERE, "Unknown IO error occurred in method devices.", ex); //NON-NLS
}
}
/**
* Parses the passed in device ID and returns info that includes make and
* model.
*
* @param dev String to parse (i.e.: Vid_XXXX&Pid_XXXX)
*
* @return
*/
public USBInfo parseAndLookup(String dev) {
String[] dtokens = dev.split("[_&]");
String vID = dtokens[1].toUpperCase();
String pID;
if (dtokens.length < 4 || dtokens[3].length() < 4) {
pID = "0000";
} else {
pID = dtokens[3];
}
pID = pID.toUpperCase();
// first try the full key
String key = vID + pID;
if (devices.containsKey(key)) {
return devices.get(key);
}
// try just the vendor ID -> In case database doesn't know about this specific product
key = vID + "0000";
if (devices.containsKey(key)) {
USBInfo info = devices.get(key);
return new USBInfo(info.getVendor(),
NbBundle.getMessage(this.getClass(), "UsbDeviceIdMapper.parseAndLookup.text", pID));
}
return new USBInfo(null, null);
}
/**
* Reads the local USB txt file and stores in map.
*
* @throws FileNotFoundException
* @throws IOException
*/
private void loadDeviceMap() throws FileNotFoundException, IOException {
devices = new HashMap<>();
PlatformUtil.extractResourceToUserConfigDir(this.getClass(), DataFile, false);
try (Scanner dat = new Scanner(new FileInputStream(new java.io.File(PlatformUtil.getUserConfigDirectory() + File.separator + "USB_DATA.txt")))) {
/*
* Syntax of file:
*
* # vendor vendor_name # device device_name <-- single tab #
* interface interface_name <-- two tabs
*/
String line = dat.nextLine();
while (dat.hasNext()) {
// comments
if ((line.startsWith("#")) || (line.equals(""))) {
line = dat.nextLine();
continue;
}
// stop once we've hitten the part of the file that starts to talk about class types
if (line.startsWith("C 00")) { //NON-NLS
return;
}
String dvc = "";
String[] tokens = line.split("[\\t\\s]+"); //NON-NLS
String vID = tokens[0];
for (int n = 1; n < tokens.length; n++) {
dvc += tokens[n] + " ";
}
// make an entry with just the vendor ID
String pID = vID + "0000";
pID = pID.toUpperCase();
USBInfo info = new USBInfo(dvc, null);
devices.put(pID, info);
// parseAndLookup the later lines that have specific products
line = dat.nextLine();
if (line.startsWith("\t")) {
while (dat.hasNext() && line.startsWith("\t")) {
tokens = line.split("[\\t\\s]+"); //NON-NLS
// make key based on upper case version of vendor and product IDs
pID = vID + tokens[1];
pID = pID.toUpperCase();
String device = "";
line = dat.nextLine();
for (int n = 2; n < tokens.length; n++) {
device += tokens[n] + " ";
}
info = new USBInfo(dvc, device);
// store based on the previously generated key
devices.put(pID, info);
}
}
}
}
}
/**
* Stores the vendor information about a USB device
*/
public class USBInfo {
private final String vendor;
private final String product;
private USBInfo(String vend, String prod) {
vendor = vend;
product = prod;
}
/**
* Get Vendor (make) information
*
* @return
*/
public String getVendor() {
return vendor;
}
/**
* Get product (model) information
*
* @return
*/
public String getProduct() {
return product;
}
@Override
public String toString() {
return vendor + product;
}
}
}