19 package org.sleuthkit.datamodel.blackboardutils.attributes;
21 import com.google.common.collect.ImmutableList;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.List;
71 private final String url;
116 private final String path;
117 private final long objectID;
127 transient private static final List<String> KNOWN_MOUNTPOINTS
130 "/storage/emulated/");
149 this.path = normalizePath(pathName);
151 String fileName = path.substring(path.lastIndexOf(
'/') + 1);
152 if (fileName.isEmpty()) {
153 throw new TskCoreException(String.format(
"No file name specified for attachment file: %s, on data source = %d", path, dataSource.getId()));
156 String parentPathSubString = (path.lastIndexOf(
'/') < 0) ?
"" : path.substring(0, path.lastIndexOf(
'/'));
159 objectID = findAttachmentFile(caseDb, fileName, parentPathSubString, dataSource);
173 objectID = derivedFile.
getId();
183 objectID = abstractFile.
getId();
214 private String normalizePath(String path) {
216 String adjustedPath = path.replace(
"\\",
"/").replace(
"%20",
" ");
219 for (String mountPoint : KNOWN_MOUNTPOINTS) {
220 if (adjustedPath.toLowerCase().startsWith(mountPoint)) {
221 adjustedPath = (
"/").concat(adjustedPath.substring(mountPoint.length()));
247 String whereClause = String.format(
"LOWER(name) = LOWER('%s') AND LOWER(parent_path) LIKE LOWER('%%%s%%')", fileName, parentPathSubstring);
248 List<AbstractFile> matchedFiles = caseDb.findAllFilesWhere(whereClause);
252 List<Long> allocFileMatchesOnSameDatasource =
new ArrayList<>();
253 List<Long> allocFileMatchesOnOtherDatasources =
new ArrayList<>();
254 List<Long> unallocFileMatches =
new ArrayList<>();
258 if (dataSource.getId() == file.getDataSource().getId()) {
259 allocFileMatchesOnSameDatasource.add(file.getId());
261 allocFileMatchesOnOtherDatasources.add(file.getId());
264 unallocFileMatches.add(file.getId());
269 return pickBestMatchFile(allocFileMatchesOnSameDatasource, allocFileMatchesOnOtherDatasources, unallocFileMatches);
300 private long pickBestMatchFile(List<Long> allocFileMatchesOnSameDatasource,
301 List<Long> allocFileMatchesOnOtherDatasources,
302 List<Long> unallocFileMatches) {
305 if (!allocFileMatchesOnSameDatasource.isEmpty() && allocFileMatchesOnSameDatasource.size() == 1) {
306 return allocFileMatchesOnSameDatasource.get(0);
309 if (!allocFileMatchesOnOtherDatasources.isEmpty()
310 && allocFileMatchesOnOtherDatasources.size() == 1) {
311 return allocFileMatchesOnOtherDatasources.get(0);
314 if (!unallocFileMatches.isEmpty()
315 && unallocFileMatches.size() == 1) {
316 return unallocFileMatches.get(0);
330 return this.objectID;
335 private final Collection<FileAttachment> fileAttachments;
336 private final Collection<URLAttachment> urlAttachments;
345 public MessageAttachments(Collection<FileAttachment> fileAttachments, Collection<URLAttachment> urlAttachments) {
346 this.fileAttachments = fileAttachments;
347 this.urlAttachments = urlAttachments;
356 return Collections.unmodifiableCollection(fileAttachments);
365 return Collections.unmodifiableCollection(urlAttachments);
374 return (fileAttachments.size() + urlAttachments.size());
FileAttachment(SleuthkitCase caseDb, Content dataSource, String pathName)
Collection< URLAttachment > getUrlAttachments()
ALLOC
Metadata structure is currently in an allocated state.
URLAttachment(String url)
MessageAttachments(Collection< FileAttachment > fileAttachments, Collection< URLAttachment > urlAttachments)
FileAttachment(DerivedFile derivedFile)
Collection< FileAttachment > getFileAttachments()
FileAttachment(AbstractFile abstractFile)
int getAttachmentsCount()