19 package org.sleuthkit.autopsy.coreutils;
 
   22 import java.nio.ByteBuffer;
 
   23 import java.nio.ByteOrder;
 
   24 import java.util.ArrayList;
 
   25 import java.util.Arrays;
 
   26 import java.util.List;
 
   27 import java.util.logging.Level;
 
   47         content = 
new byte[length];
 
   50         } 
catch (IOException ex) {
 
   57             ByteBuffer bb = ByteBuffer.wrap(content);
 
   58             bb.order(ByteOrder.LITTLE_ENDIAN);
 
   59             int header = bb.getInt();
 
   60             ByteBuffer linkClassIdentifier = bb.get(
new byte[16]);
 
   61             int linkFlags = bb.getInt();
 
   62             int fileAttributes = bb.getInt();
 
   63             long crtime = bb.getLong();
 
   64             long atime = bb.getLong();
 
   65             long mtime = bb.getLong();
 
   66             int fileSize = bb.getInt();
 
   67             int iconIndex = bb.getInt();
 
   68             int showCommand = bb.getInt();
 
   69             short hotkey = bb.getShort();
 
   71             List<String> linkTargetIdList = 
new ArrayList<String>();
 
   72             if((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) == 
 
   73                     LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) {
 
   74                 int idListSize = bb.getShort();
 
   76                 List<byte[]> linkTargetIdListBytes = 
new ArrayList<byte[]>();
 
   78                     short itemIdSize = bb.getShort();
 
   83                     byte[] theArray = 
new byte[itemIdSize-2];
 
   85                     linkTargetIdListBytes.add(theArray);
 
   86                     bytesRead = bytesRead + itemIdSize;
 
   90             boolean hasUnicodeLocalBaseAndCommonSuffixOffset = 
false;
 
   91             String localBasePath = null;
 
   92             String commonPathSuffix = null;
 
   93             String localBasePathUnicode = null;
 
   94             String commonPathSuffixUnicode = null;
 
   95             int driveSerialNumber = -1;
 
   97             String volumeLabel = null;
 
   98             int commonNetworkRelativeLinkFlags = -1;
 
  100             boolean unicodeNetAndDeviceName = 
false;
 
  101             String netName = null;
 
  102             String netNameUnicode = null;
 
  103             String deviceName = null;
 
  104             String deviceNameUnicode = null;
 
  106             if((linkFlags & LnkEnums.LinkFlags.HasLinkInfo.getFlag()) ==
 
  107                     LnkEnums.LinkFlags.HasLinkInfo.getFlag()) {
 
  108                 int startOfLinkInfo = bb.position();
 
  109                 int linkInfoSize = bb.getInt();
 
  110                 int linkInfoHeaderSize = bb.getInt();
 
  111                 hasUnicodeLocalBaseAndCommonSuffixOffset = linkInfoHeaderSize >= 0x24;
 
  112                 int linkInfoFlags = bb.getInt();
 
  113                 int volumeIdOffset = bb.getInt();
 
  114                 int localBasePathOffset = bb.getInt();
 
  115                 int commonNetworkRelativeLinkOffset = bb.getInt();
 
  116                 int commonPathSuffixOffset = bb.getInt();
 
  117                 int localBasePathOffsetUnicode = 0;
 
  118                 int commonPathSuffixOffsetUnicode = 0;
 
  119                 if (hasUnicodeLocalBaseAndCommonSuffixOffset) {
 
  120                     localBasePathOffsetUnicode = bb.getInt();
 
  121                     commonPathSuffixOffsetUnicode = bb.getInt();
 
  123                 if ((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
 
  124                         == LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag()) {
 
  125                     bb.position(startOfLinkInfo+volumeIdOffset);
 
  126                     int volumeIdSize = bb.getInt();
 
  128                     driveSerialNumber = bb.getInt();
 
  129                     int volumeLabelOffset = bb.getInt();
 
  130                     if (volumeLabelOffset != 0x14) {
 
  131                         volumeLabel = 
parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffset, 
false, volumeIdSize - 0x10);
 
  133                         int volumeLabelOffsetUnicode = bb.getInt();
 
  134                         volumeLabel = 
parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffsetUnicode, 
false, volumeIdSize - 0x14);
 
  138                 if ((linkInfoFlags & LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag())
 
  139                         == LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag()) {
 
  140                     bb.position(startOfLinkInfo+commonNetworkRelativeLinkOffset);
 
  141                     int commonNetworkRelativeLinkSize = bb.getInt();
 
  142                     commonNetworkRelativeLinkFlags = bb.getInt();
 
  143                     int netNameOffset = bb.getInt();
 
  144                     unicodeNetAndDeviceName = netNameOffset > 0x14;
 
  145                     int deviceNameOffset = bb.getInt();
 
  146                     int netType = bb.getInt();
 
  147                     int netNameOffsetUnicode = 0;
 
  148                     int deviceNameOffsetUnicode = 0;
 
  149                     if (unicodeNetAndDeviceName) {
 
  150                         netNameOffsetUnicode = bb.getInt();
 
  151                         deviceNameOffsetUnicode = bb.getInt();
 
  153                     netName = 
parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffset, 
false);
 
  154                     if (unicodeNetAndDeviceName) {
 
  155                         netNameUnicode = 
parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffsetUnicode, 
true);
 
  157                     if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag())
 
  158                             == LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag()) {
 
  161                     if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag())
 
  162                             == LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag()) {
 
  163                         deviceName = 
parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffset, 
false);
 
  164                         if (unicodeNetAndDeviceName) {
 
  165                             deviceNameUnicode = 
parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffsetUnicode, 
true);
 
  170                 if (((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
 
  171                         == LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
 
  172                         && hasUnicodeLocalBaseAndCommonSuffixOffset) {
 
  173                     localBasePathUnicode = 
parseLocalBasePath(startOfLinkInfo + localBasePathOffsetUnicode, 
true);
 
  174                     commonPathSuffixUnicode = 
parseCommonPathSuffix(startOfLinkInfo + commonPathSuffixOffsetUnicode, 
true);
 
  177                 bb.position(startOfLinkInfo+linkInfoSize);
 
  180             if((linkFlags & LnkEnums.LinkFlags.HasName.getFlag()) ==
 
  181                     LnkEnums.LinkFlags.HasName.getFlag()) {
 
  184             String relativePath = null;
 
  185             if((linkFlags & LnkEnums.LinkFlags.HasRelativePath.getFlag()) ==
 
  186                     LnkEnums.LinkFlags.HasRelativePath.getFlag()) {
 
  189             String workingDir = null;
 
  190             if((linkFlags & LnkEnums.LinkFlags.HasWorkingDir.getFlag()) ==
 
  191                     LnkEnums.LinkFlags.HasWorkingDir.getFlag()) {
 
  194             String arguments = null;
 
  195             if((linkFlags & LnkEnums.LinkFlags.HasArguments.getFlag()) ==
 
  196                     LnkEnums.LinkFlags.HasArguments.getFlag()) {
 
  199             String iconLocation = null;
 
  200             if((linkFlags & LnkEnums.LinkFlags.HasIconLocation.getFlag()) ==
 
  201                     LnkEnums.LinkFlags.HasIconLocation.getFlag()) {
 
  205             return new JLNK(header, linkClassIdentifier.array(), linkFlags, fileAttributes,
 
  206                     crtime, atime, mtime, fileSize, iconIndex, showCommand, hotkey,
 
  208                     hasUnicodeLocalBaseAndCommonSuffixOffset, localBasePath,
 
  209                     commonPathSuffix, localBasePathUnicode, commonPathSuffixUnicode,
 
  210                     name, relativePath, workingDir, arguments, iconLocation, driveSerialNumber,
 
  211                     driveType, volumeLabel, commonNetworkRelativeLinkFlags,
 
  212                     networkProviderType, unicodeNetAndDeviceName, netName, netNameUnicode,
 
  213                     deviceName, deviceNameUnicode);
 
  214         } 
catch (Exception e) {
 
  215             throw new JLnkParserException(e);
 
  220         short countCharacters = bb.getShort();
 
  221         if(countCharacters == 0) {
 
  224         byte[] theString = 
new byte[countCharacters*2];
 
  227             return new String(theString, 
"UTF-16LE");
 
  228         } 
catch (UnsupportedEncodingException ex) {
 
  229             logger.info(
"Shouldn't happen"); 
 
  234     private String 
parseString(
int offset, 
boolean unicode, 
int maxlen) {
 
  235         ByteBuffer bb = ByteBuffer.wrap(content);
 
  236         bb.order(ByteOrder.LITTLE_ENDIAN);
 
  238         StringBuilder sb = 
new StringBuilder(bb.limit());
 
  240         while (bb.remaining() > 0 && (i < maxlen || maxlen == -1)) 
 
  254         return sb.toString();
 
  276         List<String> ret = 
new ArrayList<String>();
 
  277         if(!idList.isEmpty()) {
 
  281                     ret.add(
new String(Arrays.copyOfRange(idList.remove(0), 1, 17)).split(
"\0")[0]);
 
  299         List<String> ret = 
new ArrayList<String>();
 
  300         for (byte[] pathElement : idList) {
 
  301             ByteBuffer bb = ByteBuffer.wrap(pathElement);
 
  302             bb.order(ByteOrder.LITTLE_ENDIAN);
 
  303             int offset = bb.getShort(bb.limit() - 2)-2;
 
  304             if (pathElement[offset + 0x02] < 0x03
 
  305                     || pathElement[offset + 0x10] >= pathElement[offset]
 
  306                     || pathElement[offset + 0x10] < 0x14) {
 
  310             if (pathElement[offset + 0x10] != 0) {
 
  311                 ret.add(
getStringAt(bb, offset + pathElement[offset + 0x10], 
true));
 
  314                 if (pathElement[offset + 0x12] >= pathElement[offset]
 
  315                         || pathElement[offset + 0x12] < 0x14) {
 
  319                     ret.add(
getStringAt(bb, offset + pathElement[offset + 0x12], 
false));
 
  331     private String 
getStringAt(ByteBuffer bb, 
int offset, 
boolean unicode) {
 
  332         byte[] nameArr = Arrays.copyOfRange(bb.array(), offset, bb.limit());
 
  335                 return new String(nameArr, 
"UTF-16LE").split(
"\0")[0];
 
  336             } 
catch (UnsupportedEncodingException ex) {
 
  340         return new String(nameArr).split(
"\0")[0];
 
String getStringAt(ByteBuffer bb, int offset, boolean unicode)
 
NetworkProviderType(int flag)
 
List< String > parsePathElements(List< byte[]> idList)
 
static final Logger logger
 
List< String > parseLinkTargetIdList(List< byte[]> idList)
 
String readStringData(ByteBuffer bb)
 
String parseCommonPathSuffix(int offset, boolean unicode)
 
String parseNetName(int offset, boolean unicode)
 
JLnkParser(InputStream is, int length)
 
String parseString(int offset, boolean unicode, int maxlen)
 
String parseDeviceName(int offset, boolean unicode)
 
String parseLocalBasePath(int offset, boolean unicode)
 
String get0xC(ByteBuffer bb)
 
static DriveType valueOf(int type)
 
static CommonCLSIDS valueOf(byte[] type)
 
static Logger getLogger(String name)