WXReader.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. using SQLite;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Documents;
  10. using System.Windows.Interop;
  11. using WechatPCMsgBakTool.Helpers;
  12. using WechatPCMsgBakTool.Model;
  13. namespace WechatPCMsgBakTool
  14. {
  15. public class WXReader
  16. {
  17. private DBInfo DecDBInfo;
  18. private Dictionary<string, SQLiteConnection> DBInfo = new Dictionary<string, SQLiteConnection>();
  19. public WXReader(DBInfo? info = null) {
  20. if (info == null)
  21. DecDBInfo = WechatDBHelper.GetDBInfo();
  22. else
  23. DecDBInfo = info;
  24. string[] dbFileList = Directory.GetFiles(Path.Combine(DecDBInfo.UserPath, "DecDB"));
  25. foreach (var item in dbFileList)
  26. {
  27. FileInfo fileInfo = new FileInfo(item);
  28. if (fileInfo.Extension != ".db")
  29. continue;
  30. SQLiteConnection con = new SQLiteConnection(item);
  31. string dbName = fileInfo.Name.Split('.')[0];
  32. DBInfo.Add(dbName, con);
  33. }
  34. }
  35. public List<WXSession>? GetWXSessions(string? name = null)
  36. {
  37. SQLiteConnection con = DBInfo["MicroMsg"];
  38. if (con == null)
  39. return null;
  40. string query = "select * from session";
  41. if(name != null)
  42. {
  43. query = "select * from session where strUsrName = ?";
  44. return con.Query<WXSession>(query, name);
  45. }
  46. return con.Query<WXSession>(query);
  47. }
  48. public List<WXContact>? GetUser(string? name = null)
  49. {
  50. SQLiteConnection con = DBInfo["MicroMsg"];
  51. if (con == null)
  52. return null;
  53. string query = "select * from contact";
  54. if (name != null)
  55. {
  56. query = "select * from contact where username = ? or alias = ?";
  57. return con.Query<WXContact>(query, name, name);
  58. }
  59. return con.Query<WXContact>(query);
  60. }
  61. public WXSessionAttachInfo? GetWXMsgAtc(WXMsg msg)
  62. {
  63. SQLiteConnection con = DBInfo["MultiSearchChatMsg"];
  64. if (con == null)
  65. return null;
  66. string query = "select * from SessionAttachInfo where msgId = ? order by attachsize desc";
  67. List<WXSessionAttachInfo> list = con.Query<WXSessionAttachInfo>(query, msg.MsgSvrID);
  68. if (list.Count != 0)
  69. return list[0];
  70. else
  71. return null;
  72. }
  73. public List<WXMsg> GetMsgs(string uid)
  74. {
  75. List<WXMsg> tmp = new List<WXMsg>();
  76. for(int i = 0; i <= DecDBInfo.MaxMsgDBCount; i++)
  77. {
  78. SQLiteConnection con = DBInfo["MSG" + i.ToString()];
  79. if (con == null)
  80. continue;
  81. string query = "select * from MSG where StrTalker=?";
  82. List<WXMsg> wXMsgs = con.Query<WXMsg>(query, uid);
  83. foreach(WXMsg w in wXMsgs)
  84. {
  85. tmp.Add(w);
  86. }
  87. }
  88. return tmp;
  89. }
  90. public string? GetVideo(WXMsg msg)
  91. {
  92. WXSessionAttachInfo? attachInfo = GetWXMsgAtc(msg);
  93. if (attachInfo == null)
  94. return null;
  95. string resBasePath = Path.Combine(DecDBInfo.ResPath, attachInfo.attachPath);
  96. if (!File.Exists(resBasePath))
  97. return null;
  98. string videoPath = Path.Combine(DecDBInfo.UserPath, msg.StrTalker, "Video");
  99. if (!Directory.Exists(videoPath))
  100. Directory.CreateDirectory(videoPath);
  101. FileInfo fileInfo = new FileInfo(resBasePath);
  102. string savePath = Path.Combine(videoPath, fileInfo.Name);
  103. if(!File.Exists(savePath))
  104. File.Copy(resBasePath, savePath, false);
  105. return savePath;
  106. }
  107. public string GetSavePath(WXSession session)
  108. {
  109. string savePath = Path.Combine(DecDBInfo.UserPath, session.UserName + ".html");
  110. return savePath;
  111. }
  112. public string? GetImage(WXMsg msg)
  113. {
  114. WXSessionAttachInfo? attachInfo = GetWXMsgAtc(msg);
  115. if (attachInfo == null)
  116. return null;
  117. string resBasePath = Path.Combine(DecDBInfo.ResPath, attachInfo.attachPath);
  118. //部分attachpath可能会附加md5校验,这里做处理
  119. int index = attachInfo.attachPath.IndexOf(".dat");
  120. if (attachInfo.attachPath.Length - index > 10)
  121. {
  122. resBasePath = resBasePath.Substring(0, resBasePath.Length - 32);
  123. }
  124. if (!File.Exists(resBasePath))
  125. return null;
  126. string imgPath = Path.Combine(DecDBInfo.UserPath, msg.StrTalker, "Image");
  127. if (!Directory.Exists(imgPath))
  128. Directory.CreateDirectory(imgPath);
  129. string img = DecImage(resBasePath, imgPath);
  130. return img;
  131. }
  132. private string DecImage(string source,string toPath)
  133. {
  134. //读取数据
  135. byte[] fileBytes = File.ReadAllBytes(source);
  136. //算差异转换
  137. byte key = getImgKey(fileBytes);
  138. fileBytes = ConvertData(fileBytes, key);
  139. //取文件类型
  140. string type = CheckFileType(fileBytes);
  141. //
  142. FileInfo fileInfo = new FileInfo(source);
  143. string fileName = fileInfo.Name.Substring(0, fileInfo.Name.Length - 4);
  144. string saveFilePath = Path.Combine(toPath, fileName + type);
  145. using (FileStream fileStream = File.OpenWrite(saveFilePath))
  146. {
  147. fileStream.Write(fileBytes, 0, fileBytes.Length);
  148. fileStream.Flush();
  149. }
  150. return saveFilePath;
  151. }
  152. private string CheckFileType(byte[] data)
  153. {
  154. switch (data[0])
  155. {
  156. case 0XFF: //byte[] jpg = new byte[] { 0xFF, 0xD8, 0xFF };
  157. {
  158. if (data[1] == 0xD8 && data[2] == 0xFF)
  159. {
  160. return ".jpg";
  161. }
  162. break;
  163. }
  164. case 0x89: //byte[] png = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
  165. {
  166. if (data[1] == 0x50 && data[2] == 0x4E && data[7] == 0x0A)
  167. {
  168. return ".png";
  169. }
  170. break;
  171. }
  172. case 0x42: //byte[] bmp = new byte[] { 0x42, 0x4D };
  173. {
  174. if (data[1] == 0X4D)
  175. {
  176. return ".bmp";
  177. }
  178. break;
  179. }
  180. case 0x47: //byte[] gif = new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39(0x37), 0x61 };
  181. {
  182. if (data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x38 && data[5] == 0x61)
  183. {
  184. return ".gif";
  185. }
  186. break;
  187. }
  188. case 0x49: // byte[] tif = new byte[] { 0x49, 0x49, 0x2A, 0x00 };
  189. {
  190. if (data[1] == 0x49 && data[2] == 0x2A && data[3] == 0x00)
  191. {
  192. return ".tif";
  193. }
  194. break;
  195. }
  196. case 0x4D: //byte[] tif = new byte[] { 0x4D, 0x4D, 0x2A, 0x00 };
  197. {
  198. if (data[1] == 0x4D && data[2] == 0x2A && data[3] == 0x00)
  199. {
  200. return ".tif";
  201. }
  202. break;
  203. }
  204. }
  205. return ".dat";
  206. }
  207. private byte getImgKey(byte[] fileRaw)
  208. {
  209. byte[] raw = new byte[8];
  210. for (int i = 0; i < 8; i++)
  211. {
  212. raw[i] = fileRaw[i];
  213. }
  214. for (byte key = 0x01; key < 0xFF; key++)
  215. {
  216. byte[] buf = new byte[8];
  217. raw.CopyTo(buf, 0);
  218. if (CheckFileType(ConvertData(buf, key)) != ".dat")
  219. {
  220. return key;
  221. }
  222. }
  223. return 0x00;
  224. }
  225. private byte[] ConvertData(byte[] data, byte key)
  226. {
  227. for (int i = 0; i < data.Length; i++)
  228. {
  229. data[i] ^= key;
  230. }
  231. return data;
  232. }
  233. }
  234. }