Полезные фишки в BAT/CMD файлах.

Выход из BAT-файла

exit /B

Ключ /B обязателен! Если использовать просто exit — закроется командный интерпретатор.

Проверка, пустая ли переменная

Можно использовать для проверки параметров в командной строке.

if "%~1"=="" (
	echo Use %0 ^<address^>
	echo Address must be without http://, https:// or www
	echo e.g. riseup.net
	pause
	exit /B
)

Запись вывода программы в переменную

Аналог VAR=`program` в bash.

for /f %%i in ('program') do set "API_URI=%%i"& goto f1
:f1

Пример:

for /f %%i in ('bin\jq .api_uri %WORKDIR%/provider.json') do set "API_URI=%%i"& goto f1
:f1

Источник

SetLocal и расширенная обработка команд

Статья на Киберфоруме Копия в PDF

Экранирование спецсимволов

В BAT/CMD файле некоторые символы (перенаправления > и <, конвейера |, символ &, указание переменной %) считаются специальными. Если символ должен быть включен в команду как символ, могут быть глюки. Перед символом нужно указать символ экранирования: ^ (крышку).

Пример:

echo Use batfile.bat ^<address^>

(выведет на экран Use batfile.bat <address>)

Источник Копия в PDF Там есть и другие полезные штуковины.

Удаление определенного символа из строки.

Например, надо удалить из переменной %VAR% все кавычки:

set VAR=%VAR:"=%

Источник Копия в PDF В источнике есть и другие примеры работы со строками.

C#, HttpWebRequest: использование самоподписанного (self-signed) сертификата.

Преамбула

Если попытаться соединиться с HTTPS-сервером, имеющим самоподписанный сертификат, то HttpWebRequest сгенерирует исключение WebException Базовое соединение закрыто: Не удалось установить доверительные отношения для защищенного канала SSL/TLS. (The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.). Оно и понятно, HttpWebRequest не смог проверить сертификат узла и закономерно нас послал.

Решение заключается в переопределении глобального обработчика System.Net.ServicePointManager.ServerCertificateValidationCallback.

Внимание! Изменение ServerCertificateValidationCallback повлияет на все соединения в программе, пока обработчик не будет установлен по умолчанию, надо не забывать это, и возвращать обработчик к стандартному значению, после того, как работа с сервером, имеющим самоподписанный сертификат, завершена.

Предположим, есть класс-обертка над HttpWebRequest, надо его дополнить так, чтоб можно было работать с серверами с self-signed сертификатами.

Игнорирование неправильных сертификатов

Самый простой способ, но не самый безопасный. ServerCertificateValidationCallback передается делегат, который всегда возвращает true. Добавляем в класс функцию:

public void EnableIgnoreCertError()
{
    ServicePointManager.ServerCertificateValidationCallback =
        delegate { return true; };
}

И функцию, которая возвращает ServerCertificateValidationCallback к значению по умолчанию:

public void DisableIgnoreCertError()
{
    ServicePointManager.ServerCertificateValidationCallback = 
        null;
}

Начали работать с сервером — вызвали первую, закончили — вызвали вторую.

Самостоятельная проверка сертификата

Немного более сложный, но более безопасный способ. Необходимо заранее либо иметь сам сертификат, либо знать его хэш. В следующем примере будем проверять как раз хэш SHA1 сертификата.
1. Подключим в References’ах System.Security.Cryptography.
2. Подключим необходимые пространства имен:

using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

3. Заведем в классе поле, куда из вызывающей программы будем передавать заранее известный хэш сертификата:

public string CertHashString { get; set; }

4. Заведем две функции, для включения и выключения самостоятельной проверки сертификата:

public void EnableValidateCert()
{
    ServicePointManager.ServerCertificateValidationCallback =
        ValidateCert;
    
}

public void DisableValidateCert()
{
    ServicePointManager.ServerCertificateValidationCallback =
        null;
}

В первой функции вместо делегата, возвращающего true, указываем нашу функцию проверки.

Функция проверки сертификата

Функция проверки сертификата обязательно должна иметь следующий заголовок:
bool FunctionName (object, X509Certificate, X509Chain, SslPolicyErrors), т.е., например:

private bool ValidateCert(object sender, X509Certificate cert,
    X509Chain chain, SslPolicyErrors sslPolicyErrors)

В функции:
1. Проверяем наличие ошибок SSL, если их нет, значит сертификат уже был опознан:

if (sslPolicyErrors == SslPolicyErrors.None)
{
    return true;
}

2. Если известный хэш сертификата не был передан вызывающей программой, значит и проверять нечего:

if (string.IsNullOrEmpty(CertHashString))
{
    return false;
}

3. Получаем хэш сертификата сервера в виде строки:

string hashstring = cert.GetCertHashString();

4. Если хэши полученного и известного сертификата совпадают — все ок, возвращаем true, иначе false.

if (hashstring == CertHashString)
{
    return true;
}

return false;

Функция целиком:

private bool ValidateCert(object sender, X509Certificate cert,
    X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    //все и так хорошо
    if (sslPolicyErrors == SslPolicyErrors.None)
    {
        return true;
    }

    //не передан хэш сертификата
    //значит и проверять нечего
    if (string.IsNullOrEmpty(CertHashString))
    {
        return false;
    }

    //получаем хэш сертификата сервера в виде строки
    string hashstring = cert.GetCertHashString();

    //если хэши полученного и известного 
    //сертификата совпадают - все ок.
    if (hashstring == CertHashString)
    {
        return true;
    }

    return false;
}

Класс целиком на PasteBin
На GitHub

Источник

C#, получение хэша (fingerprint) сертификата X509.

Преамбула

Понадобилось проверить сертификат X509 на целостность и подлинность. Поставщик сертификата отдельно передает его fingerprint и алгоритм хэширования по которому тот вычисляется.

