diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/Bundle.properties b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/Bundle.properties index b8ebe373f5..1cdf2f77c1 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/Bundle.properties +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/Bundle.properties @@ -204,3 +204,5 @@ HashDbSearchAction.getName.text=Hash Search HashDbSearchPanel.dlgMsg.title=File Search by MD5 Hash AddContentToHashDbAction.singleSelectionName=Add file to hash database AddContentToHashDbAction.multipleSelectionName=Add files to hash database +HashDbManager.ingestRunningExceptionMsg=Ingest is ongoing; this service will be unavailable until it finishes. +HashDbManager.saveErrorExceptionMsg=Error saving hash configuration diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/Bundle_ja.properties b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/Bundle_ja.properties index 189c4b9ed5..36016e2499 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/Bundle_ja.properties +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/Bundle_ja.properties @@ -191,4 +191,6 @@ HashDbSearchPanel.dlgMsg.title=MD5\u30CF\u30C3\u30B7\u30E5\u306B\u57FA\u3065\u30 AddContentToHashDbAction.singleSelectionName=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0 AddContentToHashDbAction.multipleSelectionName=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0 OptionsCategory_Name_HashDatabase=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -OptionsCategory_Keywords_HashDatabase=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 \ No newline at end of file +OptionsCategory_Keywords_HashDatabase=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 +HashDbManager.ingestRunningExceptionMsg=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u4E2D\uFF1B\u5B8C\u4E86\u3059\u308B\u307E\u3067\u3053\u306E\u30B5\u30FC\u30D3\u30B9\u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002 + diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbConfigPanel.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbConfigPanel.java index ac224925e4..ae2acfabd6 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbConfigPanel.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbConfigPanel.java @@ -275,7 +275,7 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio void removeThese(List toRemove) { for (HashDb hashDb : toRemove) { - hashSetManager.removeHashDatabase(hashDb); + hashSetManager.removeHashDatabaseInternal(hashDb); } hashSetTableModel.refreshModel(); } @@ -744,7 +744,7 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { HashDb hashDb = ((HashSetTable)hashSetTable).getSelection(); if (hashDb != null) { - hashSetManager.removeHashDatabase(hashDb); + hashSetManager.removeHashDatabaseInternal(hashDb); hashSetTableModel.refreshModel(); } } @@ -754,7 +754,7 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio if (evt.getKeyCode() == KeyEvent.VK_DELETE) { HashDb hashDb = ((HashSetTable)hashSetTable).getSelection(); if (hashDb != null) { - hashSetManager.removeHashDatabase(hashDb); + hashSetManager.removeHashDatabaseInternal(hashDb); hashSetTableModel.refreshModel(); } } diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbCreateDatabaseDialog.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbCreateDatabaseDialog.java index 2935304dcb..e7e25a25ef 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbCreateDatabaseDialog.java @@ -34,10 +34,7 @@ import org.apache.commons.io.FilenameUtils; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb.KnownFilesType; -import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDatabaseFileAlreadyExistsException; -import org.sleuthkit.autopsy.hashdatabase.HashDbManager.DuplicateHashSetNameException; -import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDatabaseAlreadyAddedException; -import org.sleuthkit.autopsy.hashdatabase.HashDbManager.IllegalHashDatabaseFileNameExtensionException; +import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDbManagerException; /** * Instances of this class allow a user to create a new hash database and @@ -355,7 +352,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { .getMessage(this.getClass(), "HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr"); try { - newHashDb = HashDbManager.getInstance().addNewHashDatabase(hashSetNameTextField.getText(), fileChooser.getSelectedFile().getCanonicalPath(), searchDuringIngestCheckbox.isSelected(), sendIngestMessagesCheckbox.isSelected(), type); + newHashDb = HashDbManager.getInstance().addNewHashDatabaseInternal(hashSetNameTextField.getText(), fileChooser.getSelectedFile().getCanonicalPath(), searchDuringIngestCheckbox.isSelected(), sendIngestMessagesCheckbox.isSelected(), type); } catch (IOException ex) { Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex); @@ -367,7 +364,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { JOptionPane.ERROR_MESSAGE); return; } - catch (HashDatabaseFileAlreadyExistsException | DuplicateHashSetNameException | HashDatabaseAlreadyAddedException | IllegalHashDatabaseFileNameExtensionException ex) { + catch (HashDbManagerException ex) { Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex); JOptionPane.showMessageDialog(this, ex.getMessage(), diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbImportDatabaseDialog.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbImportDatabaseDialog.java index 0262ed74db..5af9f8e57d 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbImportDatabaseDialog.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbImportDatabaseDialog.java @@ -34,9 +34,7 @@ import org.sleuthkit.datamodel.TskCoreException; import org.apache.commons.io.FilenameUtils; import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb; -import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDatabaseDoesNotExistException; -import org.sleuthkit.autopsy.hashdatabase.HashDbManager.DuplicateHashSetNameException; -import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDatabaseAlreadyAddedException; +import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDbManagerException; /** * Instances of this class allow a user to select an existing hash database and @@ -342,9 +340,9 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { "HashDbImportDatabaseDialog.errorMessage.failedToOpenHashDbMsg", selectedFilePath); try { - selectedHashDb = HashDbManager.getInstance().addExistingHashDatabase(hashSetNameTextField.getText(), selectedFilePath, searchDuringIngestCheckbox.isSelected(), sendIngestMessagesCheckbox.isSelected(), type); + selectedHashDb = HashDbManager.getInstance().addExistingHashDatabaseInternal(hashSetNameTextField.getText(), selectedFilePath, searchDuringIngestCheckbox.isSelected(), sendIngestMessagesCheckbox.isSelected(), type); } - catch (HashDatabaseDoesNotExistException | DuplicateHashSetNameException | HashDatabaseAlreadyAddedException ex) { + catch (HashDbManagerException ex) { Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex); JOptionPane.showMessageDialog(this, ex.getMessage(), diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbManager.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbManager.java index 781082ee24..394b7461c3 100755 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbManager.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbManager.java @@ -51,10 +51,12 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.HashInfo; +import org.sleuthkit.datamodel.HashEntry; import org.sleuthkit.datamodel.SleuthkitJNI; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.ingest.IngestManager; /** * This class implements a singleton that manages the set of hash databases * used to classify files as unknown, known or known bad. @@ -122,36 +124,39 @@ public class HashDbManager implements PropertyChangeListener { return HASH_DATABASE_FILE_EXTENSON; } - class DuplicateHashSetNameException extends Exception { - private DuplicateHashSetNameException(String hashSetName) { - super(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName)); - } + public class HashDbManagerException extends Exception { + private HashDbManagerException(String message) { + super(message); + } } - class HashDatabaseDoesNotExistException extends Exception { - private HashDatabaseDoesNotExistException(String path) { - super(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbDoesNotExistExceptionMsg", path)); + /** + * Adds an existing hash database to the set of hash databases used to classify files as known or known bad + * and saves the configuration. + * @param hashSetName Name used to represent the hash database in user interface components. + * @param path Full path to either a hash database file or a hash database index file. + * @param searchDuringIngest A flag indicating whether or not the hash database should be searched during ingest. + * @param sendIngestMessages A flag indicating whether hash set hit messages should be sent as ingest messages. + * @param knownFilesType The classification to apply to files whose hashes are found in the hash database. + * @return A HashDb representing the hash database. + * @throws HashDbManagerException + */ + public HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException{ + HashDb hashDb = null; + try{ + addExistingHashDatabaseInternal(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType); } - } - - class HashDatabaseFileAlreadyExistsException extends Exception { - private HashDatabaseFileAlreadyExistsException(String path) { - super(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbFileExistsExceptionMsg", path)); + catch(TskCoreException ex){ + throw new HashDbManagerException(ex.getMessage()); } - } - - class HashDatabaseAlreadyAddedException extends Exception { - private HashDatabaseAlreadyAddedException(String path) { - super(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path)); + + // Save the configuration + if(! save()){ + throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg")); } - } - - class IllegalHashDatabaseFileNameExtensionException extends Exception { - private IllegalHashDatabaseFileNameExtensionException() { - super(NbBundle.getMessage(HashDbManager.class, "HashDbManager.illegalHashDbFileNameExtensionMsg", - getHashDatabaseFileExtension())); - } - } + + return hashDb; + } /** * Adds an existing hash database to the set of hash databases used to classify files as known or known bad. @@ -163,23 +168,53 @@ public class HashDbManager implements PropertyChangeListener { * @param sendIngestMessages A flag indicating whether hash set hit messages should be sent as ingest messages. * @param knownFilesType The classification to apply to files whose hashes are found in the hash database. * @return A HashDb representing the hash database. - * @throws HashDatabaseDoesNotExistException, DuplicateHashSetNameException, HashDatabaseAlreadyAddedException, TskCoreException + * @throws HashDbManagerException, TskCoreException */ - synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDatabaseDoesNotExistException, DuplicateHashSetNameException, HashDatabaseAlreadyAddedException, TskCoreException { + synchronized HashDb addExistingHashDatabaseInternal(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException, TskCoreException { if (!new File(path).exists()) { - throw new HashDatabaseDoesNotExistException(path); + throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbDoesNotExistExceptionMsg", path)); } - if (hashSetPaths.contains(path)) { - throw new HashDatabaseAlreadyAddedException(path); + if (hashSetPaths.contains(path)) { + throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path)); } if (hashSetNames.contains(hashSetName)) { - throw new DuplicateHashSetNameException(hashSetName); + throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName)); } return addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); } + + /** + * Adds a new hash database to the set of hash databases used to classify files as known or known bad + * and saves the configuration. + * @param hashSetName Hash set name used to represent the hash database in user interface components. + * @param path Full path to the database file to be created. + * @param searchDuringIngest A flag indicating whether or not the hash database should be searched during ingest. + * @param sendIngestMessages A flag indicating whether hash set hit messages should be sent as ingest messages. + * @param knownFilesType The classification to apply to files whose hashes are found in the hash database. + * @return A HashDb representing the hash database. + * @throws HashDbManagerException + */ + public HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, + HashDb.KnownFilesType knownFilesType) throws HashDbManagerException{ + + HashDb hashDb = null; + try{ + hashDb = addNewHashDatabaseInternal(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType); + } + catch(TskCoreException ex){ + throw new HashDbManagerException(ex.getMessage()); + } + + // Save the configuration + if(! save()){ + throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg")); + } + + return hashDb; + } /** * Adds a new hash database to the set of hash databases used to classify files as known or known bad. @@ -191,23 +226,24 @@ public class HashDbManager implements PropertyChangeListener { * @param sendIngestMessages A flag indicating whether hash set hit messages should be sent as ingest messages. * @param knownFilesType The classification to apply to files whose hashes are found in the hash database. * @return A HashDb representing the hash database. - * @throws TskCoreException + * @throws HashDbManagerException, TskCoreException */ - synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDatabaseFileAlreadyExistsException, IllegalHashDatabaseFileNameExtensionException, DuplicateHashSetNameException, HashDatabaseAlreadyAddedException, TskCoreException { + synchronized HashDb addNewHashDatabaseInternal(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException, TskCoreException { File file = new File(path); if (file.exists()) { - throw new HashDatabaseFileAlreadyExistsException(path); + throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbFileExistsExceptionMsg", path)); } if (!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(HASH_DATABASE_FILE_EXTENSON)) { - throw new IllegalHashDatabaseFileNameExtensionException(); + throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.illegalHashDbFileNameExtensionMsg", + getHashDatabaseFileExtension())); } if (hashSetPaths.contains(path)) { - throw new HashDatabaseAlreadyAddedException(path); + throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path)); } if (hashSetNames.contains(hashSetName)) { - throw new DuplicateHashSetNameException(hashSetName); + throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName)); } return addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); @@ -277,6 +313,24 @@ public class HashDbManager implements PropertyChangeListener { } } } + + /** + * Removes a hash database from the set of hash databases used to classify + * files as known or known bad and saves the configuration. + * @param hashDb + * @throws HashDbManagerException + */ + public synchronized void removeHashDatabase(HashDb hashDb) throws HashDbManagerException { + // Don't remove a database if ingest is running + boolean ingestIsRunning = IngestManager.getDefault().isIngestRunning(); + if(ingestIsRunning){ + throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.ingestRunningExceptionMsg")); + } + removeHashDatabaseInternal(hashDb); + if(! save()){ + throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg")); + } + } /** * Removes a hash database from the set of hash databases used to classify @@ -285,7 +339,7 @@ public class HashDbManager implements PropertyChangeListener { * configuration panels. * @throws TskCoreException */ - synchronized void removeHashDatabase(HashDb hashDb) { + synchronized void removeHashDatabaseInternal(HashDb hashDb) { // Remove the database from whichever hash set list it occupies, // and remove its hash set name from the hash set used to ensure unique // hash set names are used, before undertaking These operations will succeed and constitute @@ -408,7 +462,7 @@ public class HashDbManager implements PropertyChangeListener { * saved on demand to support cancellation of configuration panels. * @return True on success, false otherwise. */ - public synchronized boolean save() { + synchronized boolean save() { return writeHashSetConfigurationToDisk(); } @@ -604,9 +658,9 @@ public class HashDbManager implements PropertyChangeListener { if (null != dbPath) { try { - addExistingHashDatabase(hashSetName, dbPath, seearchDuringIngestFlag, sendIngestMessagesFlag, HashDb.KnownFilesType.valueOf(knownFilesType)); + addExistingHashDatabaseInternal(hashSetName, dbPath, seearchDuringIngestFlag, sendIngestMessagesFlag, HashDb.KnownFilesType.valueOf(knownFilesType)); } - catch (HashDatabaseDoesNotExistException | DuplicateHashSetNameException | HashDatabaseAlreadyAddedException | TskCoreException ex) { + catch (HashDbManagerException | TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash database", ex); JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), @@ -832,6 +886,15 @@ public class HashDbManager implements PropertyChangeListener { } } } + + /** + * Adds a list of hashes to the hash database at once + * @param hashes List of hashes + * @throws TskCoreException + */ + public void addHashes(List hashes) throws TskCoreException{ + SleuthkitJNI.addToHashDatabase(hashes, handle); + } public boolean hasMd5HashOf(Content content) throws TskCoreException { boolean result = false; diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 9fc095c4a7..8e777360ff 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Wed, 15 Jan 2014 15:11:33 -0500 +#Thu, 20 Feb 2014 12:30:26 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=288 SPLASH_WIDTH=538 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index eaa57124f0..1ee8ae75a2 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Wed, 15 Jan 2014 15:11:33 -0500 +#Thu, 20 Feb 2014 12:30:26 -0500 CTL_MainWindow_Title=Autopsy 3.0.8 CTL_MainWindow_Title_No_Project=Autopsy 3.0.8 diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties index 16657aac7f..c91a51a355 100644 --- a/nbproject/genfiles.properties +++ b/nbproject/genfiles.properties @@ -7,5 +7,5 @@ nbproject/build-impl.xml.data.CRC32=2e7964b0 nbproject/build-impl.xml.script.CRC32=b72261eb nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.47.1 nbproject/platform.xml.data.CRC32=2e7964b0 -nbproject/platform.xml.script.CRC32=db9e1f43 -nbproject/platform.xml.stylesheet.CRC32=df8ac4dd@2.47.1 +nbproject/platform.xml.script.CRC32=6dcbd131 +nbproject/platform.xml.stylesheet.CRC32=4e1f53d4@2.62.1 diff --git a/nbproject/platform.xml b/nbproject/platform.xml index 1c86efdbef..020ab53b8a 100644 --- a/nbproject/platform.xml +++ b/nbproject/platform.xml @@ -17,7 +17,7 @@ - +