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;
 
   44         content = 
new byte[length];
 
   47         } 
catch (IOException ex) {
 
   54             ByteBuffer bb = ByteBuffer.wrap(content);
 
   55             bb.order(ByteOrder.LITTLE_ENDIAN);
 
   56             int header = bb.getInt();
 
   57             ByteBuffer linkClassIdentifier = bb.get(
new byte[16]);
 
   58             int linkFlags = bb.getInt();
 
   59             int fileAttributes = bb.getInt();
 
   60             long crtime = bb.getLong();
 
   61             long atime = bb.getLong();
 
   62             long mtime = bb.getLong();
 
   63             int fileSize = bb.getInt();
 
   64             int iconIndex = bb.getInt();
 
   65             int showCommand = bb.getInt();
 
   66             short hotkey = bb.getShort();
 
   68             List<String> linkTargetIdList = 
new ArrayList<>();
 
   69             if ((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag())
 
   70                     == LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) {
 
   71                 int idListSize = bb.getShort();
 
   73                 List<byte[]> linkTargetIdListBytes = 
new ArrayList<>();
 
   75                     short itemIdSize = bb.getShort();
 
   76                     if (itemIdSize == 0) {
 
   80                     byte[] theArray = 
new byte[itemIdSize - 2];
 
   82                     linkTargetIdListBytes.add(theArray);
 
   83                     bytesRead += itemIdSize;
 
   87             boolean hasUnicodeLocalBaseAndCommonSuffixOffset = 
false;
 
   88             String localBasePath = null;
 
   89             String commonPathSuffix = null;
 
   90             String localBasePathUnicode = null;
 
   91             String commonPathSuffixUnicode = null;
 
   92             int driveSerialNumber = -1;
 
   94             String volumeLabel = null;
 
   95             int commonNetworkRelativeLinkFlags = -1;
 
   97             boolean unicodeNetAndDeviceName = 
false;
 
   98             String netName = null;
 
   99             String netNameUnicode = null;
 
  100             String deviceName = null;
 
  101             String deviceNameUnicode = null;
 
  103             if ((linkFlags & LnkEnums.LinkFlags.HasLinkInfo.getFlag())
 
  104                     == LnkEnums.LinkFlags.HasLinkInfo.getFlag()) {
 
  105                 int startOfLinkInfo = bb.position();
 
  106                 int linkInfoSize = bb.getInt();
 
  107                 int linkInfoHeaderSize = bb.getInt();
 
  108                 hasUnicodeLocalBaseAndCommonSuffixOffset = linkInfoHeaderSize >= 0x24;
 
  109                 int linkInfoFlags = bb.getInt();
 
  110                 int volumeIdOffset = bb.getInt();
 
  111                 int localBasePathOffset = bb.getInt();
 
  112                 int commonNetworkRelativeLinkOffset = bb.getInt();
 
  113                 int commonPathSuffixOffset = bb.getInt();
 
  114                 int localBasePathOffsetUnicode = 0;
 
  115                 int commonPathSuffixOffsetUnicode = 0;
 
  116                 if (hasUnicodeLocalBaseAndCommonSuffixOffset) {
 
  117                     localBasePathOffsetUnicode = bb.getInt();
 
  118                     commonPathSuffixOffsetUnicode = bb.getInt();
 
  120                 if ((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
 
  121                         == LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag()) {
 
  122                     bb.position(startOfLinkInfo + volumeIdOffset);
 
  123                     int volumeIdSize = bb.getInt();
 
  125                     driveSerialNumber = bb.getInt();
 
  126                     int volumeLabelOffset = bb.getInt();
 
  127                     if (volumeLabelOffset != 0x14) {
 
  128                         volumeLabel = 
parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffset, 
false, volumeIdSize - 0x10);
 
  130                         int volumeLabelOffsetUnicode = bb.getInt();
 
  131                         volumeLabel = 
parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffsetUnicode, 
false, volumeIdSize - 0x14);
 
  135                 if ((linkInfoFlags & LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag())
 
  136                         == LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag()) {
 
  137                     bb.position(startOfLinkInfo + commonNetworkRelativeLinkOffset);
 
  138                     int commonNetworkRelativeLinkSize = bb.getInt();
 
  139                     commonNetworkRelativeLinkFlags = bb.getInt();
 
  140                     int netNameOffset = bb.getInt();
 
  141                     unicodeNetAndDeviceName = netNameOffset > 0x14;
 
  142                     int deviceNameOffset = bb.getInt();
 
  143                     int netType = bb.getInt();
 
  144                     int netNameOffsetUnicode = 0;
 
  145                     int deviceNameOffsetUnicode = 0;
 
  146                     if (unicodeNetAndDeviceName) {
 
  147                         netNameOffsetUnicode = bb.getInt();
 
  148                         deviceNameOffsetUnicode = bb.getInt();
 
  150                     netName = 
parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffset, 
false);
 
  151                     if (unicodeNetAndDeviceName) {
 
  152                         netNameUnicode = 
parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffsetUnicode, 
true);
 
  154                     if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag())
 
  155                             == LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag()) {
 
  158                     if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag())
 
  159                             == LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag()) {
 
  160                         deviceName = 
parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffset, 
false);
 
  161                         if (unicodeNetAndDeviceName) {
 
  162                             deviceNameUnicode = 
parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffsetUnicode, 
true);
 
  167                 if (((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
 
  168                         == LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
 
  169                         && hasUnicodeLocalBaseAndCommonSuffixOffset) {
 
  170                     localBasePathUnicode = 
parseLocalBasePath(startOfLinkInfo + localBasePathOffsetUnicode, 
true);
 
  171                     commonPathSuffixUnicode = 
parseCommonPathSuffix(startOfLinkInfo + commonPathSuffixOffsetUnicode, 
true);
 
  174                 bb.position(startOfLinkInfo + linkInfoSize);
 
  177             if ((linkFlags & LnkEnums.LinkFlags.HasName.getFlag())
 
  178                     == LnkEnums.LinkFlags.HasName.getFlag()) {
 
  181             String relativePath = null;
 
  182             if ((linkFlags & LnkEnums.LinkFlags.HasRelativePath.getFlag())
 
  183                     == LnkEnums.LinkFlags.HasRelativePath.getFlag()) {
 
  186             String workingDir = null;
 
  187             if ((linkFlags & LnkEnums.LinkFlags.HasWorkingDir.getFlag())
 
  188                     == LnkEnums.LinkFlags.HasWorkingDir.getFlag()) {
 
  191             String arguments = null;
 
  192             if ((linkFlags & LnkEnums.LinkFlags.HasArguments.getFlag())
 
  193                     == LnkEnums.LinkFlags.HasArguments.getFlag()) {
 
  196             String iconLocation = null;
 
  197             if ((linkFlags & LnkEnums.LinkFlags.HasIconLocation.getFlag())
 
  198                     == LnkEnums.LinkFlags.HasIconLocation.getFlag()) {
 
  202             return new JLNK(header, linkClassIdentifier.array(), linkFlags, fileAttributes,
 
  203                     crtime, atime, mtime, fileSize, iconIndex, showCommand, hotkey,
 
  205                     hasUnicodeLocalBaseAndCommonSuffixOffset, localBasePath,
 
  206                     commonPathSuffix, localBasePathUnicode, commonPathSuffixUnicode,
 
  207                     name, relativePath, workingDir, arguments, iconLocation, driveSerialNumber,
 
  208                     driveType, volumeLabel, commonNetworkRelativeLinkFlags,
 
  209                     networkProviderType, unicodeNetAndDeviceName, netName, netNameUnicode,
 
  210                     deviceName, deviceNameUnicode);
 
  211         } 
catch (Exception e) {
 
  212             throw new JLnkParserException(e);
 
  217         short countCharacters = bb.getShort();
 
  218         if (countCharacters == 0) {
 
  221         byte[] theString = 
new byte[countCharacters * 2];
 
  224             return new String(theString, 
"UTF-16LE");
 
  225         } 
catch (UnsupportedEncodingException ex) {
 
  226             logger.info(
"Shouldn't happen"); 
 
  231     private String 
parseString(
int offset, 
boolean unicode, 
int maxlen) {
 
  232         ByteBuffer bb = ByteBuffer.wrap(content);
 
  233         bb.order(ByteOrder.LITTLE_ENDIAN);
 
  235         StringBuilder sb = 
new StringBuilder(bb.limit());
 
  237         while (bb.remaining() > 0 && (i < maxlen || maxlen == -1)) 
 
  251         return sb.toString();
 
  273         List<String> ret = 
new ArrayList<>();
 
  274         if (!idList.isEmpty()) {
 
  278                     ret.add(
new String(Arrays.copyOfRange(idList.remove(0), 1, 17)).split(
"\0")[0]);
 
  296         List<String> ret = 
new ArrayList<>();
 
  297         for (byte[] pathElement : idList) {
 
  298             ByteBuffer bb = ByteBuffer.wrap(pathElement);
 
  299             bb.order(ByteOrder.LITTLE_ENDIAN);
 
  300             int offset = bb.getShort(bb.limit() - 2) - 2;
 
  301             if (pathElement[offset + 0x02] < 0x03
 
  302                     || pathElement[offset + 0x10] >= pathElement[offset]
 
  303                     || pathElement[offset + 0x10] < 0x14) {
 
  307             if (pathElement[offset + 0x10] != 0) {
 
  308                 ret.add(
getStringAt(bb, offset + pathElement[offset + 0x10], 
true));
 
  311                 if (pathElement[offset + 0x12] >= pathElement[offset]
 
  312                         || pathElement[offset + 0x12] < 0x14) {
 
  316                     ret.add(
getStringAt(bb, offset + pathElement[offset + 0x12], 
false));
 
  328     private String 
getStringAt(ByteBuffer bb, 
int offset, 
boolean unicode) {
 
  329         byte[] nameArr = Arrays.copyOfRange(bb.array(), offset, bb.limit());
 
  332                 return new String(nameArr, 
"UTF-16LE").split(
"\0")[0];
 
  333             } 
catch (UnsupportedEncodingException ex) {
 
  337         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)
synchronized static Logger getLogger(String name)
String get0xC(ByteBuffer bb)
static DriveType valueOf(int type)
static CommonCLSIDS valueOf(byte[] type)