DatabaseUtilities.cpp 13 KB

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