DatabaseUtilities.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. // DatabaseUtilites.cpp: implementation of the CDatabaseUtilites class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "CP_Main.h"
  6. #include "DatabaseUtilities.h"
  7. #include "ProcessPaste.h"
  8. #include <io.h>
  9. #include "AccessToSqlite.h"
  10. //////////////////////////////////////////////////////////////////////
  11. // Construction/Destruction
  12. //////////////////////////////////////////////////////////////////////
  13. BOOL CreateBackup(CString csPath)
  14. {
  15. CString csOriginal;
  16. int count = 0;
  17. // create a backup of the existing database
  18. do
  19. {
  20. count++;
  21. csOriginal = csPath + StrF(_T(".%03d"), count);
  22. // in case of some weird infinite loop
  23. if( count > 50 )
  24. {
  25. ASSERT(0);
  26. return FALSE;
  27. }
  28. } while( !::CopyFile(csPath, csOriginal, TRUE));
  29. return TRUE;
  30. }
  31. CString GetDBName()
  32. {
  33. return CGetSetOptions::GetDBPath();
  34. }
  35. CString GetOLDDefaultDBName()
  36. {
  37. CString csDefaultPath;
  38. LPMALLOC pMalloc;
  39. if(SUCCEEDED(::SHGetMalloc(&pMalloc)))
  40. {
  41. LPITEMIDLIST pidlPrograms;
  42. SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidlPrograms);
  43. TCHAR string[MAX_PATH];
  44. SHGetPathFromIDList(pidlPrograms, string);
  45. pMalloc->Free(pidlPrograms);
  46. pMalloc->Release();
  47. csDefaultPath = string;
  48. csDefaultPath += "\\Ditto\\";
  49. csDefaultPath += "DittoDB.mdb";
  50. }
  51. return csDefaultPath;
  52. }
  53. CString GetDefaultDBName()
  54. {
  55. CString csDefaultPath = _T("c:\\program files\\Ditto\\");
  56. if(g_Opt.m_bU3)
  57. {
  58. csDefaultPath = CGetSetOptions::GetPath(PATH_DATABASE);
  59. }
  60. else
  61. {
  62. LPMALLOC pMalloc;
  63. if(SUCCEEDED(::SHGetMalloc(&pMalloc)))
  64. {
  65. LPITEMIDLIST pidlPrograms;
  66. SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidlPrograms);
  67. TCHAR string[MAX_PATH];
  68. SHGetPathFromIDList(pidlPrograms, string);
  69. pMalloc->Free(pidlPrograms);
  70. pMalloc->Release();
  71. csDefaultPath = string;
  72. }
  73. FIX_CSTRING_PATH(csDefaultPath);
  74. csDefaultPath += "Ditto\\";
  75. }
  76. if(FileExists(csDefaultPath) == FALSE)
  77. CreateDirectory(csDefaultPath, NULL);
  78. CString csTempName = csDefaultPath + "Ditto.db";
  79. int i = 1;
  80. while(FileExists(csTempName))
  81. {
  82. csTempName.Format(_T("%sDitto_%d.db"), csDefaultPath, i);
  83. i++;
  84. }
  85. csDefaultPath = csTempName;
  86. return csDefaultPath;
  87. }
  88. BOOL CheckDBExists(CString csDBPath)
  89. {
  90. //If this is the first time running this version then convert the old database to the new db
  91. if(csDBPath.IsEmpty() && g_Opt.m_bU3 == false)
  92. {
  93. csDBPath = GetDefaultDBName();
  94. if(FileExists(csDBPath) == FALSE)
  95. {
  96. CString csOldDB = CGetSetOptions::GetDBPathOld();
  97. if(csOldDB.IsEmpty())
  98. {
  99. csOldDB = GetOLDDefaultDBName();
  100. }
  101. if(FileExists(csOldDB))
  102. {
  103. //create the new sqlite db
  104. CreateDB(csDBPath);
  105. CAccessToSqlite Convert;
  106. Convert.ConvertDatabase(csDBPath, csOldDB);
  107. }
  108. }
  109. }
  110. BOOL bRet = FALSE;
  111. if(FileExists(csDBPath) == FALSE)
  112. {
  113. csDBPath = GetDefaultDBName();
  114. // -- create a new one
  115. bRet = CreateDB(csDBPath);
  116. }
  117. else
  118. {
  119. if(ValidDB(csDBPath) == FALSE)
  120. {
  121. //Db existed but was bad
  122. CString csMarkAsBad;
  123. csMarkAsBad = csDBPath;
  124. csMarkAsBad.Replace(_T("."), _T("_BAD."));
  125. CString csPath = GetDefaultDBName();
  126. CString cs;
  127. cs.Format(_T("%s \"%s\",\n")
  128. _T("%s \"%s\",\n")
  129. _T("%s,\n")
  130. _T("\"%s\""),
  131. theApp.m_Language.GetString("Database_Format", "Unrecognized Database Format"),
  132. csDBPath,
  133. theApp.m_Language.GetString("File_Renamed", "the file will be renamed"),
  134. csMarkAsBad,
  135. theApp.m_Language.GetString("New_Database", "and a new database will be created"),
  136. csPath);
  137. AfxMessageBox(cs);
  138. CFile::Rename(csDBPath, csMarkAsBad);
  139. csDBPath = csPath;
  140. bRet = CreateDB(csDBPath);
  141. }
  142. else
  143. bRet = TRUE;
  144. }
  145. if(bRet)
  146. {
  147. bRet = OpenDatabase(csDBPath);
  148. }
  149. return bRet;
  150. }
  151. BOOL OpenDatabase(CString csDB)
  152. {
  153. try
  154. {
  155. theApp.m_db.close();
  156. theApp.m_db.open(csDB);
  157. CGetSetOptions::SetDBPath(csDB);
  158. return TRUE;
  159. }
  160. CATCH_SQLITE_EXCEPTION
  161. return FALSE;
  162. }
  163. BOOL ValidDB(CString csPath, BOOL bUpgrade)
  164. {
  165. try
  166. {
  167. CppSQLite3DB db;
  168. db.open(csPath);
  169. db.execQuery(_T("SELECT lID, lDate, mText, lShortCut, lDontAutoDelete, ")
  170. _T("CRC, bIsGroup, lParentID, QuickPasteText ")
  171. _T("FROM Main"));
  172. db.execQuery(_T("SELECT lID, lParentID, strClipBoardFormat, ooData FROM Data"));
  173. db.execQuery(_T("SELECT lID, TypeText FROM Types"));
  174. //This was added later so try to add each time and catch the exception here
  175. try
  176. {
  177. db.execDML(_T("CREATE TRIGGER delete_data_trigger BEFORE DELETE ON Main FOR EACH ROW\n")
  178. _T("BEGIN\n")
  179. _T("DELETE FROM Data WHERE lParentID = old.lID;\n")
  180. _T("END\n"));
  181. }
  182. catch(CppSQLite3Exception& e)
  183. {
  184. e.errorCode();
  185. }
  186. }
  187. CATCH_SQLITE_EXCEPTION_AND_RETURN(FALSE)
  188. return TRUE;
  189. }
  190. BOOL CreateDB(CString csPath)
  191. {
  192. try
  193. {
  194. CppSQLite3DB db;
  195. db.open(csPath);
  196. db.execDML(_T("CREATE TABLE Main(")
  197. _T("lID INTEGER PRIMARY KEY AUTOINCREMENT, ")
  198. _T("lDate INTEGER, ")
  199. _T("mText TEXT, ")
  200. _T("lShortCut INTEGER, ")
  201. _T("lDontAutoDelete INTEGER, ")
  202. _T("CRC INTEGER, ")
  203. _T("bIsGroup INTEGER, ")
  204. _T("lParentID INTEGER, ")
  205. _T("QuickPasteText TEXT);"));
  206. db.execDML(_T("CREATE TABLE Data(")
  207. _T("lID INTEGER PRIMARY KEY AUTOINCREMENT, ")
  208. _T("lParentID INTEGER, ")
  209. _T("strClipBoardFormat TEXT, ")
  210. _T("ooData BLOB);"));
  211. db.execDML(_T("CREATE TABLE Types(")
  212. _T("lID INTEGER PRIMARY KEY AUTOINCREMENT, ")
  213. _T("TypeText TEXT)"));
  214. db.execDML(_T("CREATE UNIQUE INDEX Main_ID on Main(lID ASC)"));
  215. db.execDML(_T("CREATE UNIQUE INDEX Data_ID on Data(lID ASC)"));
  216. db.execDML(_T("CREATE INDEX Main_Date on Main(lDate DESC)"));
  217. db.execDML(_T("CREATE TRIGGER delete_data_trigger BEFORE DELETE ON Main FOR EACH ROW\n")
  218. _T("BEGIN\n")
  219. _T("DELETE FROM Data WHERE lParentID = old.lID;\n")
  220. _T("END\n"));
  221. db.close();
  222. }
  223. CATCH_SQLITE_EXCEPTION_AND_RETURN(FALSE)
  224. return TRUE;
  225. }
  226. BOOL CompactDatabase()
  227. {
  228. // if(!theApp.CloseDB())
  229. // return FALSE;
  230. //
  231. // CString csDBName = GetDBName();
  232. // CString csTempDBName = csDBName;
  233. // csTempDBName.Replace(".mdb", "TempDBName.mdb");
  234. //
  235. // //Compact the database
  236. // try
  237. // {
  238. // CDaoWorkspace::CompactDatabase(csDBName, csTempDBName);//, dbLangGeneral, 0, "andrew");//DATABASE_PASSWORD);
  239. // }
  240. // catch(CDaoException* e)
  241. // {
  242. // AfxMessageBox(e->m_pErrorInfo->m_strDescription);
  243. // DeleteFile(csTempDBName);
  244. // e->Delete();
  245. // return FALSE;
  246. // }
  247. // catch(CMemoryException* e)
  248. // {
  249. // AfxMessageBox("Memory Exception");
  250. // DeleteFile(csTempDBName);
  251. // e->Delete();
  252. // return FALSE;
  253. // }
  254. //
  255. // //Since compacting the database creates a new db delete the old one and replace it
  256. // //with the compacted db
  257. // if(DeleteFile(csDBName))
  258. // {
  259. // try
  260. // {
  261. // CFile::Rename(csTempDBName, csDBName);
  262. // }
  263. // catch(CFileException *e)
  264. // {
  265. // e->ReportError();
  266. // e->Delete();
  267. // return FALSE;
  268. // }
  269. // }
  270. // else
  271. // AfxMessageBox("Error Compacting Database");
  272. return TRUE;
  273. }
  274. BOOL RepairDatabase()
  275. {
  276. // if(!theApp.CloseDB())
  277. // return FALSE;
  278. // try
  279. // {
  280. // CDaoWorkspace::RepairDatabase(GetDBName());
  281. // }
  282. // catch(CDaoException *e)
  283. // {
  284. // AfxMessageBox(e->m_pErrorInfo->m_strDescription);
  285. // e->Delete();
  286. // return FALSE;
  287. // }
  288. return TRUE;
  289. }
  290. BOOL RemoveOldEntries()
  291. {
  292. try
  293. {
  294. if(CGetSetOptions::GetCheckForMaxEntries())
  295. {
  296. long lMax = CGetSetOptions::GetMaxEntries();
  297. if(lMax >= 0)
  298. {
  299. CClipIDs IDs;
  300. CppSQLite3Query q = theApp.m_db.execQueryEx(_T("SELECT lID, lShortCut, lDontAutoDelete FROM Main ORDER BY lDate DESC LIMIT -1 OFFSET %d"), lMax);
  301. while(q.eof() == false)
  302. {
  303. //Only delete entries that have no shortcut and don't have the flag set
  304. if(q.getIntField(_T("lShortCut")) == 0 && q.getIntField(_T("lDontAutoDelete")) == 0)
  305. IDs.Add(q.getIntField(_T("lID")));
  306. q.nextRow();
  307. }
  308. IDs.DeleteIDs();
  309. }
  310. }
  311. if(CGetSetOptions::GetCheckForExpiredEntries())
  312. {
  313. long lExpire = CGetSetOptions::GetExpiredEntries();
  314. if(lExpire)
  315. {
  316. CTime now = CTime::GetCurrentTime();
  317. now -= CTimeSpan(lExpire, 0, 0, 0);
  318. CClipIDs IDs;
  319. CppSQLite3Query q = theApp.m_db.execQueryEx(_T("SELECT lID FROM Main ")
  320. _T("WHERE lDate < %d AND ")
  321. _T("lShortCut = 0 AND lDontAutoDelete = 0"), now.GetTime());
  322. while(q.eof() == false)
  323. {
  324. IDs.Add(q.getIntField(_T("lID")));
  325. q.nextRow();
  326. }
  327. IDs.DeleteIDs();
  328. }
  329. }
  330. }
  331. CATCH_SQLITE_EXCEPTION
  332. return TRUE;
  333. }
  334. BOOL EnsureDirectory(CString csPath)
  335. {
  336. TCHAR drive[_MAX_DRIVE];
  337. TCHAR dir[_MAX_DIR];
  338. TCHAR fname[_MAX_FNAME];
  339. TCHAR ext[_MAX_EXT];
  340. SPLITPATH(csPath, drive, dir, fname, ext);
  341. CString csDir(drive);
  342. csDir += dir;
  343. if(FileExists(csDir) == FALSE)
  344. {
  345. if(CreateDirectory(csDir, NULL))
  346. return TRUE;
  347. }
  348. else
  349. return TRUE;
  350. return FALSE;
  351. }
  352. // BOOL RunZippApp(CString csCommandLine)
  353. // {
  354. // CString csLocalPath = GETENV(_T("U3_HOST_EXEC_PATH"));
  355. // FIX_CSTRING_PATH(csLocalPath);
  356. //
  357. // CString csZippApp = GETENV(_T("U3_DEVICE_EXEC_PATH"));
  358. // FIX_CSTRING_PATH(csZippApp);
  359. // csZippApp += "7za.exe";
  360. //
  361. // csZippApp += " ";
  362. // csZippApp += csCommandLine;
  363. //
  364. // Log(csZippApp);
  365. //
  366. // STARTUPINFO StartupInfo;
  367. // PROCESS_INFORMATION ProcessInformation;
  368. //
  369. // ZeroMemory(&StartupInfo, sizeof(StartupInfo));
  370. // StartupInfo.cb = sizeof(StartupInfo);
  371. // ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
  372. //
  373. // StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  374. // StartupInfo.wShowWindow = SW_HIDE;
  375. //
  376. // BOOL bRet = CreateProcess(NULL, csZippApp.GetBuffer(csZippApp.GetLength()), NULL, NULL, FALSE,
  377. // CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, csLocalPath,
  378. // &StartupInfo, &ProcessInformation);
  379. //
  380. // if(bRet)
  381. // {
  382. // WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
  383. //
  384. // DWORD dwExitCode;
  385. // GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
  386. //
  387. // CString cs;
  388. // cs.Format(_T("Exit code from unzip = %d"), dwExitCode);
  389. // Log(cs);
  390. //
  391. // if(dwExitCode != 0)
  392. // {
  393. // bRet = FALSE;
  394. // }
  395. // }
  396. // else
  397. // {
  398. // bRet = FALSE;
  399. // Log(_T("Create Process Failed"));
  400. // }
  401. //
  402. // csZippApp.ReleaseBuffer();
  403. //
  404. // return bRet;
  405. // }
  406. // BOOL CopyDownDatabase()
  407. // {
  408. // BOOL bRet = FALSE;
  409. //
  410. // CString csZippedPath = GETENV(_T("U3_APP_DATA_PATH"));
  411. // FIX_CSTRING_PATH(csZippedPath);
  412. //
  413. // CString csUnZippedPath = csZippedPath;
  414. // csUnZippedPath += "Ditto.db";
  415. //
  416. // csZippedPath += "Ditto.7z";
  417. //
  418. // CString csLocalPath = GETENV(_T("U3_HOST_EXEC_PATH"));
  419. // FIX_CSTRING_PATH(csLocalPath);
  420. //
  421. // if(FileExists(csZippedPath))
  422. // {
  423. // CString csCommandLine;
  424. //
  425. // //e = extract
  426. // //surround command line arguments with quotes
  427. // //-aoa = overight files with extracted files
  428. //
  429. // csCommandLine += "e ";
  430. // csCommandLine += "\"";
  431. // csCommandLine += csZippedPath;
  432. // csCommandLine += "\"";
  433. // csCommandLine += " -o";
  434. // csCommandLine += "\"";
  435. // csCommandLine += csLocalPath;
  436. // csCommandLine += "\"";
  437. // csCommandLine += " -aoa";
  438. //
  439. // bRet = RunZippApp(csCommandLine);
  440. //
  441. // csLocalPath += "Ditto.db";
  442. // }
  443. // else if(FileExists(csUnZippedPath))
  444. // {
  445. // csLocalPath += "Ditto.db";
  446. // bRet = CopyFile(csUnZippedPath, csLocalPath, FALSE);
  447. // }
  448. //
  449. // if(FileExists(csLocalPath) == FALSE)
  450. // {
  451. // Log(_T("Failed to copy files from device zip file"));
  452. // }
  453. //
  454. // g_Opt.nLastDbWriteTime = GetLastWriteTime(csLocalPath);
  455. //
  456. // return bRet;
  457. // }
  458. //BOOL CopyUpDatabase()
  459. //{
  460. // CStringA csZippedPath = "C:\\";//getenv("U3_APP_DATA_PATH");
  461. // FIX_CSTRING_PATH(csZippedPath);
  462. // csZippedPath += "Ditto.zip";
  463. // CStringA csLocalPath = GetDBName();//getenv("U3_HOST_EXEC_PATH");
  464. // //FIX_CSTRING_PATH(csLocalPath);
  465. // //csLocalPath += "Ditto.db";
  466. //
  467. // CZipper Zip;
  468. //
  469. // if(Zip.OpenZip(csZippedPath))
  470. // {
  471. // Zip.AddFileToZip(csLocalPath);
  472. // }
  473. //
  474. // return TRUE;
  475. //}