CategoryFileDB.cpp
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:22k
源码类别:

P2P编程

开发平台:

Visual C++

  1. // CategoryFileDB.cpp: implementation of the CCategoryFileDB class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "testbt.h"
  6. #include "CategoryFileDB.h"
  7. #include "BTFormat.h"
  8. #include "FileBase.h"
  9. #include "val.h"
  10. #include "FileDB.h"
  11. #include "download.h"
  12. #include "SetupRegister.h"
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char THIS_FILE[]=__FILE__;
  16. #define new DEBUG_NEW
  17. #endif
  18. #define LOLONG(x) ((ULONG) x)
  19. #define HILONG(x) ((ULONG) (x / 0x100000000))
  20. #define MAKELONG64(x, y)((_int64) x * 0x100000000 | (ULONG)y)
  21. string m_strDBFileSection = "Database";
  22. string m_strDBFileKey = "path";
  23. //////////////////////////////////////////////////////////////////////
  24. // Construction/Destruction
  25. //////////////////////////////////////////////////////////////////////
  26. CCategoryFileDB::CCategoryFileDB()
  27. {
  28. m_bNoNotifications = false;
  29. m_lDirectoryIDMax = 0;
  30. m_pSetupRegister = 0;
  31. m_bModified = false;
  32. }
  33. CCategoryFileDB::~CCategoryFileDB()
  34. {
  35. }
  36. BOOL CCategoryFileDB::CreateEx(CWnd *pParent, CRect &rc, long lParam, CSetupRegister* pSetupRegister)
  37. {
  38. m_pSetupRegister = pSetupRegister;
  39. // SetDBSavePath(m_pSetupRegister);
  40. return Create(WS_VISIBLE|WS_CHILD|WS_BORDER|TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES|TVS_SHOWSELALWAYS, 
  41. rc, pParent, 32563215);
  42. }
  43. void CCategoryFileDB::DeleteAllData(CTreeCursor& curDel) 
  44. {
  45. assert(false);
  46. }
  47. CSetupRegister* CCategoryFileDB::GetSetupRegister() const
  48. {
  49. assert(m_pSetupRegister);
  50. return m_pSetupRegister;
  51. }
  52. /*
  53. bool CCategoryFileDB::IsLinkFileDBItem(CTreeCursor curItem, CFileDBItem* pFileDBItem)
  54. {
  55. if (curItem != m_curDownloading)
  56. return false;
  57. CCategoryDBItem* pCategoryDBItem = (CCategoryDBItem*)m_curDownloading.GetData();
  58. if (pCategoryDBItem->m_lDirectoryID == pFileDBItem->m_lDirectoryID)
  59. return false;
  60. return true;
  61. }
  62. //*/
  63. ////////////////////////////////////////////////////////////////////////
  64. // file manipulate.
  65. bool CCategoryFileDB::OpenDBFile(string strDatabasePath)
  66. {
  67. if (strDatabasePath.empty())
  68. return false;
  69. // assert(!m_bModified);
  70. m_bModified = false;
  71. // clear data loaded from db file
  72. DeleteAllData(GetRootItem());
  73. GetRootItem().Delete();
  74. m_curRoot = m_curDownloading = m_curDownloaded = m_curRecycle = CTreeCursor();
  75. if (!LoadDatabase(strDatabasePath))
  76. {
  77. AfxMessageBox(CString("load db file(") + strDatabasePath.data() + ")error" );
  78. NewDatabase();
  79. return false;
  80. }
  81. GetRootItem().Select();
  82. AfxGetApp()->WriteProfileString(m_strDBFileSection.data(), m_strDBFileKey.data(), strDatabasePath.data());
  83. m_strDatabaseFileName = strDatabasePath;
  84. return false;
  85. }
  86. void CCategoryFileDB::LoadDBFile()
  87. {
  88. CString strDatabasePath = AfxGetApp()->GetProfileString(m_strDBFileSection.data(), m_strDBFileKey.data());
  89. if (!strDatabasePath.IsEmpty())
  90. {
  91. if (LoadDatabase(strDatabasePath.GetBuffer(0)))
  92. {
  93. m_strDatabaseFileName = strDatabasePath;
  94. return;
  95. }
  96. else
  97. {
  98. AfxMessageBox(CString("load db file(") + strDatabasePath + ")error");
  99. }
  100. }
  101. // load default database left by the uninstalled, create new database, register it.
  102. strDatabasePath = GetDefaultDatabasePath().data();
  103. if (!LoadDatabase(strDatabasePath.GetBuffer(0)))
  104. {
  105. NewDatabase();
  106. SaveDatabase(strDatabasePath.GetBuffer(0));
  107. }
  108. AfxGetApp()->WriteProfileString(m_strDBFileSection.data(), m_strDBFileKey.data(), strDatabasePath);
  109. m_strDatabaseFileName = strDatabasePath;
  110. }
  111. void CCategoryFileDB::NewDatabase()
  112. {
  113. m_bModified = true;
  114. // clear data loaded from db file
  115. DeleteAllData(GetRootItem());
  116. GetRootItem().Delete();
  117. m_curRoot = m_curDownloading = m_curDownloaded = m_curRecycle = CTreeCursor();
  118. // create default dir.
  119. m_lDirectoryIDMax = 0;
  120. m_curRoot = GetRootItem().AddTail("根目录", IID_ROOT);
  121. m_curRoot.SetData((long) new CCategoryDBItem("c:\download", m_lDirectoryIDMax++));
  122. m_curDownloading = m_curRoot.AddTail("未完成任务", IID_DOWNLOADING_DIRECTORY);
  123. m_curDownloading.SetData((long) new CCategoryDBItem("c:\download\downloading", m_lDirectoryIDMax++));
  124. m_curDownloaded = m_curRoot.AddTail("下载保存目录", IID_DOWNLOADED_DIRECTORY);
  125. m_curDownloaded.SetData((long) new CCategoryDBItem("c:\download\downloaded", m_lDirectoryIDMax++));
  126. CTreeCursor curMusic = m_curDownloaded.AddTail("音乐", IID_DIRECTORY);
  127. curMusic.SetData((long) new CCategoryDBItem("c:\download\downloaded\music", m_lDirectoryIDMax++));
  128. CTreeCursor cuMovie = m_curDownloaded.AddTail("影视", IID_DIRECTORY);
  129. cuMovie.SetData((long) new CCategoryDBItem("c:\download\downloaded\Movie", m_lDirectoryIDMax++));
  130. CTreeCursor cuSoftware = m_curDownloaded.AddTail("软件", IID_DIRECTORY);
  131. cuSoftware.SetData((long) new CCategoryDBItem("c:\download\downloaded\SoftWare", m_lDirectoryIDMax++));
  132. m_curRecycle = m_curRoot.AddTail("回收站", IID_RECYCLE);
  133. m_curRecycle.SetData((long) new CCategoryDBItem("c:\download\recycle", m_lDirectoryIDMax++));
  134. assert(m_curRoot == GetRootItem() != 0);
  135. // m_strDatabaseFileName = "Untitled";
  136. }
  137. void CCategoryFileDB::SaveAs(string strDatabasePath)
  138. {
  139. if (strDatabasePath.empty())
  140. {
  141. assert(false);
  142. return;
  143. }
  144. if (m_strDatabaseFileName == strDatabasePath)
  145. return;
  146. string strOldTorrentDir = _GetDBSavePath(m_strDatabaseFileName),
  147. strNewTorrentDir = _GetDBSavePath(strDatabasePath);
  148. SaveDatabase(strDatabasePath);
  149. AfxGetApp()->WriteProfileString(m_strDBFileSection.data(), m_strDBFileKey.data(), strDatabasePath.data());
  150. m_strDatabaseFileName = strDatabasePath;
  151. DWORD dwAttr = GetFileAttributes(strNewTorrentDir.data());
  152. if (dwAttr == 0xffffffff )
  153. {
  154. if (!MakeDirecotry(strNewTorrentDir))
  155. {
  156. AfxMessageBox(CString("can't create direcotry (") + strNewTorrentDir.data() + ")" );
  157. return ;
  158. }
  159. }
  160. else if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
  161. {
  162. AfxMessageBox(CString("can't create direcotry (") + strNewTorrentDir.data() + ")" );
  163. return ;
  164. }
  165. if (strOldTorrentDir != strNewTorrentDir)
  166. {
  167. if (!MoveDiretory(strOldTorrentDir, strNewTorrentDir))
  168. {
  169. AfxMessageBox(CString("move from (") + strOldTorrentDir.data() + ") to (" + strNewTorrentDir.data() + ") error." );
  170. return ;
  171. }
  172. }
  173. }
  174. void CCategoryFileDB::Save()
  175. {
  176. if (m_bModified)
  177. {
  178. assert(false);
  179. return;
  180. }
  181. CString strDatabasePath = AfxGetApp()->GetProfileString(m_strDBFileSection.data(), m_strDBFileKey.data());
  182. if (strDatabasePath.IsEmpty())
  183. {
  184. assert(false);
  185. return;
  186. }
  187. SaveDatabase(strDatabasePath.GetBuffer(0));
  188. }
  189. bool CCategoryFileDB::IsModifyed()
  190. {
  191. return m_bModified;
  192. }
  193. void CCategoryFileDB::SetModifed(bool bModified)
  194. {
  195. m_bModified = bModified;
  196. }
  197. string CCategoryFileDB::GetDBSavePath() const
  198. {
  199. if (m_strDatabaseFileName.empty())
  200. {
  201. assert(false);
  202. }
  203. string strSavePath = _GetDBSavePath(m_strDatabaseFileName);
  204. return strSavePath;
  205. /*
  206. string strName;
  207. string strSavePath;
  208. bool bRet = SplitPathName(m_strDatabaseFileName, strSavePath, strName);
  209. assert(bRet && strSavePath.empty());
  210. strSavePath = formatDir(strSavePath) + "Torrent Files\";
  211. return strSavePath;
  212. //*/
  213. }
  214. string CCategoryFileDB::_GetDBSavePath(const string strDatabaseFileName) const
  215. {
  216. string strName;
  217. string strSavePath;
  218. bool bRet = SplitPathName(strDatabaseFileName, strSavePath, strName);
  219. assert(bRet && !strSavePath.empty());
  220. strSavePath = formatDir(strSavePath) + "Torrent Files\";
  221. return strSavePath;
  222. }
  223. string CCategoryFileDB::GetDatabaseFullPath()
  224. {
  225. return m_strDatabaseFileName;
  226. }
  227. string CCategoryFileDB::GetDatabaseName()
  228. {
  229. if (IsModifyed())
  230. return "无标题";
  231. string strName;
  232. string strSavePath;
  233. SplitPathName(m_strDatabaseFileName, strSavePath, strName);
  234. if (strName.empty())
  235. strName = "无标题";
  236. return strName;
  237. }
  238. string CCategoryFileDB::GetDefaultDatabasePath()
  239. {
  240. // get the directory in which the exe file exist.
  241. char szModuleFileName[1024] = {0};
  242. if (!GetModuleFileName(AfxGetApp()->m_hInstance, szModuleFileName, 1024))
  243. {
  244. assert(false);
  245. return "";
  246. }
  247. char path_buffer[_MAX_PATH];
  248. char drive[_MAX_DRIVE];
  249. char dir[_MAX_DIR];
  250. char fname[_MAX_FNAME];
  251. char ext[_MAX_EXT];
  252. _splitpath(szModuleFileName, drive, dir, fname, ext );
  253. _makepath(path_buffer, drive, dir, 0, 0);
  254. string strDatabasePath = path_buffer;
  255. if (strDatabasePath.size() <= 0)
  256. {
  257. assert(false);
  258. return "";
  259. }
  260. if (strDatabasePath[strDatabasePath.size() - 1] != '\')
  261. strDatabasePath+= '\';
  262. strDatabasePath += "default.bt";
  263. return strDatabasePath;
  264. }
  265. ////////////////////////////////////////////////////////////////////////
  266. // file db save.
  267. void CCategoryFileDB::SaveDatabase(string strDatabasePath)
  268. {
  269. m_bModified = false;
  270. try
  271. {
  272. CVal* pRet = bencode_rec(m_curRoot);
  273. if (!pRet) 
  274. {
  275. AfxMessageBox("encode tree data error");
  276. return;
  277. }
  278. auto_ptr<CVal> aRet(pRet);
  279. CFileDB::WriteFileEx(strDatabasePath, pRet);
  280. }
  281. catch (string e)
  282. {
  283. AfxMessageBox((string("SaveDatabase error : ") + e).data());
  284. }
  285. }
  286. CVal* CCategoryFileDB::bencode_FileDBItems(vector<CFileDBItem*>& vFileDbItems)
  287. {
  288. // format data
  289. PVALLIST pFileList = new VALLIST();
  290. for (int i=0; i<vFileDbItems.size(); i++)
  291. {
  292. CFileDBItem* pItem = vFileDbItems[i];
  293. PVALMAP pFileInfoMap = new VALMAP();
  294. (*pFileInfoMap)["TFileName"] = new CVal(pItem->m_strTorrentFileName);
  295. (*pFileInfoMap)["filename"] = new CVal(pItem->m_strFileName);
  296. (*pFileInfoMap)["complete"] = new CVal((long)(((float)pItem->m_fComplete)*100));
  297. (*pFileInfoMap)["time"] = new CVal(pItem->m_tTime);
  298. (*pFileInfoMap)["infohash"] = new CVal(pItem->m_strHash);
  299. (*pFileInfoMap)["dirid"] = new CVal(pItem->m_lDirectoryID);
  300. (*pFileInfoMap)["ModifiedTime"] = new CVal(pItem->m_tModifiedTime);
  301. (*pFileInfoMap)["PieceCount"] = new CVal(pItem->m_lPieceCount);
  302. (*pFileInfoMap)["special"] = new CVal(pItem->m_bSpecialRunParameter ? 1L : 0L);
  303. (*pFileInfoMap)["SpeedMode"] = new CVal(pItem->m_lUploadSpeedMode);
  304. (*pFileInfoMap)["UpMaxSpeed"] = new CVal(pItem->m_lUploadSpeedMax);
  305. (*pFileInfoMap)["UpMaxpeers"] = new CVal(pItem->m_lUploadPeerMax);
  306. (*pFileInfoMap)["fc"] = new CVal((long)(((float)pItem->m_fCompletePart)*100));
  307. (*pFileInfoMap)["kpHour"] = new CVal(pItem->m_lCompleteKeepSeedHour);
  308. (*pFileInfoMap)["PeersMin"] = new CVal(pItem->m_lPeersMin);
  309. (*pFileInfoMap)["PeersMax"] = new CVal(pItem->m_lPeersMax);
  310. (*pFileInfoMap)["errMax"] = new CVal(pItem->m_lConnectErrorMax);
  311. (*pFileInfoMap)["ConIntval"] = new CVal(pItem->m_lConnectIntval);
  312. //
  313. // file size.
  314. //
  315. ASSERT(pItem->m_lFileSize >= 0);
  316. (*pFileInfoMap)["size"] = new CVal(LOLONG(pItem->m_lFileSize));
  317. if (HILONG(pItem->m_lFileSize))
  318. (*pFileInfoMap)["sizeh"] = new CVal(HILONG(pItem->m_lFileSize));
  319. if (!pItem->m_strComment.empty())
  320. (*pFileInfoMap)["comment"] = new CVal(pItem->m_strComment);
  321. // UnneededFiles.
  322. if (!pItem->m_vUnneededFileInx.empty())
  323. (*pFileInfoMap)["UnNeed"] = bencode_UnNeededFiles(pItem->m_vUnneededFileInx);
  324. // mark the unclosed.
  325. if (pItem->m_bUnclosed)// && pItem->m_pDownload->IsDownloading())
  326. (*pFileInfoMap)["Unclosed"] = new CVal(1);
  327. memstream memBuf;
  328. pItem->GetHave(memBuf);
  329. if (memBuf.size())
  330. {
  331. (*pFileInfoMap)["haves"] = new CVal(memBuf, memBuf.size());
  332. }
  333. pFileList->push_back(new CVal(pFileInfoMap));
  334. }
  335. CVal* pVal = new CVal(pFileList);
  336. return pVal;
  337. }
  338. CVal* CCategoryFileDB::bencode_UnNeededFiles(vector<CSize>& vUnNeededFiles)
  339. {
  340. // format data
  341. PVALLIST pFileList = new VALLIST();
  342. for (int i=0; i<vUnNeededFiles.size(); i++)
  343. {
  344. CSize sizeUnNeedFile = vUnNeededFiles[i];
  345. PVALMAP pFileInfoMap = new VALMAP();
  346. (*pFileInfoMap)["x"] = new CVal(sizeUnNeedFile.cx);
  347. (*pFileInfoMap)["y"] = new CVal(sizeUnNeedFile.cy);
  348. pFileList->push_back(new CVal(pFileInfoMap));
  349. }
  350. CVal* pVal = new CVal(pFileList);
  351. return pVal;
  352. }
  353. CVal* CCategoryFileDB::bencode_rec(CTreeCursor& curItem)
  354. {
  355. if (!curItem)
  356. {
  357. assert(curItem);
  358. return 0;
  359. }
  360. PVALLIST pChildList = new VALLIST();
  361. if (curItem.HasChildren())
  362. {
  363. CTreeCursor curChild = curItem.GetChild();
  364. while (curChild)
  365. {
  366. CVal* pRet = bencode_rec(curChild);
  367. pChildList->push_back(pRet);
  368. curChild = curChild.GetNext(TVGN_NEXT);
  369. }
  370. }
  371. CCategoryDBItem* pItem = (CCategoryDBItem*)curItem.GetData();
  372. PVALMAP pDirInfoMap = new VALMAP();
  373. (*pDirInfoMap)["dirname"] = new CVal(string(curItem.GetText()));
  374. (*pDirInfoMap)["directory"] = new CVal(pItem->m_strDefaultDirectory);
  375. (*pDirInfoMap)["childlist"] = new CVal(pChildList);
  376. (*pDirInfoMap)["type"] = new CVal((long)curItem.GetImageID());
  377. (*pDirInfoMap)["id"] = new CVal(pItem->m_lDirectoryID);
  378. (*pDirInfoMap)["filedbitems"] = bencode_FileDBItems(pItem->m_vFileDBItems);
  379. CVal* pRetVal = new CVal(pDirInfoMap);
  380. return pRetVal;
  381. }
  382. ////////////////////////////////////////////////////////////////////////
  383. // file db load.
  384. bool CCategoryFileDB::LoadDatabase(string strDatabasePath)
  385. {
  386. m_bNoNotifications = true;
  387. string strErr;
  388. bool bRet = true;
  389. try
  390. {
  391. CVal* pVal = CFileDB::OpenFileEx(strDatabasePath);
  392. auto_ptr<CVal> aVal(pVal);
  393. if (pVal && bdencode_rec(pVal, GetRootItem()))
  394. bRet = true;
  395. else 
  396. {
  397. m_bNoNotifications = false;
  398. return false;
  399. }
  400. /*
  401. if (!LoadGenerateLinks())
  402. bRet = false;
  403. //*/
  404. m_bNoNotifications = false;
  405. }
  406. catch (string e)
  407. {
  408. strErr = e;
  409. bRet = false;
  410. m_bNoNotifications = false;
  411. }
  412. if (!bRet || !m_curRoot || !m_curDownloading || !m_curDownloaded || !m_curRecycle)
  413. {
  414. m_bNoNotifications = true;
  415. DeleteAllData(GetRootItem());
  416. GetRootItem().Delete();
  417. m_curRoot = m_curDownloading = m_curDownloaded = m_curRecycle = CTreeCursor();
  418. m_bNoNotifications = false;
  419. return false;
  420. }
  421. return true;
  422. }
  423. bool CCategoryFileDB::bdencode_FileDBItems(CVal* pVal, vector<CFileDBItem*>& vFileDbItems, HTREEITEM hTreeItem)
  424. {
  425. if (pVal->vt != VT_PLIST)
  426. return false;
  427. VALLIST& FileList = *(pVal->plistVal);
  428. for (int i=0; i<FileList.size(); i++)
  429. {
  430. if (FileList[i]->vt != VT_PMAP)
  431. return false;
  432. PVALMAP pFileInfoMap = FileList[i]->pmapVal; 
  433. if (!HasKey(pFileInfoMap, "TFileName") ||
  434. !HasKey(pFileInfoMap, "filename") || 
  435. !HasKey(pFileInfoMap, "size") ||
  436. !HasKey(pFileInfoMap, "complete") ||
  437. !HasKey(pFileInfoMap, "time") ||
  438. !HasKey(pFileInfoMap, "infohash") ||
  439. !HasKey(pFileInfoMap, "dirid") ||
  440. !HasKey(pFileInfoMap, "ModifiedTime") ||
  441. !HasKey(pFileInfoMap, "PieceCount") 
  442. )
  443. return false;
  444. //
  445. // filesize.
  446. //
  447. long lFileSizeLow = (*pFileInfoMap)["size"]->lVal;
  448. long lFileSizeHigh = 0;
  449. if (HasKey(pFileInfoMap, "sizeh"))
  450. lFileSizeHigh = (*pFileInfoMap)["sizeh"]->lVal;
  451. BLONG lFileSize = MAKELONG64(lFileSizeHigh, lFileSizeLow);
  452. //
  453. // comment
  454. //
  455. string strComment;
  456. if (HasKey(pFileInfoMap, "comment"))
  457. {
  458. strComment = (*pFileInfoMap)["comment"]->pstrVal;
  459. }
  460. CFileDBItem * pFileDBItem = new CFileDBItem((*pFileInfoMap)["TFileName"]->pstrVal, 
  461. (*pFileInfoMap)["filename"]->pstrVal,
  462. lFileSize,
  463. ((float)(*pFileInfoMap)["complete"]->lVal)/100,
  464. (*pFileInfoMap)["time"]->lVal,
  465. (*pFileInfoMap)["infohash"]->pstrVal,
  466. (*pFileInfoMap)["dirid"]->lVal,
  467. (*pFileInfoMap)["ModifiedTime"]->lVal,
  468. (*pFileInfoMap)["PieceCount"]->lVal,
  469. strComment);
  470. if (HasKey(pFileInfoMap, "special") &&
  471. HasKey(pFileInfoMap, "SpeedMode") &&
  472. HasKey(pFileInfoMap, "UpMaxSpeed") &&
  473. HasKey(pFileInfoMap, "UpMaxpeers"))
  474. {
  475. pFileDBItem->m_bSpecialRunParameter = (*pFileInfoMap)["special"]->lVal > 0;
  476. pFileDBItem->m_lUploadSpeedMode = (*pFileInfoMap)["SpeedMode"]->lVal;
  477. pFileDBItem->m_lUploadSpeedMax = (*pFileInfoMap)["UpMaxSpeed"]->lVal;
  478. pFileDBItem->m_lUploadPeerMax = (*pFileInfoMap)["UpMaxpeers"]->lVal;
  479. if (
  480. !HasKey(pFileInfoMap, "kpHour") ||
  481. !HasKey(pFileInfoMap, "PeersMin") ||
  482. !HasKey(pFileInfoMap, "PeersMax") ||
  483. !HasKey(pFileInfoMap, "errMax") ||
  484. !HasKey(pFileInfoMap, "ConIntval")
  485. )
  486. {
  487. return false;
  488. }
  489. pFileDBItem->m_lCompleteKeepSeedHour = (*pFileInfoMap)["kpHour"]->lVal;
  490. pFileDBItem->m_lPeersMin = (*pFileInfoMap)["PeersMin"]->lVal;
  491. pFileDBItem->m_lPeersMax = (*pFileInfoMap)["PeersMax"]->lVal;
  492. pFileDBItem->m_lConnectErrorMax = (*pFileInfoMap)["errMax"]->lVal;
  493. pFileDBItem->m_lConnectIntval = (*pFileInfoMap)["ConIntval"]->lVal;
  494. }
  495. // UnNeedFiles.
  496. if (HasKey(pFileInfoMap, "UnNeed"))
  497. {
  498. if (!bdencode_UnNeedFiles((*pFileInfoMap)["UnNeed"], pFileDBItem->m_vUnneededFileInx))
  499. return false;
  500. }
  501. if (HasKey(pFileInfoMap, "fc"))
  502. pFileDBItem->m_fCompletePart = ((float)(*pFileInfoMap)["fc"]->lVal)/100;
  503. if (HasKey(pFileInfoMap, "haves"))
  504. {
  505. assert((pFileDBItem->m_fComplete < 1) || pFileDBItem->m_fComplete != 0);
  506. memstream memBuf;
  507. memBuf.write((*pFileInfoMap)["haves"]->pstrVal, (*pFileInfoMap)["haves"]->lstrLen);
  508. pFileDBItem->SetHave(memBuf);
  509. }
  510. // mark the unclosed.
  511. if (HasKey(pFileInfoMap, "Unclosed"))
  512. m_vUncloseds.push_back(CUnclosed(pFileDBItem, hTreeItem));
  513. vFileDbItems.push_back(pFileDBItem);
  514. }
  515. return true;
  516. }
  517. bool CCategoryFileDB::bdencode_UnNeedFiles(CVal* pVal, vector<CSize>& vFileDbItems)
  518. {
  519. if (pVal->vt != VT_PLIST)
  520. return false;
  521. VALLIST& FileList = *(pVal->plistVal);
  522. for (int i=0; i<FileList.size(); i++)
  523. {
  524. if (FileList[i]->vt != VT_PMAP)
  525. return false;
  526. PVALMAP pFileInfoMap = FileList[i]->pmapVal; 
  527. if (!HasKey(pFileInfoMap, "x") || !HasKey(pFileInfoMap, "y"))
  528. return false;
  529. CSize size((*pFileInfoMap)["x"]->lVal, (*pFileInfoMap)["y"]->lVal);
  530. vFileDbItems.push_back(size);
  531. }
  532. return true;
  533. }
  534. bool CCategoryFileDB::bdencode_rec(CVal* pVal, CTreeCursor& curItem)
  535. {
  536. // check type.
  537. if (pVal->vt != VT_PMAP)
  538. return false;
  539. if (!HasKey(pVal->pmapVal, "dirname") ||
  540. !HasKey(pVal->pmapVal, "directory") || 
  541. !HasKey(pVal->pmapVal, "childlist") ||
  542. !HasKey(pVal->pmapVal, "type") ||
  543. !HasKey(pVal->pmapVal, "filedbitems")||
  544. !HasKey(pVal->pmapVal, "id"))
  545. return false;
  546. if ((*pVal)["dirname"]->vt != VT_PSTR || 
  547. (*pVal)["directory"]->vt != VT_PSTR ||
  548. (*pVal)["childlist"]->vt != VT_PLIST ||
  549. (*pVal)["type"]->vt != VT_LONG ||
  550. (*pVal)["filedbitems"]->vt != VT_PLIST ||
  551. (*pVal)["id"]->vt != VT_LONG)
  552. return false;
  553. // ltype is imageid, default item has identity imageid, others must be IID_DIRECTORY.
  554. long lType = (*pVal)["type"]->lVal;
  555. assert(lType >= IID_ROOT && lType <= IID_DIRECTORY);
  556. long lDirectoryId = (*pVal)["id"]->lVal;
  557. if (lDirectoryId >= m_lDirectoryIDMax)
  558. m_lDirectoryIDMax = lDirectoryId + 1;
  559. // fill the data.***
  560. CTreeCursor curNew = curItem.AddTail((*pVal)["dirname"]->pstrVal, lType);
  561. CCategoryDBItem* pDBItem = new CCategoryDBItem((*pVal)["directory"]->pstrVal, lDirectoryId);
  562. curNew.SetData((long)pDBItem);
  563. if (!bdencode_FileDBItems((*pVal)["filedbitems"], pDBItem->m_vFileDBItems, curNew))
  564. return false;
  565. // check whether the default items exist, if not the db file corrupted.
  566. switch (lType)
  567. {
  568. case IID_ROOT:
  569. if (m_curRoot)
  570. return false;
  571. else
  572. {
  573. m_curRoot = curNew;
  574. m_curRoot.SetText("根目录");
  575. }
  576. break;
  577. case IID_DOWNLOADED_DIRECTORY:
  578. if (m_curDownloaded)
  579. return false;
  580. else
  581. {
  582. m_curDownloaded = curNew;
  583. m_curDownloaded.SetText("下载保存目录");
  584. }
  585. break;
  586. case IID_DOWNLOADING_DIRECTORY:
  587. if (m_curDownloading)
  588. return false;
  589. else
  590. {
  591. m_curDownloading = curNew;
  592. m_curDownloading.SetText("未完成任务");
  593. }
  594. break;
  595. case IID_RECYCLE:
  596. if (m_curRecycle)
  597. return false;
  598. else
  599. {
  600. m_curRecycle = curNew;
  601. m_curRecycle.SetText("回收站");
  602. }
  603. break;
  604. case IID_DIRECTORY:
  605. break;
  606. default:
  607. return false;
  608. break;
  609. }
  610. // recurse into childs.
  611. VALLIST& ChildList = *(*pVal)["childlist"]->plistVal;
  612. for (int i=0; i<ChildList.size(); i++)
  613. {
  614. if (!bdencode_rec(ChildList[i], curNew))
  615. return false;
  616. }
  617. return true;
  618. }
  619. /*
  620. CFileDBItem* CCategoryFileDB::GetLinkTrueFileDBItem(CFileDBItem* pLinkFileDBItem)
  621. {
  622. CTreeCursor curTrueCategory = findCursorByDirid(pLinkFileDBItem->m_lDirectoryID);
  623. CCategoryDBItem* pTrueCategory = (CCategoryDBItem*)curTrueCategory.GetData();
  624. assert(curTrueCategory && pTrueCategory);
  625. for (int i=0; i<pTrueCategory->m_vFileDBItems.size(); i++)
  626. {
  627. if (pTrueCategory->m_vFileDBItems[i]->m_strHash == pLinkFileDBItem->m_strHash)
  628. {
  629. return pTrueCategory->m_vFileDBItems[i];
  630. }
  631. }
  632. return 0;
  633. }
  634. bool CCategoryFileDB::LoadGenerateLinks()
  635. {
  636. CCategoryDBItem* pItem = (CCategoryDBItem*)m_curDownloading.GetData();
  637. assert(pItem && m_curDownloading);
  638. bool bRet = true;
  639. for (int i=0; i<pItem->m_vFileDBItems.size(); i++)
  640. {
  641. if (IsLinkFileDBItem(m_curDownloading, pItem->m_vFileDBItems[i]))
  642. {
  643. // get true FileDBItem.can't return. continue release mem. otherwise destroy wnd not release the mem.
  644. assert(!pItem->m_vFileDBItems[i]->m_pDownload);
  645. CFileDBItem* pTrueFileDBItem = GetLinkTrueFileDBItem(pItem->m_vFileDBItems[i]);
  646. if (!pTrueFileDBItem)
  647. {
  648. assert(pTrueFileDBItem);
  649. bRet = false;
  650. }
  651. delete pItem->m_vFileDBItems[i];
  652. pItem->m_vFileDBItems[i] = pTrueFileDBItem;
  653. }
  654. }
  655. return bRet;
  656. }
  657. //*/
  658. CTreeCursor CCategoryFileDB::findCursorByDirid(long lDirectoryID)
  659. {
  660. return findCursorByDiridRec(GetRootItem(), lDirectoryID);
  661. }
  662. CTreeCursor CCategoryFileDB::findCursorByDiridRec(CTreeCursor curItem, long lDirectoryID)
  663. {
  664. CCategoryDBItem* pItem = (CCategoryDBItem*)curItem.GetData();
  665. if (pItem->m_lDirectoryID == lDirectoryID)
  666. return curItem;
  667. if (curItem.HasChildren())
  668. {
  669. CTreeCursor curChild = curItem.GetChild();
  670. while (curChild)
  671. {
  672. CTreeCursor curRet = findCursorByDiridRec(curChild, lDirectoryID);
  673. if (curRet) 
  674. {
  675. return curRet;
  676. }
  677. curChild = curChild.GetNext(TVGN_NEXT);
  678. }
  679. }
  680. return CTreeCursor(0, 0);
  681. }
  682. /*
  683. void CCategoryFileDB::SetDBSavePath(CSetupRegister* pSetupRegister)
  684. {
  685. assert(pSetupRegister);
  686. m_strDBSavePath = pSetupRegister->m_strTorrentDir;
  687. }
  688. string CCategoryFileDB::GetDBSavePath() const
  689. {
  690. assert(!m_strDBSavePath.empty());
  691. return formatDir(m_strDBSavePath);
  692. }
  693. //*/