This commit is contained in:
j4587698 2017-02-05 16:11:10 +08:00
parent a6058b84bc
commit 0da096d765
40 changed files with 4101 additions and 0 deletions

28
BaiduYunSync.sln Normal file
View File

@ -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

View File

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F063180E-E354-4DB4-96F8-154D1D949240}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BaiduYunSync</RootNamespace>
<AssemblyName>BaiduYunSync</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="LiteDB, Version=2.0.4.0, Culture=neutral, PublicKeyToken=4ee40123013c9f27, processorArchitecture=MSIL">
<HintPath>..\packages\LiteDB.2.0.4\lib\net35\LiteDB.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="log4net, Version=2.0.7.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.7\lib\net40-full\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Encrypt3DS.cs" />
<Compile Include="frmLogin.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="frmLogin.Designer.cs">
<DependentUpon>frmLogin.cs</DependentUpon>
</Compile>
<Compile Include="frmMain.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="frmMain.Designer.cs">
<DependentUpon>frmMain.cs</DependentUpon>
</Compile>
<Compile Include="frmReadLog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="frmReadLog.Designer.cs">
<DependentUpon>frmReadLog.cs</DependentUpon>
</Compile>
<Compile Include="frmUploadList.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="frmUploadList.Designer.cs">
<DependentUpon>frmUploadList.cs</DependentUpon>
</Compile>
<Compile Include="LiteDbHelper.cs" />
<Compile Include="LogSettings.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sync.cs" />
<Compile Include="SyncItemsDao.cs" />
<Compile Include="UpdateInfoDao.cs" />
<Compile Include="UserInfoDao.cs" />
<EmbeddedResource Include="frmLogin.resx">
<DependentUpon>frmLogin.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="frmMain.resx">
<DependentUpon>frmMain.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="frmReadLog.resx">
<DependentUpon>frmReadLog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="frmUploadList.resx">
<DependentUpon>frmUploadList.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NetDisk\NetDisk.csproj">
<Project>{74ECA1BF-6508-417D-BC57-DB00DAECA618}</Project>
<Name>NetDisk</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -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)
/// <summary>
/// 加密字符串
/// </summary>
/// <param name="Value">输入的字符串</param>
/// <returns>加密后的字符串</returns>
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)
/// <summary>
/// 解密字符串
/// </summary>
/// <param name="Value">加过密的字符串</param>
/// <returns>解密后的字符串</returns>
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
}
}

View File

