icqdb.cpp
上传用户:zslianheng
上传日期:2013-04-03
资源大小:946k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Visual C++

  1. /***************************************************************************
  2.  *                                                                         *
  3.  *   This program is free software; you can redistribute it and/or modify  *
  4.  *   it under the terms of the GNU General Public License as published by  *
  5.  *   the Free Software Foundation; either version 2 of the License, or     *
  6.  *   (at your option) any later version.                                   *
  7.  *                                                                         *
  8.  *   copyright            : (C) 2002 by Zhang Yong                         *
  9.  *   email                : z-yong163@163.com                              *
  10.  ***************************************************************************/
  11. #include "icqdb.h"
  12. #include "icqclient.h"
  13. #define INDEX_USER 0
  14. #define INDEX_OPTIONS 0xffffffff
  15. #define INDEX_GROUP 0xfffffffe
  16. string IcqDB::dbDir;
  17. DBOutStream &DBOutStream::operator <<(uint8 b)
  18. {
  19. if (cursor <= data + MAX_BLOCK_SIZE - sizeof(b))
  20. *cursor++ = b;
  21. return (*this);
  22. }
  23. DBOutStream &DBOutStream::operator <<(uint16 w)
  24. {
  25. if (cursor <= data + MAX_BLOCK_SIZE - sizeof(w)) {
  26. *(uint16 *) cursor = w;
  27. cursor += sizeof(w);
  28. }
  29. return (*this);
  30. }
  31. DBOutStream &DBOutStream::operator <<(uint32 dw)
  32. {
  33. if (cursor <= data + MAX_BLOCK_SIZE - sizeof(dw)) {
  34. *(uint32 *) cursor = dw;
  35. cursor += sizeof(dw);
  36. }
  37. return (*this);
  38. }
  39. DBOutStream &DBOutStream::operator <<(const char *str)
  40. {
  41. uint16 len = strlen(str) + 1;
  42. if (cursor <= data + MAX_BLOCK_SIZE - sizeof(len) - len) {
  43. *this << len;
  44. memcpy(cursor, str, len);
  45. cursor += len;
  46. }
  47. return (*this);
  48. }
  49. DBOutStream &DBOutStream::operator <<(StrList &strList)
  50. {
  51. uint16 n = 0;
  52. char *old = cursor;
  53. cursor += sizeof(n);
  54. StrList::iterator i;
  55. for (i = strList.begin(); i != strList.end(); i++) {
  56. operator <<(*i);
  57. n++;
  58. }
  59. char *p = cursor;
  60. cursor = old;
  61. operator <<(n);
  62. cursor = p;
  63. return (*this);
  64. }
  65. DBInStream &DBInStream::operator >>(uint8 &b)
  66. {
  67. if (cursor <= data + datalen - sizeof(b))
  68. b = *cursor++;
  69. else
  70. b = 0;
  71. return (*this);
  72. }
  73. DBInStream &DBInStream::operator >>(uint16 &w)
  74. {
  75. if (cursor <= data + datalen - sizeof(w)) {
  76. w = *(uint16 *) cursor;
  77. cursor += sizeof(w);
  78. } else
  79. w = 0;
  80. return (*this);
  81. }
  82. DBInStream &DBInStream::operator >>(uint32 &dw)
  83. {
  84. if (cursor <= data + datalen - sizeof(dw)) {
  85. dw = *(uint32 *) cursor;
  86. cursor += sizeof(dw);
  87. } else
  88. dw = 0;
  89. return (*this);
  90. }
  91. DBInStream &DBInStream::operator >>(string &str)
  92. {
  93. uint16 len;
  94. operator >>(len);
  95. if (cursor <= data + datalen - len && !cursor[len - 1]) {
  96. str = cursor;
  97. cursor += len;
  98. } else
  99. str = "";
  100. return (*this);
  101. }
  102. DBInStream &DBInStream::operator >>(StrList &strList)
  103. {
  104. uint16 num;
  105. operator >>(num);
  106. int n = (int) num;
  107. strList.clear();
  108. while (n-- > 0) {
  109. string s;
  110. operator >>(s);
  111. strList.push_back(s);
  112. }
  113. return (*this);
  114. }
  115. static const char userFile[] = "user.db";
  116. static const char msgFile[] = "msg.db";
  117. static const char quickReplyFile[] = "quickreply.txt";
  118. static const char autoReplyFile[] = "autoreply.txt";
  119. DB *IcqDB::getDBFullPath(const char *pathName, bool dup)
  120. {
  121. DB *db;
  122. if (db_create(&db, NULL, 0) != 0)
  123. return NULL;
  124. if (dup && db->set_flags(db, DB_DUP) != 0) {
  125. db->close(db, 0);
  126. return NULL;
  127. }
  128. if (db->open(db, pathName, NULL, DB_HASH, DB_CREATE, 0600) != 0) {
  129. db->close(db, 0);
  130. return NULL;
  131. }
  132. return db;
  133. }
  134. bool IcqDB::saveBlock(DB *db, uint32 index, DBSerialize &obj)
  135. {
  136. DBOutStream out;
  137. obj.save(out);
  138. DBT key, data;
  139. memset(&key, 0, sizeof(key));
  140. memset(&data, 0, sizeof(data));
  141. key.data = &index;
  142. key.size = sizeof(index);
  143. data.data = out.getData();
  144. data.size = out.getSize();
  145. return (db->put(db, NULL, &key, &data, 0) == 0);
  146. }
  147. bool IcqDB::saveBlock(const char *fileName, uint32 index, DBSerialize &obj, bool dup)
  148. {
  149. DB *db = getDB(fileName, dup);
  150. if (!db)
  151. return false;
  152. int ret = saveBlock(db, index, obj);
  153. db->close(db, 0);
  154. return (ret == 0);
  155. }
  156. bool IcqDB::loadBlock(const char *fileName, uint32 index, DBSerialize &obj)
  157. {
  158. DB *db = getDB(fileName, false);
  159. if (!db)
  160. return false;
  161. DBT key, data;
  162. memset(&key, 0, sizeof(key));
  163. memset(&data, 0, sizeof(data));
  164. key.data = &index;
  165. key.size = sizeof(index);
  166. if (db->get(db, NULL, &key, &data, 0) != 0) {
  167. db->close(db, 0);
  168. return false;
  169. }
  170. DBInStream in(data.data, data.size);
  171. obj.load(in);
  172. db->close(db, 0);
  173. return true;
  174. }
  175. bool IcqDB::delIndex(const char *fileName, uint32 index)
  176. {
  177. DB *db = getDB(fileName);
  178. if (!db)
  179. return false;
  180. DBT key;
  181. memset(&key, 0, sizeof(key));
  182. key.data = &index;
  183. key.size = sizeof(index);
  184. int ret = db->del(db, NULL, &key, 0);
  185. db->close(db, 0);
  186. return (ret == 0);
  187. }
  188. bool IcqDB::saveMsg(IcqMsg &msg)
  189. {
  190. uint32 uin = (msg.isSysMsg() ? 0 : msg.uin);
  191. return saveBlock(msgFile, uin, msg, true);
  192. }
  193. bool IcqDB::delMsg(uint32 uin)
  194. {
  195. return delIndex(msgFile, uin);
  196. }
  197. bool IcqDB::delMsg(uint32 uin, int item)
  198. {
  199. DB *db = getDB(msgFile);
  200. if (!db)
  201. return false;
  202. DBC *cursor;
  203. if (db->cursor(db, NULL, &cursor, 0) != 0) {
  204. db->close(db, 0);
  205. return false;
  206. }
  207. DBT key, data;
  208. memset(&key, 0, sizeof(key));
  209. memset(&data, 0, sizeof(data));
  210. key.data = &uin;
  211. key.size = sizeof(uin);
  212. if (cursor->c_get(cursor, &key, &data, DB_SET) != 0) {
  213. db->close(db, 0);
  214. return false;
  215. }
  216. for (int i = 0; i < item; ++i) {
  217. if (cursor->c_get(cursor, &key, &data, DB_NEXT_DUP) != 0)
  218. break;
  219. }
  220. if (i < item) {
  221. cursor->c_close(cursor);
  222. db->close(db, 0);
  223. return false;
  224. }
  225. int ret = cursor->c_del(cursor, 0);
  226. cursor->c_close(cursor);
  227. db->close(db, 0);
  228. return (ret == 0);
  229. }
  230. bool IcqDB::loadMsg(uint32 uin, PtrList &msgList)
  231. {
  232. DB *db = getDB(msgFile, true);
  233. if (!db)
  234. return false;
  235. DBC *cursor;
  236. if (db->cursor(db, NULL, &cursor, 0) != 0) {
  237. db->close(db, 0);
  238. return false;
  239. }
  240. DBT key, data;
  241. memset(&key, 0, sizeof(key));
  242. memset(&data, 0, sizeof(data));
  243. key.data = &uin;
  244. key.size = sizeof(uin);
  245. if (cursor->c_get(cursor, &key, &data, DB_SET) != 0) {
  246. cursor->c_close(cursor);
  247. db->close(db, 0);
  248. return false;
  249. }
  250. do {
  251. DBInStream in(data.data, data.size);
  252. IcqMsg *msg = new IcqMsg;
  253. msg->load(in);
  254. msgList.push_back(msg);
  255. } while (cursor->c_get(cursor, &key, &data, DB_NEXT_DUP) == 0);
  256. cursor->c_close(cursor);
  257. db->close(db, 0);
  258. return true;
  259. }
  260. bool IcqDB::saveContact(IcqContact &c)
  261. {
  262. return saveBlock(userFile, c.uin, c, false);
  263. }
  264. bool IcqDB::loadContact(IcqContact &c)
  265. {
  266. return loadBlock(userFile, c.uin, c);
  267. }
  268. bool IcqDB::loadContact(PtrList &contactList)
  269. {
  270. DB *db = getDB(userFile);
  271. if (!db)
  272. return false;
  273. DBC *cursor;
  274. if (db->cursor(db, NULL, &cursor, 0) != 0) {
  275. db->close(db, 0);
  276. return false;
  277. }
  278. DBT key, data;
  279. memset(&key, 0, sizeof(key));
  280. memset(&data, 0, sizeof(data));
  281. while (cursor->c_get(cursor, &key, &data, DB_NEXT) == 0) {
  282. uint32 uin = *(uint32 *) key.data;
  283. if (uin > 0 && uin <= 0xfffffff0) {
  284. DBInStream in(data.data, data.size);
  285. IcqContact *c = new IcqContact;
  286. c->load(in);
  287. contactList.push_back(c);
  288. }
  289. }
  290. cursor->c_close(cursor);
  291. db->close(db, 0);
  292. return true;
  293. }
  294. bool IcqDB::delContact(uint32 uin)
  295. {
  296. return delIndex(userFile, uin);
  297. }
  298. bool IcqDB::saveUser(IcqUser &user)
  299. {
  300. return saveBlock(userFile, INDEX_USER, user, false);
  301. }
  302. bool IcqDB::loadUser(IcqUser &user)
  303. {
  304. return loadBlock(userFile, INDEX_USER, user);
  305. }
  306. bool IcqDB::saveOptions(IcqOption &options)
  307. {
  308. return saveBlock(userFile, INDEX_OPTIONS, options, false);
  309. }
  310. bool IcqDB::loadOptions(IcqOption &options)
  311. {
  312. return loadBlock(userFile, INDEX_OPTIONS, options);
  313. }
  314. bool IcqDB::saveGroupInfo(DBSerialize &obj)
  315. {
  316. return saveBlock(userFile, INDEX_GROUP, obj, false);
  317. }
  318. bool IcqDB::loadGroupInfo(DBSerialize &obj)
  319. {
  320. return loadBlock(userFile, INDEX_GROUP, obj);
  321. }
  322. bool IcqDB::exportMsg(const char *pathName, uint32 uin)
  323. {
  324. PtrList msgList;
  325. if (!loadMsg(uin, msgList))
  326. return false;
  327. DB *db = getDBFullPath(pathName, true);
  328. if (!db)
  329. return false;
  330. bool cont = true;
  331. while (!msgList.empty() && cont) {
  332. IcqMsg *msg = (IcqMsg *) msgList.front();
  333. msgList.pop_front();
  334. cont = saveBlock(db, uin, *msg);
  335. delete msg;
  336. }
  337. db->close(db, 0);
  338. return cont;
  339. }
  340. bool IcqDB::importRecord(const char *pathName)
  341. {
  342. bool ret = false;
  343. DB *db = getDBFullPath(pathName, true);
  344. DB *dbOut = getDB(msgFile, true);
  345. if (!db || !dbOut)
  346. goto import_exit;
  347. DBC *cursor;
  348. if (db->cursor(db, NULL, &cursor, 0) != 0)
  349. goto import_exit;
  350. DBT key, data;
  351. memset(&key, 0, sizeof(key));
  352. memset(&data, 0, sizeof(data));
  353. ret = true;
  354. while (cursor->c_get(cursor, &key, &data, DB_NEXT) == 0 && ret)
  355. ret = (dbOut->put(dbOut, NULL, &key, &data, 0) == 0);
  356. import_exit:
  357. if (db)
  358. db->close(db, 0);
  359. if (dbOut)
  360. dbOut->close(dbOut, 0);
  361. return ret;
  362. }
  363. bool IcqDB::saveConfig(const char *fileName, DBSerialize &obj)
  364. {
  365. string pathName = dbDir + fileName;
  366. FILE *file = fopen(pathName.c_str(), "wb");
  367. if (!file)
  368. return false;
  369. DBOutStream out;
  370. obj.save(out);
  371. fwrite(out.getData(), out.getSize(), 1, file);
  372. fclose(file);
  373. return true;
  374. }
  375. bool IcqDB::loadConfig(const char *fileName, DBSerialize &obj)
  376. {
  377. string pathName = dbDir + fileName;
  378. FILE *file = fopen(pathName.c_str(), "rb");
  379. if (!file)
  380. return false;
  381. char buf[4096];
  382. int n = fread(buf, 1, sizeof(buf), file);
  383. fclose(file);
  384. DBInStream in(buf, n);
  385. obj.load(in);
  386. return true;
  387. }
  388. bool IcqDB::getMsgUinList(UinList &uinList)
  389. {
  390. DB *db = getDB(msgFile, true);
  391. if (!db)
  392. return false;
  393. DBC *cursor;
  394. if (db->cursor(db, NULL, &cursor, 0) != 0) {
  395. db->close(db, 0);
  396. return false;
  397. }
  398. DBT key, data;
  399. memset(&key, 0, sizeof(key));
  400. memset(&data, 0, sizeof(data));
  401. while (cursor->c_get(cursor, &key, &data, DB_NEXT_NODUP) == 0)
  402. uinList.push_back(*(uint32 *) key.data);
  403. return true;
  404. }
  405. void IcqDB::loadStrList(const char *fileName, StrList &l)
  406. {
  407. string pathName = dbDir + fileName;
  408. FILE *file = fopen(pathName.c_str(), "r");
  409. if (file) {
  410. char line[128];
  411. while (fgets(line, sizeof(line), file)) {
  412. int len = strlen(line);
  413. if (len > 0) {
  414. if (line[len - 1] == 'n')
  415. line[len - 1] = '';
  416. l.push_back(line);
  417. }
  418. }
  419. fclose(file);
  420. }
  421. }
  422. void IcqDB::saveStrList(const char *fileName, StrList &l)
  423. {
  424. string pathName = dbDir + fileName;
  425. FILE *file = fopen(pathName.c_str(), "w");
  426. if (file) {
  427. StrList::iterator it;
  428. for (it = l.begin(); it != l.end(); ++it)
  429. fprintf(file, "%sn", (*it).c_str());
  430. fclose(file);
  431. }
  432. }
  433. void IcqDB::loadQuickReply(StrList &l) {
  434. loadStrList(quickReplyFile, l);
  435. }
  436. void IcqDB::saveQuickReply(StrList &l) {
  437. saveStrList(quickReplyFile, l);
  438. }
  439. void IcqDB::loadAutoReply(StrList &l) {
  440. loadStrList(autoReplyFile, l);
  441. }
  442. void IcqDB::saveAutoReply(StrList &l) {
  443. saveStrList(autoReplyFile, l);
  444. }