Судя по документации от MS, получить fingerprint, он же хэш, можно функцией GetCertHashString() (или GetCertHash() в виде массива байт) класса X509Certificate2, однако, в .NET 2.0 отсутствует перегрузка функции GetCertHashString(HashAlgorithmName), которая позволяет выбрать алгоритм хеширования (GetCertHashString() возвращает хэш SHA1). Потому сделаем руками, благо ничего сложного в этом нет.

Получение fingerprint

1. Подключаем в References System.Security.Cryptography
2. Подключаем необходимые пространства имен в классе:

using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

3. Загружать сертификат будем из файла, потому проверяем его наличие:

if (!File.Exists(CertFile))
{
    Console.WriteLine("File not found.");
    return null;
}

4. Загружаем сертификат (создаем экземпляр класса X509Certificate2). Если вдруг файл сертификата поврежден, то конструктор X509Certificate2 вызовет Exception Требуемый объект не найден. Поэтому конструктор надо обернуть в try...catch:

try
{
    X509 = new X509Certificate2(CertFile);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
    return null;
}

5. Получаем загруженный сертификат в виде массива байт:

byte[] cert = X509.GetRawCertData();

6. Создаем объект HashAlgorithm, который и займется вычислением хэша/fingerprint’а. Я завел в функции входную переменную AlgName, куда записывается строка с названием алгоритма, что бы иметь возможность выбора алгоритма хэширования если что:

HashAlgorithm alg = null;
switch (AlgName.ToUpperInvariant())
{
    case "MD5": alg = MD5.Create(); break;
    case "SHA1": alg = SHA1.Create(); break;
    case "SHA256": alg = SHA256.Create(); break;
    case "SHA384": alg = SHA384.Create(); break;
    case "SHA512": alg = SHA512.Create(); break;
    default:
        {
            Console.WriteLine("Unknow algorithm.");
            return null;
        }
}

7. Получаем хэш в виде массива байт:

byte[] hash = alg.ComputeHash(cert);

8. Преобразуем массив байт в строку шестнадцатеричных чисел:

string hex = BitConverter.ToString(hash).ToLowerInvariant().
    Replace("-", "");

ToLowerInvariant() преобразует буквы в строке, полученной BitConverter в строчные, а Replace("-", "") удаляет разделители (-) между значениями байтов, которые BitConverter вставляет в строку.

Код функции целиком
Тестовый пример на GitHub

C#, парсинг и прочая работа с JSON. В том числе и в .NET 2.0

Преамбула

Понадобилось достать несколько значений из JSON-файла, искал, чем это сделать и нашел просто офигенную библиотеку Json.NET. Это не просто парсер, это целый набор инструментов: парсер, сериализаторы, десериализаторы, конвертеры. Кроме банального вытаскивания значений, можно формировать JSON, конвертировать его в XML и XML в JSON, обращаться к объектам JSON через запрос SelectToken или LINQ. А можно и просто вытащить нужное значение, обращаясь к полям JSON, используя встроенные функции объектов.

Несомненный плюс библиотеки в том, что даже в последней версии она поддерживает .NET Framework 2.0 Правда нельзя будет использовать синтаксис LINQ, но и без него инструментов хватает.

Простой парсинг и извлечение значений

С помощью JObject и JToken

1. Подключаем библиотеку для своего Framework’а через References и в исходнике:

using Newtonsoft.Json.Linq;

2. Загружаем JSON в переменную, например из файла.

3. Парсим JSON в JObject:

JObject JSONObj = JObject.Parse(JSONBuf);

JObject.Parse может вызвать exception, если есть синтаксические ошибки в JSON, так что лучше поместить его в try...catch:

public static JObject ParseJSON(string JSONBuf)
{
    JObject JSONObj = null;
    try
    {
        JSONObj = JObject.Parse(JSONBuf);
    }
    catch (Exception ex)
    {
        Console.WriteLine("ERROR: " + ex.Message);
        return null;
    }
    return JSONObj;
}

Пример реакции на ошибку синтаксиса:

Invalid character after parsing property name. Expected ':' but got: {. Path description.languages', line 15, position 9.

4. Далее, можно вытащить значение поля JSON в объект JToken помощью функции JSONObj.GetValue(FieldName);, если поле со значением находится сразу в корне JSON, как, например, api_uri в этом примере, то JToken можно сразу преобразовать в строку с помощью функции .ToString:

JToken tok = JSONObj.GetValue("api_uri");
tok.ToString();

Однако, если поле отсутствует, то это вызовет exception:

В экземпляре объекта не задана ссылка на объект.

Этого можно избежать, отловив исключение в try...catch, либо проверив наличие поля функцией JObject.ContainsKey("имя_поля") перед вызовом GetValue, либо воспользовавшись функцией TryGetValue вместо GetValue

Примеры кода на PasteBin
Тестовый проект

Если же нужное значение находится где-то глубоко в недрах JSON, то необходимо воспользоваться функцией JObject.SelectToken() Пример в официальной документации Копия

Что дальше?

Как я уже говорил, инструмент очень мощный, так что лучше начать с изучения официальной документации

Скачать

Json.NET с официального сайта
Копия библиотеки v 120r3

OpenVPN для Windows XP.

Последняя поддерживающая Windows XP версия OpenVPN это 2.3.18.

Please note that OpenVPN 2.4 installers will not work on Windows XP. The last OpenVPN version that supports Windows XP is 2.3.18, which is downloadable as 32-bit and 64-bit versions.

Скачать с официального сайта

Версия x86 (32-разрядная)
Версия x64 (64-разрядная)

Копии

Версия x86 (32-разрядная)
Версия x64 (64-разрядная)