@ -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";
/// <summary>
/// 本地保存更新信息,防止频繁读写文件
/// </summary>
private static List<UpdateInfoDao> updateInfoList;
/// <summary>
/// 同步文件锁
/// </summary>
private static object updateInfoLocker = new object();
static LiteDbHelper()
{
Init();
}
/// <summary>
/// 初始化数据库相关内容
/// </summary>
public static void Init()
{
if (updateInfoList == null)
{
using (var db = new LiteDatabase(dbUrl))
{
var col = db.GetCollection<UpdateInfoDao>("updateinfo");
var list = col.FindAll();
updateInfoList = (list == null ? new List<UpdateInfoDao>() : list.ToList());
}
}
}
private static UserInfoDao userInfo;
/// <summary>
/// 获取或设置用户信息
/// </summary>
public static UserInfoDao UserInfo
{
get
{
if (userInfo == null)
{
using (var db = new LiteDatabase(dbUrl))
{
var col = db.GetCollection<UserInfoDao>("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<UserInfoDao>("userinfo");
if (value.Id == 0)
{
col.Insert(value);
}
else
{
col.Update(value);
}
userInfo = value;
}
}
}
/// <summary>
/// 插入或更新需要同步的文件夹
/// </summary>
/// <param name="dao"></param>
public static void UpdateSyncItem(SyncItemsDao dao)
{
using (var db = new LiteDatabase(dbUrl))
{
var col = db.GetCollection<SyncItemsDao>("syncitem");
if (dao.Id == 0)
{
col.Insert(dao);
}
else
{
col.Update(dao);
}
}
}
/// <summary>
/// 获取需要同步的文件夹列表
/// </summary>
/// <returns>同步文件夹信息</returns>
public static List<SyncItemsDao> GetAllSyncItems()
{
using (var db = new LiteDatabase(dbUrl))
{
var col = db.GetCollection<SyncItemsDao>("syncitem");
return col.FindAll().ToList();
}
}
/// <summary>
/// 删除同步文件夹
/// </summary>
/// <param name="dao"></param>
public static void DeleteSyncItem(SyncItemsDao dao)
{
using (var db = new LiteDatabase(dbUrl))
{
var col = db.GetCollection<SyncItemsDao>("syncitem");
col.Delete(dao.Id);
}
}
/// <summary>
/// 获取所有的更新信息
/// </summary>
/// <returns></returns>
public static UpdateInfoDao[] GetAllUpdateInfos()
{
lock (updateInfoLocker)
{
return updateInfoList.ToArray();
}
}
/// <summary>
/// 插入新的更新信息
/// </summary>
/// <param name="dao"></param>
public static void InsertUpdateInfo(UpdateInfoDao dao)
{
using (var db = new LiteDatabase(dbUrl))
{
var col = db.GetCollection<UpdateInfoDao>("updateinfo");
col.Insert(dao);
}
lock (updateInfoLocker)
updateInfoList.Add(dao);
}
/// <summary>
/// 删除更新信息
/// </summary>
/// <param name="dao"></param>
public static void DeleteUpdateInfo(UpdateInfoDao dao)
{
using (var db = new LiteDatabase(dbUrl))
{
var col = db.GetCollection<UpdateInfoDao>("updateinfo");
col.Delete(dao.Id);
}
lock (updateInfoLocker)
updateInfoList.Remove(dao);
}
/// <summary>
/// 获取需更新数量
/// </summary>
/// <returns>数量</returns>
public static int GetUpdateInfoCount()
{
lock (updateInfoLocker)
return updateInfoList.Count();
}
/// <summary>
/// 判断文件是否已存在
/// </summary>
/// <param name="path">文件全路径</param>
/// <returns></returns>
public static bool ContainsPath(string path)
{
lock (updateInfoLocker)
return updateInfoList.Select(x => x.Path).Contains(path);
}
/// <summary>
/// 根据路径获取对应的更新信息
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static UpdateInfoDao GetUpdateInfoFormPath(string path)
{
if (!ContainsPath(path))
{
return null;
}
lock (updateInfoLocker)
return updateInfoList.Where(x => x.Path == path).First();
}
}
}

View File

@ -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);
}
}
}

21
BaiduYunSync/Program.cs Normal file
View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace BaiduYunSync
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmMain());
}
}
}

View File

@ -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")]

View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本: 4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace BaiduYunSync.Properties
{
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 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()
{
}
/// <summary>
/// 返回此类使用的、缓存的 ResourceManager 实例。
/// </summary>
[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;
}
}
/// <summary>
/// 为所有资源查找重写当前线程的 CurrentUICulture 属性,
/// 方法是使用此强类型资源类。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

294
BaiduYunSync/Sync.cs Normal file
View File

