diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68e61ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,217 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions \ No newline at end of file diff --git a/ChangeLog.txt b/ChangeLog.txt index cca973b..5414db6 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,9 +1,17 @@ +3.2.0 + * "Location" + * chunked + * POST/PUT/DELETE "Content-Length: 0", + * "Authorization" , . HttpRequest.Authorization + * , User-Agent + * . HttpHelper/HtmlHelper Http/Html. StringHelper Html. xNet + 3.1.4 - * POST-. , . + * POST-. , * HttpRequest.CharacterSet POST-. , , , 1251 , HttpRequest.CharacterSet = Encoding.GetEncoding(1251) - * , User-Agent. + * , User-Agent 3.1.3 - * HttpRequest SSL, SslCertificateValidatorCallback null. - * HttpRequest.AddField(name, value, encoding), - UTF-8 , . StringContent , . - * . \ No newline at end of file + * HttpRequest SSL, SslCertificateValidatorCallback null + * HttpRequest.AddField(name, value, encoding), - UTF-8 , . StringContent , + * \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt index 0bfb736..4c741ac 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,10 +1,19 @@ -Copyright 2011-2014, X-rus -All rights reserved. +Copyright 2012-2015 Ruslan Khuduev -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/Net/HtmlHelper.cs b/Net/HtmlHelper.cs deleted file mode 100644 index 638f642..0000000 --- a/Net/HtmlHelper.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.Text.RegularExpressions; - -namespace xNet.Net -{ - /// - /// Представляет статический класс, предназначенный для помощи в работе с HTML. - /// - public static class HtmlHelper - { - #region _htmlMnemonics - - private static readonly Dictionary _htmlMnemonics = new Dictionary() - { - { "apos", "'" }, - { "quot", "\"" }, - { "amp", "&" }, - { "lt", "<" }, - { "gt", ">" } - }; - - #endregion - - - #region Статические методы (открытые) - - /// - /// Заменяет в строке HTML-сущности на представляющие их символы. - /// - /// Строка, в которой будет произведена замена. - /// Строка с заменёнными HTML-сущностями. - /// Заменяются только следующие мнемоники: apos, quot, amp, lt и gt. И все виды кодов. - public static string ReplaceEntities(string str) - { - if (string.IsNullOrEmpty(str)) - { - return string.Empty; - } - - var regex = new Regex(@"(\&(?\w{1,4})\;)|(\&#(?\w{1,4})\;)", RegexOptions.Compiled); - - string result = regex.Replace(str, match => - { - if (match.Groups["text"].Success) - { - string value; - - if (_htmlMnemonics.TryGetValue(match.Groups["text"].Value, out value)) - { - return value; - } - } - else if (match.Groups["code"].Success) - { - int code = int.Parse(match.Groups["code"].Value); - return ((char)code).ToString(); - } - - return match.Value; - }); - - return result; - } - - /// - /// Заменяет в строке Unicode-сущности на представляющие их символы. - /// - /// Строка, в которой будет произведена замена. - /// Строка с заменёнными Unicode-сущностями. - /// Unicode-сущности имеют вид: \u2320 или \U044F - public static string ReplaceUnicode(string str) - { - if (string.IsNullOrEmpty(str)) - { - return string.Empty; - } - - var regex = new Regex(@"\\[uU](?[0-9A-F]{4})", RegexOptions.Compiled); - - string result = regex.Replace(str, match => - { - int code = int.Parse(match.Groups["code"].Value, NumberStyles.HexNumber); - - return ((char)code).ToString(); - }); - - return result; - } - - #endregion - } -} \ No newline at end of file diff --git a/Net/~Http/HttpClient.cs b/Net/~Http/HttpClient.cs deleted file mode 100644 index 78d6b91..0000000 --- a/Net/~Http/HttpClient.cs +++ /dev/null @@ -1,514 +0,0 @@ -using System; -using xNet.Collections; - -namespace xNet.Net -{ - /// - /// Представляет статические класс, предназначенный для работы с HTTP-сервером. - /// - public static class HttpClient - { - #region Статические свойства (открытые) - - /// - /// Возвращает или задаёт значение, указывающие, нужно ли использовать прокси-клиент Internet Explorer'a, если нет прямого подключения к интернету и не задан прокси-клиент. - /// - /// Значение по умолчанию — . - public static bool UseIeProxy - { - get - { - return HttpRequest.UseIeProxy; - } - set - { - HttpRequest.UseIeProxy = value; - } - } - - /// - /// Возвращает или задаёт значение, указывающие, нужно ли отключать прокси-клиент для локальных адресов. - /// - /// Значение по умолчанию — . - public static bool DisableProxyForLocalAddress - { - get - { - return HttpRequest.DisableProxyForLocalAddress; - } - set - { - HttpRequest.DisableProxyForLocalAddress = value; - } - } - - /// - /// Возвращает или задаёт глобальный прокси-клиент. - /// - /// Значение по умолчанию — . - public static ProxyClient GlobalProxy - { - get - { - return HttpRequest.GlobalProxy; - } - set - { - HttpRequest.GlobalProxy = value; - } - } - - #endregion - - - #region Статические методы (открытые) - - #region Get - - /// - /// Отправляет GET-запрос HTTP-серверу. - /// - /// Адрес интернет-ресурса. - /// Параметры URL-адреса, или значение . - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Значение параметра равно . - /// Значение параметра является пустой строкой. - /// Ошибка при работе с HTTP-протоколом. - public static void Get(string address, RequestParams urlParams = null, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - request.Get(address, urlParams).None(); - } - } - - /// - /// Отправляет GET-запрос HTTP-серверу. - /// - /// Адрес интернет-ресурса. - /// Параметры URL-адреса, или значение . - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Значение параметра равно . - /// Ошибка при работе с HTTP-протоколом. - public static void Get(Uri address, RequestParams urlParams = null, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - request.Get(address, urlParams).None(); - } - } - - #endregion - - #region GetString - - /// - /// Отправляет GET-запрос HTTP-серверу. Загружает тело сообщения и возвращает его в виде строки. - /// - /// Адрес интернет-ресурса. - /// Параметры URL-адреса, или значение . - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Если тело сообщения отсутствует, то будет возвращена пустая строка. - /// Значение параметра равно . - /// Значение параметра является пустой строкой. - /// Ошибка при работе с HTTP-протоколом. - public static string GetString(string address, RequestParams urlParams = null, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - return request.Get(address, urlParams).ToString(); - } - } - - /// - /// Отправляет GET-запрос HTTP-серверу. Загружает тело сообщения и возвращает его в виде строки. - /// - /// Адрес интернет-ресурса. - /// Параметры URL-адреса, или значение . - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Если тело сообщения отсутствует, то будет возвращена пустая строка. - /// Значение параметра равно . - /// Ошибка при работе с HTTP-протоколом. - public static string GetString(Uri address, RequestParams urlParams = null, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - return request.Get(address, urlParams).ToString(); - } - } - - #endregion - - #region GetBytes - - /// - /// Отправляет GET-запрос HTTP-серверу. Загружает тело сообщения и возвращает его в виде текста. - /// - /// Адрес интернет-ресурса. - /// Параметры URL-адреса, или значение . - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Если тело сообщения отсутствует, то будет возвращён пустой массив байтов. - /// Значение параметра равно . - /// Значение параметра является пустой строкой. - /// Ошибка при работе с HTTP-протоколом. - public static byte[] GetBytes(string address, RequestParams urlParams = null, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - return request.Get(address, urlParams).ToBytes(); - } - } - - /// - /// Отправляет GET-запрос HTTP-серверу. Загружает тело сообщения и возвращает его в виде текста. - /// - /// Адрес интернет-ресурса. - /// Параметры URL-адреса, или значение . - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Если тело сообщения отсутствует, то будет возвращён пустой массив байтов. - /// Значение параметра равно . - /// Ошибка при работе с HTTP-протоколом. - public static byte[] GetBytes(Uri address, RequestParams urlParams = null, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - return request.Get(address, urlParams).ToBytes(); - } - } - - #endregion - - #region GetFile - - /// - /// Отправляет GET-запрос HTTP-серверу. Загружает тело сообщения и сохраняет его в новый файл по указанному пути. Если файл уже существует, то он будет перезаписан. - /// - /// Адрес интернет-ресурса. - /// Путь к файлу, в котором будет сохранено тело сообщения. - /// Параметры URL-адреса, или значение . - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// - /// Значение параметра равно . - /// -или- - /// Значение параметра равно . - /// - /// Значение параметра является пустой строкой. - /// Значение параметра является пустой строкой, содержит только пробелы или содержит недопустимые символы. - /// Указанный путь, имя файла или и то и другое превышает наибольшую возможную длину, определенную системой. Например, для платформ на основе Windows длина пути не должна превышать 248 знаков, а имена файлов не должны содержать более 260 знаков. - /// Значение параметра указывает на несуществующий файл. - /// Значение параметра указывает на недопустимый путь. - /// При открытии файла возникла ошибка ввода-вывода. - /// Вызывающий оператор не имеет необходимого разрешения. - /// - /// Операция чтения файла не поддерживается на текущей платформе. - /// -или- - /// Значение параметра определяет каталог. - /// -или- - /// Вызывающий оператор не имеет необходимого разрешения. - /// - /// Ошибка при работе с HTTP-протоколом. - public static void GetFile(string address, string path, RequestParams urlParams = null, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - request.Get(address, urlParams).ToFile(path); - } - } - - /// - /// Отправляет GET-запрос HTTP-серверу. Загружает тело сообщения и сохраняет его в новый файл по указанному пути. Если файл уже существует, то он будет перезаписан. - /// - /// Адрес интернет-ресурса. - /// Путь к файлу, в котором будет сохранено тело сообщения. - /// Параметры URL-адреса, или значение . - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// - /// Значение параметра равно . - /// -или- - /// Значение параметра равно . - /// - /// Значение параметра является пустой строкой, содержит только пробелы или содержит недопустимые символы. - /// Указанный путь, имя файла или и то и другое превышает наибольшую возможную длину, определенную системой. Например, для платформ на основе Windows длина пути не должна превышать 248 знаков, а имена файлов не должны содержать более 260 знаков. - /// Значение параметра указывает на несуществующий файл. - /// Значение параметра указывает на недопустимый путь. - /// При открытии файла возникла ошибка ввода-вывода. - /// Вызывающий оператор не имеет необходимого разрешения. - /// - /// Операция чтения файла не поддерживается на текущей платформе. - /// -или- - /// Значение параметра определяет каталог. - /// -или- - /// Вызывающий оператор не имеет необходимого разрешения. - /// - /// Ошибка при работе с HTTP-протоколом. - public static void GetFile(Uri address, string path, RequestParams urlParams = null, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - request.Get(address, urlParams).ToFile(path); - } - } - - #endregion - - #region Post - - /// - /// Отправляет POST-запрос HTTP-серверу. Загружает тело сообщения и возвращает его в виде строки. - /// - /// Адрес интернет-ресурса. - /// Параметры запроса, отправляемые HTTP-серверу. - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Если тело сообщения отсутствует, то будет возвращена пустая строка. - /// - /// Значение параметра равно . - /// -или- - /// Значение параметра равно . - /// - /// Значение параметра является пустой строкой. - /// Ошибка при работе с HTTP-протоколом. - public static string Post(string address, RequestParams reqParams, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - return request.Post(address, reqParams).ToString(); - } - } - - /// - /// Отправляет POST-запрос HTTP-серверу. Загружает тело сообщения и возвращает его в виде строки. - /// - /// Адрес интернет-ресурса. - /// Параметры запроса, отправляемые HTTP-серверу. - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Если тело сообщения отсутствует, то будет возвращена пустая строка. - /// - /// Значение параметра равно . - /// -или- - /// Значение параметра равно . - /// - /// Ошибка при работе с HTTP-протоколом. - public static string Post(Uri address, RequestParams reqParams, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - return request.Post(address, reqParams).ToString(); - } - } - - /// - /// Отправляет POST-запрос HTTP-серверу. Загружает тело сообщения и возвращает его в виде строки. - /// - /// Адрес интернет-ресурса. - /// Контент, отправляемый HTTP-серверу. - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Если тело сообщения отсутствует, то будет возвращена пустая строка. - /// - /// Значение параметра равно . - /// -или- - /// Значение параметра равно . - /// - /// Значение параметра является пустой строкой. - /// Ошибка при работе с HTTP-протоколом. - public static string Post(string address, HttpContent content, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - return request.Post(address, content).ToString(); - } - } - - /// - /// Отправляет POST-запрос HTTP-серверу. Загружает тело сообщения и возвращает его в виде строки. - /// - /// Адрес интернет-ресурса. - /// Контент, отправляемый HTTP-серверу. - /// Кукисы, отправляемые HTTP-серверу, или значение . - /// Прокси-клиент, используемый для запроса, или значение . - /// Если тело сообщения отсутствует, то будет возвращена пустая строка. - /// - /// Значение параметра равно . - /// -или- - /// Значение параметра равно . - /// - /// Ошибка при работе с HTTP-протоколом. - public static string Post(Uri address, HttpContent content, CookieDictionary cookies = null, ProxyClient proxy = null) - { - using (var request = new HttpRequest()) - { - if (cookies == null) - { - request.Cookies = new CookieDictionary(); - } - else - { - request.Cookies = cookies; - } - - request.Proxy = proxy; - request.KeepAlive = false; - request.UserAgent = HttpHelper.ChromeUserAgent(); - - return request.Post(address, content).ToString(); - } - } - - #endregion - - #endregion - } -} \ No newline at end of file diff --git a/Net/~Http/IHttpConnect.cs b/Net/~Http/IHttpConnect.cs deleted file mode 100644 index b87608f..0000000 --- a/Net/~Http/IHttpConnect.cs +++ /dev/null @@ -1,21 +0,0 @@ - -namespace xNet.Net -{ - /// - /// Определяет свойство объекта, используемого для работы с HTTP-протоколом и метод для его инициализации. - /// - /// Данный интерфейс может пригодиться в случае, если класс использует для работы с HTTP-протоколом. Так как может содержать постоянное соединение и различные настройки, то желательно для всех запросов использовать один и тот же объект класса , что позволит сократить объём кода и увеличить скорость работы. - public interface IHttpConnect - { - /// - /// Объект для отправки запросов HTTP-серверу. - /// - HttpRequest Request { get; set; } - - /// - /// Инициализирует объект для отправки запросов HTTP-серверу. Здесь можно установить необходимые настройки запроса для конкретного класса. - /// - /// Объект для отправки запросов HTTP-серверу. - void InitRequest(HttpRequest request); - } -} \ No newline at end of file diff --git a/Net/~Proxy/ProxyHelper.cs b/Net/~Proxy/ProxyHelper.cs deleted file mode 100644 index 289d8f0..0000000 --- a/Net/~Proxy/ProxyHelper.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; - -namespace xNet.Net -{ - /// - /// Представляет статический класс, предназначенный для помощи в работе с прокси. - /// - public static class ProxyHelper - { - /// - /// Создаёт клиент для заданного типа прокси-сервера. - /// - /// Тип прокси-сервера. - /// Хост прокси-сервера, или значение . - /// Порт прокси-сервера. - /// Имя пользователя для авторизации на прокси-сервере, или значение . - /// Пароль для авторизации на прокси-сервере, или значение . - /// Экземпляр класса прокси-клиента, унаследованный от . - /// Получен неподдерживаемый тип прокси-сервера. - public static ProxyClient CreateProxyClient(ProxyType proxyType, string host = null, - int port = 0, string username = null, string password = null) - { - switch (proxyType) - { - case ProxyType.Http: - return (port == 0) ? - new HttpProxyClient(host) : new HttpProxyClient(host, port, username, password); - - case ProxyType.Socks4: - return (port == 0) ? - new Socks4ProxyClient(host) : new Socks4ProxyClient(host, port, username); - - case ProxyType.Socks4a: - return (port == 0) ? - new Socks4aProxyClient(host) : new Socks4aProxyClient(host, port, username); - - case ProxyType.Socks5: - return (port == 0) ? - new Socks5ProxyClient(host) : new Socks5ProxyClient(host, port, username, password); - - default: - throw new InvalidOperationException(string.Format( - Resources.InvalidOperationException_ProxyHelper_NotSupportedProxyType, proxyType)); - } - } - } -} \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index eb052df..092e587 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -9,9 +9,9 @@ [assembly: AssemblyTitle("xNet")] [assembly: AssemblyDescription("http://habrahabr.ru/post/146475/")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("X-rus")] +[assembly: AssemblyCompany("Ruslan Khuduev")] [assembly: AssemblyProduct("xNet")] -[assembly: AssemblyCopyright("Copyright © X-rus 2011-2014")] +[assembly: AssemblyCopyright("Copyright © 2012-2015 Ruslan Khuduev ")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -33,6 +33,6 @@ // Можно задать все значения или принять номер построения и номер редакции по умолчанию, // используя "*", как показано ниже: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.1.4.0")] -[assembly: AssemblyFileVersion("3.1.4.0")] +[assembly: AssemblyVersion("3.2.0.0")] +[assembly: AssemblyFileVersion("3.2.0.0")] [assembly: NeutralResourcesLanguageAttribute("ru")] diff --git a/README.md b/README.md index a7b65e7..61d31ed 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,17 @@ * PL: C# -* Version: 3.0 * Version .NET: 4.0 Client Profile -xNet - a class library for .NET Framework, which includes: +xNet - a class library for .NET Framework which includes: * Classes for work with proxy servers: _HTTP, Socks4(a), Socks5, Chain_. * Classes for work with *HTTP 1.0/1.1* protocol: _keep-alive, gzip, deflate, chunked, SSL, proxies and more_. -* Classes for work with multithreading: _a multithreaded bypassing the collection, asynchronous events and more_. Detailed description: http://habrahabr.ru/post/146475/ Example:
-using (var request = new HttpRequest("http://site.com"))
+using (var request = new HttpRequest("http://site.com/"))
 {
-    request.UserAgent = HttpHelper.ChromeUserAgent();
+    request.UserAgent = Http.ChromeUserAgent();
 	request.Proxy = Socks5ProxyClient.Parse("127.0.0.1:1080");
 
     request
@@ -36,7 +34,7 @@ using (var request = new HttpRequest("http://site.com"))
     // These parameters are sent in this request.
     request.Post("/").None();
 
-    // But in this request, they will be gone.
+    // But in this request they will be gone.
     request.Post("/").None();
 }
 
\ No newline at end of file diff --git a/Resources.Designer.cs b/Resources.Designer.cs index a13797c..3af1561 100644 --- a/Resources.Designer.cs +++ b/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Этот код создан программой. -// Исполняемая версия:4.0.30319.1 +// Исполняемая версия:4.0.30319.36119 // // Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае // повторной генерации кода. @@ -348,24 +348,6 @@ internal static string InvalidOperationException_HttpResponse_HasError { } } - /// - /// Ищет локализованную строку, похожую на Невозможно начать новую работу во время выполнения асинхронной операции.. - /// - internal static string InvalidOperationException_MultiThreading_CannotStart { - get { - return ResourceManager.GetString("InvalidOperationException_MultiThreading_CannotStart", resourceCulture); - } - } - - /// - /// Ищет локализованную строку, похожую на Невозможно установить значение во время выполнения асинхронного действия.. - /// - internal static string InvalidOperationException_NetProcesses_CannotSetValue { - get { - return ResourceManager.GetString("InvalidOperationException_NetProcesses_CannotSetValue", resourceCulture); - } - } - /// /// Ищет локализованную строку, похожую на Получен неподдерживаемый формат кодирования: {0}. /// @@ -411,15 +393,6 @@ internal static string InvalidOperationException_ProxyClient_WrongUsername { } } - /// - /// Ищет локализованную строку, похожую на Не поддерживаемый тип прокси-сервера '{0}'.. - /// - internal static string InvalidOperationException_ProxyHelper_NotSupportedProxyType { - get { - return ResourceManager.GetString("InvalidOperationException_ProxyHelper_NotSupportedProxyType", resourceCulture); - } - } - /// /// Ищет локализованную строку, похожую на Произошла ошибка при работе с сетью.. /// diff --git a/Resources.resx b/Resources.resx index 2623300..2d7e927 100644 --- a/Resources.resx +++ b/Resources.resx @@ -180,12 +180,6 @@ Невозможно выполнить метод, так как при получении ответа произошла ошибка. - - Невозможно установить значение во время выполнения асинхронного действия. - - - Невозможно начать новую работу во время выполнения асинхронной операции. - Получен неподдерживаемый формат кодирования: {0} @@ -201,9 +195,6 @@ Длина имени пользователя не может быть больше 255 символов. - - Не поддерживаемый тип прокси-сервера '{0}'. - {0} Прокси-сервер '{1}'. diff --git a/Security/Cryptography/CryptographyHelper.cs b/Security/Cryptography/CryptographyHelper.cs deleted file mode 100644 index d5ada9f..0000000 --- a/Security/Cryptography/CryptographyHelper.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Security.Cryptography; -using System.Text; - -namespace xNet.Security.Cryptography -{ - /// - /// Представляет статический класс, предназначенный для помощи в работе с криптографией. - /// - public static class CryptographyHelper - { - #region Статические методы (открытые) - - /// - /// Вычесляет MD5 хэш-значение для заданного массива байтов. - /// - /// Входные данные, для которых вычисляется MD5 хэш-значение. - /// Вычисляемое MD5 хэш-значение. - /// Значение параметра равно . - /// Политика FIPS-совместимого алгоритма не задействована. - public static string GetMd5Hash(byte[] data) - { - #region Проверка параметров - - if (data == null) - { - throw new ArgumentNullException("data"); - } - - #endregion - - if (data.Length == 0) - { - return string.Empty; - } - - using (HashAlgorithm hashProvider = new MD5CryptoServiceProvider()) - { - var strBuilder = new StringBuilder(32); - byte[] hashData = hashProvider.ComputeHash(data); - - for (int i = 0; i < hashData.Length; ++i) - { - strBuilder.Append(hashData[i].ToString("x2")); - } - - return strBuilder.ToString(); - } - } - - /// - /// Вычесляет MD5 хэш-значение для заданной строки. - /// - /// Входные данные, для которых вычисляется MD5 хэш-значение. - /// Кодировка, применяемая для преобразования данных в последовательность байтов. Если значение параметра равно , то будет использоваться . - /// Вычисляемое MD5 хэш-значение. - /// Политика FIPS-совместимого алгоритма не задействована. - public static string GetMd5Hash(string data, Encoding encoding = null) - { - if (string.IsNullOrEmpty(data)) - { - return string.Empty; - } - - encoding = encoding ?? Encoding.Default; - - return GetMd5Hash(encoding.GetBytes(data)); - } - - #endregion - } -} \ No newline at end of file diff --git a/Threading/AsyncEvent.cs b/Threading/AsyncEvent.cs deleted file mode 100644 index 47d5873..0000000 --- a/Threading/AsyncEvent.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.ComponentModel; -using System.Threading; - -namespace xNet.Threading -{ - /// - /// Представляет оболочку для асинхронного вызова события с помощью класса . - /// - /// Тип данных аргументов события. Должен наследоваться от . - public class AsyncEvent where TEventArgs : EventArgs - { - #region Поля (закрытые) - - private readonly Action _onEvent; - private readonly SendOrPostCallback _callbackOnEvent; - - #endregion - - - /// - /// Обработчик события. - /// - public EventHandler EventHandler { get; set; } - - - /// - /// Инициализирует новый экземпляр класса заданным методом вызова события. - /// - /// Метод вызова события. - /// Значение параметра равно . - public AsyncEvent(Action onEvent) - { - #region Проверка параметров - - if (onEvent == null) - { - throw new ArgumentNullException("onEvent"); - } - - #endregion - - _onEvent = onEvent; - _callbackOnEvent = new SendOrPostCallback(OnCallback); - } - - - #region Методы (открытые) - - /// - /// Вызывает событие обычным образом. - /// - /// Источник события. - /// Аргументы события. - public void On(object sender, TEventArgs eventArgs) - { - EventHandler handler = EventHandler; - - if (handler != null) - { - handler(sender, eventArgs); - } - } - - /// - /// Асинхронно вызывает событие. - /// - /// Объект для асинхронных операций. - /// Источник события. - /// Аргументы события. - /// Если значение параметра равно , то событие будет вызвано обычным образом. - /// Уже было завершено выполнение асинхронных операций для . - public void Post(AsyncOperation asyncOperation, object sender, TEventArgs eventArgs) - { - if (asyncOperation == null) - { - On(sender, eventArgs); - } - else - { - asyncOperation.Post(_callbackOnEvent, eventArgs); - } - } - - /// - /// Асинхронно вызывает событие и завершает выполнение асинхронной операции объекта . - /// - /// Объект для асинхронных операций. - /// Источник события. - /// Аргументы события. - /// Если значение параметра равно , то событие будет вызвано обычным образом. - /// Уже было завершено выполнение асинхронных операций для . - public void PostOperationCompleted(AsyncOperation asyncOperation, object sender, TEventArgs eventArgs) - { - if (asyncOperation == null) - { - On(sender, eventArgs); - } - else - { - asyncOperation.PostOperationCompleted(_callbackOnEvent, eventArgs); - } - } - - #endregion - - - private void OnCallback(object param) - { - _onEvent(param as TEventArgs); - } - } -} \ No newline at end of file diff --git a/Threading/~MultiThreading/MultiThreading.cs b/Threading/~MultiThreading/MultiThreading.cs deleted file mode 100644 index 8f97372..0000000 --- a/Threading/~MultiThreading/MultiThreading.cs +++ /dev/null @@ -1,998 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Threading; - -namespace xNet.Threading -{ - /// - /// Представляет класс для выполнения операции в отдельных фоновых потоках. - /// - public class MultiThreading : IDisposable - { - #region Структуры (закрытые) - - private struct ForParams - { - public int Begin, End; - - public Action Action; - } - - private struct ForEachParams - { - public IEnumerator Source; - public Action Action; - } - - private struct ForEachListParams - { - public int Begin, End; - - public IList List; - public Action Action; - } - - #endregion - - - #region Поля (закрытые) - - private bool _disposed; - - private ulong _repeatCount; - private Barrier _barrierForReps; - - private int _threadCount; - private int _currentThreadCount; - - private bool _endEnumerator; - private bool _enableInfiniteRepeat; - private bool _notImplementedReset; - - private bool _canceling; - private readonly ReaderWriterLockSlim _lockForCanceling = new ReaderWriterLockSlim(); - - private object _lockForEndThread = new object(); - - private AsyncOperation _asyncOperation; - private SendOrPostCallback _callbackEndWork; - - private EventHandler _beginningWorkHandler; - private EventHandler _workCompletedAsyncEvent; - private EventHandler _repeatCompletedHandler; - private AsyncEvent _progressChangedAsyncEvent; - private AsyncEvent _cancelingWorkAsyncEvent; - - #endregion - - - #region События (открытые) - - /// - /// Возникает при вызове метода , или . - /// - public event EventHandler BeginningWork - { - add - { - _beginningWorkHandler += value; - } - remove - { - _beginningWorkHandler -= value; - } - } - - /// - /// Возникает при завершение работы всех потоков. - /// - /// Данное событие вызывается асинхронно. - public event EventHandler WorkCompleted - { - add - { - _workCompletedAsyncEvent += value; - } - remove - { - _workCompletedAsyncEvent -= value; - } - } - - /// - /// Возникает при завершение одного из повторов выполнения асинхронной операции. - /// - public event EventHandler RepeatCompleted - { - add - { - _repeatCompletedHandler += value; - } - remove - { - _repeatCompletedHandler -= value; - } - } - - /// - /// Возникает при вызове метода . - /// - /// Данное событие вызывается асинхронно. - public event EventHandler ProgressChanged - { - add - { - _progressChangedAsyncEvent.EventHandler += value; - } - remove - { - _progressChangedAsyncEvent.EventHandler -= value; - } - } - - /// - /// Возникает при отмене выполнения асинхронной операции. - /// - /// Данное событие может быть вызвано автоматически, если во время выполнения асинхронной операции произойдёт исключение. Вызов происходит асинхронно. - public event EventHandler CancelingWork - { - add - { - _cancelingWorkAsyncEvent.EventHandler += value; - } - remove - { - _cancelingWorkAsyncEvent.EventHandler -= value; - } - } - - #endregion - - - #region Свойства (открытые) - - /// - /// Возвращает значение, указывающие, выполняется ли асинхронная операция. - /// - public bool Working { get; private set; } - - /// - /// Возвращает значение, указывающие, была ли запрошена отмена выполнения асинхронной операции. - /// - public bool Canceling - { - get - { - _lockForCanceling.EnterReadLock(); - - try - { - return _canceling; - } - finally - { - _lockForCanceling.ExitReadLock(); - } - } - } - - /// - /// Возвращает или задаёт значение, указывающие, нужно ли бесконечно выполнять асинхронную операцию. - /// - /// Значение по умолчанию - . - /// Установка значения во время выполнения асинхронной операции. - public bool EnableInfiniteRepeat - { - get - { - return _enableInfiniteRepeat; - } - set - { - #region Проверка состояния - - if (Working) - { - throw new InvalidOperationException( - Resources.InvalidOperationException_NetProcesses_CannotSetValue); - } - - #endregion - - _enableInfiniteRepeat = value; - } - } - - /// - /// Возвращает или задаёт число потоков используемое для выполнения асинхронной операции. - /// - /// Значение по умолчанию - 1. - /// Установка значения во время выполнения асинхронной операции. - /// Значение параметра меньше 1. - public int ThreadCount - { - get - { - return _threadCount; - } - set - { - #region Проверка состояния - - if (Working) - { - throw new InvalidOperationException( - Resources.InvalidOperationException_NetProcesses_CannotSetValue); - } - - #endregion - - #region Проверка параметра - - if (value < 1) - { - throw ExceptionHelper.CanNotBeLess("ThreadsCount", 1); - } - - #endregion - - _threadCount = value; - } - } - - #endregion - - - /// - /// Возвращает объект для асинхронных операций. - /// - protected AsyncOperation AsyncOperation - { - get - { - return _asyncOperation; - } - } - - - /// - /// Инициализирует новый экземпляр класса . - /// - /// Число потоков используемое для выполнения асинхронной операции. - /// Значение параметра меньше 1. - public MultiThreading(int threadCount = 1) - { - #region Проверка параметров - - if (threadCount < 1) - { - throw ExceptionHelper.CanNotBeLess("threadCount", 1); - } - - #endregion - - _threadCount = threadCount; - - _callbackEndWork = new SendOrPostCallback(EndWorkCallback); - - _cancelingWorkAsyncEvent = new AsyncEvent(OnCancelingWork); - _progressChangedAsyncEvent = new AsyncEvent(OnProgressChanged); - } - - - #region Методы (открытые) - - #region Run - - /// - /// Запускает выполнение операции в отдельных фоновых потоках. - /// - /// Операция, которая будет выполнятся в отдельных фоновых потоках. - /// Текущий экземпляр уже был удалён. - /// Вызов метода во время выполнения асинхронной операции. - /// Значение параметра равно . - public virtual void Run(Action action) - { - #region Проверка состояния - - ThrowIfDisposed(); - - if (Working) - { - throw new InvalidOperationException( - Resources.InvalidOperationException_MultiThreading_CannotStart); - } - - #endregion - - #region Проверка параметров - - if (action == null) - { - throw new ArgumentNullException("action"); - } - - #endregion - - InitBeforeRun(_threadCount); - - try - { - for (int i = 0; i < _threadCount; ++i) - { - StartThread(Thread, action); - } - } - catch (Exception) - { - EndWork(); - throw; - } - } - - /// - /// Запускает выполнение цикла в отдельных фоновых потоках. Операция выполняется на каждой итерации цикла. - /// - /// Начальный индекс (включительный). - /// Конечный индекс (исключительный). - /// Операция, которая будет выполнятся в отдельных фоновых потоках на каждой итерации цикла. - /// Текущий экземпляр уже был удалён. - /// Вызов метода во время выполнения асинхронной операции. - /// - /// Значение параметра меньше 0. - /// -или- - /// Значение параметра больше значения параметра . - /// - /// Значение параметра равно . - public virtual void RunFor(int fromInclusive, int toExclusive, Action action) - { - #region Проверка состояния - - ThrowIfDisposed(); - - if (Working) - { - throw new InvalidOperationException( - Resources.InvalidOperationException_MultiThreading_CannotStart); - } - - #endregion - - #region Проверка параметров - - if (fromInclusive < 0) - { - throw ExceptionHelper.CanNotBeLess("fromInclusive", 0); - } - - if (fromInclusive > toExclusive) - { - throw new ArgumentOutOfRangeException("fromInclusive", - Resources.ArgumentException_MultiThreading_BegIndexRangeMoreEndIndex); - } - - if (action == null) - { - throw new ArgumentNullException("action"); - } - - #endregion - - int range = toExclusive - fromInclusive; - - if (range == 0) - { - return; - } - - int threadCount = _threadCount; - - if (threadCount > range) - { - threadCount = range; - } - - InitBeforeRun(threadCount); - - int pos = 0; - ForParams forParams; - int[] threadsIteration = CalculateThreadsIterations(range, threadCount); - - try - { - for (int i = 0; i < threadsIteration.Length; i++) - { - forParams.Action = action; - - // Высчитываем индексы диапазона итераций для текущего потока. - forParams.Begin = pos + fromInclusive; - forParams.End = (pos + threadsIteration[i]) + fromInclusive; - - StartThread(ForInThread, forParams); - - pos += threadsIteration[i]; - } - } - catch (Exception) - { - EndWork(); - throw; - } - } - - /// - /// Запускает выполнение цикла в отдельных фоновых потоках. Операция выполняется на каждой итерации цикла. - /// - /// Тип данных в источнике. - /// Источник данных. - /// Операция, которая будет выполнятся в отдельных фоновых потоках на каждой итерации цикла. - /// Текущий экземпляр уже был удалён. - /// Вызов метода во время выполнения асинхронной операции. - /// - /// Значение параметра равно . - /// -или- - /// Значение параметра равно . - /// - public virtual void RunForEach(IEnumerable source, Action action) - { - #region Проверка состояния - - ThrowIfDisposed(); - - if (Working) - { - throw new InvalidOperationException( - Resources.InvalidOperationException_MultiThreading_CannotStart); - } - - #endregion - - #region Проверка параметров - - if (source == null) - { - throw new ArgumentNullException("source"); - } - - if (action == null) - { - throw new ArgumentNullException("action"); - } - - #endregion - - if (source is IList) - { - RunForEachList(source, action); - } - else - { - RunForEachOther(source, action); - } - } - - #endregion - - #region Report - - /// - /// Вызывает событие . - /// - /// Значение передаваемое событием, или значение . - /// Текущий экземпляр уже был удалён. - public void ReportProgress(object value = null) - { - ThrowIfDisposed(); - - _progressChangedAsyncEvent.Post(_asyncOperation, - this, new MultiThreadingProgressEventArgs(value)); - } - - /// - /// Вызывает обычным способом событие . - /// - /// Значение передаваемое событием, или значение . - /// Текущий экземпляр уже был удалён. - /// Если возможности асинхронных событий не требуются, то используйте данный метод, так как это повысит производительность. - public void ReportProgressSync(object value = null) - { - ThrowIfDisposed(); - - OnProgressChanged(new MultiThreadingProgressEventArgs(value)); - } - - #endregion - - /// - /// Запрашивает отмену выполнения асинхронной операции и вызывает событие . - /// - /// Текущий экземпляр уже был удалён. - /// Если отмена уже была запрошена, то повторного вызова события не будет. - public virtual void Cancel() - { - ThrowIfDisposed(); - - _lockForCanceling.EnterWriteLock(); - - try - { - if (!_canceling) - { - _canceling = true; - _cancelingWorkAsyncEvent.Post(_asyncOperation, this, EventArgs.Empty); - } - } - finally - { - _lockForCanceling.ExitWriteLock(); - } - } - - /// - /// Освобождает все ресурсы, используемые текущим экземпляром класса . - /// - public void Dispose() - { - Dispose(true); - } - - #endregion - - - #region Методы (защищённые) - - /// Освобождает неуправляемые (а при необходимости и управляемые) ресурсы, используемые объектом . - /// - /// Значение позволяет освободить управляемые и неуправляемые ресурсы; значение позволяет освободить только неуправляемые ресурсы. - protected virtual void Dispose(bool disposing) - { - if (disposing && !_disposed) - { - _disposed = true; - _lockForCanceling.Dispose(); - } - } - - /// - /// Вызывает событие . - /// - /// Аргументы события. - protected virtual void OnBeginningWork(EventArgs e) - { - EventHandler eventHandler = _beginningWorkHandler; - - if (eventHandler != null) - { - eventHandler(this, e); - } - } - - /// - /// Вызывает событие . - /// - /// Аргументы события. - protected virtual void OnWorkCompleted(EventArgs e) - { - EventHandler eventHandler = _workCompletedAsyncEvent; - - if (eventHandler != null) - { - eventHandler(this, e); - } - } - - /// - /// Вызывает событие . - /// - /// Аргументы события. - protected virtual void OnRepeatCompleted(MultiThreadingRepeatEventArgs e) - { - EventHandler eventHandler = _repeatCompletedHandler; - - if (eventHandler != null) - { - eventHandler(this, e); - } - } - - /// - /// Вызывает событие . - /// - /// Аргументы события. - protected virtual void OnProgressChanged(MultiThreadingProgressEventArgs e) - { - _progressChangedAsyncEvent.On(this, e); - } - - /// - /// Вызывает событие . - /// - /// Аргументы события. - protected virtual void OnCancelingWork(EventArgs e) - { - _cancelingWorkAsyncEvent.On(this, e); - } - - #endregion - - - #region Методы (закрытые) - - private void InitBeforeRun(int threadCount, bool needCreateBarrierForReps = true) - { - _repeatCount = 0; - _notImplementedReset = false; - _currentThreadCount = threadCount; - - if (needCreateBarrierForReps) - { - _barrierForReps = new Barrier(threadCount, (b) => - { - if (!Canceling) - { - OnRepeatCompleted( - new MultiThreadingRepeatEventArgs(++_repeatCount)); - } - }); - } - - _canceling = false; - _asyncOperation = AsyncOperationManager.CreateOperation(new object()); - - Working = true; - - OnBeginningWork(EventArgs.Empty); - } - - private bool EndThread() - { - lock (_lockForEndThread) - { - --_currentThreadCount; - - if (_currentThreadCount == 0) - { - _asyncOperation.PostOperationCompleted( - _callbackEndWork, new EventArgs()); - - return true; - } - } - - return false; - } - - private void EndWork() - { - Working = false; - - if (_barrierForReps != null) - { - _barrierForReps.Dispose(); - _barrierForReps = null; - } - - _asyncOperation = null; - } - - private void EndWorkCallback(object param) - { - EndWork(); - OnWorkCompleted(param as EventArgs); - } - - private int[] CalculateThreadsIterations(int iterationCount, int threadsCount) - { - // Список итераций для всех потоков. - int[] threadsIteration = new int[threadsCount]; - - // Число итераций для одного потока (без учёта остатка). - int iterationOnOneThread = iterationCount / threadsCount; - - for (int i = 0; i < threadsIteration.Length; ++i) - { - threadsIteration[i] = iterationOnOneThread; - } - - int index = 0; - int balance = iterationCount - - (threadsCount * iterationOnOneThread); - - // Распределяем оставшиеся итерации между потоками. - for (int i = 0; i < balance; ++i) - { - ++threadsIteration[index]; - - if (++index == threadsIteration.Length) - { - index = 0; - } - } - - return threadsIteration; - } - - #region Запуск потоков - - private void StartThread(Action body, object param) - { - var thread = new Thread(new ParameterizedThreadStart(body)) - { - IsBackground = true - }; - - thread.Start(param); - } - - private void RunForEachList(IEnumerable source, Action action) - { - var list = source as IList; - - int range = list.Count; - - if (range == 0) - { - return; - } - - int threadCount = _threadCount; - - if (threadCount > range) - { - threadCount = range; - } - - InitBeforeRun(threadCount); - - int pos = 0; - ForEachListParams forEachParams; - int[] threadsIteration = CalculateThreadsIterations(range, threadCount); - - try - { - for (int i = 0; i < threadsIteration.Length; i++) - { - forEachParams.Action = action; - forEachParams.List = list; - - // Высчитываем индексы диапазона итераций для текущего потока. - forEachParams.Begin = pos; - forEachParams.End = pos + threadsIteration[i]; - - StartThread(ForEachListInThread, forEachParams); - - pos += threadsIteration[i]; - } - } - catch (Exception) - { - EndWork(); - throw; - } - } - - private void RunForEachOther(IEnumerable source, Action action) - { - _endEnumerator = false; - - InitBeforeRun(_threadCount, false); - - ForEachParams forEachParams; - - forEachParams.Action = action; - forEachParams.Source = source.GetEnumerator(); - - try - { - for (int i = 0; i < _threadCount; ++i) - { - StartThread(ForEachInThread, forEachParams); - } - } - catch (Exception) - { - EndWork(); - throw; - } - } - - #endregion - - #region Методы потоков - - private void Thread(object param) - { - var action = param as Action; - - try - { - while (!Canceling) - { - action(); - - if (_enableInfiniteRepeat) - { - _barrierForReps.SignalAndWait(); - } - else - { - break; - } - } - } - catch (Exception) - { - Cancel(); - - if (_enableInfiniteRepeat) - { - _barrierForReps.RemoveParticipant(); - } - - throw; - } - finally - { - EndThread(); - } - } - - private void ForInThread(object param) - { - var forParams = (ForParams)param; - - try - { - do - { - for (int i = forParams.Begin; i < forParams.End && !Canceling; ++i) - { - forParams.Action(i); - } - - if (_enableInfiniteRepeat) - { - _barrierForReps.SignalAndWait(); - } - else - { - break; - } - } while (!Canceling); - } - catch (Exception) - { - Cancel(); - - if (_enableInfiniteRepeat) - { - _barrierForReps.RemoveParticipant(); - } - - throw; - } - finally - { - EndThread(); - } - } - - private void ForEachListInThread(object param) - { - var forEachParams = (ForEachListParams)param; - IList list = forEachParams.List; - - try - { - do - { - for (int i = forEachParams.Begin; i < forEachParams.End && !Canceling; ++i) - { - forEachParams.Action(list[i]); - } - - if (_enableInfiniteRepeat) - { - _barrierForReps.SignalAndWait(); - } - else - { - break; - } - } while (!Canceling); - } - catch (Exception) - { - Cancel(); - - if (_enableInfiniteRepeat) - { - _barrierForReps.RemoveParticipant(); - } - - throw; - } - finally - { - EndThread(); - } - } - - private void ForEachInThread(object param) - { - var forEachParams = (ForEachParams)param; - - try - { - while (!Canceling) - { - T value; - - lock (forEachParams.Source) - { - if (Canceling) - { - break; - } - - if (!forEachParams.Source.MoveNext()) - { - if (_enableInfiniteRepeat && !_notImplementedReset) - { - try - { - forEachParams.Source.Reset(); - } - catch (NotImplementedException) - { - _notImplementedReset = true; - break; - } - - OnRepeatCompleted( - new MultiThreadingRepeatEventArgs(++_repeatCount)); - - continue; - } - else - { - break; - } - } - - value = forEachParams.Source.Current; - } - - forEachParams.Action(value); - } - } - catch (Exception ex) - { - Cancel(); - } - finally - { - bool isLastThread = EndThread(); - - if (isLastThread) - { - forEachParams.Source.Dispose(); - } - } - } - - #endregion - - private void ThrowIfDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException("MultiThreading"); - } - } - - #endregion - } -} \ No newline at end of file diff --git a/Threading/~MultiThreading/MultiThreadingProgressEventArgs.cs b/Threading/~MultiThreading/MultiThreadingProgressEventArgs.cs deleted file mode 100644 index 8a023c7..0000000 --- a/Threading/~MultiThreading/MultiThreadingProgressEventArgs.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace xNet.Threading -{ - /// - /// Предоставляет данные для события, сообщающим о прогрессе выполнения асинхронной операции. - /// - public sealed class MultiThreadingProgressEventArgs : EventArgs - { - /// - /// Возвращает передаваемое значение. - /// - public object Result { get; private set; } - - - /// - /// Инициализирует новый экземпляр класса заданным значением. - /// - /// Передаваемое значение. - public MultiThreadingProgressEventArgs(object result) - { - Result = result; - } - } -} \ No newline at end of file diff --git a/Threading/~MultiThreading/MultiThreadingRepeatEventArgs.cs b/Threading/~MultiThreading/MultiThreadingRepeatEventArgs.cs deleted file mode 100644 index 8652991..0000000 --- a/Threading/~MultiThreading/MultiThreadingRepeatEventArgs.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace xNet.Threading -{ - /// - /// Предоставляет данные для события, сообщающим о завершение одного из повторов выполнения асинхронной операции. - /// - public sealed class MultiThreadingRepeatEventArgs : EventArgs - { - /// - /// Возвращает число выполненных повторов. - /// - public ulong RepeatCount { get; private set; } - - - /// - /// Инициализирует новый экземпляр класса . - /// - /// Число выполненных повторов. - public MultiThreadingRepeatEventArgs(ulong repeatCount) - { - RepeatCount = repeatCount; - } - } -} \ No newline at end of file diff --git a/example.cs b/example.cs deleted file mode 100644 index 9c595ee..0000000 --- a/example.cs +++ /dev/null @@ -1,146 +0,0 @@ -public class Captcha -{ - public string Url { get; private set; } - public string Key { get; set; } - - public Captcha(string url) - { - Url = url; - } -} - -public enum AccountStatus -{ - None, - Valid, - NotValid -} - -public class Message -{ - public string AuthorID { get; set; } - public string AuthorName { get; set; } - - public string Value { get; set; } -} - -public class Account : IHttpConnect -{ - public HttpRequest Request { get; set; } - - public string Login { get; private set; } - public string Password { get; private set; } - public CookieDictionary Cookies { get; private set; } - - public Account(string login, string password) - { - Login = login; - Password = password; - } - - public void InitRequest(HttpRequest request) - { - Request = request; - - request.Cookies = Cookies; // На случай, если аккаунт уже авторизован. - request.AllowAutoRedirect = false; - - request.Referer = "http://www.site.com"; - request.BaseAddress = new Uri("http://www.site.com"); - } - - public AccountStatus Logining(ref Captcha captcha) - { - // Если это первое обращение, то устанавливаем новые куки. - if (captcha == null) - { - Cookies = new CookieDictionary(); - Request.Cookies = Cookies; - } - - Request.AddParam("login", Login).AddParam("password", Password); - - // Если до этого требовался ввод капчи. - if (captcha != null) - { - Request.AddParam("c_key", captcha.Key); - } - - string loginingResult = Request.Post("/logining.php").ToString(); - - // Если требуется ввод капчи. - if (loginingResult.Contains("need_captcha")) - { - string captchaUrl = loginingResult.Substring("captcha_url=", "&"); - captcha = new Captcha(captchaUrl); - - return AccountStatus.None; - } - - if (loginingResult.Contains("ok")) - { - return AccountStatus.Valid; - } - - return AccountStatus.NotValid; - } - - public Message[] GetPrivateMessages() - { - string getPmResult = Request.Post("/get_pm.php").ToString(); - - var messages = new List(); - - // парсим список личных сообщений - - return messages.ToArray(); - } - - public void ReplyToMessage(string userId, string message) - { - Request.AddParam("to_id", userId).AddParam("msg", message); - - Request.Post("/send_pm.php").None(); - } -} - -static void Main() -{ - using (var request = new HttpRequest()) - { - request.UserAgent = HttpHelper.ChromeUserAgent(); - request.Proxy = HttpProxyClient.Parse("127.0.0.18080"); - - var account = new Account("John", "Smith"); - account.InitRequest(request); - - Captcha captcha = null; - AccountStatus accountStatus = AccountStatus.None; - - do - { - accountStatus = account.Logining(ref captcha); - - // Нужно ввести капчу. - if (captcha != null) - { - request.Get(captcha.Url).ToFile("cap.jpg"); - captcha.Key = Console.ReadLine(); - } - } while (captcha != null); - - if (accountStatus == AccountStatus.Valid) - { - var messages = account.GetPrivateMessages(); - - foreach (var message in messages) - { - string answer = string.Format( - "Привет, {0}! Мой хозяин сейчас занят и не может ответить тебе...", - message.AuthorName); - - account.ReplyToMessage(message.AuthorID, answer); - } - } - } -} \ No newline at end of file diff --git a/xNet.csproj b/xNet.csproj index 596be60..f39bd57 100644 --- a/xNet.csproj +++ b/xNet.csproj @@ -46,54 +46,45 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True True Resources.resx - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - @@ -101,8 +92,15 @@ Resources.Designer.cs - + + + + + + + +