diff --git a/BaiduYunSync.sln b/BaiduYunSync.sln
new file mode 100644
index 0000000..d36c34b
--- /dev/null
+++ b/BaiduYunSync.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaiduYunSync", "BaiduYunSync\BaiduYunSync.csproj", "{F063180E-E354-4DB4-96F8-154D1D949240}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetDisk", "NetDisk\NetDisk.csproj", "{74ECA1BF-6508-417D-BC57-DB00DAECA618}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F063180E-E354-4DB4-96F8-154D1D949240}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F063180E-E354-4DB4-96F8-154D1D949240}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F063180E-E354-4DB4-96F8-154D1D949240}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F063180E-E354-4DB4-96F8-154D1D949240}.Release|Any CPU.Build.0 = Release|Any CPU
+ {74ECA1BF-6508-417D-BC57-DB00DAECA618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {74ECA1BF-6508-417D-BC57-DB00DAECA618}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {74ECA1BF-6508-417D-BC57-DB00DAECA618}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {74ECA1BF-6508-417D-BC57-DB00DAECA618}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/BaiduYunSync/BaiduYunSync.csproj b/BaiduYunSync/BaiduYunSync.csproj
new file mode 100644
index 0000000..24d70bc
--- /dev/null
+++ b/BaiduYunSync/BaiduYunSync.csproj
@@ -0,0 +1,134 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {F063180E-E354-4DB4-96F8-154D1D949240}
+ WinExe
+ Properties
+ BaiduYunSync
+ BaiduYunSync
+ v4.0
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\LiteDB.2.0.4\lib\net35\LiteDB.dll
+ True
+
+
+ ..\packages\log4net.2.0.7\lib\net40-full\log4net.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ frmLogin.cs
+
+
+ Form
+
+
+ frmMain.cs
+
+
+ Form
+
+
+ frmReadLog.cs
+
+
+ Form
+
+
+ frmUploadList.cs
+
+
+
+
+
+
+
+
+
+
+ frmLogin.cs
+
+
+ frmMain.cs
+
+
+ frmReadLog.cs
+
+
+ frmUploadList.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+ {74ECA1BF-6508-417D-BC57-DB00DAECA618}
+ NetDisk
+
+
+
+
+
\ No newline at end of file
diff --git a/BaiduYunSync/Encrypt3DS.cs b/BaiduYunSync/Encrypt3DS.cs
new file mode 100644
index 0000000..0dfd8b2
--- /dev/null
+++ b/BaiduYunSync/Encrypt3DS.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace BaiduYunSync
+{
+ class Encrypt3DS
+ {
+ //密钥
+ private const string sKey = "qJzGEh6hESZDVJeCnFPGuxzaiB7NLQM3";
+ //矢量,矢量可以为空
+ private const string sIV = "qcDY6X+aPLw=";
+ //构造一个对称算法
+ private SymmetricAlgorithm mCSP = new TripleDESCryptoServiceProvider();
+
+ #region public string EncryptString(string Value)
+ ///
+ /// 加密字符串
+ ///
+ /// 输入的字符串
+ /// 加密后的字符串
+ public string EncryptString(string Value)
+ {
+ ICryptoTransform ct;
+ MemoryStream ms;
+ CryptoStream cs;
+ byte[] byt;
+ mCSP.Key = Convert.FromBase64String(sKey);
+ mCSP.IV = Convert.FromBase64String(sIV);
+ //指定加密的运算模式
+ mCSP.Mode = System.Security.Cryptography.CipherMode.ECB;
+ //获取或设置加密算法的填充模式
+ mCSP.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
+ ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV);
+ byt = Encoding.UTF8.GetBytes(Value);
+ ms = new MemoryStream();
+ cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
+ cs.Write(byt, 0, byt.Length);
+ cs.FlushFinalBlock();
+ cs.Close();
+ return Convert.ToBase64String(ms.ToArray());
+ }
+ #endregion
+ #region public string DecryptString(string Value)
+ ///
+ /// 解密字符串
+ ///
+ /// 加过密的字符串
+ /// 解密后的字符串
+ public string DecryptString(string Value)
+ {
+ ICryptoTransform ct;
+ MemoryStream ms;
+ CryptoStream cs;
+ byte[] byt;
+ mCSP.Key = Convert.FromBase64String(sKey);
+ mCSP.IV = Convert.FromBase64String(sIV);
+ mCSP.Mode = System.Security.Cryptography.CipherMode.ECB;
+ mCSP.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
+ ct = mCSP.CreateDecryptor(mCSP.Key, mCSP.IV);
+ byt = Convert.FromBase64String(Value);
+ ms = new MemoryStream();
+ cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
+ cs.Write(byt, 0, byt.Length);
+ cs.FlushFinalBlock();
+ cs.Close();
+ return Encoding.UTF8.GetString(ms.ToArray());
+ }
+ #endregion
+
+ }
+}
diff --git a/BaiduYunSync/LiteDbHelper.cs b/BaiduYunSync/LiteDbHelper.cs
new file mode 100644
index 0000000..7e3534a
--- /dev/null
+++ b/BaiduYunSync/LiteDbHelper.cs
@@ -0,0 +1,210 @@
+using LiteDB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BaiduYunSync
+{
+ class LiteDbHelper
+ {
+
+ private static string dbUrl = "db.db";
+
+ ///
+ /// 本地保存更新信息,防止频繁读写文件
+ ///
+ private static List updateInfoList;
+
+ ///
+ /// 同步文件锁
+ ///
+ private static object updateInfoLocker = new object();
+
+ static LiteDbHelper()
+ {
+ Init();
+ }
+
+ ///
+ /// 初始化数据库相关内容
+ ///
+ public static void Init()
+ {
+ if (updateInfoList == null)
+ {
+ using (var db = new LiteDatabase(dbUrl))
+ {
+ var col = db.GetCollection("updateinfo");
+ var list = col.FindAll();
+ updateInfoList = (list == null ? new List() : list.ToList());
+ }
+ }
+ }
+
+ private static UserInfoDao userInfo;
+
+ ///
+ /// 获取或设置用户信息
+ ///
+ public static UserInfoDao UserInfo
+ {
+ get
+ {
+ if (userInfo == null)
+ {
+ using (var db = new LiteDatabase(dbUrl))
+ {
+ var col = db.GetCollection("userinfo");
+ userInfo = col.FindOne(Query.All());
+ if (userInfo == null)
+ {
+ userInfo = new UserInfoDao();
+ }
+ }
+ }
+ return userInfo;
+ }
+ set
+ {
+ using (var db = new LiteDatabase(dbUrl))
+ {
+ var col = db.GetCollection("userinfo");
+ if (value.Id == 0)
+ {
+ col.Insert(value);
+ }
+ else
+ {
+ col.Update(value);
+ }
+ userInfo = value;
+ }
+ }
+ }
+
+ ///
+ /// 插入或更新需要同步的文件夹
+ ///
+ ///
+ public static void UpdateSyncItem(SyncItemsDao dao)
+ {
+ using (var db = new LiteDatabase(dbUrl))
+ {
+ var col = db.GetCollection("syncitem");
+ if (dao.Id == 0)
+ {
+ col.Insert(dao);
+ }
+ else
+ {
+ col.Update(dao);
+ }
+ }
+ }
+
+ ///
+ /// 获取需要同步的文件夹列表
+ ///
+ /// 同步文件夹信息
+ public static List GetAllSyncItems()
+ {
+ using (var db = new LiteDatabase(dbUrl))
+ {
+ var col = db.GetCollection("syncitem");
+ return col.FindAll().ToList();
+ }
+ }
+
+ ///
+ /// 删除同步文件夹
+ ///
+ ///
+ public static void DeleteSyncItem(SyncItemsDao dao)
+ {
+ using (var db = new LiteDatabase(dbUrl))
+ {
+ var col = db.GetCollection("syncitem");
+ col.Delete(dao.Id);
+ }
+ }
+
+ ///
+ /// 获取所有的更新信息
+ ///
+ ///
+ public static UpdateInfoDao[] GetAllUpdateInfos()
+ {
+ lock (updateInfoLocker)
+ {
+ return updateInfoList.ToArray();
+ }
+ }
+
+ ///
+ /// 插入新的更新信息
+ ///
+ ///
+ public static void InsertUpdateInfo(UpdateInfoDao dao)
+ {
+ using (var db = new LiteDatabase(dbUrl))
+ {
+ var col = db.GetCollection("updateinfo");
+ col.Insert(dao);
+ }
+ lock (updateInfoLocker)
+ updateInfoList.Add(dao);
+ }
+
+ ///
+ /// 删除更新信息
+ ///
+ ///
+ public static void DeleteUpdateInfo(UpdateInfoDao dao)
+ {
+ using (var db = new LiteDatabase(dbUrl))
+ {
+ var col = db.GetCollection("updateinfo");
+ col.Delete(dao.Id);
+ }
+ lock (updateInfoLocker)
+ updateInfoList.Remove(dao);
+ }
+
+ ///
+ /// 获取需更新数量
+ ///
+ /// 数量
+ public static int GetUpdateInfoCount()
+ {
+ lock (updateInfoLocker)
+ return updateInfoList.Count();
+ }
+
+ ///
+ /// 判断文件是否已存在
+ ///
+ /// 文件全路径
+ ///
+ public static bool ContainsPath(string path)
+ {
+ lock (updateInfoLocker)
+ return updateInfoList.Select(x => x.Path).Contains(path);
+ }
+
+ ///
+ /// 根据路径获取对应的更新信息
+ ///
+ ///
+ ///
+ public static UpdateInfoDao GetUpdateInfoFormPath(string path)
+ {
+ if (!ContainsPath(path))
+ {
+ return null;
+ }
+ lock (updateInfoLocker)
+ return updateInfoList.Where(x => x.Path == path).First();
+ }
+ }
+}
diff --git a/BaiduYunSync/LogSettings.cs b/BaiduYunSync/LogSettings.cs
new file mode 100644
index 0000000..9412a7d
--- /dev/null
+++ b/BaiduYunSync/LogSettings.cs
@@ -0,0 +1,49 @@
+using log4net;
+using log4net.Appender;
+using log4net.Layout;
+using log4net.Repository.Hierarchy;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BaiduYunSync
+{
+ class LogSettings
+ {
+ static LogSettings()
+ {
+ string LOG_PATTERN = "%d [%t] %-5p %c [%x] - %m%n";
+ string LOG_FILE_PATH = "log/job.log";
+ Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
+ hierarchy.Name = "stdAdapter";
+ TraceAppender tracer = new TraceAppender();
+
+ PatternLayout patternLayout = new PatternLayout();
+ patternLayout.ConversionPattern = LOG_PATTERN;
+ patternLayout.ActivateOptions();
+
+ tracer.Layout = patternLayout;
+ tracer.ActivateOptions();
+ hierarchy.Root.AddAppender(tracer);
+
+ RollingFileAppender roller = new RollingFileAppender();
+ roller.Layout = patternLayout;
+ roller.AppendToFile = true;
+ roller.RollingStyle = RollingFileAppender.RollingMode.Size;
+ roller.MaxSizeRollBackups = 10;
+ roller.MaximumFileSize = "1MB";
+ roller.StaticLogFileName = true;
+ roller.File = LOG_FILE_PATH;
+ roller.ActivateOptions();
+ hierarchy.Root.AddAppender(roller);
+ hierarchy.Root.Level = log4net.Core.Level.All;
+ hierarchy.Configured = true;
+ }
+
+ public static void StdInfo(string msg)
+ {
+ LogManager.GetLogger("stdAdapter").Info(msg);
+ }
+ }
+}
diff --git a/BaiduYunSync/Program.cs b/BaiduYunSync/Program.cs
new file mode 100644
index 0000000..b1f3e40
--- /dev/null
+++ b/BaiduYunSync/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace BaiduYunSync
+{
+ static class Program
+ {
+ ///
+ /// 应用程序的主入口点。
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new frmMain());
+ }
+ }
+}
diff --git a/BaiduYunSync/Properties/AssemblyInfo.cs b/BaiduYunSync/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1ee8bf9
--- /dev/null
+++ b/BaiduYunSync/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的常规信息通过以下
+// 特性集控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("BaiduYunSync")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BaiduYunSync")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 使此程序集中的类型
+// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
+// 则将该类型上的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("4e80c253-7d19-44cc-a24b-8f92154fbc6e")]
+
+// 程序集的版本信息由下面四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/BaiduYunSync/Properties/Resources.Designer.cs b/BaiduYunSync/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..8db3a6f
--- /dev/null
+++ b/BaiduYunSync/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本: 4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace BaiduYunSync.Properties
+{
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// 返回此类使用的、缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BaiduYunSync.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 为所有资源查找重写当前线程的 CurrentUICulture 属性,
+ /// 方法是使用此强类型资源类。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/BaiduYunSync/Properties/Resources.resx b/BaiduYunSync/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/BaiduYunSync/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/BaiduYunSync/Properties/Settings.Designer.cs b/BaiduYunSync/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..14d6801
--- /dev/null
+++ b/BaiduYunSync/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace BaiduYunSync.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/BaiduYunSync/Properties/Settings.settings b/BaiduYunSync/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/BaiduYunSync/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/BaiduYunSync/Sync.cs b/BaiduYunSync/Sync.cs
new file mode 100644
index 0000000..9f9c51c
--- /dev/null
+++ b/BaiduYunSync/Sync.cs
@@ -0,0 +1,294 @@
+using NetDisk;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace BaiduYunSync
+{
+ ///
+ /// 同步类
+ ///
+ class Sync
+ {
+
+ static Sync()
+ {
+ Operation.InitUploadFile += Operation_InitUploadFile;
+ Operation.StartUploadBlock += Operation_StartUploadBlock;
+ Operation.ComplateUploadBlock += Operation_ComplateUploadBlock;
+ Operation.UpdateComplate += Operation_UpdateComplate;
+
+ }
+
+ private static void Operation_UpdateComplate(string filePath)
+ {
+ lock (locker)
+ {
+ LiteDbHelper.DeleteUpdateInfo(LiteDbHelper.GetAllUpdateInfos().Where(x => x.Path == filePath).First());
+ }
+
+ LogSettings.StdInfo(filePath + "上传完成,从队列中删除");
+ if (StatusModify != null)
+ StatusModify(filePath, StatusEnum.Delete);
+ mre.Set();
+ }
+
+ private static void Operation_ComplateUploadBlock(string filePath, int endBlockNum, int totalBlockNum)
+ {
+ LiteDbHelper.GetAllUpdateInfos().Where(x => x.Path == filePath).ToList().ForEach(
+ x =>
+ {
+ x.ComplateBlockNum = endBlockNum;
+ });
+ LogSettings.StdInfo(string.Format("{0}完成第{1}个块,共{2}个块", filePath, endBlockNum, totalBlockNum));
+ if (StatusModify != null)
+ StatusModify(filePath, StatusEnum.Modify);
+ }
+
+ private static void Operation_StartUploadBlock(string filePath, int startBlockNum, int totalBlockNum)
+ {
+ LogSettings.StdInfo(string.Format("{0}开始上传第{1}个块,共{2}个块", filePath, startBlockNum, totalBlockNum));
+ }
+
+ private static void Operation_InitUploadFile(string filePath, int fileBlockNum, int needUploadBlockNum)
+ {
+ LiteDbHelper.GetAllUpdateInfos().Where(x => x.Path == filePath).ToList().ForEach(
+ x =>
+ {
+ x.Status = "正在上传";
+ x.TotalBlockNum = fileBlockNum;
+ });
+ LogSettings.StdInfo(filePath + "准备开始上传");
+ if (StatusModify != null)
+ StatusModify(filePath, StatusEnum.Start);
+ }
+
+ public static AutoResetEvent mre = new AutoResetEvent(false);
+
+ ///
+ /// 任务
+ ///
+ private static AutoResetEvent taskmre = new AutoResetEvent(false);
+
+
+ private static object locker = new object();
+
+ ///
+ /// 开始新同步时发生
+ ///
+ /// 文件夹名称
+ public delegate void StartSyncHandle(string folder);
+
+ public static event StartSyncHandle StartSync;
+
+ ///
+ /// 同步结束时发生
+ ///
+ ///
+ public delegate void EndSyncHandle(SyncItemsDao folder);
+
+ public static event EndSyncHandle EndSync;
+
+ ///
+ /// 文件上传状态改变
+ ///
+ ///
+ ///
+ public delegate void StatusModifyHandle(string path, StatusEnum status);
+
+ public static event StatusModifyHandle StatusModify;
+
+ ///
+ /// 文件状态
+ ///
+ public enum StatusEnum
+ {
+ ///
+ /// 添加新项
+ ///
+ Add,
+ ///
+ /// 开始上传
+ ///
+ Start,
+ ///
+ /// 上传状态改变
+ ///
+ Modify,
+ ///
+ /// 结束删除
+ ///
+ Delete
+ }
+
+ ///
+ /// 启动同步线程
+ ///
+ /// 身份信息
+ public static void SyncNow( Credential credential)
+ {
+ // 启动5个上传线程进行上传
+ for (int i = 0; i < 5; i++)
+ {
+ var thread = new Thread(() => UpdateFile(credential));
+ thread.IsBackground = true;
+ thread.Start();
+ }
+ while (true)
+ {
+ // 如果队列中存在未完成的任务,则不进行下一轮扫描
+ while (LiteDbHelper.GetUpdateInfoCount() > 0)
+ {
+ mre.WaitOne();
+ }
+ LogSettings.StdInfo("开始文件夹同步");
+ // 查找距离上次同步时间超过6小时的文件夹
+ var folderList = LiteDbHelper.GetAllSyncItems().Where(x => (DateTime.Now - x.LastSync).TotalHours > 6);
+ foreach (var folder in folderList)
+ {
+ LogSettings.StdInfo("需要同步的文件夹为:" + folder.Folder);
+ if (StartSync != null)
+ {
+ StartSync(folder.Folder);
+ }
+ SearchAllFile(folder.Folder, "/", credential);
+ folder.LastSync = DateTime.Now;
+ LiteDbHelper.UpdateSyncItem(folder);
+ LogSettings.StdInfo(folder.Folder + "同步完成");
+ if (EndSync != null)
+ {
+ EndSync(folder);
+ }
+ }
+ LogSettings.StdInfo("同步结束");
+ mre.WaitOne(new TimeSpan(6, 0, 0));
+ }
+
+ }
+
+ ///
+ /// 查找所有需要同步的文件
+ ///
+ /// 本地文件夹路径
+ /// 服务器路径(父路径)
+ /// 身份信息
+ private static void SearchAllFile(string folderPath, string serverPath, Credential credential)
+ {
+ // 获取服务器路径下文件列表
+ var fileList = Operation.GetFileList(serverPath, credential);
+ // 获取需要同步的文件夹名
+ var folderName = Path.GetFileName(folderPath);
+ // 组合成新服务器路径,由于windows文件路径为\分割,服务器为/分割,所以需要转换
+ var newServerPath = Path.Combine(serverPath, folderName).Replace('\\', '/');
+ if (fileList.list == null || !fileList.list.Select(x => x.server_filename).Contains(folderName))
+ {
+ Operation.CreateFolder(newServerPath, credential);
+ LogSettings.StdInfo("创建文件夹" + newServerPath);
+ }
+ fileList = Operation.GetFileList(newServerPath, credential);
+ var localFileList = Directory.GetFiles(folderPath);
+ var localDirectoryList = Directory.GetDirectories(folderPath);
+ foreach (var file in localFileList)
+ {
+ // 如果任务中存在该文件则放弃添加
+ if (LiteDbHelper.ContainsPath(file))
+ {
+ continue;
+ }
+ var updateInfo = new UpdateInfoDao();
+ updateInfo.FileName = Path.GetFileName(file);
+ updateInfo.FileLength = new FileInfo(file).Length;
+ updateInfo.Path = file;
+ if (updateInfo.FileLength == 0)
+ {
+ LogSettings.StdInfo(file + "大小为0,暂不支持上传");
+ continue;
+ }
+ var fileEnumberable = fileList.list == null ? null : fileList.list.Where(x => x.server_filename == Path.GetFileName(file));
+ FileInfo fi = new FileInfo(file);
+ //如果有文件,因为文件名不能相同,所以只需要判断第一个文件是否与服务器相同即可
+ if (fileEnumberable != null && fileEnumberable.Count() > 0)
+ {
+ // 服务器返回的MD5有时候好像有问题,会导致部分文件反复同步,所以删除
+ if (fileEnumberable.ElementAt(0).size == fi.Length)// && fileEnumberable.ElementAt(0).md5 == GetMD5HashFromFile(file))
+ {
+ LogSettings.StdInfo("文件已存在:" + fileEnumberable.ElementAt(0).server_filename);
+ continue;
+ }
+ updateInfo.NeedDelete = true;
+ }
+ if (!updateInfo.NeedDelete)
+ {
+ updateInfo.ServerPath = Path.Combine(newServerPath, Path.GetFileName(file)).Replace('\\', '/');
+ }
+ lock (locker)
+ {
+ LiteDbHelper.InsertUpdateInfo(updateInfo);
+ LogSettings.StdInfo("添加文件:" + updateInfo.Path);
+ }
+ if (StatusModify != null)
+ StatusModify(updateInfo.Path, StatusEnum.Add);
+ taskmre.Set();
+ }
+ foreach (var directory in localDirectoryList)
+ {
+ SearchAllFile(directory, newServerPath, credential);
+ }
+ }
+
+ ///
+ /// 上传文件
+ ///
+ /// 身份信息
+ private static void UpdateFile(Credential credential)
+ {
+ while (true)
+ {
+ UpdateInfoDao updateInfo;
+ lock (locker)
+ {
+ // 查找第一个未开始同步的文件
+ updateInfo = LiteDbHelper.GetAllUpdateInfos().Where(x => !x.IsUsed).FirstOrDefault();
+ if (updateInfo != null)
+ {
+ updateInfo.IsUsed = true;
+ }
+
+ }
+ // 如果没有找到,则证明
+ if (updateInfo == null)
+ {
+ taskmre.Reset();
+ taskmre.WaitOne();
+ continue;
+ }
+ if (updateInfo.NeedDelete)
+ {
+ var fileOperationResult = Operation.Delete(updateInfo.ServerPath, credential);
+ if (!fileOperationResult.success)
+ {
+
+ }
+ LogSettings.StdInfo("删除文件:" + updateInfo.ServerPath);
+ }
+ for (int i = 0; i < 3; i++)
+ {
+ try
+ {
+ Operation.ChunkedUpload(updateInfo.Path, updateInfo.ServerPath, credential);
+ LogSettings.StdInfo("上传文件成功:" + updateInfo.FileName);
+ break;
+ }
+ catch (Exception ex)
+ {
+ LogSettings.StdInfo(string.Format("第{0}次上传失败,文件名:{1},失败原因:{2}", i, updateInfo.Path, ex));
+ }
+ }
+ }
+
+ }
+ }
+}
diff --git a/BaiduYunSync/SyncItemsDao.cs b/BaiduYunSync/SyncItemsDao.cs
new file mode 100644
index 0000000..e2bb83c
--- /dev/null
+++ b/BaiduYunSync/SyncItemsDao.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BaiduYunSync
+{
+ public class SyncItemsDao
+ {
+ public int Id { get; set; }
+
+ public string Folder { get; set; }
+
+ public DateTime LastSync { get; set; }
+ }
+}
diff --git a/BaiduYunSync/UpdateInfoDao.cs b/BaiduYunSync/UpdateInfoDao.cs
new file mode 100644
index 0000000..7281d29
--- /dev/null
+++ b/BaiduYunSync/UpdateInfoDao.cs
@@ -0,0 +1,61 @@
+using NetDisk;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BaiduYunSync
+{
+ ///
+ /// 上传信息类
+ ///
+ public class UpdateInfoDao
+ {
+ public int Id { get; set; }
+
+ ///
+ /// 总共完成数量
+ ///
+ public int ComplateBlockNum { get; set; }
+
+ ///
+ /// 总块数
+ ///
+ public int TotalBlockNum { get; set; }
+
+ ///
+ /// 文件路径
+ ///
+ public string Path { get; set; }
+
+ ///
+ /// 服务器路径
+ ///
+ public string ServerPath { get; set; }
+
+ ///
+ /// 文件名
+ ///
+ public string FileName { get; set; }
+
+ ///
+ /// 当前状态
+ ///
+ public string Status { get; set; }
+
+ ///
+ /// 文件大小
+ ///
+ public long FileLength { get; set; }
+
+ ///
+ /// 是否需要先删除文件
+ ///
+ public bool NeedDelete { get; set; }
+
+ ///
+ /// 是否已经被使用
+ ///
+ public bool IsUsed { get; set; }
+ }
+}
diff --git a/BaiduYunSync/UserInfoDao.cs b/BaiduYunSync/UserInfoDao.cs
new file mode 100644
index 0000000..2d1b6be
--- /dev/null
+++ b/BaiduYunSync/UserInfoDao.cs
@@ -0,0 +1,31 @@
+using NetDisk;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BaiduYunSync
+{
+ ///
+ /// 用户信息类
+ ///
+ public class UserInfoDao
+ {
+ public int Id { get; set; }
+
+ ///
+ /// 用户名
+ ///
+ public string UserName { get; set; }
+
+ ///
+ /// 密码
+ ///
+ public string Password { get; set; }
+
+ ///
+ /// 用户凭据
+ ///
+ public string UserCredentialStr { get; set; }
+ }
+}
diff --git a/BaiduYunSync/frmLogin.Designer.cs b/BaiduYunSync/frmLogin.Designer.cs
new file mode 100644
index 0000000..833cd28
--- /dev/null
+++ b/BaiduYunSync/frmLogin.Designer.cs
@@ -0,0 +1,153 @@
+namespace BaiduYunSync
+{
+ partial class frmLogin
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.btnLogin = new System.Windows.Forms.Button();
+ this.pbVcode = new System.Windows.Forms.PictureBox();
+ this.txtVCode = new System.Windows.Forms.TextBox();
+ this.txtPassword = new System.Windows.Forms.TextBox();
+ this.txtUserName = new System.Windows.Forms.TextBox();
+ this.lbVcode = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ ((System.ComponentModel.ISupportInitialize)(this.pbVcode)).BeginInit();
+ this.SuspendLayout();
+ //
+ // btnLogin
+ //
+ this.btnLogin.Location = new System.Drawing.Point(15, 146);
+ this.btnLogin.Name = "btnLogin";
+ this.btnLogin.Size = new System.Drawing.Size(324, 28);
+ this.btnLogin.TabIndex = 12;
+ this.btnLogin.Text = "登录";
+ this.btnLogin.UseVisualStyleBackColor = true;
+ this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
+ //
+ // pbVcode
+ //
+ this.pbVcode.Location = new System.Drawing.Point(241, 91);
+ this.pbVcode.Name = "pbVcode";
+ this.pbVcode.Size = new System.Drawing.Size(99, 44);
+ this.pbVcode.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pbVcode.TabIndex = 9;
+ this.pbVcode.TabStop = false;
+ this.pbVcode.Visible = false;
+ this.pbVcode.Click += new System.EventHandler(this.pbVcode_Click);
+ //
+ // txtVCode
+ //
+ this.txtVCode.Location = new System.Drawing.Point(90, 97);
+ this.txtVCode.Name = "txtVCode";
+ this.txtVCode.Size = new System.Drawing.Size(119, 25);
+ this.txtVCode.TabIndex = 11;
+ this.txtVCode.Visible = false;
+ //
+ // txtPassword
+ //
+ this.txtPassword.Location = new System.Drawing.Point(90, 56);
+ this.txtPassword.Name = "txtPassword";
+ this.txtPassword.PasswordChar = '*';
+ this.txtPassword.Size = new System.Drawing.Size(251, 25);
+ this.txtPassword.TabIndex = 10;
+ //
+ // txtUserName
+ //
+ this.txtUserName.Location = new System.Drawing.Point(90, 14);
+ this.txtUserName.Name = "txtUserName";
+ this.txtUserName.Size = new System.Drawing.Size(251, 25);
+ this.txtUserName.TabIndex = 8;
+ this.txtUserName.Leave += new System.EventHandler(this.txtUserName_Leave);
+ //
+ // lbVcode
+ //
+ this.lbVcode.AutoSize = true;
+ this.lbVcode.Location = new System.Drawing.Point(12, 100);
+ this.lbVcode.Name = "lbVcode";
+ this.lbVcode.Size = new System.Drawing.Size(67, 15);
+ this.lbVcode.TabIndex = 5;
+ this.lbVcode.Text = "验证码:";
+ this.lbVcode.Visible = false;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(12, 59);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(52, 15);
+ this.label2.TabIndex = 6;
+ this.label2.Text = "密码:";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(12, 18);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(67, 15);
+ this.label1.TabIndex = 7;
+ this.label1.Text = "用户名:";
+ //
+ // frmLogin
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(362, 189);
+ this.Controls.Add(this.btnLogin);
+ this.Controls.Add(this.pbVcode);
+ this.Controls.Add(this.txtVCode);
+ this.Controls.Add(this.txtPassword);
+ this.Controls.Add(this.txtUserName);
+ this.Controls.Add(this.lbVcode);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "frmLogin";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "登录";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmLogin_FormClosing);
+ this.Load += new System.EventHandler(this.frmLogin_Load);
+ ((System.ComponentModel.ISupportInitialize)(this.pbVcode)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button btnLogin;
+ private System.Windows.Forms.PictureBox pbVcode;
+ private System.Windows.Forms.TextBox txtVCode;
+ private System.Windows.Forms.TextBox txtPassword;
+ private System.Windows.Forms.TextBox txtUserName;
+ private System.Windows.Forms.Label lbVcode;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label label1;
+ }
+}
\ No newline at end of file
diff --git a/BaiduYunSync/frmLogin.cs b/BaiduYunSync/frmLogin.cs
new file mode 100644
index 0000000..e72574b
--- /dev/null
+++ b/BaiduYunSync/frmLogin.cs
@@ -0,0 +1,91 @@
+using NetDisk;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace BaiduYunSync
+{
+ public partial class frmLogin : Form
+ {
+ public frmLogin()
+ {
+ InitializeComponent();
+ }
+
+ ///
+ /// 返回内容
+ ///
+ public LoginResult result;
+
+ private LoginCheckResult lcr;
+
+ private void txtUserName_Leave(object sender, EventArgs e)
+ {
+ if (txtUserName.Text == "")
+ {
+ lcr = null;
+ return;
+ }
+ lcr = Authentication.LoginCheck(txtUserName.Text);
+ if (!lcr.success)
+ {
+ MessageBox.Show("错误:" + lcr.exception);
+ return;
+ }
+ lbVcode.Visible = txtVCode.Visible = pbVcode.Visible = lcr.needVCode;
+ txtVCode.Text = "";
+ if (lcr.needVCode)
+ {
+ pbVcode.Image = ByteToImage(lcr.image);
+ }
+ }
+
+ private static Bitmap ByteToImage(byte[] blob)
+ {
+ MemoryStream mStream = new MemoryStream();
+ byte[] pData = blob;
+ mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
+ Bitmap bm = new Bitmap(mStream, false);
+ mStream.Dispose();
+ return bm;
+ }
+
+ private void frmLogin_Load(object sender, EventArgs e)
+ {
+ txtUserName.Focus();
+ }
+
+ private void btnLogin_Click(object sender, EventArgs e)
+ {
+ if (lcr == null) return;
+ lcr.verifyCode = txtVCode.Text;
+ result = Authentication.Login(txtUserName.Text, txtPassword.Text, lcr);
+ if (!result.success)
+ {
+ MessageBox.Show("出现错误: " + result.exception);
+ txtUserName_Leave(null, null);
+ return;
+ }
+ var userInfo = LiteDbHelper.UserInfo;
+ userInfo.UserName = txtUserName.Text;
+ userInfo.UserCredentialStr = result.credential.Serialize();
+ LiteDbHelper.UserInfo = userInfo;
+ DialogResult = DialogResult.OK;
+ }
+
+ private void pbVcode_Click(object sender, EventArgs e)
+ {
+ txtUserName_Leave(null, null);
+ }
+
+ private void frmLogin_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ }
+ }
+}
diff --git a/BaiduYunSync/frmLogin.resx b/BaiduYunSync/frmLogin.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/BaiduYunSync/frmLogin.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/BaiduYunSync/frmMain.Designer.cs b/BaiduYunSync/frmMain.Designer.cs
new file mode 100644
index 0000000..4739124
--- /dev/null
+++ b/BaiduYunSync/frmMain.Designer.cs
@@ -0,0 +1,179 @@
+namespace BaiduYunSync
+{
+ partial class frmMain
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.statusStrip1 = new System.Windows.Forms.StatusStrip();
+ this.tsslQuota = new System.Windows.Forms.ToolStripStatusLabel();
+ this.btnAddSync = new System.Windows.Forms.Button();
+ this.lvSyncFolder = new System.Windows.Forms.ListView();
+ this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.btnDelSync = new System.Windows.Forms.Button();
+ this.fbdSyncFloder = new System.Windows.Forms.FolderBrowserDialog();
+ this.txtReadLog = new System.Windows.Forms.Button();
+ this.btnUploadList = new System.Windows.Forms.Button();
+ this.statusStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // statusStrip1
+ //
+ this.statusStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
+ this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsslQuota});
+ this.statusStrip1.Location = new System.Drawing.Point(0, 361);
+ this.statusStrip1.Name = "statusStrip1";
+ this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 10, 0);
+ this.statusStrip1.Size = new System.Drawing.Size(620, 22);
+ this.statusStrip1.TabIndex = 3;
+ this.statusStrip1.Text = "statusStrip1";
+ //
+ // tsslQuota
+ //
+ this.tsslQuota.Name = "tsslQuota";
+ this.tsslQuota.Size = new System.Drawing.Size(131, 17);
+ this.tsslQuota.Text = "toolStripStatusLabel1";
+ this.tsslQuota.Click += new System.EventHandler(this.tsslQuota_Click);
+ //
+ // btnAddSync
+ //
+ this.btnAddSync.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnAddSync.Location = new System.Drawing.Point(535, 10);
+ this.btnAddSync.Name = "btnAddSync";
+ this.btnAddSync.Size = new System.Drawing.Size(75, 23);
+ this.btnAddSync.TabIndex = 0;
+ this.btnAddSync.Text = "添加新同步";
+ this.btnAddSync.UseVisualStyleBackColor = true;
+ this.btnAddSync.Click += new System.EventHandler(this.btnAddSync_Click);
+ //
+ // lvSyncFolder
+ //
+ this.lvSyncFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.lvSyncFolder.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeader1,
+ this.columnHeader2,
+ this.columnHeader3});
+ this.lvSyncFolder.FullRowSelect = true;
+ this.lvSyncFolder.GridLines = true;
+ this.lvSyncFolder.Location = new System.Drawing.Point(0, 0);
+ this.lvSyncFolder.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
+ this.lvSyncFolder.Name = "lvSyncFolder";
+ this.lvSyncFolder.Size = new System.Drawing.Size(531, 362);
+ this.lvSyncFolder.TabIndex = 4;
+ this.lvSyncFolder.UseCompatibleStateImageBehavior = false;
+ this.lvSyncFolder.View = System.Windows.Forms.View.Details;
+ //
+ // columnHeader1
+ //
+ this.columnHeader1.Text = "地址";
+ this.columnHeader1.Width = 265;
+ //
+ // columnHeader2
+ //
+ this.columnHeader2.Text = "同步状态";
+ this.columnHeader2.Width = 139;
+ //
+ // columnHeader3
+ //
+ this.columnHeader3.Text = "最后同步时间";
+ this.columnHeader3.Width = 116;
+ //
+ // btnDelSync
+ //
+ this.btnDelSync.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnDelSync.Location = new System.Drawing.Point(535, 53);
+ this.btnDelSync.Name = "btnDelSync";
+ this.btnDelSync.Size = new System.Drawing.Size(75, 23);
+ this.btnDelSync.TabIndex = 5;
+ this.btnDelSync.Text = "删除同步";
+ this.btnDelSync.UseVisualStyleBackColor = true;
+ this.btnDelSync.Click += new System.EventHandler(this.btnDelSync_Click);
+ //
+ // txtReadLog
+ //
+ this.txtReadLog.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtReadLog.Location = new System.Drawing.Point(535, 137);
+ this.txtReadLog.Name = "txtReadLog";
+ this.txtReadLog.Size = new System.Drawing.Size(75, 23);
+ this.txtReadLog.TabIndex = 6;
+ this.txtReadLog.Text = "查看日志";
+ this.txtReadLog.UseVisualStyleBackColor = true;
+ this.txtReadLog.Click += new System.EventHandler(this.txtReadLog_Click);
+ //
+ // btnUploadList
+ //
+ this.btnUploadList.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnUploadList.Location = new System.Drawing.Point(535, 97);
+ this.btnUploadList.Name = "btnUploadList";
+ this.btnUploadList.Size = new System.Drawing.Size(75, 23);
+ this.btnUploadList.TabIndex = 7;
+ this.btnUploadList.Text = "传输列表";
+ this.btnUploadList.UseVisualStyleBackColor = true;
+ this.btnUploadList.Click += new System.EventHandler(this.btnUploadList_Click);
+ //
+ // frmMain
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(620, 383);
+ this.Controls.Add(this.btnUploadList);
+ this.Controls.Add(this.txtReadLog);
+ this.Controls.Add(this.btnDelSync);
+ this.Controls.Add(this.lvSyncFolder);
+ this.Controls.Add(this.statusStrip1);
+ this.Controls.Add(this.btnAddSync);
+ this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
+ this.Name = "frmMain";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "百度云自动同步";
+ this.Load += new System.EventHandler(this.frmMain_Load);
+ this.statusStrip1.ResumeLayout(false);
+ this.statusStrip1.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+ private System.Windows.Forms.StatusStrip statusStrip1;
+ private System.Windows.Forms.ToolStripStatusLabel tsslQuota;
+ private System.Windows.Forms.Button btnAddSync;
+ private System.Windows.Forms.ListView lvSyncFolder;
+ private System.Windows.Forms.ColumnHeader columnHeader1;
+ private System.Windows.Forms.ColumnHeader columnHeader2;
+ private System.Windows.Forms.Button btnDelSync;
+ private System.Windows.Forms.FolderBrowserDialog fbdSyncFloder;
+ private System.Windows.Forms.ColumnHeader columnHeader3;
+ private System.Windows.Forms.Button txtReadLog;
+ private System.Windows.Forms.Button btnUploadList;
+ }
+}
+
diff --git a/BaiduYunSync/frmMain.cs b/BaiduYunSync/frmMain.cs
new file mode 100644
index 0000000..0010972
--- /dev/null
+++ b/BaiduYunSync/frmMain.cs
@@ -0,0 +1,174 @@
+using NetDisk;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace BaiduYunSync
+{
+ public partial class frmMain : Form
+ {
+ public frmMain()
+ {
+ InitializeComponent();
+ }
+
+ private void frmMain_Load(object sender, EventArgs e)
+ {
+ //var checkResult = Authentication.LoginCheck("2000208");
+ //MessageBox.Show(checkResult.needVCode.ToString());
+ if (!SetQuota())
+ {
+ var login = new frmLogin();
+ if (login.ShowDialog() == DialogResult.OK)
+ {
+ if (!SetQuota())
+ {
+ Application.Exit();
+ }
+ }
+ else
+ {
+ Application.Exit();
+ }
+ }
+ var items = LiteDbHelper.GetAllSyncItems();
+ foreach (var item in items)
+ {
+ addListViewItem(item);
+ }
+ Sync.StartSync += Sync_StartSync;
+ Sync.EndSync += Sync_EndSync;
+ Thread thread = new Thread(() => { Sync.SyncNow(Credential.Deserialize(LiteDbHelper.UserInfo.UserCredentialStr)); });
+ thread.IsBackground = true;
+ thread.Start();
+ }
+
+ private void Sync_EndSync(SyncItemsDao folder)
+ {
+ lvSyncFolder.BeginInvoke(new Action(
+ () =>
+ {
+ var items = lvSyncFolder.Items.Cast().Where(x => x.Text == folder.Folder);
+ if (items.Count() > 0)
+ {
+ items.ElementAt(0).SubItems[1].Text = "分析完成";
+ items.ElementAt(0).SubItems[2].Text = folder.LastSync.ToString();
+ }
+ }
+ ), null);
+ }
+
+ private void Sync_StartSync(string folder)
+ {
+ lvSyncFolder.BeginInvoke(new Action(
+ () =>
+ {
+ var items = lvSyncFolder.Items.Cast().Where(x => x.Text == folder);
+ if (items.Count() > 0)
+ {
+ items.ElementAt(0).SubItems[1].Text = "开始分析";
+ }
+ }
+ ), null);
+ }
+
+ private bool SetQuota()
+ {
+ var userInfo = LiteDbHelper.UserInfo;
+ if (userInfo == null || userInfo.UserCredentialStr == null)
+ {
+ return false;
+ }
+ var quotaResult = Operation.GetQuota(Credential.Deserialize(userInfo.UserCredentialStr));
+ if (!quotaResult.success)
+ {
+ MessageBox.Show("Error:" + quotaResult.exception);
+ return false;
+ }
+ else if (quotaResult.errno != 0)
+ {
+ return false;
+ }
+ tsslQuota.Text = "空间使用:已用" + GetGB(quotaResult.used) + "/总共" + GetGB(quotaResult.total);
+ return true;
+ }
+
+ ///
+ /// 将B转换为GB
+ ///
+ ///
+ ///
+ private string GetGB(long b)
+ {
+ var bb = (double)b;
+ for (int i = 0; i < 3; i++)
+ {
+ bb /= 1024;
+ }
+ return bb.ToString("f2") + "GB";
+ }
+
+ private void btnAddSync_Click(object sender, EventArgs e)
+ {
+ if (fbdSyncFloder.ShowDialog() == DialogResult.OK)
+ {
+ if (lvSyncFolder.Items.Cast().Select(x => (x.Tag as SyncItemsDao).Folder).Contains(fbdSyncFloder.SelectedPath))
+ {
+ MessageBox.Show("当前文件夹已在同步列表中,无需再次添加");
+ return;
+ }
+ var dao = new SyncItemsDao();
+ dao.Folder = fbdSyncFloder.SelectedPath;
+ dao.LastSync = new DateTime(1970, 1, 1);
+ LiteDbHelper.UpdateSyncItem(dao);
+ addListViewItem(dao);
+ Sync.mre.Set();
+ }
+ }
+
+ private void addListViewItem(SyncItemsDao dao)
+ {
+ var item = new ListViewItem(dao.Folder);
+ item.SubItems.Add("准备同步");
+ item.SubItems.Add(dao.LastSync.ToString());
+ item.Tag = dao;
+ item.ToolTipText = dao.Folder;
+ lvSyncFolder.Items.Add(item);
+ }
+
+ private void txtReadLog_Click(object sender, EventArgs e)
+ {
+ new frmReadLog().ShowDialog();
+ }
+
+ private void tsslQuota_Click(object sender, EventArgs e)
+ {
+ SetQuota();
+ }
+
+ private void btnDelSync_Click(object sender, EventArgs e)
+ {
+ foreach (ListViewItem item in lvSyncFolder.SelectedItems)
+ {
+ LiteDbHelper.DeleteSyncItem(item.Tag as SyncItemsDao);
+ lvSyncFolder.Items.Remove(item);
+ }
+ }
+
+ frmUploadList updateListForm;
+ private void btnUploadList_Click(object sender, EventArgs e)
+ {
+ if (updateListForm == null || updateListForm.IsDisposed)
+ {
+ updateListForm = new frmUploadList();
+ }
+ updateListForm.Show();
+ }
+ }
+}
diff --git a/BaiduYunSync/frmMain.resx b/BaiduYunSync/frmMain.resx
new file mode 100644
index 0000000..05f4ca0
--- /dev/null
+++ b/BaiduYunSync/frmMain.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 161, 17
+
+
\ No newline at end of file
diff --git a/BaiduYunSync/frmReadLog.Designer.cs b/BaiduYunSync/frmReadLog.Designer.cs
new file mode 100644
index 0000000..3873b21
--- /dev/null
+++ b/BaiduYunSync/frmReadLog.Designer.cs
@@ -0,0 +1,63 @@
+namespace BaiduYunSync
+{
+ partial class frmReadLog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.txtLog = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // txtLog
+ //
+ this.txtLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtLog.Location = new System.Drawing.Point(0, 0);
+ this.txtLog.Multiline = true;
+ this.txtLog.Name = "txtLog";
+ this.txtLog.ReadOnly = true;
+ this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.txtLog.Size = new System.Drawing.Size(554, 490);
+ this.txtLog.TabIndex = 0;
+ //
+ // frmReadLog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(554, 490);
+ this.Controls.Add(this.txtLog);
+ this.Name = "frmReadLog";
+ this.Text = "frmReadLog";
+ this.Load += new System.EventHandler(this.frmReadLog_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox txtLog;
+ }
+}
\ No newline at end of file
diff --git a/BaiduYunSync/frmReadLog.cs b/BaiduYunSync/frmReadLog.cs
new file mode 100644
index 0000000..d170397
--- /dev/null
+++ b/BaiduYunSync/frmReadLog.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace BaiduYunSync
+{
+ public partial class frmReadLog : Form
+ {
+ public frmReadLog()
+ {
+ InitializeComponent();
+ }
+
+ private void frmReadLog_Load(object sender, EventArgs e)
+ {
+ if (File.Exists("log/job.log"))
+ {
+ using (var fs = new FileStream("log/job.log", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ int fsLen = (int)fs.Length;
+ byte[] heByte = new byte[fsLen];
+ int r = fs.Read(heByte, 0, heByte.Length);
+ string myStr = System.Text.Encoding.Default.GetString(heByte);
+ txtLog.Text = myStr;
+ }
+ }
+ }
+ }
+}
diff --git a/BaiduYunSync/frmReadLog.resx b/BaiduYunSync/frmReadLog.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/BaiduYunSync/frmReadLog.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/BaiduYunSync/frmUploadList.Designer.cs b/BaiduYunSync/frmUploadList.Designer.cs
new file mode 100644
index 0000000..139b184
--- /dev/null
+++ b/BaiduYunSync/frmUploadList.Designer.cs
@@ -0,0 +1,140 @@
+namespace BaiduYunSync
+{
+ partial class frmUploadList
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.lvList = new System.Windows.Forms.ListView();
+ this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.cmsUploadList = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.删除选中任务ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.cmsUploadList.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // lvList
+ //
+ this.lvList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeader1,
+ this.columnHeader2,
+ this.columnHeader3,
+ this.columnHeader4,
+ this.columnHeader5,
+ this.columnHeader6});
+ this.lvList.ContextMenuStrip = this.cmsUploadList;
+ this.lvList.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lvList.FullRowSelect = true;
+ this.lvList.GridLines = true;
+ this.lvList.Location = new System.Drawing.Point(0, 0);
+ this.lvList.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
+ this.lvList.Name = "lvList";
+ this.lvList.ShowItemToolTips = true;
+ this.lvList.Size = new System.Drawing.Size(1023, 571);
+ this.lvList.TabIndex = 0;
+ this.lvList.UseCompatibleStateImageBehavior = false;
+ this.lvList.View = System.Windows.Forms.View.Details;
+ //
+ // columnHeader1
+ //
+ this.columnHeader1.Text = "文件名";
+ this.columnHeader1.Width = 138;
+ //
+ // columnHeader2
+ //
+ this.columnHeader2.Text = "传输状态";
+ this.columnHeader2.Width = 129;
+ //
+ // columnHeader3
+ //
+ this.columnHeader3.Text = "文件大小";
+ this.columnHeader3.Width = 128;
+ //
+ // columnHeader4
+ //
+ this.columnHeader4.Text = "分块信息";
+ this.columnHeader4.Width = 137;
+ //
+ // columnHeader5
+ //
+ this.columnHeader5.Text = "传输信息";
+ this.columnHeader5.Width = 140;
+ //
+ // columnHeader6
+ //
+ this.columnHeader6.Text = "绝对路径";
+ this.columnHeader6.Width = 346;
+ //
+ // cmsUploadList
+ //
+ this.cmsUploadList.ImageScalingSize = new System.Drawing.Size(20, 20);
+ this.cmsUploadList.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.删除选中任务ToolStripMenuItem});
+ this.cmsUploadList.Name = "cmsUploadList";
+ this.cmsUploadList.Size = new System.Drawing.Size(149, 26);
+ //
+ // 删除选中任务ToolStripMenuItem
+ //
+ this.删除选中任务ToolStripMenuItem.Name = "删除选中任务ToolStripMenuItem";
+ this.删除选中任务ToolStripMenuItem.Size = new System.Drawing.Size(148, 22);
+ this.删除选中任务ToolStripMenuItem.Text = "删除选中任务";
+ this.删除选中任务ToolStripMenuItem.Click += new System.EventHandler(this.删除选中任务ToolStripMenuItem_Click);
+ //
+ // frmUploadList
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1023, 571);
+ this.Controls.Add(this.lvList);
+ this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
+ this.Name = "frmUploadList";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "frmUploadList";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmUploadList_FormClosing);
+ this.Load += new System.EventHandler(this.frmUploadList_Load);
+ this.cmsUploadList.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ListView lvList;
+ private System.Windows.Forms.ColumnHeader columnHeader1;
+ private System.Windows.Forms.ColumnHeader columnHeader2;
+ private System.Windows.Forms.ColumnHeader columnHeader3;
+ private System.Windows.Forms.ColumnHeader columnHeader4;
+ private System.Windows.Forms.ColumnHeader columnHeader5;
+ private System.Windows.Forms.ColumnHeader columnHeader6;
+ private System.Windows.Forms.ContextMenuStrip cmsUploadList;
+ private System.Windows.Forms.ToolStripMenuItem 删除选中任务ToolStripMenuItem;
+ }
+}
\ No newline at end of file
diff --git a/BaiduYunSync/frmUploadList.cs b/BaiduYunSync/frmUploadList.cs
new file mode 100644
index 0000000..6fad032
--- /dev/null
+++ b/BaiduYunSync/frmUploadList.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace BaiduYunSync
+{
+ public partial class frmUploadList : Form
+ {
+ public frmUploadList()
+ {
+ InitializeComponent();
+ }
+
+ private void modifyTitle(int listCount, int totalCount)
+ {
+ Text = string.Format("传输文件列表:当前显示{0}条/共{1}条", listCount, totalCount);
+ }
+
+ ///
+ /// 将B转换为MB
+ ///
+ ///
+ ///
+ private string getMB(long b)
+ {
+ var bb = (double)b;
+ for (int i = 0; i < 2; i++)
+ {
+ bb /= 1024;
+ }
+ return bb.ToString("f2") + "MB";
+ }
+
+ private void initList()
+ {
+ lvList.Items.Clear();
+ var updateInfoList = LiteDbHelper.GetAllUpdateInfos();
+ var count = updateInfoList.Length > 99 ? 99 : updateInfoList.Length;
+ for (int i = 0; i < count; i++)
+ {
+ var updateInfo = updateInfoList[i];
+ addItem(updateInfo);
+ }
+ modifyTitle(count, updateInfoList.Length);
+ }
+
+ private void addItem(UpdateInfoDao updateInfo, int position = -1)
+ {
+ ListViewItem item = new ListViewItem(updateInfo.FileName);
+ item.Tag = updateInfo;
+ item.ToolTipText = updateInfo.Path;
+ item.SubItems.Add(updateInfo.Status == null ? "准备传输" : updateInfo.Status);
+ item.SubItems.Add(getMB(updateInfo.FileLength));
+ item.SubItems.Add(updateInfo.Status == null ? "" :
+ string.Format("已完成{0}块/共{1}块", updateInfo.ComplateBlockNum, updateInfo.TotalBlockNum));
+ item.SubItems.Add(updateInfo.Status == null ? "" :
+ string.Format("已完成{0}/共{1}", updateInfo.ComplateBlockNum == updateInfo.TotalBlockNum ?
+ getMB(updateInfo.FileLength) : updateInfo.ComplateBlockNum * 4 + "MB", getMB(updateInfo.FileLength)));
+ item.SubItems.Add(updateInfo.Path);
+ if (position == -1)
+ {
+ lvList.Items.Add(item);
+ }
+ else
+ {
+ lvList.Items.Insert(position, item);
+ }
+ }
+
+ private void removeItem(string path)
+ {
+ if (lvList.Items.Cast().Select(x => x.SubItems[5].Text).Contains(path))
+ {
+ lvList.Items.Cast().Where(x => x.SubItems[5].Text == path).First().Remove();
+ }
+ }
+
+ private void modifyItem(UpdateInfoDao updateInfo)
+ {
+ if (lvList.Items.Cast().Select(x => x.SubItems[5].Text).Contains(updateInfo.Path))
+ {
+ var item = lvList.Items.Cast().Where(x => x.SubItems[5].Text == updateInfo.Path).First();
+ item.SubItems[1].Text = updateInfo.Status;
+ item.SubItems[3].Text = updateInfo.Status == null ? "" :
+ string.Format("已完成{0}块/共{1}块", updateInfo.ComplateBlockNum, updateInfo.TotalBlockNum);
+ item.SubItems[4].Text = updateInfo.Status == null ? "" :
+ string.Format("已完成{0}/共{1}", updateInfo.ComplateBlockNum == updateInfo.TotalBlockNum ?
+ getMB(updateInfo.FileLength) : updateInfo.ComplateBlockNum * 4 + "MB", getMB(updateInfo.FileLength));
+ item.Tag = updateInfo;
+ }
+ }
+
+ private void frmUploadList_Load(object sender, EventArgs e)
+ {
+ initList();
+ Sync.StatusModify += Sync_StatusModify;
+ }
+
+ private void Sync_StatusModify(string path, Sync.StatusEnum status)
+ {
+ lvList.BeginInvoke(new Action(
+ () =>
+ {
+ UpdateInfoDao updateInfo;
+ switch (status)
+ {
+ case Sync.StatusEnum.Add:
+ if (lvList.Items.Count < 99)
+ {
+ updateInfo = LiteDbHelper.GetUpdateInfoFormPath(path);
+ if (updateInfo != null)
+ {
+ addItem(LiteDbHelper.GetUpdateInfoFormPath(path));
+ }
+
+ }
+ break;
+ case Sync.StatusEnum.Start:
+ case Sync.StatusEnum.Modify:
+ updateInfo = LiteDbHelper.GetUpdateInfoFormPath(path);
+ if (updateInfo != null)
+ {
+ modifyItem(updateInfo);
+ }
+
+ break;
+ case Sync.StatusEnum.Delete:
+ removeItem(path);
+ var count = LiteDbHelper.GetUpdateInfoCount();
+ if (count > 98)
+ {
+ addItem(LiteDbHelper.GetAllUpdateInfos()[98]);
+ }
+ modifyTitle(count > 99 ? 99 : lvList.Items.Count, count);
+ break;
+ default:
+ break;
+ }
+ }
+ ), null);
+
+ }
+
+ private void 删除选中任务ToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ foreach (ListViewItem item in lvList.SelectedItems)
+ {
+ var updateInfo = item.Tag as UpdateInfoDao;
+ if (updateInfo.Status != null)
+ {
+ MessageBox.Show(updateInfo.FileName + "正在传输,暂不支持移除", "提示");
+ return;
+ }
+ LiteDbHelper.DeleteUpdateInfo(updateInfo);
+ }
+ initList();
+ if (lvList.Items.Count == 0)
+ {
+ Sync.mre.Set();
+ }
+ }
+
+ private void frmUploadList_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ Sync.StatusModify -= Sync_StatusModify;
+ }
+ }
+}
diff --git a/BaiduYunSync/frmUploadList.resx b/BaiduYunSync/frmUploadList.resx
new file mode 100644
index 0000000..48a459e
--- /dev/null
+++ b/BaiduYunSync/frmUploadList.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/BaiduYunSync/packages.config b/BaiduYunSync/packages.config
new file mode 100644
index 0000000..55a9c3d
--- /dev/null
+++ b/BaiduYunSync/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NetDisk/Authentication.cs b/NetDisk/Authentication.cs
new file mode 100644
index 0000000..2cd050c
--- /dev/null
+++ b/NetDisk/Authentication.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace NetDisk
+{
+ public static class Authentication
+ {
+ public static bool IsLoggedIn(Credential credential)
+ {
+ var res = Operation.GetQuota(credential);
+ if (res == null || res.errno != 0) return false;
+ else return true;
+ }
+ public static LoginResult Login(string username, string password, LoginCheckResult checkResult)
+ {
+ var result = new LoginResult();
+ try
+ {
+ using (var wc = new CookieAwareWebClient())
+ {
+ wc.Cookies.Add(checkResult.baiduid);
+ var ltoken = checkResult.ltoken;
+ var lstr = "loginmerge=true&token=" + ltoken + "&tpl=netdisk&username=" + Uri.EscapeDataString(username) + "&password=" + Uri.EscapeDataString(password);
+ if (checkResult.needVCode) lstr += "&codestring=" + checkResult.codeString + "&verifycode=" + Uri.EscapeDataString(checkResult.verifyCode);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var str = Encoding.UTF8.GetString(wc.UploadData("https://passport.baidu.com/v2/api/?login", Encoding.UTF8.GetBytes(lstr)));
+ var match = Regex.Match(str, "error=(\\d+)");
+ var errno = match.Success ? int.Parse(match.Groups[1].Value) : 0;
+ if (errno != 0)
+ {
+ result.exception = new Exception("Login returned error = " + errno);
+ result.errno = errno;
+ }
+ else
+ {
+ str = wc.DownloadString("https://passport.baidu.com/v3/login/api/auth/?return_type=3&tpl=netdisk&u=http%3A%2F%2Fpan.baidu.com%2Fdisk%2Fhome");
+ long uid = 0;
+ match = Regex.Match(str, "\"uk\"\\s*:\\s*(\\d+)");
+ if (match.Success) long.TryParse(match.Groups[1].Value, out uid);
+ string baiduid = null, bduss = null, stoken = null;
+ foreach (Cookie cookie in wc.Cookies.GetAllCookies())
+ {
+ if (cookie.Name.ToLower() == "baiduid") baiduid = cookie.Value;
+ else if (cookie.Name.ToLower() == "bduss") bduss = cookie.Value;
+ else if (cookie.Name.ToLower() == "stoken" && cookie.Domain.ToLower().Contains("pan.")) stoken = cookie.Value;
+ }
+ if (baiduid != null && bduss != null && stoken != null)
+ {
+ result.credential = new Credential(baiduid, bduss, stoken, uid);
+ result.success = true;
+ }
+ else result.exception = new Exception("Cannot find required cookies.");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ result.exception = ex;
+ }
+ return result;
+ }
+ public static LoginCheckResult LoginCheck(string username)
+ {
+ var result = new LoginCheckResult();
+ try
+ {
+ using (var wc = new CookieAwareWebClient())
+ {
+ wc.DownloadData("http://pan.baidu.com/");
+ Cookie baiduid = null;
+ foreach (Cookie cookie in wc.Cookies.GetAllCookies())
+ {
+ if (cookie.Name.ToLower() == "baiduid") baiduid = cookie;
+ }
+ if (baiduid == null) throw new Exception("Cannot obtain BAIDUID.");
+ result.baiduid = baiduid;
+ var str = wc.DownloadString("https://passport.baidu.com/v2/api/?getapi&tpl=netdisk&subpro=netdisk_web&apiver=v3");
+ var ltoken = Regex.Match(str, "\"token\"\\s*:\\s*\"(.+?)\"").Groups[1].Value;
+ result.ltoken = ltoken;
+ str = wc.DownloadString("https://passport.baidu.com/v2/api/?logincheck&token=" + ltoken + "&tpl=netdisk&subpro=netdisk_web&apiver=v3&username=" + Uri.EscapeDataString(username));
+ var codeString = Regex.Match(str, "\"codeString\"\\s*:\\s*\"(.*?)\"").Groups[1].Value;
+ if (codeString == "")
+ {
+ result.success = true;
+ }
+ else
+ {
+ result.image = wc.DownloadData("https://passport.baidu.com/cgi-bin/genimage?" + codeString);
+ result.success = true;
+ result.needVCode = true;
+ result.codeString = codeString;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ result.exception = ex;
+ }
+ return result;
+ }
+ }
+}
diff --git a/NetDisk/CRC32.cs b/NetDisk/CRC32.cs
new file mode 100644
index 0000000..0da824c
--- /dev/null
+++ b/NetDisk/CRC32.cs
@@ -0,0 +1,119 @@
+// Copyright (c) Damien Guard. All rights reserved.
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+// Originally published at http://damieng.com/blog/2006/08/08/calculating_crc32_in_c_and_net
+
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+
+namespace DamienG.Security.Cryptography
+{
+ ///
+ /// Implements a 32-bit CRC hash algorithm compatible with Zip etc.
+ ///
+ ///
+ /// Crc32 should only be used for backward compatibility with older file formats
+ /// and algorithms. It is not secure enough for new applications.
+ /// If you need to call multiple times for the same data either use the HashAlgorithm
+ /// interface or remember that the result of one Compute call needs to be ~ (XOR) before
+ /// being passed in as the seed for the next Compute call.
+ ///
+ public sealed class Crc32 : HashAlgorithm
+ {
+ public const UInt32 DefaultPolynomial = 0xedb88320u;
+ public const UInt32 DefaultSeed = 0xffffffffu;
+
+ static UInt32[] defaultTable;
+
+ readonly UInt32 seed;
+ readonly UInt32[] table;
+ UInt32 hash;
+
+ public Crc32()
+ : this(DefaultPolynomial, DefaultSeed)
+ {
+ }
+
+ public Crc32(UInt32 polynomial, UInt32 seed)
+ {
+ table = InitializeTable(polynomial);
+ this.seed = hash = seed;
+ }
+
+ public override void Initialize()
+ {
+ hash = seed;
+ }
+
+ protected override void HashCore(byte[] array, int ibStart, int cbSize)
+ {
+ hash = CalculateHash(table, hash, array, ibStart, cbSize);
+ }
+
+ protected override byte[] HashFinal()
+ {
+ var hashBuffer = UInt32ToBigEndianBytes(~hash);
+ HashValue = hashBuffer;
+ return hashBuffer;
+ }
+
+ public override int HashSize { get { return 32; } }
+
+ public static UInt32 Compute(byte[] buffer)
+ {
+ return Compute(DefaultSeed, buffer);
+ }
+
+ public static UInt32 Compute(UInt32 seed, byte[] buffer)
+ {
+ return Compute(DefaultPolynomial, seed, buffer);
+ }
+
+ public static UInt32 Compute(UInt32 polynomial, UInt32 seed, byte[] buffer)
+ {
+ return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
+ }
+
+ static UInt32[] InitializeTable(UInt32 polynomial)
+ {
+ if (polynomial == DefaultPolynomial && defaultTable != null)
+ return defaultTable;
+
+ var createTable = new UInt32[256];
+ for (var i = 0; i < 256; i++)
+ {
+ var entry = (UInt32)i;
+ for (var j = 0; j < 8; j++)
+ if ((entry & 1) == 1)
+ entry = (entry >> 1) ^ polynomial;
+ else
+ entry = entry >> 1;
+ createTable[i] = entry;
+ }
+
+ if (polynomial == DefaultPolynomial)
+ defaultTable = createTable;
+
+ return createTable;
+ }
+
+ static UInt32 CalculateHash(UInt32[] table, UInt32 seed, IList buffer, int start, int size)
+ {
+ var hash = seed;
+ for (var i = start; i < start + size; i++)
+ hash = (hash >> 8) ^ table[buffer[i] ^ hash & 0xff];
+ return hash;
+ }
+
+ static byte[] UInt32ToBigEndianBytes(UInt32 uint32)
+ {
+ var result = BitConverter.GetBytes(uint32);
+
+ if (BitConverter.IsLittleEndian)
+ Array.Reverse(result);
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NetDisk/CookieAwareWebClient.cs b/NetDisk/CookieAwareWebClient.cs
new file mode 100644
index 0000000..2196052
--- /dev/null
+++ b/NetDisk/CookieAwareWebClient.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Net;
+
+namespace NetDisk
+{
+ public class CookieAwareWebClient : WebClient
+ {
+ public CookieContainer Cookies { get; set; }
+ public Uri Uri { get; set; }
+ Uri _responseUri;
+ public Uri ResponseUri
+ {
+ get { return _responseUri; }
+ }
+ public CookieAwareWebClient()
+ : this(new CookieContainer())
+ {
+ }
+
+ public CookieAwareWebClient(CookieContainer cookies)
+ {
+ this.Cookies = cookies;
+ }
+
+ protected override WebRequest GetWebRequest(Uri address)
+ {
+ WebRequest request = base.GetWebRequest(address);
+ if (request is HttpWebRequest)
+ {
+ ClearCookiesVersion();
+ (request as HttpWebRequest).CookieContainer = this.Cookies;
+ }
+ HttpWebRequest httpRequest = (HttpWebRequest)request;
+ httpRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
+ return httpRequest;
+ }
+ protected override WebResponse GetWebResponse(WebRequest request)
+ {
+ WebResponse response = base.GetWebResponse(request);
+ _responseUri = response.ResponseUri;
+ return response;
+ }
+ private void ClearCookiesVersion()
+ {
+ var cc = new CookieContainer();
+ foreach (Cookie cookie in Cookies.GetAllCookies())
+ {
+ cookie.Version = 0;
+ cc.Add(cookie);
+ }
+ Cookies = cc;
+ }
+ }
+}
diff --git a/NetDisk/Credential.cs b/NetDisk/Credential.cs
new file mode 100644
index 0000000..92bce50
--- /dev/null
+++ b/NetDisk/Credential.cs
@@ -0,0 +1,74 @@
+using System.Net;
+
+namespace NetDisk
+{
+ public class Credential
+ {
+ private string baiduid;
+ public string Baiduid
+ {
+ get
+ {
+ return baiduid;
+ }
+ }
+
+ private string bduss;
+ public string Bduss
+ {
+ get
+ {
+ return bduss;
+ }
+ }
+
+ private string stoken;
+ public string Stoken
+ {
+ get
+ {
+ return stoken;
+ }
+ }
+
+ private long uid;
+ public long Uid
+ {
+ get
+ {
+ return uid;
+ }
+ }
+
+ private string cookieString;
+ public Credential(string baiduid, string bduss, string stoken, long uid)
+ {
+ this.baiduid = baiduid;
+ this.bduss = bduss;
+ this.stoken = stoken;
+ this.uid = uid;
+ cookieString = "BAIDUID=" + baiduid + "; BDUSS=" + bduss + "; STOKEN=" + stoken;
+ }
+ public static implicit operator string(Credential credential)
+ {
+ return credential.cookieString;
+ }
+ public static implicit operator CookieCollection(Credential credential)
+ {
+ var c = new CookieCollection();
+ c.Add(new Cookie("BAIDUID", credential.baiduid, "/", ".baidu.com"));
+ c.Add(new Cookie("BDUSS", credential.bduss, "/", ".baidu.com"));
+ c.Add(new Cookie("STOKEN", credential.stoken, "/", ".pan.baidu.com"));
+ return c;
+ }
+ public string Serialize()
+ {
+ return baiduid + "$" + bduss + "$" + stoken + "$" + uid;
+ }
+ public static Credential Deserialize(string str)
+ {
+ var tokens = str.Split('$');
+ return new Credential(tokens[0], tokens[1], tokens[2], long.Parse(tokens[3]));
+ }
+ }
+}
diff --git a/NetDisk/Extension.cs b/NetDisk/Extension.cs
new file mode 100644
index 0000000..5f8aaf3
--- /dev/null
+++ b/NetDisk/Extension.cs
@@ -0,0 +1,28 @@
+using System.Collections;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+
+namespace NetDisk
+{
+ public static class Extension
+ {
+ public static CookieCollection GetAllCookies(this CookieContainer container)
+ {
+ var allCookies = new CookieCollection();
+ var domainTableField = container.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).FirstOrDefault(x => x.Name == "m_domainTable");
+ var domains = (IDictionary)domainTableField.GetValue(container);
+
+ foreach (var val in domains.Values)
+ {
+ var type = val.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).First(x => x.Name == "m_list");
+ var values = (IDictionary)type.GetValue(val);
+ foreach (CookieCollection cookies in values.Values)
+ {
+ allCookies.Add(cookies);
+ }
+ }
+ return allCookies;
+ }
+ }
+}
diff --git a/NetDisk/NetDisk.csproj b/NetDisk/NetDisk.csproj
new file mode 100644
index 0000000..fe1e988
--- /dev/null
+++ b/NetDisk/NetDisk.csproj
@@ -0,0 +1,79 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {74ECA1BF-6508-417D-BC57-DB00DAECA618}
+ Library
+ Properties
+ NetDisk
+ NetDisk
+ v4.0
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+ ..\packages\Newtonsoft.Json.9.0.1\lib\net40\Newtonsoft.Json.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Component
+
+
+
+
+
+
+ Component
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetDisk/Operation.cs b/NetDisk/Operation.cs
new file mode 100644
index 0000000..0eee553
--- /dev/null
+++ b/NetDisk/Operation.cs
@@ -0,0 +1,674 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Runtime.Serialization;
+using System.Text;
+using Newtonsoft.Json;
+using System.Text.RegularExpressions;
+using System.IO;
+using System.Web;
+
+namespace NetDisk
+{
+ public static class Operation
+ {
+ ///
+ /// 块完成事件(顺序提交)
+ ///
+ /// 文件名
+ /// 当前完成的块
+ /// 总块数
+ public delegate void ComplateUploadBlockHandle(string filePath, int endBlockNum, int totalBlockNum);
+
+ public static event ComplateUploadBlockHandle ComplateUploadBlock;
+
+ ///
+ /// 初始化上传
+ ///
+ /// 文件名
+ /// 文件所拥有的块数
+ /// 服务器需要上传的块数
+ public delegate void InitUploadFileHandle(string filePath, int fileBlockNum, int needUploadBlockNum);
+
+ public static event InitUploadFileHandle InitUploadFile;
+
+ ///
+ /// 开始上传块
+ ///
+ /// 文件名
+ /// 当前开始的块
+ /// 总块数
+ public delegate void StartUploadBlockHandle(string filePath, int startBlockNum, int totalBlockNum);
+
+ public static event StartUploadBlockHandle StartUploadBlock;
+
+ ///
+ /// 上传完成
+ ///
+ /// 文件名
+ public delegate void UpdateComplateHandle(string filePath);
+
+ public static event UpdateComplateHandle UpdateComplate;
+
+
+ public static QuotaResult GetQuota(Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ var res = wc.DownloadString("http://pan.baidu.com/api/quota?checkexpire=1&checkfree=1");
+ var obj = JsonConvert.DeserializeObject(res);
+ obj.success = true;
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new QuotaResult() { exception = ex };
+ }
+ }
+ public static UserInfoResult GetUserInfo(Credential credential)
+ {
+ try
+ {
+ if (credential.Uid <= 0) throw new Exception("Invalid uid.");
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ var res = wc.DownloadString("http://pan.baidu.com/api/user/getinfo?user_list=[" + credential.Uid + "]");
+ var obj = JsonConvert.DeserializeObject(res);
+ obj.success = true;
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new UserInfoResult() { exception = ex };
+ }
+ }
+ public static FileListResult GetFileList(string path, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ var res = wc.DownloadString("http://pan.baidu.com/api/list?page=1&num=10000000&dir=" + HttpUtility.UrlEncode(path));
+ var obj = JsonConvert.DeserializeObject(res);
+ obj.success = true;
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new FileListResult() { exception = ex };
+ }
+ }
+ public static ThumbnailResult GetThumbnail(string path, Credential credential, int width = 125, int height = 90, int quality = 100)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ var res = wc.DownloadData("http://pcsdata.baidu.com/rest/2.0/pcs/thumbnail?app_id=250528&method=generate&path=" + HttpUtility.UrlEncode(path) + "&quality=" + quality + "&height=" + height + "&width=" + width);
+ return new ThumbnailResult() { success = true, image = res };
+ }
+ }
+ catch (Exception ex)
+ {
+ return new ThumbnailResult() { exception = ex };
+ }
+ }
+ public static GetDownloadResult GetDownload(string path, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.UserAgent, "netdisk;5.4.5.4;PC;PC-Windows;10.0.14393;WindowsBaiduYunGuanJia");
+ var res = wc.DownloadString("http://d.pcs.baidu.com/rest/2.0/pcs/file?app_id=250528&method=locatedownload&ver=4.0&path=" + HttpUtility.UrlEncode(path));
+ var obj = JsonConvert.DeserializeObject(res);
+ obj.success = true;
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new GetDownloadResult() { exception = ex };
+ }
+ }
+ public static FileOperationResult CreateFolder(string path, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var str = "isdir=1&path=" + HttpUtility.UrlEncode(path);
+ var res = wc.UploadData("http://pan.baidu.com/api/create?a=commit", Encoding.UTF8.GetBytes(str));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ obj.success = true;
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new FileOperationResult() { exception = ex };
+ }
+ }
+ public static FileOperationResult Copy(string path, string dest, string newname, Credential credential)
+ {
+ var str = "filelist=[{\"path\":\"" + HttpUtility.UrlEncode(path) + "\",\"dest\":\"" + HttpUtility.UrlEncode(dest) + "\",\"newname\":\"" + HttpUtility.UrlEncode(newname) + "\"}]";
+ return FileOp("http://pan.baidu.com/api/filemanager?opera=copy&clienttype=8", str, credential);
+ }
+ public static FileOperationResult Delete(string path, Credential credential)
+ {
+ var str = "filelist=[\"" + HttpUtility.UrlEncode(path) + "\"]";
+ return FileOp("http://pan.baidu.com/api/filemanager?opera=delete&clienttype=8", str, credential);
+ }
+ public static FileOperationResult Move(string path, string dest, string newname, Credential credential)
+ {
+ var str = "filelist=[{\"path\":\"" + HttpUtility.UrlEncode(path) + "\",\"dest\":\"" + HttpUtility.UrlEncode(dest) + "\",\"newname\":\"" + HttpUtility.UrlEncode(newname) + "\"}]";
+ return FileOp("http://pan.baidu.com/api/filemanager?opera=move&clienttype=8", str, credential);
+ }
+ public static FileOperationResult Rename(string path, string newname, Credential credential)
+ {
+ var str = "filelist=[{\"path\":\"" + HttpUtility.UrlEncode(path) + "\",\"newname\":\"" + HttpUtility.UrlEncode(newname) + "\"}]";
+ return FileOp("http://pan.baidu.com/api/filemanager?opera=rename&clienttype=8", str, credential);
+ }
+ private static FileOperationResult FileOp(string url, string str, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var res = wc.UploadData(url, Encoding.UTF8.GetBytes(str));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ if (obj.info.Length == 0 && obj.errno != 0)
+ return new FileOperationResult() { success = true, errno = obj.errno };
+ else if (obj.info.Length == 0 || obj.errno != 0 && obj.info[0].errno == 0)
+ throw new Exception("Response data malformat.");
+ else
+ return new FileOperationResult() { success = true, errno = obj.info[0].errno, path = obj.info[0].path };
+ }
+ }
+ catch (Exception ex)
+ {
+ return new FileOperationResult() { exception = ex };
+ }
+ }
+ public static OfflineListResult GetOfflineList(Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ var res1 = wc.DownloadString("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&method=list_task&need_task_info=1&status=255");
+ var ltr = JsonConvert.DeserializeObject(res1);
+ if (ltr.task_info.Length == 0) return new OfflineListResult() { success = true, tasks = new OfflineListResult.Entry[0] };
+ var str = "method=query_task&op_type=1&task_ids=" + HttpUtility.UrlEncode(string.Join(",", ltr.task_info.Select(e => e.task_id.ToString())));
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var res2 = wc.UploadData("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528", Encoding.UTF8.GetBytes(str));
+ var qtr = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res2));
+ return new OfflineListResult()
+ {
+ tasks = ltr.task_info.Select(e =>
+ {
+ var ai = qtr.task_info[e.task_id.ToString()];
+ return new OfflineListResult.Entry()
+ {
+ create_time = e.create_time,
+ od_type = e.od_type,
+ save_path = e.save_path,
+ source_url = e.source_url,
+ task_id = e.task_id,
+ task_name = e.task_name,
+ file_size = ai.file_size,
+ finished_size = ai.finished_size,
+ status = ai.status
+ };
+ }).ToArray(),
+ success = true
+ };
+ }
+ }
+ catch (Exception ex)
+ {
+ return new OfflineListResult() { exception = ex };
+ }
+ }
+ public static Result CancelOfflineTask(long taskid, Credential credential)
+ {
+ return OfflineTaskOp(taskid, "cancel_task", credential);
+ }
+ public static Result DeleteOfflineTask(long taskid, Credential credential)
+ {
+ return OfflineTaskOp(taskid, "delete_task", credential);
+ }
+ public static Result ClearOfflineTask(Credential credential)
+ {
+ return OfflineTaskOp(0, "clear_task", credential);
+ }
+ private static Result OfflineTaskOp(long taskid, string oper, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.DownloadData("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&method=" + oper + "&task_id=" + taskid);
+ return new Result() { success = true };
+ }
+ }
+ catch (Exception ex)
+ {
+ return new Result() { exception = ex };
+ }
+ }
+ public static QueryLinkResult QueryLinkFiles(string link, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.UserAgent, "netdisk;5.4.5.4;PC;PC-Windows;10.0.14393;WindowsBaiduYunGuanJia");
+ if (link.StartsWith("magnet:", StringComparison.OrdinalIgnoreCase))
+ {
+ var res = wc.DownloadString("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&clienttype=8&method=query_magnetinfo&source_url=" + HttpUtility.UrlEncode(link));
+ var obj = JsonConvert.DeserializeObject(res);
+ return new QueryLinkResult() { success = true, files = obj.magnet_info };
+ }
+ else if (link.EndsWith(".torrent", StringComparison.OrdinalIgnoreCase))
+ {
+ var res = wc.DownloadString("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&clienttype=8&method=query_sinfo&type=2&source_path=" + HttpUtility.UrlEncode(link));
+ var obj = JsonConvert.DeserializeObject(res);
+ return new QueryLinkResult() { success = true, files = obj.torrent_info.file_info };
+ }
+ else throw new Exception("Not a magnet link or a torrent file.");
+ }
+ }
+ catch (Exception ex)
+ {
+ return new QueryLinkResult() { exception = ex };
+ }
+ }
+ public static AddOfflineTaskResult AddOfflineTask(string link, string savepath, Credential credential, int[] selected = null, string sha1 = "")
+ {
+ try
+ {
+ var str = "method=add_task&save_path=" + HttpUtility.UrlEncode(savepath) + "&";
+ if (link.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || link.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
+ str += "type=0&source_url=" + HttpUtility.UrlEncode(link);
+ else if (link.StartsWith("ed2k://", StringComparison.OrdinalIgnoreCase))
+ str += "type=3&source_url=" + HttpUtility.UrlEncode(link);
+ else if (link.StartsWith("magnet:", StringComparison.OrdinalIgnoreCase))
+ str += "type=4&task_from=5&source_url=" + HttpUtility.UrlEncode(link) + "&selected_idx=" + string.Join(",", selected.Select(i => i.ToString()));
+ else if (link.EndsWith(".torrent", StringComparison.OrdinalIgnoreCase))
+ str += "type=2&task_from=5&file_sha1=" + sha1 + "&source_path=" + HttpUtility.UrlEncode(link) + "&selected_idx=" + string.Join(",", selected.Select(i => i.ToString()));
+ else throw new Exception("Link invalid.");
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ wc.Headers.Add(HttpRequestHeader.UserAgent, "netdisk;5.4.5.4;PC;PC-Windows;10.0.14393;WindowsBaiduYunGuanJia");
+ var res = wc.UploadData("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&clienttype=8", Encoding.UTF8.GetBytes(str));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ obj.success = true;
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new AddOfflineTaskResult() { exception = ex };
+ }
+ }
+ public static ShareResult Share(string[] pathlist, Credential credential, string pwd = null)
+ {
+ try
+ {
+ if (pwd != null && pwd.Length != 4) throw new Exception("Length of pwd must be 4.");
+ var str = "path_list=[" + string.Join(",", pathlist.Select(p => '"' + HttpUtility.UrlEncode(p) + '"')) + "]&channel_list=[]&shorturl=1&";
+ if (pwd == null) str += "public=1&schannel=0";
+ else str += "public=0&schannel=4&pwd=" + pwd;
+ var rand = new Random();
+ var logid = new string(Enumerable.Range(0, 100).Select(i => (char)('a' + rand.Next(26))).ToArray());
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var res = wc.UploadData("http://pan.baidu.com/share/pset?clienttype=8&channel=00000000000000000000000000000000&version=5.4.5.4&devuid=123456&logid=" + logid, Encoding.UTF8.GetBytes(str));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ obj.success = true;
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new ShareResult() { exception = ex };
+ }
+ }
+ public static TransferResult Transfer(string url, string path, Credential credential, string pwd = null)
+ {
+ try
+ {
+ using (var wc = new CookieAwareWebClient())
+ {
+ wc.Cookies.Add(credential);
+ var str = wc.DownloadString(url);
+ var rurl = wc.ResponseUri.ToString();
+ string shareid = null, uk = null;
+ if (rurl.Contains("/share/init"))
+ {
+ if (pwd == null) throw new Exception("Need password.");
+ shareid = Regex.Match(rurl, "shareid=(\\d+)").Groups[1].Value;
+ uk = Regex.Match(rurl, "uk=(\\d+)").Groups[1].Value;
+ wc.Headers.Add(HttpRequestHeader.Referer, rurl);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var res = wc.UploadData("http://pan.baidu.com/share/verify?shareid=" + shareid + "&uk=" + uk, Encoding.UTF8.GetBytes("vcode=&vcode_str=&pwd=" + pwd));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ if (obj.errno != 0) throw new Exception("Password verification returned errno = " + obj.errno);
+ str = wc.DownloadString(url);
+ }
+ str = Regex.Match(str, "yunData.setData(.*)").Groups[1].Value.Trim();
+ str = str.Substring(1, str.Length - 3);
+ var obj2 = JsonConvert.DeserializeObject(str);
+ str = "path=" + HttpUtility.UrlEncode(path) + "&filelist=[" + string.Join(",", obj2.file_list.list.Select(e => "\"" + HttpUtility.UrlEncode(e.path) + "\"")) + "]";
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ wc.Headers.Add(HttpRequestHeader.Referer, url);
+ var rand = new Random();
+ var logid = new string(Enumerable.Range(0, 100).Select(i => (char)('a' + rand.Next(26))).ToArray());
+ var res2 = wc.UploadData("http://pan.baidu.com/share/transfer?channel=chunlei&clienttype=0&web=1&app_id=250528&ondup=newcopy&async=1&shareid=" + shareid + "&from=" + uk + "&logid=" + logid + "&bdstoken=" + obj2.bdstoken, Encoding.UTF8.GetBytes(str));
+ var obj3 = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res2));
+ obj3.success = true;
+ return obj3;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new TransferResult() { exception = ex };
+ }
+ }
+ public static CommitUploadResult SimpleUpload(string localpath, string remotepath, Credential credential, string host = "c.pcs.baidu.com")
+ {
+ try
+ {
+ var size = new FileInfo(localpath).Length;
+ var mtime = (long)(new FileInfo(localpath).LastAccessTime.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
+ var md5 = UploadHelper.GetMD5HashFromFile(localpath);
+ var str = "path=" + remotepath + "&size=" + size + "&isdir=0&block_list=[\"" + md5 + "\"]&autoinit=1&local_mtime=" + mtime + "&method=post";
+ using (var wc = new PatientWebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var res = wc.UploadData("http://pan.baidu.com/api/precreate?clienttype=8", Encoding.UTF8.GetBytes(str));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ if (obj.errno != 0) throw new Exception("precreate had errno = " + obj.errno);
+ var boundary = GetBoundary();
+ wc.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary);
+ str = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"filename\"; filename=\"name\"\r\nContent-Type: application/octet-stream\r\n\r\n";
+ var str2 = "\r\n--" + boundary + "--\r\n";
+ var data = Encoding.UTF8.GetBytes(str).Concat(File.ReadAllBytes(localpath)).Concat(Encoding.UTF8.GetBytes(str2)).ToArray();
+ res = wc.UploadData("http://" + host + "/rest/2.0/pcs/superfile2?app_id=250528&method=upload&path=" + HttpUtility.UrlEncode(remotepath) + "&uploadid=" + HttpUtility.UrlEncode(obj.uploadid) + "&partseq=0&partoffset=0", data);
+ str = "path=" + remotepath + "&size=" + size + "&isdir=0&uploadid=" + HttpUtility.UrlEncode(obj.uploadid) + "&block_list=[\"" + md5 + "\"]&method=post&rtype=2&sequence=1&mode=1&local_mtime=" + mtime;
+ res = wc.UploadData("http://pan.baidu.com/api/create?a=commit&clienttype=8", Encoding.UTF8.GetBytes(str));
+ var obj2 = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ obj2.success = true;
+ return obj2;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new CommitUploadResult() { exception = ex };
+ }
+ }
+ public static RapidUploadResult RapidUpload(FileProperty prop, string path, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var str = "path=" + HttpUtility.UrlEncode(path) + "&content-length=" + prop.size + "&content-md5=" + prop.md5 + "&slice-md5=" + prop.slice_md5 + "&content-crc32=" + prop.crc32 + "&local_mtime=" + prop.mtime + "&block_list=[" + string.Join(",", prop.blocks.Select(h => '"' + h + '"')) + "]&rtype=2";
+ var res = wc.UploadData("http://pan.baidu.com/api/rapidupload?clienttype=8", Encoding.UTF8.GetBytes(str));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ obj.success = true;
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new RapidUploadResult() { exception = ex };
+ }
+ }
+ public static InitUploadResult InitUpload(FileProperty prop, string path, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var str = "path=" + HttpUtility.UrlEncode(path) + "&size=" + prop.size + "&isdir=0&local_mtime=" + prop.mtime + "&block_list=[" + string.Join(",", prop.blocks.Select(h => '"' + h + '"')) + "]&autoinit=1&method=post";
+ var res = wc.UploadData("http://pan.baidu.com/api/precreate?clienttype=8", Encoding.UTF8.GetBytes(str));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ obj.success = true;
+ if (InitUploadFile != null && obj.errno == 0)
+ {
+ InitUploadFile(prop.path, prop.blocks.Length, obj.block_list.Length);
+ }
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new InitUploadResult() { exception = ex };
+ }
+ }
+ public static Result UploadBlock(FileProperty prop, string path, InitUploadResult session, FileStream stream, int blockid, string host, Credential credential)
+ {
+ try
+ {
+ using (var wc = new PatientWebClient())
+ {
+ if (StartUploadBlock != null)
+ {
+ StartUploadBlock(prop.path, blockid + 1, prop.blocks.Length);
+ }
+ var boundary = GetBoundary();
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary);
+ var str = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"filename\"; filename=\"name\"\r\nContent-Type: application/octet-stream\r\n\r\n";
+ var str2 = "\r\n--" + boundary + "--\r\n";
+ stream.Seek((long)blockid * 4 * 1024 * 1024, SeekOrigin.Begin);
+ var fdata = new byte[4 * 1024 * 1024];
+ var len = stream.Read(fdata, 0, fdata.Length);
+ if (len < fdata.Length)
+ {
+ var arr = new byte[len];
+ Array.Copy(fdata, arr, len);
+ fdata = arr;
+ }
+ var data = Encoding.UTF8.GetBytes(str).Concat(fdata).Concat(Encoding.UTF8.GetBytes(str2)).ToArray();
+ var res = wc.UploadData("http://" + host + "/rest/2.0/pcs/superfile2?app_id=250528&method=upload&path=" + HttpUtility.UrlEncode(path) + "&uploadid=" + HttpUtility.UrlEncode(session.uploadid) + "&partseq=" + blockid + "&partoffset=" + (long)blockid * 4 * 1024 * 1024, data);
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ if (obj.md5 != prop.blocks[blockid]) throw new Exception("MD5 mismatch.");
+ if (ComplateUploadBlock != null)
+ {
+ ComplateUploadBlock(prop.path, blockid + 1, prop.blocks.Length);
+ }
+ return new Result() { success = true };
+ }
+ }
+ catch (Exception ex)
+ {
+ return new Result() { exception = ex };
+ }
+ }
+ public static CommitUploadResult CommitUpload(FileProperty prop, string path, InitUploadResult session, Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ var str = "path=" + HttpUtility.UrlEncode(path) + "&size=" + prop.size + "&isdir=0&uploadid=" + HttpUtility.UrlEncode(session.uploadid) + "&block_list=[" + string.Join(",", prop.blocks.Select(h => '"' + h + '"')) + "]&method=post&rtype=2&sequence=1&mode=1&local_mtime=" + prop.mtime;
+ var res = wc.UploadData("http://pan.baidu.com/api/create?a=commit&clienttype=8", Encoding.UTF8.GetBytes(str));
+ var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ obj.success = true;
+ if (UpdateComplate != null)
+ {
+ UpdateComplate(prop.path);
+ }
+ return obj;
+ }
+ }
+ catch (Exception ex)
+ {
+ return new CommitUploadResult() { exception = ex };
+ }
+ }
+ public static CommitUploadResult ChunkedUpload(string localpath, string remotepath, Credential credential)
+ {
+ try
+ {
+
+ var servers = GetUploadServers(credential);
+ if (!servers.success) throw servers.exception;
+ var prop = UploadHelper.GetFileProperty(localpath);
+ var session = InitUpload(prop, remotepath, credential);
+ if (!session.success) throw session.exception;
+ if (session.errno != 0) throw new Exception("Init upload returned errno = " + session.errno);
+ using (var fs = new FileStream(localpath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ for(int i = 0; i < prop.blocks.Length; i++)
+ {
+ var res = UploadBlock(prop, remotepath, session, fs, i, servers.servers[0], credential);
+ if (!res.success) throw res.exception;
+ }
+ }
+ var comres = CommitUpload(prop, remotepath, session, credential);
+ if (!comres.success) throw comres.exception;
+ if (comres.errno != 0) throw new Exception("Commit upload returned errno = " + comres.errno);
+ return comres;
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ }
+ public static GetUploadServersResult GetUploadServers(Credential credential)
+ {
+ try
+ {
+ using (var wc = new WebClient())
+ {
+ wc.Headers.Add(HttpRequestHeader.Cookie, credential);
+ wc.Headers.Add(HttpRequestHeader.UserAgent, "netdisk;5.4.5.4;PC;PC-Windows;10.0.14393;WindowsBaiduYunGuanJia");
+ var res = wc.DownloadString("http://d.pcs.baidu.com/rest/2.0/pcs/file?app_id=250528&method=locateupload&esl=1&ehps=0&upload_version=2.0");
+ var obj = JsonConvert.DeserializeObject(res);
+ return new GetUploadServersResult() { success = true, servers = obj.servers.Select(s => Regex.Match(s.server, ":\\/\\/(.+)$").Groups[1].Value).ToArray() };
+ }
+ }
+ catch (Exception ex)
+ {
+ return new GetUploadServersResult() { exception = ex };
+ }
+ }
+ private static string GetBoundary()
+ {
+ var rand = new Random();
+ var sb = new StringBuilder();
+ for (int i = 0; i < 28; i++) sb.Append('-');
+ for (int i = 0; i < 15; i++) sb.Append((char)(rand.Next(0, 26) + 'a'));
+ var boundary = sb.ToString();
+ return boundary;
+ }
+ private class FileOpResult
+ {
+ public int errno;
+ public Entry[] info;
+ public class Entry
+ {
+ public int errno;
+ public string path;
+ }
+ }
+ private class ListTaskResult
+ {
+ public Entry[] task_info;
+ public class Entry
+ {
+ public long create_time;
+ public int od_type;
+ public string save_path;
+ public string source_url;
+ public long task_id;
+ public string task_name;
+ }
+ }
+ private class QueryTaskResult
+ {
+ public Dictionary task_info;
+ public class Entry
+ {
+ public long file_size;
+ public long finished_size;
+ public int status;
+ }
+ }
+ private class QueryTorrentResult
+ {
+ public TorrentInfo torrent_info;
+ public class TorrentInfo
+ {
+ public QueryLinkResult.Entry[] file_info;
+ public string sha1;
+ }
+ }
+ private class QueryMagnetResult
+ {
+ public QueryLinkResult.Entry[] magnet_info;
+ }
+ private class VerifyPwdResult
+ {
+ public int errno;
+ }
+ private class SharePageData
+ {
+ public string bdstoken;
+ public FileList file_list;
+ public class FileList
+ {
+ public Entry[] list;
+ public class Entry
+ {
+ public string path;
+ }
+ }
+ }
+ private class SuperFileResponse
+ {
+ public string md5;
+ }
+ private class LocateUploadResponse
+ {
+ public Entry[] servers;
+ public class Entry
+ {
+ public string server;
+ }
+ }
+ }
+}
diff --git a/NetDisk/PatientWebClient.cs b/NetDisk/PatientWebClient.cs
new file mode 100644
index 0000000..c88e2af
--- /dev/null
+++ b/NetDisk/PatientWebClient.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Net;
+
+class PatientWebClient : WebClient
+{
+ public int Timeout = 300000;
+ public PatientWebClient(int Timeout): base()
+ {
+ this.Timeout = Timeout;
+ }
+ public PatientWebClient() : base()
+ {
+
+ }
+ protected override WebRequest GetWebRequest(Uri uri)
+ {
+ WebRequest w = base.GetWebRequest(uri);
+ w.Timeout = Timeout;
+ (w as HttpWebRequest).ReadWriteTimeout = Timeout;
+ return w;
+ }
+}
diff --git a/NetDisk/Properties/AssemblyInfo.cs b/NetDisk/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..590cb02
--- /dev/null
+++ b/NetDisk/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("NetDisk")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("NetDisk")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//将 ComVisible 设置为 false 将使此程序集中的类型
+//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("74eca1bf-6508-417d-bc57-db00daeca618")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”: :
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/NetDisk/Result.cs b/NetDisk/Result.cs
new file mode 100644
index 0000000..49c52e0
--- /dev/null
+++ b/NetDisk/Result.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Net;
+
+namespace NetDisk
+{
+ public class Result
+ {
+ public bool success;
+ public Exception exception;
+ }
+ public class QuotaResult : Result
+ {
+ public int errno;
+ public long total;
+ public long free;
+ public bool expire;
+ public long used;
+ }
+ public class UserInfoResult : Result
+ {
+ public int errno;
+ public Entry[] records;
+ public class Entry
+ {
+ public string avatar_url;
+ public string uname;
+ public string priority_name;
+ }
+ }
+ public class FileListResult : Result
+ {
+ public int errno;
+ public Entry[] list;
+ public class Entry
+ {
+ public int isdir;
+ public string path;
+ public string server_filename;
+ public long size;
+ public long server_mtime;
+ public string md5;
+ }
+ }
+ public class ThumbnailResult : Result
+ {
+ public byte[] image;
+ }
+ public class GetDownloadResult : Result
+ {
+ public Entry[] urls;
+ public class Entry
+ {
+ public int rank;
+ public string url;
+ }
+ }
+ public class FileOperationResult : Result
+ {
+ public int errno;
+ public string path;
+ }
+ public class OfflineListResult : Result
+ {
+ public Entry[] tasks;
+ public class Entry
+ {
+ public long create_time;
+ public int od_type;
+ public string save_path;
+ public string source_url;
+ public long task_id;
+ public string task_name;
+ public long file_size;
+ public long finished_size;
+ public int status;
+ }
+ }
+ public class QueryLinkResult : Result
+ {
+ public Entry[] files;
+ public string sha1;
+ public class Entry
+ {
+ public string file_name;
+ public long size;
+ }
+ }
+ public class AddOfflineTaskResult : Result
+ {
+ public int rapid_download;
+ public long task_id;
+ }
+ public class ShareResult : Result
+ {
+ public int errno;
+ public long shareid;
+ public string link;
+ public string shorturl;
+ }
+ public class TransferResult : Result
+ {
+ public int errno;
+ public Extra extra;
+ public class Extra
+ {
+ public Entry[] list;
+ public class Entry
+ {
+ public string from;
+ public string to;
+ }
+ }
+ }
+ public class InitUploadResult : Result
+ {
+ public int[] block_list;
+ public int errno;
+ public string uploadid;
+ }
+ public class CommitUploadResult : Result
+ {
+ public long ctime;
+ public int errno;
+ public long fs_id;
+ public int isdir;
+ public string md5;
+ public long mtime;
+ public string name;
+ public string path;
+ public long size;
+ }
+ public class RapidUploadResult : Result
+ {
+ public int errno;
+ public FileListResult.Entry info;
+ }
+ public class LoginResult : Result
+ {
+ public int errno;
+ public Credential credential;
+ }
+ public class LoginCheckResult : Result
+ {
+ public bool needVCode;
+ public string codeString;
+ public string verifyCode;
+ public byte[] image;
+ public Cookie baiduid;
+ public string ltoken;
+ }
+ public class GetUploadServersResult: Result
+ {
+ public string[] servers;
+ }
+}
diff --git a/NetDisk/UploadHelper.cs b/NetDisk/UploadHelper.cs
new file mode 100644
index 0000000..f2e88df
--- /dev/null
+++ b/NetDisk/UploadHelper.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+using DamienG.Security.Cryptography;
+
+namespace NetDisk
+{
+ public static class UploadHelper
+ {
+ public static FileProperty GetFileProperty(string path)
+ {
+ var ret = new FileProperty() { path = path };
+ var info = new FileInfo(path);
+ ret.size = info.Length;
+ ret.mtime= (long)(info.LastAccessTime.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
+ ret.md5 = GetMD5HashFromFile(path);
+ using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ var md5 = new MD5CryptoServiceProvider();
+ var arr = new byte[4 * 1024 * 1024];
+ var len = fs.Read(arr, 0, 256 * 1024);
+ ret.slice_md5 = ByteArrayToHexString(md5.ComputeHash(arr, 0, len));
+ fs.Seek(0, SeekOrigin.Begin);
+ var blocks = new List();
+ while (true)
+ {
+ len = fs.Read(arr, 0, 4 * 1024 * 1024);
+ if (len <= 0) break;
+ blocks.Add(ByteArrayToHexString(md5.ComputeHash(arr, 0, len)));
+ }
+ ret.blocks = blocks.ToArray();
+ fs.Seek(0, SeekOrigin.Begin);
+ var crc32 = new Crc32();
+ ret.crc32 = string.Empty;
+ foreach (byte b in crc32.ComputeHash(fs)) ret.crc32 += b.ToString("x2").ToLower();
+ }
+ return ret;
+ }
+ public static string GetMD5HashFromFile(string fileName)
+ {
+ using (var file = new FileStream(fileName, FileMode.Open))
+ {
+ var md5 = new MD5CryptoServiceProvider();
+ var retVal = md5.ComputeHash(file);
+ return ByteArrayToHexString(retVal);
+ }
+ }
+ private static string ByteArrayToHexString(byte[] arr)
+ {
+ var sb = new StringBuilder();
+ for (int i = 0; i < arr.Length; i++)
+ {
+ sb.Append(arr[i].ToString("x2"));
+ }
+ return sb.ToString();
+ }
+ }
+ public class FileProperty
+ {
+ public string path;
+ public long size;
+ public string md5;
+ public string slice_md5;
+ public string crc32;
+ public long mtime;
+ public string[] blocks;
+ }
+}
diff --git a/NetDisk/packages.config b/NetDisk/packages.config
new file mode 100644
index 0000000..7c276ed
--- /dev/null
+++ b/NetDisk/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file