@ -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
{
/// <summary>
/// 同步类
/// </summary>
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);
/// <summary>
/// 任务
/// </summary>
private static AutoResetEvent taskmre = new AutoResetEvent(false);
private static object locker = new object();
/// <summary>
/// 开始新同步时发生
/// </summary>
/// <param name="folder">文件夹名称</param>
public delegate void StartSyncHandle(string folder);
public static event StartSyncHandle StartSync;
/// <summary>
/// 同步结束时发生
/// </summary>
/// <param name="folder"></param>
public delegate void EndSyncHandle(SyncItemsDao folder);
public static event EndSyncHandle EndSync;
/// <summary>
/// 文件上传状态改变
/// </summary>
/// <param name="path"></param>
/// <param name="status"></param>
public delegate void StatusModifyHandle(string path, StatusEnum status);
public static event StatusModifyHandle StatusModify;
/// <summary>
/// 文件状态
/// </summary>
public enum StatusEnum
{
/// <summary>
/// 添加新项
/// </summary>
Add,
/// <summary>
/// 开始上传
/// </summary>
Start,
/// <summary>
/// 上传状态改变
/// </summary>
Modify,
/// <summary>
/// 结束删除
/// </summary>
Delete
}
/// <summary>
/// 启动同步线程
/// </summary>
/// <param name="credential">身份信息</param>
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));
}
}
/// <summary>
/// 查找所有需要同步的文件
/// </summary>
/// <param name="folderPath">本地文件夹路径</param>
/// <param name="serverPath">服务器路径(父路径)</param>
/// <param name="credential">身份信息</param>
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);
}
}
/// <summary>
/// 上传文件
/// </summary>
/// <param name="credential">身份信息</param>
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));
}
}
}
}
}
}

View File

@ -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; }
}
}

View File

@ -0,0 +1,61 @@
using NetDisk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BaiduYunSync
{
/// <summary>
/// 上传信息类
/// </summary>
public class UpdateInfoDao
{
public int Id { get; set; }
/// <summary>
/// 总共完成数量
/// </summary>
public int ComplateBlockNum { get; set; }
/// <summary>
/// 总块数
/// </summary>
public int TotalBlockNum { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string Path { get; set; }
/// <summary>
/// 服务器路径
/// </summary>
public string ServerPath { get; set; }
/// <summary>
/// 文件名
/// </summary>
public string FileName { get; set; }
/// <summary>
/// 当前状态
/// </summary>
public string Status { get; set; }
/// <summary>
/// 文件大小
/// </summary>
public long FileLength { get; set; }
/// <summary>
/// 是否需要先删除文件
/// </summary>
public bool NeedDelete { get; set; }
/// <summary>
/// 是否已经被使用
/// </summary>
public bool IsUsed { get; set; }
}
}

View File

@ -0,0 +1,31 @@
using NetDisk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BaiduYunSync
{
/// <summary>
/// 用户信息类
/// </summary>
public class UserInfoDao
{
public int Id { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
/// <summary>
/// 用户凭据
/// </summary>
public string UserCredentialStr { get; set; }
}
}

153
BaiduYunSync/frmLogin.Designer.cs generated Normal file
View File

@ -0,0 +1,153 @@
namespace BaiduYunSync
{
partial class frmLogin
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

91
BaiduYunSync/frmLogin.cs Normal file
View File

@ -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();
}
/// <summary>
/// 返回内容
/// </summary>
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)
{
}
}
}

120
BaiduYunSync/frmLogin.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

179
BaiduYunSync/frmMain.Designer.cs generated Normal file
View File

@ -0,0 +1,179 @@
namespace BaiduYunSync
{
partial class frmMain
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
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;
}
}

174
BaiduYunSync/frmMain.cs Normal file
View File

@ -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<ListViewItem>().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<ListViewItem>().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;
}
/// <summary>
/// 将B转换为GB
/// </summary>
/// <param name="b"></param>
/// <returns></returns>
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<ListViewItem>().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();
}
}
}

126
BaiduYunSync/frmMain.resx Normal file
View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="fbdSyncFloder.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>161, 17</value>
</metadata>
</root>

63
BaiduYunSync/frmReadLog.Designer.cs generated Normal file
View File

@ -0,0 +1,63 @@
namespace BaiduYunSync
{
partial class frmReadLog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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;
}
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

140
BaiduYunSync/frmUploadList.Designer.cs generated Normal file
View File

