void Run() { var saveBase = textBox1.Text; //读取文本框中的保存地址 Directory.CreateDirectory(saveBase); //创建这个文件夹 该函数为创建多级文件夹 AddLog("分析文件夹结构"); //((IPhoneBackup)comboBox1.SelectedItem).path 找到苹果备份的文件夹的绝对路径 wechat = new WeChatInterface(((IPhoneBackup)comboBox1.SelectedItem).path, files92); wechat.BuildFilesDictionary(); AddLog("查找UID"); var UIDs = wechat.FindUIDs(); AddLog("找到" + UIDs.Count + "个账号的消息记录"); var uidList = new List <DisplayItem>(); foreach (var uid in UIDs) { var userBase = Path.Combine("Documents", uid); AddLog("开始处理UID: " + uid); AddLog("读取账号信息"); if (wechat.GetUserBasics(uid, userBase, out Friend myself)) { AddLog("微信号:" + myself.ID() + " 昵称:" + myself.DisplayName()); } else { AddLog("没有找到本人信息,用默认值替代"); } var userSaveBase = Path.Combine(saveBase, myself.ID()); Directory.CreateDirectory(userSaveBase); AddLog("正在打开数据库"); if (!wechat.OpenMMSqlite(userBase, out SQLiteConnection conn))//conn { AddLog("打开MM.sqlite失败,跳过"); continue; } if (wechat.OpenWCDBContact(userBase, out SQLiteConnection wcdb))//wcdb { AddLog("存在WCDB,与旧版好友列表合并使用"); } AddLog("读取好友列表"); if (!wechat.GetFriendsDict(conn, wcdb, myself, out Dictionary <string, Friend> friends, out int friendcount)) { AddLog("读取好友列表失败,跳过"); continue; } AddLog("找到" + friendcount + "个好友/聊天室"); AddLog("查找对话"); wechat.GetChatSessions(conn, out List <string> chats); AddLog("找到" + chats.Count + "个对话"); var emojidown = new HashSet <DownloadTask>(); var chatList = new List <DisplayItem>(); foreach (var chat in chats) { var hash = chat; string displayname = chat, id = displayname; Friend friend = null; if (friends.ContainsKey(hash)) { friend = friends[hash]; displayname = friend.DisplayName(); AddLog("处理与" + displayname + "的对话"); id = friend.ID(); } else { AddLog("未找到好友信息,用默认名字代替"); } if (radioButton4.Checked) { if (wechat.SaveTextRecord(conn, Path.Combine(userSaveBase, id + ".txt"), displayname, id, myself, chat, friend, friends, out int count)) { AddLog("成功处理" + count + "条"); } else { AddLog("失败"); } } else if (radioButton3.Checked) { if (wechat.SaveHtmlRecord(conn, userBase, userSaveBase, displayname, id, myself, chat, friend, friends, out int count, out HashSet <DownloadTask> _emojidown)) { AddLog("成功处理" + count + "条"); chatList.Add(new DisplayItem() { pic = "Portrait/" + (friend != null ? friend.FindPortrait() : "*****@*****.**"), text = displayname, link = id + ".html" }); } else { AddLog("失败"); } emojidown.UnionWith(_emojidown); } } conn.Close(); if (radioButton3.Checked) { wechat.MakeListHTML(chatList, Path.Combine(userSaveBase, "聊天记录.html")); } var portraitdir = Path.Combine(userSaveBase, "Portrait"); Directory.CreateDirectory(portraitdir); var downlist = new HashSet <DownloadTask>(); foreach (var item in friends) { var tfriend = item.Value; if (!tfriend.PortraitRequired) { continue; } if (tfriend.Portrait != null && tfriend.Portrait != "") { downlist.Add(new DownloadTask() { url = tfriend.Portrait, filename = tfriend.ID() + ".jpg" }); } //if (tfriend.PortraitHD != null && tfriend.PortraitHD != "") downlist.Add(new DownloadTask() { url = tfriend.PortraitHD, filename = tfriend.ID() + "_hd.jpg" }); } var downloader = new Downloader(6); if (downlist.Count > 0) { AddLog("下载" + downlist.Count + "个头像"); foreach (var item in downlist) { downloader.AddTask(item.url, Path.Combine(portraitdir, item.filename)); } try { File.Copy("res\\[email protected]", Path.Combine(portraitdir, "*****@*****.**")); } catch (Exception) { } } var emojidir = Path.Combine(userSaveBase, "Emoji"); Directory.CreateDirectory(emojidir); if (emojidown != null && emojidown.Count > 0) { AddLog("下载" + emojidown.Count + "个表情"); foreach (var item in emojidown) { downloader.AddTask(item.url, Path.Combine(emojidir, item.filename)); } } uidList.Add(new DisplayItem() { pic = myself.ID() + "/Portrait/" + myself.FindPortrait(), text = myself.DisplayName(), link = myself.ID() + "/聊天记录.html" }); downloader.StartDownload(); downloader.WaitToEnd(); AddLog("完成当前账号"); }
public bool SaveHtmlRecord(SQLiteConnection conn, string userBase, string path, string displayname, string id, Friend myself, string table, Friend friend, Dictionary <string, Friend> friends, out int count, out HashSet <DownloadTask> emojidown) { bool succ = false; emojidown = new HashSet <DownloadTask>(); count = 0; try { Dictionary <string, string> chatremark = new Dictionary <string, string>(); if (id.EndsWith("@chatroom") && friend != null && friend.dbContactChatRoom != null) { chatremark = ReadChatRoomRemark(friend.dbContactChatRoom); } using (var cmd = new SQLiteCommand(conn)) { cmd.CommandText = "SELECT CreateTime,Message,Des,Type,MesLocalID FROM Chat_" + table; using (var reader = cmd.ExecuteReader()) { var assetsdir = Path.Combine(path, id + "_files"); Directory.CreateDirectory(assetsdir); using (var sw = new StreamWriter(Path.Combine(path, id + ".html"))) { sw.WriteLine(@"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">"); sw.WriteLine(@"<html xmlns=""http://www.w3.org/1999/xhtml""><head><meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" /><title>" + displayname + " - 微信聊天记录</title></head>"); sw.WriteLine(@"<body><table width=""600"" border=""0"" style=""font-size:12px;border-collapse:separate;border-spacing:0px 20px;word-break:break-all;table-layout:fixed;word-wrap:break-word;"" align=""center"">"); while (reader.Read()) { try { var unixtime = reader.GetInt32(0); var message = reader.GetString(1); var des = reader.GetInt32(2); var type = reader.GetInt32(3); var msgid = reader.GetInt32(4); if (type == 10000) { sw.WriteLine(@"<tr><td width=""80""> </td><td width=""100""> </td><td>系统消息: " + message + @"</td></tr>"); continue; } var ts = ""; if (id.EndsWith("@chatroom")) { if (des == 0) { var txtsender = myself.DisplayName(); if (chatremark.ContainsKeySafe(myself.UsrName)) { txtsender = chatremark[myself.UsrName]; } else if (chatremark.ContainsKeySafe(myself.alias)) { txtsender = chatremark[myself.alias]; } ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/" + myself.FindPortrait() + @""" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } else { var enter = message.IndexOf(":\n"); if (enter > 0 && enter + 2 < message.Length) { var txtsender = message.Substring(0, enter); var senderid = txtsender; message = message.Substring(enter + 2); if (chatremark.ContainsKeySafe(txtsender)) { txtsender = chatremark[txtsender]; } else if (friends.ContainsKeySafe(txtsender)) { txtsender = friends[txtsender].DisplayName(); } if (friends.ContainsKeySafe(senderid)) { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/" + friends[senderid].FindPortrait() + @""" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } else { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/[email protected]"" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } } else { ts += @"<tr><td width=""80"" align=""center""> </td>"; } } } else { if (des == 0) { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/" + myself.FindPortrait() + @""" width=""50"" height=""50"" /><br />" + myself.DisplayName() + @"</td>"; } else if (friend != null) { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/" + friend.FindPortrait() + @""" width=""50"" height=""50"" /><br />" + friend.DisplayName() + @"</td>"; } else { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/[email protected]"" width=""50"" height=""50"" /><br />" + displayname + @"</td>"; } } if (type == 34) { var voicelen = -1; var match = Regex.Match(message, @"voicelength=""(\d+?)"""); if (match.Success) { voicelen = int.Parse(match.Groups[1].Value); } var audiosrc = GetBackupFilePath(MyPath.Combine(userBase, "Audio", table, msgid + ".aud")); if (audiosrc == null) { message = voicelen == -1 ? "[语音]" : "[语音 " + DisplayTime(voicelen) + "]"; } else { ShellWait("silk_v3_decoder.exe", "\"" + audiosrc + "\" 1.pcm"); ShellWait("lame.exe", "-r -s 24000 --preset voice 1.pcm \"" + Path.Combine(assetsdir, msgid + ".mp3") + "\""); message = "<audio controls><source src=\"" + id + "_files/" + msgid + ".mp3\" type=\"audio/mpeg\"><a href=\"" + id + "_files/" + msgid + ".mp3\">播放</a></audio>"; } } else if (type == 47) { var match = Regex.Match(message, @"cdnurl ?= ?""(.+?)"""); if (match.Success) { var localfile = RemoveCdata(match.Groups[1].Value); var match2 = Regex.Match(localfile, @"\/(\w+?)\/\w*$"); if (!match2.Success) { localfile = RandomString(10); } else { localfile = match2.Groups[1].Value; } emojidown.Add(new DownloadTask() { url = match.Groups[1].Value, filename = localfile + ".gif" }); message = "<img src=\"Emoji/" + localfile + ".gif\" style=\"max-width:100px;max-height:60px\" />"; } else { message = "[表情]"; } } else if (type == 62) { var hasthum = RequireResource(MyPath.Combine(userBase, "Video", table, msgid + ".video_thum"), Path.Combine(assetsdir, msgid + "_thum.jpg")); var hasvid = RequireResource(MyPath.Combine(userBase, "Video", table, msgid + ".mp4"), Path.Combine(assetsdir, msgid + ".mp4")); if (hasthum && hasvid) { message = "<video controls poster=\"" + id + "_files/" + msgid + "_thum.jpg\"><source src=\"" + id + "_files/" + msgid + ".mp4\" type=\"video/mp4\"><a href=\"" + id + "_files/" + msgid + ".mp4\">播放</a></video>"; } else if (hasthum) { message = "<img src=\"" + id + "_files/" + msgid + "_thum.jpg\" /> (视频丢失)"; } else if (hasvid) { message = "<video controls><source src=\"" + id + "_files/" + msgid + ".mp4\" type=\"video/mp4\"><a href=\"" + id + "_files/" + msgid + ".mp4\">播放</a></video>"; } else { message = "[视频]"; } } else if (type == 50) { message = "[视频/语音通话]"; } else if (type == 3) { var hasthum = RequireResource(MyPath.Combine(userBase, "Img", table, msgid + ".pic_thum"), Path.Combine(assetsdir, msgid + "_thum.jpg")); var haspic = RequireResource(MyPath.Combine(userBase, "Img", table, msgid + ".pic"), Path.Combine(assetsdir, msgid + ".jpg")); if (hasthum && haspic) { message = "<a href=\"" + id + "_files/" + msgid + ".jpg\"><img src=\"" + id + "_files/" + msgid + "_thum.jpg\" style=\"max-width:100px;max-height:60px\" /></a>"; } else if (hasthum) { message = "<img src=\"" + id + "_files/" + msgid + "_thum.jpg\" style=\"max-width:100px;max-height:60px\" />"; } else if (haspic) { message = "<img src=\"" + id + "_files/" + msgid + ".jpg\" style=\"max-width:100px;max-height:60px\" />"; } else { message = "[图片]"; } } else if (type == 48) { var match1 = Regex.Match(message, @"x ?= ?""(.+?)"""); var match2 = Regex.Match(message, @"y ?= ?""(.+?)"""); var match3 = Regex.Match(message, @"label ?= ?""(.+?)"""); if (match1.Success && match2.Success && match3.Success) { message = "[位置 (" + RemoveCdata(match2.Groups[1].Value) + "," + RemoveCdata(match1.Groups[1].Value) + ") " + RemoveCdata(match3.Groups[1].Value) + "]"; } else { message = "[位置]"; } } else if (type == 49) { if (message.Contains("<type>2001<")) { message = "[红包]"; } else if (message.Contains("<type>2000<")) { message = "[转账]"; } else if (message.Contains("<type>17<")) { message = "[实时位置共享]"; } else if (message.Contains("<type>6<")) { message = "[文件]"; } else { var match1 = Regex.Match(message, @"<title>(.+?)<\/title>"); var match2 = Regex.Match(message, @"<des>(.*?)<\/des>"); var match3 = Regex.Match(message, @"<url>(.+?)<\/url>"); var match4 = Regex.Match(message, @"<thumburl>(.+?)<\/thumburl>"); if (match1.Success && match3.Success) { message = ""; if (match4.Success) { message += "<img src=\"" + RemoveCdata(match4.Groups[1].Value) + "\" style=\"float:left;max-width:100px;max-height:60px\" />"; } message += "<a href=\"" + RemoveCdata(match3.Groups[1].Value) + "\"><b>" + RemoveCdata(match1.Groups[1].Value) + "</b></a>"; if (match2.Success) { message += "<br />" + RemoveCdata(match2.Groups[1].Value); } } else { message = "[链接]"; } } } else if (type == 42) { var match1 = Regex.Match(message, "nickname ?= ?\"(.+?)\""); var match2 = Regex.Match(message, "smallheadimgurl ?= ?\"(.+?)\""); if (match1.Success) { message = ""; if (match2.Success) { message += "<img src=\"" + RemoveCdata(match2.Groups[1].Value) + "\" style=\"float:left;max-width:100px;max-height:60px\" />"; } message += "[名片] " + RemoveCdata(match1.Groups[1].Value); } else { message = "[名片]"; } } else { message = SafeHTML(message); } ts += @"<td width=""100"" align=""center"">" + FromUnixTime(unixtime).ToLocalTime().ToString().Replace(" ", "<br />") + "</td>"; ts += @"<td>" + message + @"</td></tr>"; sw.WriteLine(ts); count++; } catch (Exception) { } } sw.WriteLine(@"</body></html>"); } } } succ = true; } catch (Exception) { } return(succ); }
private void IphoneRun() { int maxCount = int.MaxValue; if (!softReg.GetIsReg()) { maxCount = 10; MessageBox.Show("非注册用户暂时支持部分导出 \n如果导出全量信息请到https://www.weixinxqm.com/购买注册!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); } var saveBase = textBox1.Text; Directory.CreateDirectory(saveBase); AddLog("分析文件夹结构"); IphoneWeChatInterface wechat = new IphoneWeChatInterface(((IPhoneBackup)comboBox1.SelectedItem).path, files92); wechat.BuildFilesDictionary(); AddLog("查找UID"); var UIDs = wechat.FindUIDs(); AddLog("找到" + UIDs.Count + "个账号的消息记录"); var uidList = new List <DisplayItem>(); int delta = 90 / ((UIDs.Count > 0 ? UIDs.Count : 1) * 5); foreach (var uid in UIDs) { var userBase = Path.Combine("Documents", uid); AddLog("开始处理UID: " + uid); AddLog("读取账号信息"); if (wechat.GetUserBasics(uid, userBase, out Friend myself)) { AddLog("微信号:" + myself.ID() + " 昵称:" + myself.DisplayName()); } else { AddLog("没有找到本人信息,用默认值替代"); } var userSaveBase = Path.Combine(saveBase, myself.ID()); Directory.CreateDirectory(userSaveBase); AddLog("正在打开数据库"); if (!wechat.OpenMMSqlite(userBase, out System.Data.SQLite.SQLiteConnection conn)) { AddLog("打开MM.sqlite失败,跳过"); continue; } if (wechat.OpenWCDBContact(userBase, out SQLiteConnection wcdb)) { AddLog("存在WCDB,与旧版好友列表合并使用"); } AddLog("读取好友列表"); if (!wechat.GetFriendsDict(conn, wcdb, myself, out Dictionary <string, Friend> friends, out int friendcount)) { AddLog("读取好友列表失败,跳过"); continue; } AddLog("找到" + friendcount + "个好友/聊天室"); AddLog("导出好友列表:"); BaseWeChat.saveFriends(Path.Combine(userSaveBase, "好友列表.txt"), friends, maxCount, out int exportCount); AddLog("导出" + exportCount + "个好友"); conn.Close(); wcdb.Close(); var emojidown = new HashSet <DownloadTask>(); var chatList = new List <DisplayItem>(); var messageDBs = wechat.FindMessageDB(uid); foreach (var messageDB in messageDBs) { if (!wechat.OpenMessageSqlite(messageDB, out SQLiteConnection msgConn)) { AddLog("读取" + messageDB + "出错,跳过"); continue; } AddLog("查找对话:" + messageDB); wechat.GetChatSessions(msgConn, out List <string> chats); AddLog("找到" + chats.Count + "个对话"); foreach (var chat in chats) { var hash = chat; string displayname = chat, id = displayname; Friend friend = null; if (friends.ContainsKey(hash)) { friend = friends[hash]; displayname = friend.DisplayName(); AddLog("处理与" + displayname + "的对话"); id = friend.ID(); } else { AddLog("未找到好友信息,用默认名字代替"); } if (textRadioButton.Checked) { if (wechat.SaveTextRecord(msgConn, Path.Combine(userSaveBase, id + ".txt"), displayname, id, myself, chat, friend, friends, maxCount, out int count)) { AddLog("成功处理" + count + "条"); } else { AddLog("失败"); } } else if (htmlRadioButton.Checked) { if (wechat.SaveHtmlRecord(msgConn, userBase, userSaveBase, displayname, id, myself, chat, friend, friends, maxCount, out int count, out HashSet <DownloadTask> _emojidown)) { AddLog("成功处理" + count + "条"); chatList.Add(new DisplayItem() { pic = "Portrait/" + (friend != null ? friend.FindPortrait() : "*****@*****.**"), text = displayname, link = id + ".html" }); } else { AddLog("失败"); } emojidown.UnionWith(_emojidown); } } msgConn.Close(); } if (htmlRadioButton.Checked) { BaseWeChat.MakeListHTML(chatList, Path.Combine(userSaveBase, "聊天记录.html")); } var portraitdir = Path.Combine(userSaveBase, "Portrait"); Directory.CreateDirectory(portraitdir); var downlist = new HashSet <DownloadTask>(); foreach (var item in friends) { var tfriend = item.Value; if (!tfriend.PortraitRequired) { continue; } if (tfriend.Portrait != null && tfriend.Portrait != "") { downlist.Add(new DownloadTask() { url = tfriend.Portrait, filename = tfriend.ID() + ".jpg" }); } //if (tfriend.PortraitHD != null && tfriend.PortraitHD != "") downlist.Add(new DownloadTask() { url = tfriend.PortraitHD, filename = tfriend.ID() + "_hd.jpg" }); } var downloader = new Downloader(6); if (downlist.Count > 0) { AddLog("下载" + downlist.Count + "个头像"); foreach (var item in downlist) { downloader.AddTask(item.url, Path.Combine(portraitdir, item.filename)); } try { File.Copy("res\\[email protected]", Path.Combine(portraitdir, "*****@*****.**")); } catch (Exception) { } } var emojidir = Path.Combine(userSaveBase, "Emoji"); Directory.CreateDirectory(emojidir); if (emojidown != null && emojidown.Count > 0) { AddLog("下载" + emojidown.Count + "个表情"); foreach (var item in emojidown) { downloader.AddTask(item.url, Path.Combine(emojidir, item.filename)); } } uidList.Add(new DisplayItem() { pic = myself.ID() + "/Portrait/" + myself.FindPortrait(), text = myself.DisplayName(), link = myself.ID() + "/聊天记录.html" }); downloader.StartDownload(); downloader.WaitToEnd(); AddLog("完成当前账号"); }