FormUpdater.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using MPQ.Updater;
  10. using MPQ.FileSystem;
  11. using System.IO;
  12. using System.Configuration;
  13. using CommonLang.IO;
  14. using CommonLang.Concurrent;
  15. using System.Net;
  16. using System.IO.Compression;
  17. using CommonLang.Xml;
  18. using System.Xml;
  19. using CommonLang;
  20. using MPQFileEntry = MPQ.FileSystem.MPQFileSystem.MPQFileEntry;
  21. using MPQStream = MPQ.FileSystem.MPQFileSystem.MPQStream;
  22. using CommonMPQ.SharpZipLib;
  23. namespace MPQFileSystemTest
  24. {
  25. public partial class FormUpdater : Form, MPQUpdaterListener
  26. {
  27. private SaveData save = new SaveData();
  28. private MPQUpdater updater;
  29. private MPQFileSystem filesystem;
  30. public class SaveData
  31. {
  32. public string DEFAULT_URL;
  33. public string DEFAULT_SUFFIX;
  34. public string SAVE_PATH;
  35. public string ZIP_TYPE;
  36. public string MPQ_TYPE;
  37. }
  38. public FormUpdater()
  39. {
  40. InitializeComponent();
  41. {
  42. string[] urls = ConfigurationManager.AppSettings["REMOTE_URLS"].Split(',');
  43. foreach (string e in urls)
  44. {
  45. string url = e.Trim();
  46. if (!string.IsNullOrEmpty(url))
  47. {
  48. comboBox_RemoteDir.Items.Add(url);
  49. comboBox_RemoteDir.Text = url;
  50. }
  51. }
  52. }
  53. {
  54. string[] suffixs = ConfigurationManager.AppSettings["REMOTE_SUFFIXS"].Split(',');
  55. foreach (string e in suffixs)
  56. {
  57. string suffix = e.Trim();
  58. if (!string.IsNullOrEmpty(suffix))
  59. {
  60. comboBox_RemoteSuffix.Items.Add(suffix);
  61. comboBox_RemoteSuffix.Text = suffix;
  62. }
  63. }
  64. }
  65. try
  66. {
  67. XmlDocument xml = XmlUtil.LoadXML(Application.StartupPath + "/save.xml");
  68. save = (SaveData)XmlUtil.XmlToObject(xml);
  69. if (!string.IsNullOrEmpty(save.DEFAULT_URL))
  70. {
  71. comboBox_RemoteDir.Text = save.DEFAULT_URL;
  72. }
  73. if (!string.IsNullOrEmpty(save.DEFAULT_SUFFIX))
  74. {
  75. comboBox_RemoteSuffix.Text = save.DEFAULT_SUFFIX;
  76. }
  77. if (!string.IsNullOrEmpty(save.SAVE_PATH))
  78. {
  79. textBox_SaveRoot.Text = save.SAVE_PATH;
  80. }
  81. if (!string.IsNullOrEmpty(save.ZIP_TYPE))
  82. {
  83. comboBox_zipType.Text = save.ZIP_TYPE;
  84. }
  85. if (!string.IsNullOrEmpty(save.MPQ_TYPE))
  86. {
  87. comboBox_mpqType.Text = save.MPQ_TYPE;
  88. }
  89. }
  90. catch (Exception err)
  91. {
  92. }
  93. }
  94. private void FormUpdater_FormClosing(object sender, FormClosingEventArgs e)
  95. {
  96. try
  97. {
  98. save.DEFAULT_URL = comboBox_RemoteDir.Text;
  99. save.DEFAULT_SUFFIX = comboBox_RemoteSuffix.Text;
  100. save.SAVE_PATH = textBox_SaveRoot.Text;
  101. save.ZIP_TYPE = comboBox_zipType.Text;
  102. save.MPQ_TYPE = comboBox_mpqType.Text;
  103. XmlDocument xml = XmlUtil.ObjectToXml(save);
  104. XmlUtil.SaveXML(Application.StartupPath + "/save.xml", xml);
  105. }
  106. catch (Exception err)
  107. {
  108. }
  109. if (filesystem != null) {
  110. filesystem.Dispose();
  111. }
  112. if (updater != null) {
  113. updater.Dispose();
  114. }
  115. }
  116. //--------------------------------------------------------------------------------------------
  117. #region AUTO_UPDATER
  118. public void onEvent(MPQUpdater updater, MPQUpdaterEvent e)
  119. {
  120. if (e.EventType == MPQUpdaterEvent.TYPE_COMPLETE)
  121. {
  122. RefreshMPQ();
  123. }
  124. else if (e.EventType == MPQUpdaterEvent.TYPE_ERROR || e.EventType == MPQUpdaterEvent.TYPE_NOT_ENOUGH_SPACE)
  125. {
  126. MessageBox.Show(e.ToString());
  127. }
  128. }
  129. private void timer1_Tick(object sender, EventArgs e)
  130. {
  131. if (updater != null)
  132. {
  133. updater.Update();
  134. try
  135. {
  136. progressBar_Download.Minimum = 0;
  137. progressBar_Download.Maximum = (int)updater.TotalDownloadBytes;
  138. progressBar_Download.Value = (int)updater.CurrentDownloadBytes;
  139. label_Download.Text = updater.CurrentDownloadFile +
  140. " (" + updater.CurrentDownloadBytes + "/" + updater.TotalDownloadBytes + ") " +
  141. " " + (updater.CurrentDownloadSpeed / 1024) + "KB/S";
  142. progressBar_Decompress.Minimum = 0;
  143. progressBar_Decompress.Maximum = (int)updater.TotalUnzipBytes;
  144. progressBar_Decompress.Value = (int)updater.CurrentUnzipBytes;
  145. label_Unzip.Text = updater.CurrentUnzipFile +
  146. " (" + updater.CurrentUnzipBytes + "/" + updater.TotalUnzipBytes + ") " +
  147. " " + (updater.CurrentUnzipSpeed / 1024) + "KB/S";
  148. }
  149. catch (Exception err) { }
  150. textBox_VersionText.Lines = updater.VersionText.Split(new char[] { '\n' });
  151. progressBar_Running.Visible = updater.IsRunning;
  152. }
  153. else
  154. {
  155. progressBar_Download.Minimum = 0;
  156. progressBar_Download.Maximum = 1;
  157. progressBar_Download.Value = 0;
  158. label_Download.Text = "";
  159. progressBar_Decompress.Minimum = 0;
  160. progressBar_Decompress.Maximum = 1;
  161. progressBar_Decompress.Value = 0;
  162. label_Unzip.Text = "";
  163. textBox_VersionText.Text = "";
  164. progressBar_Running.Visible = false;
  165. }
  166. }
  167. private void button_Start_Click(object sender, EventArgs e)
  168. {
  169. if (updater != null)
  170. {
  171. updater.Dispose();
  172. }
  173. try
  174. {
  175. progressBar_Download.Minimum = 0;
  176. progressBar_Download.Maximum = 1;
  177. progressBar_Download.Value = 0;
  178. label_Download.Text = "";
  179. Uri url = new Uri(comboBox_RemoteDir.Text);
  180. updater = new MPQUpdater(new SharpZipLibMPQDirver());
  181. updater.Init(
  182. new string[] { comboBox_RemoteDir.Text },
  183. comboBox_RemoteSuffix.Text,
  184. new DirectoryInfo(textBox_SaveRoot.Text + url.LocalPath),
  185. new DirectoryInfo(textBox_BundleDir.Text),
  186. true,
  187. this);
  188. MPQUpdater.MPQ_EXT = comboBox_mpqType.Text.Trim();
  189. MPQUpdater.ZIP_EXT = comboBox_zipType.Text.Trim();
  190. //updater.RedirectDownloadSingle = RunDownloadSingle;
  191. //updater.RedirectUnzipSingle = RunUnzipSingle;
  192. updater.Start();
  193. }
  194. catch (Exception err)
  195. {
  196. MessageBox.Show(err.Message);
  197. }
  198. }
  199. private bool RunDownloadSingle(MPQUpdater updater, MPQ.Updater.MPQUpdater.RemoteFileInfo inf, long exist_size, long need_bytes, AtomicLong process)
  200. {
  201. Uri url = new Uri(updater.UrlRoots[0] + inf.key);
  202. var webRequest = (HttpWebRequest)HttpWebRequest.Create(url);
  203. webRequest.AddRange((int)exist_size, (int)(exist_size + need_bytes));
  204. webRequest.Method = "GET";
  205. WebResponse webResponse = webRequest.GetResponse();
  206. try
  207. {
  208. if (webResponse.ContentLength == need_bytes)
  209. {
  210. byte[] io_buffer = new byte[1024 * 4];
  211. using (FileStream fos = new FileStream(inf.file.FullName, FileMode.Append, FileAccess.Write))
  212. {
  213. Stream input = webResponse.GetResponseStream();
  214. try
  215. {
  216. long total_readed = 0;
  217. while (total_readed < need_bytes)
  218. {
  219. if (updater.IsDisposing) return false;
  220. int readed = input.Read(io_buffer, 0, (int)Math.Min(io_buffer.Length, need_bytes - total_readed));
  221. total_readed += readed;
  222. process += readed;
  223. fos.Write(io_buffer, 0, readed);
  224. }
  225. fos.Flush();
  226. }
  227. finally
  228. {
  229. fos.Close();
  230. }
  231. }
  232. }
  233. else
  234. {
  235. throw new Exception("Bad response with ContentLength=" + webResponse.ContentLength);
  236. }
  237. return true;
  238. }
  239. finally
  240. {
  241. webResponse.Close();
  242. }
  243. }
  244. private bool RunUnzipSingle(MPQUpdater updater, MPQ.Updater.MPQUpdater.RemoteFileInfo zip, MPQ.Updater.MPQUpdater.RemoteFileInfo mpq, AtomicLong process)
  245. {
  246. byte[] io_buffer = new byte[1024 * 4];
  247. using (FileStream fis = new FileStream(zip.file.FullName, FileMode.Open, FileAccess.Read))
  248. {
  249. using (FileStream fos = new FileStream(mpq.file.FullName, FileMode.Create, FileAccess.Write))
  250. {
  251. GZipStream gstream = new GZipStream(fis, CompressionMode.Decompress);
  252. long total_readed = 0;
  253. long total_size = mpq.size;
  254. while (total_readed < total_size)
  255. {
  256. if (updater.IsDisposing) return false;
  257. int readed = gstream.Read(io_buffer, 0, (int)Math.Min(io_buffer.Length, total_size - total_readed));
  258. total_readed += readed;
  259. process += readed;
  260. fos.Write(io_buffer, 0, readed);
  261. }
  262. fos.Flush();
  263. gstream.Close();
  264. fos.Close();
  265. fis.Close();
  266. }
  267. }
  268. return true;
  269. }
  270. private void button_Stop_Click(object sender, EventArgs e)
  271. {
  272. if (updater != null)
  273. {
  274. updater.Dispose();
  275. updater = null;
  276. }
  277. UnloadMPQ();
  278. }
  279. private void button_clear_Click(object sender, EventArgs e)
  280. {
  281. try
  282. {
  283. if (updater != null)
  284. {
  285. updater.Dispose();
  286. updater = null;
  287. }
  288. UnloadMPQ();
  289. DirectoryInfo local = new DirectoryInfo(textBox_SaveRoot.Text);
  290. if (local.Exists)
  291. {
  292. local.Delete(true);
  293. local.Create();
  294. }
  295. }
  296. catch (Exception err)
  297. {
  298. MessageBox.Show(err.Message);
  299. }
  300. }
  301. #endregion
  302. //--------------------------------------------------------------------------------------------
  303. #region MPQ_FILE_SYSTEM
  304. public class MPQFileSystemInfo
  305. {
  306. internal Dictionary<MPQ.Updater.MPQUpdater.RemoteFileInfo, MPQFileInfo> files =
  307. new Dictionary<MPQ.Updater.MPQUpdater.RemoteFileInfo, MPQFileInfo>();
  308. [Description("文件容量")]
  309. public long FileSize
  310. {
  311. get
  312. {
  313. long ret = 0;
  314. foreach (MPQFileInfo f in files.Values)
  315. {
  316. ret += f.FileSize;
  317. }
  318. return ret;
  319. }
  320. set { }
  321. }
  322. [Description("文件个数")]
  323. public int EntryCount
  324. {
  325. get
  326. {
  327. int ret = 0;
  328. foreach (MPQFileInfo f in files.Values)
  329. {
  330. ret += f.EntryCount;
  331. }
  332. return ret;
  333. }
  334. set { }
  335. }
  336. [Description("冗余容量")]
  337. public long ReplacedSize
  338. {
  339. get
  340. {
  341. long ret = 0;
  342. foreach (MPQFileInfo f in files.Values)
  343. {
  344. ret += f.ReplacedSize;
  345. }
  346. return ret;
  347. }
  348. set { }
  349. }
  350. [Description("冗余文件数")]
  351. public int ReplacedFileCount
  352. {
  353. get
  354. {
  355. int ret = 0;
  356. foreach (MPQFileInfo f in files.Values)
  357. {
  358. ret += f.ReplacedFileCount;
  359. }
  360. return ret;
  361. }
  362. set { }
  363. }
  364. }
  365. public class MPQFileInfo
  366. {
  367. internal List<MPQFileEntry> entries = new List<MPQFileEntry>();
  368. internal FileInfo fileinfo;
  369. internal int replaced_count;
  370. internal long replaced_size;
  371. public FileInfo File
  372. {
  373. get { return fileinfo; }
  374. set { }
  375. }
  376. [Description("文件容量")]
  377. public long FileSize
  378. {
  379. get { return fileinfo.Length; }
  380. set { }
  381. }
  382. [Description("文件个数")]
  383. public int EntryCount
  384. {
  385. get { return entries.Count; }
  386. set { }
  387. }
  388. [Description("冗余容量")]
  389. public long ReplacedSize
  390. {
  391. get { return replaced_size; }
  392. set { }
  393. }
  394. [Description("冗余文件数")]
  395. public int ReplacedFileCount
  396. {
  397. get { return replaced_count; }
  398. set { }
  399. }
  400. }
  401. private void UnloadMPQ()
  402. {
  403. if (this.filesystem != null)
  404. {
  405. TreeNode root = treeView_MPQ.Nodes[0];
  406. root.Tag = null;
  407. root.Nodes.Clear();
  408. this.filesystem.Dispose();
  409. this.filesystem = null;
  410. }
  411. }
  412. private void RefreshMPQ()
  413. {
  414. this.Enabled = false;
  415. try
  416. {
  417. TreeNode root = treeView_MPQ.Nodes[0];
  418. root.Tag = null;
  419. root.Nodes.Clear();
  420. if (filesystem != null)
  421. {
  422. filesystem.Dispose();
  423. }
  424. if (updater != null)
  425. {
  426. this.filesystem = new MPQFileSystem();
  427. //this.filesystem.init(updater);
  428. MPQFileSystemInfo fsinfo = new MPQFileSystemInfo();
  429. root.Tag = fsinfo;
  430. foreach (MPQ.Updater.MPQUpdater.RemoteFileInfo rmf in updater.GetAllRemoteFiles())
  431. {
  432. if (rmf.key.EndsWith(MPQUpdater.MPQ_EXT))
  433. {
  434. MPQFileInfo mpq_info = new MPQFileInfo();
  435. mpq_info.fileinfo = rmf.file;
  436. MPQStream mpq_stream = filesystem.load(rmf.file.FullName);
  437. mpq_stream.loadEntrys(mpq_info.entries);
  438. foreach (MPQFileEntry e in mpq_info.entries)
  439. {
  440. MPQFileEntry exist_fe = filesystem.findEntry(e.Key);
  441. bool is_old = !e.Equals(exist_fe);
  442. if (is_old)
  443. {
  444. mpq_info.replaced_size += e.Size;
  445. mpq_info.replaced_count += 1;
  446. }
  447. }
  448. fsinfo.files[rmf] = mpq_info;
  449. }
  450. }
  451. }
  452. RefreshTreeNode();
  453. }
  454. catch (Exception err)
  455. {
  456. MessageBox.Show(err.Message);
  457. }
  458. finally
  459. {
  460. this.Enabled = true;
  461. treeView_MPQ.Invalidate(true);
  462. }
  463. }
  464. private void RefreshTreeNode()
  465. {
  466. TreeNode root = treeView_MPQ.Nodes[0];
  467. root.Nodes.Clear();
  468. if (filesystem != null && root.Tag is MPQFileSystemInfo)
  469. {
  470. MPQFileSystemInfo fsinfo = (MPQFileSystemInfo)root.Tag;
  471. foreach (MPQ.Updater.MPQUpdater.RemoteFileInfo rmf in fsinfo.files.Keys)
  472. {
  473. MPQFileInfo mpq_info = fsinfo.files[rmf];
  474. TreeNode mpq_file_node = new TreeNode(rmf.key);
  475. mpq_file_node.Tag = mpq_info;
  476. foreach (MPQFileEntry e in mpq_info.entries)
  477. {
  478. MPQFileEntry exist_fe = filesystem.findEntry(e.Key);
  479. bool is_old = !e.Equals(exist_fe);
  480. if (!toolStripButton_ViewReplaced.Checked || is_old)
  481. {
  482. TreeNode enode = new TreeNode(e.Key);
  483. enode.Tag = e;
  484. if (is_old)
  485. {
  486. enode.Text = "(old) " + e.Key;
  487. enode.ForeColor = Color.Gray;
  488. }
  489. enode.ContextMenuStrip = this.menu_EntryNode;
  490. mpq_file_node.Nodes.Add(enode);
  491. }
  492. }
  493. mpq_file_node.Text += " (" + (mpq_info.EntryCount - mpq_info.ReplacedFileCount) + "/" + mpq_info.EntryCount + ")";
  494. root.Nodes.Add(mpq_file_node);
  495. }
  496. }
  497. }
  498. private void toolStripMenuItem_RefreshMPQ_Click(object sender, EventArgs e)
  499. {
  500. RefreshMPQ();
  501. }
  502. private void 导出文件ToolStripMenuItem_Click(object sender, EventArgs e)
  503. {
  504. TreeNode sn = treeView_MPQ.SelectedNode;
  505. if (sn != null && sn.Tag is MPQFileEntry)
  506. {
  507. MPQFileEntry entry = (MPQFileEntry)sn.Tag;
  508. SaveFileDialog sfd = new SaveFileDialog();
  509. string name = entry.Key.Replace('\\', '/');
  510. int index = entry.Key.LastIndexOf('/');
  511. if (index >= 0) { sfd.FileName = entry.Key.Substring(index+1); }
  512. else { sfd.FileName = entry.Key; }
  513. if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  514. {
  515. byte[] data = filesystem.getEntryData(entry);
  516. using (Stream stream = sfd.OpenFile())
  517. {
  518. stream.Write(data, 0, data.Length);
  519. }
  520. }
  521. }
  522. }
  523. private void treeView_MPQ_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
  524. {
  525. if (e.Node.Tag is MPQFileSystemInfo)
  526. {
  527. MPQFileSystemInfo mpq = (MPQFileSystemInfo)e.Node.Tag;
  528. property_MPQInfo.SelectedObject = mpq;
  529. }
  530. else if (e.Node.Tag is MPQFileInfo)
  531. {
  532. MPQFileInfo mpq = (MPQFileInfo)e.Node.Tag;
  533. property_MPQInfo.SelectedObject = mpq;
  534. }
  535. else if (e.Node.Tag is MPQFileEntry)
  536. {
  537. MPQFileEntry mpq = (MPQFileEntry)e.Node.Tag;
  538. property_MPQInfo.SelectedObject = mpq;
  539. }
  540. }
  541. private void treeView_MPQ_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
  542. {
  543. if (e.Node.Tag is MPQFileEntry)
  544. {
  545. MPQFileSystem.MPQFileEntry mpq = (MPQFileSystem.MPQFileEntry)e.Node.Tag;
  546. try
  547. {
  548. new FormEntry(mpq, filesystem).ShowDialog();
  549. }
  550. catch (Exception err)
  551. {
  552. MessageBox.Show(err.Message);
  553. }
  554. }
  555. }
  556. private void toolStripButton_ViewReplaced_Click(object sender, EventArgs e)
  557. {
  558. this.Enabled = false;
  559. try
  560. {
  561. RefreshTreeNode();
  562. }
  563. finally
  564. {
  565. this.Enabled = true;
  566. treeView_MPQ.Refresh();
  567. }
  568. }
  569. #endregion
  570. //--------------------------------------------------------------------------------------------
  571. }
  572. }