@ -0,0 +1,140 @@
namespace BaiduYunSync
{
partial class frmUploadList
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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);
}
/// <summary>
/// 将B转换为MB
/// </summary>
/// <param name="b"></param>
/// <returns></returns>
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<ListViewItem>().Select(x => x.SubItems[5].Text).Contains(path))
{
lvList.Items.Cast<ListViewItem>().Where(x => x.SubItems[5].Text == path).First().Remove();
}
}
private void modifyItem(UpdateInfoDao updateInfo)
{
if (lvList.Items.Cast<ListViewItem>().Select(x => x.SubItems[5].Text).Contains(updateInfo.Path))
{
var item = lvList.Items.Cast<ListViewItem>().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;
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="cmsUploadList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="LiteDB" version="2.0.4" targetFramework="net40" />
<package id="log4net" version="2.0.7" targetFramework="net40" />
</packages>

104
NetDisk/Authentication.cs Normal file
View File

@ -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;
}
}
}

119
NetDisk/CRC32.cs Normal file
View File

@ -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
{
/// <summary>
/// Implements a 32-bit CRC hash algorithm compatible with Zip etc.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
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<byte> 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;
}
}
}

View File

@ -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;
}
}
}

74
NetDisk/Credential.cs Normal file
View File

@ -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]));
}
}
}

28
NetDisk/Extension.cs Normal file
View File

@ -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;
}
}
}

79
NetDisk/NetDisk.csproj Normal file
View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{74ECA1BF-6508-417D-BC57-DB00DAECA618}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NetDisk</RootNamespace>
<AssemblyName>NetDisk</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net40\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Authentication.cs" />
<Compile Include="CookieAwareWebClient.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="CRC32.cs" />
<Compile Include="Credential.cs" />
<Compile Include="Extension.cs" />
<Compile Include="Operation.cs" />
<Compile Include="PatientWebClient.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Result.cs" />
<Compile Include="UploadHelper.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

674
NetDisk/Operation.cs Normal file
View File

@ -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
{
/// <summary>
/// 块完成事件(顺序提交)
/// </summary>
/// <param name="filePath">文件名</param>
/// <param name="endBlockNum">当前完成的块</param>
/// <param name="totalBlockNum">总块数</param>
public delegate void ComplateUploadBlockHandle(string filePath, int endBlockNum, int totalBlockNum);
public static event ComplateUploadBlockHandle ComplateUploadBlock;
/// <summary>
/// 初始化上传
/// </summary>
/// <param name="filePath">文件名</param>
/// <param name="fileBlockNum">文件所拥有的块数</param>
/// <param name="totalBlockNum">服务器需要上传的块数</param>
public delegate void InitUploadFileHandle(string filePath, int fileBlockNum, int needUploadBlockNum);
public static event InitUploadFileHandle InitUploadFile;
/// <summary>
/// 开始上传块
/// </summary>
/// <param name="filePath">文件名</param>
/// <param name="startBlockNum">当前开始的块</param>
/// <param name="totalBlockNum">总块数</param>
public delegate void StartUploadBlockHandle(string filePath, int startBlockNum, int totalBlockNum);
public static event StartUploadBlockHandle StartUploadBlock;
/// <summary>
/// 上传完成
/// </summary>
/// <param name="filePath">文件名</param>
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<QuotaResult>(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<UserInfoResult>(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<FileListResult>(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<GetDownloadResult>(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<FileOperationResult>(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<FileOpResult>(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<ListTaskResult>(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<QueryTaskResult>(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<QueryMagnetResult>(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<QueryTorrentResult>(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<AddOfflineTaskResult>(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<ShareResult>(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<VerifyPwdResult>(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<SharePageData>(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<TransferResult>(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<InitUploadResult>(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<CommitUploadResult>(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<RapidUploadResult>(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<InitUploadResult>(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<SuperFileResponse>(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<CommitUploadResult>(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<LocateUploadResponse>(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<string, Entry> 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;
}
}
}
}

View File

@ -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;
}
}

View File

@ -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")]

155
NetDisk/Result.cs Normal file
View File

@ -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;
}
}

70
NetDisk/UploadHelper.cs Normal file
View File

@ -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<string>();
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;
}
}

4
NetDisk/packages.config Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net40" />
</packages>