import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
+import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Vector;
import org.apache.thrift.TException;
+import org.h2.tools.ChangeFileEncryption;
import com.evernote.edam.error.EDAMNotFoundException;
import com.evernote.edam.error.EDAMSystemException;
import cx.fbn.nevernote.config.StartupConfig;
import cx.fbn.nevernote.dialog.AccountDialog;
import cx.fbn.nevernote.dialog.ConfigDialog;
+import cx.fbn.nevernote.dialog.DBEncryptDialog;
import cx.fbn.nevernote.dialog.DatabaseLoginDialog;
import cx.fbn.nevernote.dialog.DatabaseStatus;
import cx.fbn.nevernote.dialog.FindDialog;
String trashNoteGuid; // Guid to restore / set into or out of trash to save position
Thumbnailer preview; // generate preview image
ThumbnailViewer thumbnailViewer; // View preview thumbnail;
+ boolean encryptOnShutdown; // should I encrypt when I close?
+ boolean decryptOnShutdown; // should I decrypt on shutdown;
+ String encryptCipher; // What cipher should I use?
String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
logger = new ApplicationLogger("nevernote.log");
logger.log(logger.HIGH, "Starting Application");
-
+
+ decryptOnShutdown = false;
+ encryptOnShutdown = false;
conn.checkDatabaseVersion();
+
+
// Start building the invalid XML tables
Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements();
List<String> elements = conn.getInvalidXMLTable().getInvalidAttributeElements();
*/
private static DatabaseConnection setupDatabaseConnection() throws InitializationException {
ApplicationLogger logger = new ApplicationLogger("nevernote-database.log");
- DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
-
+
+ File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db");
+ boolean dbExists = f.exists();
+ if (!dbExists)
+ Global.setDatabaseUrl("");
+
if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) {
boolean goodCheck = false;
while (!goodCheck) {
Global.getDatabaseUserPassword(), Global.cipherPassword);
}
}
- return dbConn;
+ DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
+ return dbConn;
+ }
+
+ // Encrypt the database upon shutdown
+ private void encryptOnShutdown() {
+ String dbPath= Global.getFileManager().getDbDirPath("");
+ String dbName = "NeverNote";
+ try {
+ Statement st = conn.getConnection().createStatement();
+ st.execute("shutdown");
+ QMessageBox box = new QMessageBox();
+ box.setText("Encrypting Database");
+ box.show();
+ ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, null, Global.cipherPassword.toCharArray(), true);
+ Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher);
+ box.setText("Encryption Complete");
+ box.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // Decrypt the database upon shutdown
+ private void decryptOnShutdown() {
+ String dbPath= Global.getFileManager().getDbDirPath("");
+ String dbName = "NeverNote";
+ try {
+ Statement st = conn.getConnection().createStatement();
+ st.execute("shutdown");
+ if (Global.getDatabaseUrl().toUpperCase().indexOf(";CIPHER=AES") > -1)
+ encryptCipher = "AES";
+ else
+ encryptCipher = "XTEA";
+ QMessageBox box = new QMessageBox();
+ box.setText("Decrypting Database");
+ box.show();
+ ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, Global.cipherPassword.toCharArray(), null, true);
+ Global.setDatabaseUrl("");
+ box.setText("Decryption Complete");
+ box.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ /**
+ * Encrypt/Decrypt the local database
+ **/
+ public void doDatabaseEncrypt() {
+ // The database is not currently encrypted
+ if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") == -1) {
+ if (QMessageBox.question(this, tr("Confirmation"), tr("Encrypting the database is used" +
+ "to enhance security and is performed\nupon shutdown, but please be aware that if"+
+ " you lose the password your\nis lost forever.\n\nIt is highly recommended you " +
+ "perform a backup and/or fully synchronize\n prior to executing this funtction.\n\n" +
+ "Do you wish to proceed?"),
+ QMessageBox.StandardButton.Yes,
+ QMessageBox.StandardButton.No)==StandardButton.No.value()) {
+ return;
+ }
+ DBEncryptDialog dialog = new DBEncryptDialog();
+ dialog.exec();
+ if (dialog.okPressed()) {
+ Global.cipherPassword = dialog.getPassword();
+ encryptOnShutdown = true;
+ encryptCipher = "AES";
+ }
+ } else {
+ DBEncryptDialog dialog = new DBEncryptDialog();
+ dialog.setWindowTitle("Database Decryption");
+ dialog.exec();
+ if (dialog.okPressed()) {
+ if (!dialog.getPassword().equals(Global.cipherPassword)) {
+ QMessageBox.critical(null, "Incorrect Password", "Incorrect Password");
+ return;
+ }
+ decryptOnShutdown = true;
+ encryptCipher = "";
+ }
+ }
+ return;
}
private static void initializeGlobalSettings(String[] args) throws InitializationException {
- StartupConfig startupConfig = new StartupConfig();
+ StartupConfig startupConfig = new StartupConfig();
- for (String arg : args) {
- String lower = arg.toLowerCase();
- if (lower.startsWith("--name="))
- startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
- if (lower.startsWith("--home="))
- startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
- if (lower.startsWith("--disable-viewing"))
- startupConfig.setDisableViewing(true);
- }
-
- Global.setup(startupConfig);
+ for (String arg : args) {
+ String lower = arg.toLowerCase();
+ if (lower.startsWith("--name="))
+ startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
+ if (lower.startsWith("--home="))
+ startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
+ if (lower.startsWith("--disable-viewing"))
+ startupConfig.setDisableViewing(true);
}
+ Global.setup(startupConfig);
+ }
// Exit point
@Override
}
}
+ if (encryptOnShutdown) {
+ encryptOnShutdown();
+ }
+ if (decryptOnShutdown) {
+ decryptOnShutdown();
+ }
logger.log(logger.HIGH, "Leaving NeverNote.closeEvent");
}
--- /dev/null
+/*\r
+ * This file is part of NeverNote \r
+ * Copyright 2009 Randy Baumgarte\r
+ * \r
+ * This file may be licensed under the terms of of the\r
+ * GNU General Public License Version 2 (the ``GPL'').\r
+ *\r
+ * Software distributed under the License is distributed\r
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
+ * express or implied. See the GPL for the specific language\r
+ * governing rights and limitations.\r
+ *\r
+ * You should have received a copy of the GPL along with this\r
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
+ * or write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+ *\r
+*/\r
+\r
+package cx.fbn.nevernote.dialog;\r
+\r
+import com.trolltech.qt.gui.QDialog;\r
+import com.trolltech.qt.gui.QGridLayout;\r
+import com.trolltech.qt.gui.QLabel;\r
+import com.trolltech.qt.gui.QLineEdit;\r
+import com.trolltech.qt.gui.QPushButton;\r
+\r
+public class DBEncryptDialog extends QDialog {\r
+\r
+ private boolean okPressed;\r
+ private final QLineEdit password1;\r
+ private final QLineEdit password2;\r
+ private final QPushButton ok;\r
+ \r
+ \r
+ // Constructor\r
+ public DBEncryptDialog() {\r
+ okPressed = false;\r
+ setWindowTitle(tr("Database Encryption"));\r
+ QGridLayout grid = new QGridLayout();\r
+ setLayout(grid);\r
+ QGridLayout passwordGrid = new QGridLayout();\r
+ QGridLayout buttonGrid = new QGridLayout();\r
+ \r
+ password1 = new QLineEdit();\r
+ password1.setEchoMode(QLineEdit.EchoMode.Password);\r
+ password2 = new QLineEdit();\r
+ password2.setEchoMode(QLineEdit.EchoMode.Password);\r
+ \r
+ password1.textChanged.connect(this, "validateInput()");\r
+ password2.textChanged.connect(this, "validateInput()");\r
+ \r
+ passwordGrid.addWidget(new QLabel(tr("Password")), 1,1);\r
+ passwordGrid.addWidget(password1, 1, 2);\r
+ passwordGrid.addWidget(new QLabel(tr("Verify Password")), 2,1);\r
+ passwordGrid.addWidget(password2, 2, 2);\r
+ passwordGrid.setContentsMargins(10, 10, -10, -10);\r
+ grid.addLayout(passwordGrid,1,1);\r
+ \r
+ ok = new QPushButton(tr("OK"));\r
+ ok.setEnabled(false);\r
+ ok.clicked.connect(this, "okButtonPressed()");\r
+ QPushButton cancel = new QPushButton(tr("Cancel"));\r
+ cancel.clicked.connect(this, "cancelButtonPressed()");\r
+ buttonGrid.addWidget(ok, 1, 1);\r
+ buttonGrid.addWidget(cancel, 1,2);\r
+ grid.addLayout(buttonGrid,2,1);\r
+ }\r
+ \r
+ // The OK button was pressed\r
+ @SuppressWarnings("unused")\r
+ private void okButtonPressed() {\r
+ okPressed = true;\r
+ close();\r
+ }\r
+ \r
+ // The CANCEL button was pressed\r
+ @SuppressWarnings("unused")\r
+ private void cancelButtonPressed() {\r
+ okPressed = false;\r
+ close();\r
+ }\r
+ \r
+ // Get the userid from the field\r
+ public String getPassword() {\r
+ return password1.text();\r
+ }\r
+ \r
+ // Check if the OK button was pressed\r
+ public boolean okPressed() {\r
+ return okPressed;\r
+ }\r
+ \r
+ // Validate user input\r
+ public void validateInput() {\r
+ ok.setEnabled(true);\r
+ if (password1.text().trim().equals("")) {\r
+ ok.setEnabled(false);\r
+ return;\r
+ } \r
+ if (password1.text().length() < 4) {\r
+ ok.setEnabled(false);\r
+ return;\r
+ }\r
+ if (!password1.text().equals(password2.text())) {\r
+ ok.setEnabled(false);\r
+ return;\r
+ }\r
+ }\r
+}\r
public QAction databaseStatusAction; // Current database status\r
public QAction folderImportAction; // Automatically import files \r
public QAction spellCheckAction; // Spell checker\r
+ public QAction encryptDatabaseAction; // Encrypt the local database\r
\r
public QAction notebookEditAction; // Edit the selected notebook\r
public QAction notebookAddAction; // Add a new notebook\r
spellCheckAction.triggered.connect(parent.browserWindow, "doSpellCheck()");\r
setupShortcut(spellCheckAction, "Tools_Spell_Check");\r
\r
+ encryptDatabaseAction = new QAction(tr("Encrypt Database"), this);\r
+ encryptDatabaseAction.setToolTip("Encrypt the database upon shutdown");\r
+ encryptDatabaseAction.triggered.connect(parent, "doDatabaseEncrypt()");\r
+ setupShortcut(encryptDatabaseAction, "Tools_Database_Encrypt");\r
+ if (Global.cipherPassword != null && Global.cipherPassword != "") {\r
+ encryptDatabaseAction.setText("Decrypt Database");\r
+ encryptDatabaseAction.setToolTip("Decrypt the database upon shutdown");\r
+ }\r
+ \r
loggerAction = new QAction(tr("Log"), this);\r
loggerAction.setToolTip("Show the detailed application log");\r
loggerAction.triggered.connect(parent, "logger()");\r
toolsMenu.addAction(fullReindexAction);\r
toolsMenu.addAction(disableIndexing);\r
// toolsMenu.addAction(compactAction);\r
+ toolsMenu.addSeparator();\r
+ toolsMenu.addAction(encryptDatabaseAction);\r
toolsMenu.addAction(databaseStatusAction);\r
toolsMenu.addSeparator();\r
toolsMenu.addAction(folderImportAction);\r