Отключение стандартных (скрытых) общих ресурсов в Windows 7 (XP, 2000)

А также игры с BAT-файлами.

В Windows 7 (кроме домашней версии), а также и в более ранних (Vista, XP, 2000) версиях присутствуют т.н. стандартные (или скрытые) общие (расшаренные, сетевые) ресурсы, «админские шары». Туда входят локальные диски (имена, например C$, D$, E$), обнаруженные во время установки, «удаленный Admin» (ADMIN$) — каталог операционной системы (например C:\Windows), и специальный ресурс «удаленный IPC» (IPC$). Все эти ресурсы доступны из локальной сети. При обычном просмотре компьютера в локальной сети, например, через «Сетевое окружение» или в проводнике их не видно, но пользователь, обладающий правами администратора, вполне может получить к ним доступ. В Windows XP или 2000 с этим была большая беда и неприятность, особенно в XP, и особенно, если она была установлена с настройками по умолчанию, а безопасности не было уделено должного внимания. Доступ к этим скрытым ресурсам мог получить любой пользователь в локальной сети, знающий логин администратора, если пароль администратора не был установлен. Часто пароль на основную админскую запись — «Администратор» банально забывали установить, даже если создавали отдельного пользователя с админскими правами и паролем.

В Windows 7 с этим вроде бы стало получше: Если на ПК, к которому мы пытаемся подключиться, установлена Windows 7 со включенным контролем учетных записей, подключиться к общим ресурсам можно только используя встроенную учетную запись «администратор». Данная учетка должна быть разблокирована и иметь пароль. Подключение под любым другим пользователем, даже обладающем правами локального админа, не пройдет. [1]

Просмотр расшаренных ресурсов.

Первый вариант. Идем в Пуск —> Все программы —> Администрирование —>Управление компьютером (или нажимаем Win+R и вводим команду compmgmt.msc /s) и выбираем в появившемся окне в левой колонке Общие папки, а потом Общие ресурсы. Должно отобразиться что-то типа этого:

Другой вариант, ввести в консоли команду net share.
Должно получиться что-то типа такого (понятно, что у вас буквы дисков будут другие):

Общее имя   Ресурс                        Заметки

-------------------------------------------------------------------------------
ADMIN$       C:\Windows                      Удаленный Admin                   
C$           C:\                             Стандартный общий ресурс          
D$           D:\                             Стандартный общий ресурс          
F$           F:\                             Стандартный общий ресурс          
IPC$                                         Удаленный IPC                     
L$           L:\                             Стандартный общий ресурс          
N$           N:\                             Стандартный общий ресурс          
Команда выполнена успешно.

Специальный ресурс IPC$

Вот что об этом ресурсе говорит официальная справка:

Общий ресурс IPC$ также известен, как подключение пустых сеансов. С помощью этих сеансов Windows позволяет анонимным пользователям выполнять определенные операции, например получать имена учетных записей домена и список общих сетевых ресурсов.

Общий ресурс IPC$ создается службой Windows Server. Этот особый общий ресурс существует для обеспечения последующих именованных каналов подключения к серверу. Именованные каналы сервера создаются для компонентов, встроенных в операционную систему и приложений или служб, которые установлены в системе. При создании именованного канала процессу задается уровень безопасности, связанный с каналом и затем это гарантирует, что доступ предоставлен только для указанных пользователей или групп. [2] [3]

Проще говоря, если IPC$ удалить, то другой компьютер не сможет посмотреть, есть ли на вашем компьютере расшаренные ресурсы. Так же могут отвалиться некоторые системные сервисы. На практике, у меня отвалился доступ только к 1С «Склад» (7.7), который и был мне не особо нужен, давно хотел откосить от забивания и проверки накладных и от материальной ответственности :). Но не стоит так делать на «сервере» 7.7, где в самом простом случае никакого сервера нет, а просто базы лежат в расшаренной папке — скорее всего, отвалится все к penis canis. 🙂

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

Отключение доступа к стандартным ресурсам через Реестр

На мой взгляд, в XP и ниже это делать надо обязательно, в семерке можно обойтись, но если вы параноик, или, как меня, вас достала какая-нибудь комиссия (да, ФСТЭК и РКН, вдругорядь, не penis canis), то это опять же надо делать.

Необходимо в ключе Реестра
HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters
добавить следующие значения:
AutoShareServer и AutoShareWks типа REG_DWORD со значением 0 (Windows XP/2000 Proffessional/2000 Server). Вообще где-то надо один, где-то второй, но если добавить оба — ничего страшного случиться не должно. Для семерки тоже должно работать. [4] [5] [6]
После добавления делаем перезагрузку.

Минусы:
— не отключить доступ к IPC$
— вырубается доступ ко всем скрытым шарам, а иногда такую корову полезно иметь самому, для некоторых дисков, и без установки стороннего ПО.
Плюсы:
+ Вырубается быстро и самое основное.

Отключение доступа через BAT/CMD файл

С одной стороны все довольно просто — можно насовать в файл однотипных команд типа
net share c$ /delete, но так, согласитесь, некрасиво, особенно, если этих самых админских шар десяток, компов сотня, а еще что-то надо кое-где оставить себе любимому. Но на то нам и командные файлы, чтоб сделать «все как ты захочешь».
Покажу на примере самого простого случая — надо удалить все шары, вместе с не удаляемой через Реестр IPC$. Пример простой, но развивая можно улучшить и углУбить под вашу задачу.
Конечно, язык командных файлов Windows жутко беден, по сравнению с огромными возможностями shell Linux, ИМХО, даже с помощью простенькой sh и BisyBox можно сделать то же самое, и даже гораздо больше, намного удобнее. Но это была секунда ворчания — оседлали корову, придется ехать на ней.

Получение и перебор всех значений

Для перебора всех значений (строк) из определенного списка, в BAT/CMD существует оператор (по правилам MS правильнее говорить «внутренняя команда») FOR, которая на самом деле ведет себя как foreach в «больших» языках программирования, т.е. перебирает список/массив данных, пока тот не лопнет кончится.

Общий синтаксис:
FOR %переменная IN (набор) DO команда [параметры] [7]

Чтобы вся магия у нас получилась, перед использованием FOR выполним такую команду:

Setlocal EnableDelayedExpansion

Обычно, в командных файлах команда FOR используется не только для разбора данных, но и их обработки, что требует использования переменных внутри цикла FOR. И здесь возникает проблема — изменения значений переменных не происходит, т.е. их применение внутри скобок невозможно. Подобное явление вызвано не логическими предпосылками, а всего лишь определенными особенностями реализации командного процессора CMD.EXE [7]

Использование Setlocal EnableDelayedExpansion позволяет использование переменных внутри цикла FOR, правда, не совсем. Но об этом далее.

Теперь разберемся откуда брать список. FOR может обрабатывать вывод заданной команды, если использовать его таким образом:

FOR /F %переменная IN (набор) DO (
command1 [parameters]
command2
. . .
)

и вместо набор вставить 'команда', где:

'команда' — любая команда Windows, выводящая на консоль некую информацию (не забудьте одинарные кавычки).
/F — указание команде FOR обрабатывать список значений, файлов или вывод команды.

В параметрах команды FOR можно задать разделитель полей. Для этого нужно указать в качестве параметра следующую конструкцию:
delims=xxxнабор разделителей между обрабатываемыми элементами строк. По умолчанию, в качестве разделителей используются пробелы и знаки табуляции. [7]

Если разделитель не задать, то FOR дойдет до первого пробела или табуляции, все остальное выкинет, и перейдет к следующей строке. Т.е. в нашем случае получим:

for /F %%i In ('net share') do (

	echo !ITEM!

)

и вывод:

Общее
-------------------------------------------------------------------------------
ADMIN$
C$ 
D$ 
F$ 
IPC$ 
L$ 
N$ 
Команда

Внезапно, почти то, что нам надо!
А надо нам отключить админские шары, а они выделяются на общем фоне — у них внутри неонка в конце имени $. Надо теперь отделить зерна от плевел.

Ищем подстроку в строке

Итак:
1. создадим переменную при помощи SET, и присвоим ей исходный текст set V1=mother (имена переменных учитывают регистр, имена команд нет).
2. Сделаем следующее:
set V2=%V1:her=%

где her — подстрока, которую надо найти. Если в переменной V1 будет подстрока her, то в переменной V2 окажется подстрока moth (т.е. содержимое переменной V2 без указанной подстроки).

Чтобы проверить, содержит ли строка из переменной V1 подстроку, заданную в пункте 2, надо сравнить результирующие строки. Если они НЕ равны — строка V1 содержит подстроку her.

if NOT %V1%==%V2%

Внезапное НО. Или то, о чем упоминал ранее.

Оказывается, IF внутри FOR не работает, точнее не принимает переменных, не в виде % ITEM%, не в виде %%ITEM%%, не в виде !ITEM!. Как только я не перепробовал (может дурак все-таки я, кто знает — поправьте). Но пока не поправили, пришлось ухищряться.

Подпрограммы

В BAT-файле можно создавать подпрограммы, кривые, косые, но подпрограммы.

Вызываются они так call :метка параметр1 параметр2 ...

После окончания основного файла делается так. Ставится метка подпрограммы, далее идут команды, в конце ставим еще одну метку, например :eof.

В конце основной программы ставим goto :eof

Параметры, переданные этой недоподпрограмме, внутри видятся точно также, как и внешние параметры BAT-файла, т.е. %1, %2. Только в подпрограмме.
После выполнения подпрограммы начинает выполняться следующая команда после call, у нас это новая итерация цикла.

А в подпрограмме мы как раз и производим сравнение, и если нашли символ $ — запускаем команду удаления ресурса:

:check

	set V1=%1
	set V2=%V1:$=%

	if NOT %V1%==%V2% (
		echo %V1%
		net share %V1% /delete
	)

:eof

BAT-файл полностью

@echo off
Setlocal EnableDelayedExpansion

for /F %%i In ('net share') do (

	set ITEM=%%i
	call :check !ITEM!

)

goto :eof

:check

	set V1=%1
	set V2=%V1:$=%

	if NOT %V1%==%V2% (
		echo %V1%
		net share %V1% /delete
	)

:eof

Можно скопировать код с PasteBin [10] или Mega.nz [11]

Автозагрузка BAT-скрипта

С автозагрузкой получается странная штука, на форумах подобный батник советуют просто кинуть в автозапуск и забыть. Может на XP/2000 так и сработает, но на Windows 7 тут кардинальное отличие.

1. Такой батник надо запускать от администратора (пользователя из группы «Администраторы«)
2. Будет заебно заставлять главбуха каждую загрузку подтверждать UAC
3. Сразу дерево почему-то не жужжит, скорее всего, потому что сетевой подсистеме требуется время на запуск, который происходит после входа пользователя в систему. А до этого команда net не работает.

Но тут на помощь пришел опять «Планировщик заданий».
Как в статье про запуск программы без сообщений UAC от имени администратора [12] [13], мы также добавляем наш батник в «Планировщик заданий», но на этот раз, создавая задание, переходим еще и на вкладку «Триггеры«. Добавляем триггер, и откладываем запуск задачи (батника) на 30 секунд. Значение 30 секунд установлено исключительно экспериментально и не на совсем говенной машине, возможно, вам потребуется больше. Ставьте минуту/две.

Источники, литература, дополнительные ссылки и код.

1. Общие ресурсы Windows 7 Копия
2. Общий ресурс IPC$ и поведение пустых сеансов в Windows
3. IPC$ share and null session behavior in Windows
4. Скрытые административные и общие сетевые ресурсы в Windows XP/2000 C$, ADMIN$, FAX$, IPC$, PRINT$
5. https://www.securitylab.ru/forum/forum18/topic15107/
6. Удаление стандартных общих ресурсов C$, ADMIN$, IPC$ Копия
7. Команда FOR КОПИЯ

Обсуждения на форумах:
8. Доступ к сетевым шарам в Windows 7
9. IPC$

Код:
10. Код на PasteBin
11. Код на Mega.NZ

12. Отключение запроса UAC для отдельных приложений
13. Отключение запроса UAC для отдельных приложений

Раритетные рекламные ролики Windows 95

Внезапно, нашел в архиве. Были на лицензионном расширенном диске Windows 95 (2 CD).
Диски за давностью лет потерялись, а ролики остались.

Довольно неказистый от Microsoft

Прямая ссылка
Скачать

Windows в мультипликации Билла Плимптона

Несколько психоделичный ролик, чем-то напоминает советский мультфильм «Контакт».

Прямая ссылка
Скачать

Windows в мультипликации Джоан К. Гратца

Мой любимый добрый ролик, вызывает ностальгию, печаль, пробивает на слезу, а еще в ролике есть котик 🙂

Прямая ссылка
Скачать

Отключение запроса UAC для отдельных приложений

Преамбула

В Windows 7 и выше есть дополнительный механизм безопасности UAC (Контроль учетных записей пользователей). Обычно пользователь заходит в систему под учетной записью с ограниченными правами, а когда приложению для каких-то целей (установка драйверов, изменение файлов в системных папках и т.д.) требуются админские права, то соответствующий запрос появляется на экране у пользователя.

В принципе, можно вообще отключить UAC, но это понизит безопасность системы, т.к. любое приложение (в т.ч. и зловредное) сможет без всякого запроса поднять себе права до уровня администратора, и сделать с системой все, что ему угодно.
А вот для отдельных программ полезно было бы иметь возможность отключить уведомления. Например, у меня в автозагрузке есть несколько служебных программ, которым требуются права администратора, но неудобно каждый раз копытом набирать номер при каждой загрузке системы прихлопывать вылетающие окна с этим запросом 🙂

На самом деле способов есть минимум 3:

— Скачать программку AdmLink и ей воспользоваться (тогда приложение можно будет запускать и пользователю вообще не входящему в группу «Администраторы»)
— Скачать Microsoft Application Compatibility Toolkit, и воспользоваться им.
— И третий, приглянувшийся мне, запускать программу с повышением прав с помощью «Планировщика заданий»

Способ собственно тем и приглянулся, что не надо ничего качать, планировщик заданий есть на любой машине, а вот интернет не везде. Да, способ будет работать только для пользователей, входящих в группу «Администраторы» (для домашнего компьютера, при установке Windows по умолчанию, пользователь обычно в нее входит).

Отключаем запрос UAC с помощью планировщика заданий

Создаем задачу

Для примера создадим ярлык для запуска Редактора реестра (regedit.exe)

1. Запускаем планировщик заданий Пуск —> Все программы —> Стандартные —> Служебные —> Планировщик заданий или в командной строке/через «Выполнить» (Win+R):

taskschd.msc /s

2. Справа в колонке Действие кликаем на Создать задачу:

3. В появившемся окне на вкладке Общие вводим в поле Имя какое-нибудь название, желательно латиницей и без пробелов, чтоб не морочиться потом с кавычками. Например, regedit_adm. Можно также оставить описание (в поле Описание), чтоб не запутаться если что, например, Запуск Regedit с правами администратора.

4. Обязательно ставим галочку Выполнить с наивысшими правами.

5. Переходим на вкладку Действия. и жмем кнопку Создать…
6. В появившемся окне в поле Действие оставляем Запуск программы, а в поле Программа или сценарий прописываем путь к нужной программе или BAT/CMD файлу. При необходимости в соответствующих полях можно указать рабочую папку или необходимые аргументы командной строки.

7. Нажимаем ОК, потом еще раз ОК, таким образом сохраняем задачу.
Задача появится в Библиотеке планировщика заданий, где ее можно при необходимости посмотреть, изменить или удалить, когда станет не нужна.

Закрываем планировщик задач

Создание ярлыка

1. Создаем ярлык на рабочем столе. Клик правой кнопкой и Создать —> Ярлык
2. В появившемся окне прописываем следующее:

C:\Windows\System32\schtasks.exe /run /tn regedit_adm

где regedit_adm — имя созданной вами задачи.

3. Нажимаем Далее, вводим имя ярлыка, например Regedit с правами администратора
4. Можно поменять в свойствах ярлыка значок для красоты. Кстати, внутри Regedit32.exe ВНЕЗАПНО обнаружился прикольный значок в винтажном стиле Windows 3.11

Запускаем ярлык. Окно UAC не появилось

ФАНФАРЫ!

Источник

Статья на oszone.net Копия

C#, .NET Framework 2.0 Декодировка URL-адреса без System.Web.

Понадобилось тут перекодировать URL с русскими буквами в нормальный текст, т.е. нечто вида https://ru.wikipedia.org/wiki/URL#%D0%9A%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_URL в читабельный вид https://ru.wikipedia.org/wiki/URL#Кодирование_URL

В MSDN сходу нашлось решение для .NET Framework 4, а вот для 2.0 так сразу не нашлось, но оказалось, что все-таки решение есть.

Декодирование URL

string text = https://ru.wikipedia.org/wiki/URL#%D0%9A%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_URL
text = text.Replace("+", " ");
text = System.Uri.UnescapeDataString(text);

Кодирование URL

string text = https://ru.wikipedia.org/wiki/URL#Кодирование_URL
text = System.Uri.EscapeDataString(text);

На самом деле, тот случай, когда мопед совершенно не мой, и я просто объяву разместил.

Источники

1. https://ru.wikipedia.org/wiki/URL#Кодирование_URL

2. Сам способ нашел здесь, у няшного серфера и программера.
Html and Uri String Encoding without System.Web
Там еще есть и способ кодирования эскейп-последовательностей HTML.

Ну чтоб не потерять, еще и класс на PasteBin и Mega.NZ

DriverPackSolutions для старых компов

Жалуются тут, что последний на старых компах падает и виснет.
Нашел старый, кому надо, вот ссылка на DriverPackSolutions 11:
https://mega.nz/#!dQUTlaxL.
Ссылка без ключа, тому ще, кто сильно жаловался, ключ был по почте отправлен. Но если кому сей раритет вдруг будет нужен, пишите в комментарии на ЛЖР, я дам, если вежливо попросить.

C#, проверка попадания IP-адреса в зарезервированные диапазоны.

Про зарезервированные диапазоны и то, как проверить, попадает ли в них адрес IPv4, я уже писал и приводил решение данной задачи на PHP. Теперь вариант на C#.

Понадобится функция IPConverter.IPToInt32(IP), которую я описывал в прошлой заметке, аналог функции ip2long() PHP

В остальном все делается также, как и в PHP-примере.

1. Заводим двумерный массив, содержащий IP начала диапазона, конечный IP и описание диапазона:

string[,] SpecList = new string[,]  {
   {"0.0.0.0","0.255.255.255", "Current network"},
   {"255.255.255.255","255.255.255.255", "Broadcast"},
   {"255.0.0.0","255.255.255.255", "Reserved by the IETF, broadcast"},
   {"10.0.0.0","10.255.255.255", "Private network"},
   {"100.64.0.0","100.127.255.255", "Shared Address Space"},
   {"127.0.0.0","127.255.255.255", "Loopback"},
   {"169.254.0.0","169.254.255.255", "Link-local"},
   {"172.16.0.0","172.31.255.255", "Private network"},
   {"192.0.0.0","192.0.0.7", "DS-Lite"},
   {"192.0.0.170","192.0.0.170", "NAT64"},
   {"192.0.0.171","192.0.0.171", "DNS64"},
   {"192.0.2.0","192.0.2.255", "Documentation example"},
   {"192.0.0.0","192.0.0.255", "Reserved by the IETF"},
   {"192.88.99.1","192.88.99.1", "IPv6 to IPv4 Incapsulation"},
   {"192.88.99.0","192.88.99.255", "Anycast"},
   {"192.168.0.0","192.168.255.255", "Private network"},
   {"198.51.100.0","198.51.100.255", "Documentation example"},
   {"198.18.0.0","198.19.255.255", "Test IP"},
   {"203.0.113.0","203.0.113.255", "Documentation example"},
   {"224.0.0.0","224.255.255.255", "Multicast"},
   {"240.0.0.0","240.255.255.255", "Future reserved"}
};

2. Пишем функцию, которая перебирает массив, и проверяет, попал ли указанный IP в один из диапазонов. Если попал — возвращает описание диапазона, если нет — пустую строку. IP-адреса конвертируются функцией IPConverter.IPToInt32(IP) в целые числа и сравниваются:

string CheckSpecDiaps(string IP)
{
    int uip = IPConverter.IPToInt32(IP);

    for (int i = 0; i < SpecList.GetLength(0); i++)
    {
        int start = IPConverter.IPToInt32(SpecList[i, 0]);
        int end = IPConverter.IPToInt32(SpecList[i, 1]);
        string desr = SpecList[i, 2];

        if (uip >= start && uip <= end)
        {
            return desr;
        }
    }

    return string.Empty;
}

Пример на GitHub

C#, проверка корректности и преобразования IP-адреса, класс IPAddress

Для работы с IP-адресами в .NET Framework есть класс IPAddress из пространства имен System.Net

Проверка корректности IP-адреса

bool IsIP(string IP)
{
    try
    {
        IPAddress addr = IPAddress.Parse(IP);
    }
    catch
    {
        return false;
    }
    return true;
}

Преобразование IP-адреса в полную форму записи.

Класс IPAddress и его функция Parse распознает сокращенную форму записи IP-адреса, например, адрес 4.0.0.1 можно записать как 4.1, и он будет таки корректным. Функция ToString() класса IPAddress всегда возвращает строку IP-адреса в полном виде, т.е. n.n.n.n, это можно использовать для преобразования адреса в полную форму записи:

string ToStandForm(string IP)
{
    if (!IsIP(IP))
    {
        return string.Empty;
    }
    IPAddress addr = IPAddress.Parse(IP);
    return addr.ToString();
}

Получение IP-адреса в виде массива байт

byte[] GetBytesBE(string IP)
{
    IPAddress addr = IPAddress.Parse(IP);
    return addr.GetAddressBytes();
}

Примечание: GetAddressBytes() выдает байты IP-адреса всегда в сетевом порядке, т.е. big-endian, в таком же, в котором байты идут при обычной записи IP. Если вдруг понадобится little-endian порядок, например, для того, чтобы преобразовать IP-адрес в целое число на little-endian системе, то массив надо перевернуть.

byte[] GetBytesLE(string IP)
{
    IPAddress addr = IPAddress.Parse(IP);
    byte[] addrbytes = addr.GetAddressBytes();
    Array.Reverse(addrbytes);
    return addrbytes;
}

Преобразование IP-адреса в знаковое 32-битное целое

Аналог PHP-функции ip2long() или сишной inet_addr()

int IPToInt32(string IP)
{
    IPAddress addr = IPAddress.Parse(IP);
    //получаем байты адреса, они всегда в big-endian
    byte[] addrbytes = addr.GetAddressBytes();
    //IP в виде Int32 big-endian
    int n = BitConverter.ToInt32(addrbytes,0);
    //если в системе little-endian порядок
    if (BitConverter.IsLittleEndian)
    {
        n = IPAddress.NetworkToHostOrder(n); //надо перевернуть
    }
    return n;
}

Изменить порядок байт можно и без использования Array.Reverse(), если число типа short или int. Для этого в классе IPAddress присутствуют функции NetworkToHostOrder(), которая меняет порядок байт в переменной с сетевого (big-endian) на используемый на локальной машине, и функция HostToNetworkOrder(), которая делает обратную операцию.

Преобразование IP-адреса в беззнаковое 32-битное целое

Скорее, чтоб два раза не вставать, делается точно так же, как и преобразование в знаковый int, но функции NetworkToHostOrder() и HostToNetworkOrder() тут уже не помогут, так что придется переворачивать массив байт адреса с помощью Array.Reverse():

public static uint IPToUInt32(string IP)
{
    IPAddress addr = IPAddress.Parse(IP);
    byte[] addrbytes = addr.GetAddressBytes();
    if (BitConverter.IsLittleEndian)
    {
        Array.Reverse(addrbytes);
    }
    return BitConverter.ToUInt32(addrbytes, 0);
}

Навеяно вопросом на stackowerflow
Объединил все вышеуказанные функции в отдельный класс.

Исходник на GitHub

C#, о порядке байт, little-endian, big-endian

Преамбула

Известно, что любые данные хранятся в памяти компьютера в виде последовательности байт, байт обычно равен 8 битам (но бывают и исключения, о которых сейчас не будем). Числа не исключение, например, когда мы определяем переменную int, фактически мы говорим компилятору «выдай нам 4 байта по такому-то адресу в памяти, для записи числа от -2147483648 до 2147483647». Конкретный адрес, конечно, заботливо выбирает для нас среда .NET, и обычно, лезть туда руками не нужно, среда все прекрасно за нас сделает. Пока не случается какой-нибудь хитрый случай, и тут уже приходится думать самому. Когда работаешь с однобайтовыми числами, обычно никаких чудес не происходит — байт он и на десктопной машине с Windows или Linux байт, и на сервере байт, и даже на роутере, телефоне и утюге, скорее всего будет тем же самым байтом. Но все было бы хорошо, если бы одного байта хватало всем 🙂
Как уже сказано выше, тот же int, это не один байт, а 4, и вот тут кроется проблема. Эти самые байты можно хранить в памяти как угодно, хоть через один, хоть в шахматном порядке.
На наше счастье, такие извращения, если и встречаются, то очень редко. В большинстве вычислительных устройств байты (одного числа, например типа int), хранятся либо в последовательности от старшего к младшему big-endian, либо от младшего к старшему little-endian. В случае big-endian первым идет старший разряд числа, а остальные по ранжиру за ним, в случае ltiite-endian — наоборот, первым идет самый младший, последним — самый старший.

Чтобы было проще представить, предположим, что в 1 байт влезает не десятичное число от 0 до 255 (256 значений), а всего 10 значений, т.е. числа от 0 до 9.
В таком случае число 1234 будет «четырехбайтовым», и в случае, если оно записывается в порядке bigendian, то в памяти оно будет храниться в обычном для нас виде, как последовательность 1 2 3 4, поэтому, порядок big-endian еще называют прямым порядком байт. Если же число хранится в порядке little-endian, то в памяти оно будет выглядеть, как последовательность 4 3 2 1, поэтому порядок little-endian называют обратным порядком байт.

В реальном компьютере, в котором байт восьмибитный, и хранит положенные ему 256 значений, все происходит точно так же.

Итак:
Big-endian — «от старшего к младшему», он же прямой, сетевой (поскольку принят в качестве стандартного порядка байт при передаче данных по сети), Motorola byte order (использовался в процессорах Motorola, а не в честь уехавшего на социальном лифте деятеля).
В big-endian формате хранятся IP-адреса.
Little-endian — «От младшего к старшему», обратный, интеловский (используется в процессорах Intel), VAX (использовался на платформе VAX).

Маленькая иллюстрация

Заведем переменную типа int, содержащую число 16909060 и два массива байт byte[] LittleEndian и byte[] BigEndian, содержащие его представление в виде последовательности байт в обратном и прямом порядке:

int Constant = 16909060;
byte[] LittleEndian = new byte[] {4, 3, 2, 1};
byte[] BigEndian = new byte[] {1, 2, 3, 4 };

Да, число подобрано специально, чтобы было красивое представление его в массиве байт. 🙂

Попробуем провести обратное преобразование с помощью класса BitConverter, который как раз и предназначен для получения из последовательности байт чисел соответствующих типов:

BitConverter.ToInt32(LittleEndian,0); //результат - 16909060
BitConverter.ToInt32(BigEndian, 0); //результат - 67305985

Класс BitConverter в теории должен использовать при преобразовании тот порядок байт, который используется на данной машине, соответственно, правильное число 16909060 было получено при преобразовании массива LittleEndian.

Этот простой пример иллюстрирует почему так важен порядок байт. Если вы получили данные в порядке, отличном от того, который используется в среде, где данные в результате обрабатываются, и соответствующей проверки не было произведено, то вы рискуете получить ошибочные данные.

Определение порядка байт, используемого в системе.

Средствами .NET

Для того, чтобы средствами .NET узнать, какой порядок байт используется на машине, где выполняется ваша программа, можно посмотреть в переменную IsLittleEndian класса BitConverter. Если она принимает значение true, то используется, соответственно, порядок little-endian (обратный):

if (BitConverter.IsLittleEndian)
{
    Console.WriteLine("little-endian");
}
else
{
    Console.WriteLine("most likely big-endian");
}

Самостоятельно

Легко написать функцию проверки самому. Достаточно взять некое заранее известное число, его представление в виде big-endian и little-endian в виде массива байт, сконвертировать массивы обратно в число, и сравнить с заранее известным.

Создадим перечисление ByteOrder(для красоты :):

private enum ByteOrder
{
    BigEndian = 0,
    LittleEndian = 1,
    Unknow = 3
}

И напишем функцию:

ByteOrder DetectBO()
{    
    int Constant = 16909060;
    byte[] LittleEndian = new byte[] { 4, 3, 2, 1 };
    byte[] BigEndian = new byte[] { 1, 2, 3, 4 };

    if (BitConverter.ToInt32(BigEndian, 0) == Constant) 
        return ByteOrder.BigEndian;
    if (BitConverter.ToInt32(LittleEndian, 0) == Constant) 
        return ByteOrder.LittleEndian;
    
    return ByteOrder.Unknow;
}

Примечание: в тексте в кодировке UTF-16 можно определить UTF-16LE или UTF-16BE при помощи BOM, при его наличии

Преобразование из big-endian в little-endian и наоборот.

А вот тут у .NET Framework’а все как-то печально, частично могут помочь статические функции класса System.Net.IPAddress NetworkToHostOrder() и HostToNetworkOrder(), преобразующие, соответственно, число, полученное в big-endian в формат, используемый на данной машине и наоборот, но они довольно ограничены, поддерживают только long, int и short значения, не поддерживают работу с беззнаковыми числами и числами с плавающей запятой, а также с массивами байт. Вот способ преобразования порядка байт:

1. Преобразовать исходное число в массив байт с помощью BitConverter.GetBytes() или взять готовый массив, если он есть.
2. Перевернуть массив функцией Array.Reverse()
3. Преобразовать развернутый массив обратно, с помощью одной из функций класса BitConverter:

byte [] ConvArray = BitConverter.GetBytes(BigEndianValue);
Array.Reverse(ConvArray);
ushort LittleEndianValue = BitConverter.ToUInt16(ConvArray,0);

Минус — относительно медленная функция Array.Reverse. И BitConverter тоже не самый быстрый класс, зато довольно наглядно.

Внимание! Функция Array.Reverse() не создает копии массива, а работает с указанным массивом прямо в памяти. Если в функцию, в которой используется Array.Reverse() будет передан массив из вызывающей подпрограммы, и функция Array.Reverse() будет к массиву применена, то массив изменится. Такое поведение может породить труднообнаруживаемую ошибку, поэтому, если массив в оригинальном виде планируется еще где-либо использовать, то перед Array.Reverse() надо сделать его копию с помощью Array.Copy().

Источники

1. Порядок байтов
2. Разбираемся с прямым и обратным порядком байтов
3. MSDN

Пример к заметке на GitHub

Отключаем SVG в Firefox

Зачем:

— Во-первых, уязвимость, которая вроде как давно устранена, но осадочек остался.
— Во-вторых, кривым SVG можно положить браузер, чем, например, пользуется вандал-кремлебот, пакостя на самом свободном блогосервисе рунета
В общем, проще нахуй отрезать, чем вылечить.

Как:

Способ для Firefox 53+

1. Набираем в адресной строке about:config
2. Устанавливаем опцию svg.enabled в false

Способ универсальный

Кроме Firefox и в Chrome работает, но тут инструкция для Firefox, для остального должно быть также.

1. Ставим блокировщик рекламы и прочей гадости uBlock Origin
2. Нажимаем на значок плагина (1 на картинке ниже) и входим в панель управления плагином (2 на картинке ниже)

Переключаемся на вкладку Мои фильтры и добавляем туда следующий код:

! block all svg
*.svg

Баста! Зловредный SVG вырезан с корнями!

Сгорела церковь

Да, все, наверное, уже видели, слышали и читали. Но раз от меня требуют комментариев, то прокомментирую. Хотелось бы поиронизировать на тему, что единственная церковь которая несет свет — это горящая церковь, но не буду. Во-первых, объект был все-таки музейный, а не РПЦ-шный, хотя службы там проводились. А во-вторых, об этом еще Дима писал, при церкви жила куча жидохвостов (кошек), и если какие-то кошки сгорели, то это пиздец, и виновный будет радоваться, если ему придется гореть в аду.

Предварительная причина возгорания — неосторожное обращение с огнем.

Вот здесь можно посмотреть на фото уже бывшей церкви
А на церкви было лого инопланетян из сериала Предел

Поскольку я сейчас ~ в 150 Км от города, подробности из первых рук не могу сообщить. Но если пострадали коты — тогда очень жаль.

C# простое преобразование Unix Time в DateTime

Unix-time — способ хранения времени, используемый обычно в POSIX-совместимых системах. Определяется, как количество секунд, прошедших с 01.01.1970 00:00:00, может встречаться в логах, базах данных, и т.д., как отметка времени (timestamp). Следующий алгоритм поможет преобразовать Unix-время в DateTime:

1. Заводим переменную DateTime и инициализируем ее точкой отсчета Unix-time, т.е. полночью 1 января 1970 года:
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0);
2. Используем метод AddSecounds(), чтобы добавить количество секунд, в качестве аргумента передаем переменную, содержащую Unix-time:
origin.AddSeconds(UnixTime);

Вся функция:

private DateTime UnixTimeToDateTime(double UnixTime)
{
    DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0);
    return origin.AddSeconds(UnixTime);
}

На PasteBin

Если Unix-time хранится в целочисленной переменной, меняем double на нужный тип, компилятор сам преобразует ее в тип double, нужный AddSecounds.

Roadsend php compiler и Roadsend php IDE (бесплатная последняя версия 2.9.0-beta)

Наконец я нашел откомпилированную версию сабжа, и теперь ее можно скачать бесплатно, без СМС и вирусов отсюда. IDE, тащемта, дерьмо, но это можно простить, ибо писалось все это дело в 2008 году, но до сей поры ничего лучшего никто не написал.
Не буду подробно рассказывать, чего мне это стоило, но было нагажено одному болгарскому файл-хостингу и инсталлятор пришлось избавлять от вирей, распространяющих рекламу и майнящих криптовалюту.
Избавили и выкладываем в нормальный открытый доступ. Кто умеет в торренты, помогите и выложите на Рутрекер и TPB, оно маленькое 20 мегабайт всего. Но очень полезное.

Итак: Roadsend PHP Studio (IDE) + Roadsend PHP Compiler
Компилятор PHP для Windows.
Умеет компилировать PHP в EXE в нескольких режимах:
— Console application — на выходе получается стандартное консольное приложение для Win32
— Desktop GUI Application — десктопное оконное приложение, для того, чтоб его собрать нужны еще библиотеки и инструментарий PHP-GTK, в комплекте нет
— Compiled Web Application (FastCGI) — скомпилированное Web-приложение, в экзешник встраивается FastCGI.
— Standalone Web Application (MicroServer) — почти тоже самое, но в экзешник встраивается Web-сервер от Roadsend.
-Library — компилирует полноценный DLL из PHP-кода, который можно встроить в свое приложение, хоть на C#, хоть на C++, хоть на небе, хоть на Аллахе.
Компилировать может в двух режимах — dynamic и static, В статическом режиме в экзешник внедряются DLL от Sheme на котором написан сам компилятор, и их не надо таскать за собой, в динамическом режиме — будет надо, но в статическом вырастает размер готового экзешника, примерно на мегабайт.

Проблемы:
— В Windows 7 не работает штатный лаунчер для IDE (сам компилятор работает).

Пришлось вспомнить молодость и расчехлить OllyDebug, вытащить из лаунчера команду, которой он запускает основной файл IDE. По итогу вышел вот такой небольшой батник, который заменяет оригинальный лаунчер:

@echo off

set ROADSEND_ROOT=#put you Roadsend root directory here, e.g. C:\roadsend#
set SH=\bin\sh.exe
set IDE=\pcc\bin\loon.exe

if not exist %ROADSEND_ROOT%%SH% goto NOSH
if not exist %ROADSEND_ROOT%%IDE% goto NOIDE

echo Files OK.
echo Launch Roadsend IDE...
%ROADSEND_ROOT%%SH% --login -c "cd /pcc/bin && start loon"


:NOSH
	echo File %ROADSEND_ROOT%%SH% not found
	exit /b 1

:NOIDE
	echo File %ROADSEND_ROOT%%IDE% not found
	exit /b 1

куда вместо #put you Roadsend root directory here, e.g. C:\roadsend# надо вставить директорию, куда установлена IDE с компилятором.

Впрочем, Леша, заглаживая вчерашний демарш, написал свой лаунчер с азартными играми и продажными женщинами на C# и даже с инсталлятором.

Подробнее про Roadsend PHP Compiler и Roadsend PHP Studio можно прочесть в статье на Хабре

Скачать бесплатно, без СМС и вирусов

Оригинальный инсталлятор Roadsend PHP Studio (IDE + компилятор)

Лаунчер для Windows 7 (C#) с Mega.nz
Лаунчер для Windows 7 (C#) с GitHub

Лаунчер для Windows 7 (BAT/CMD) с Mega.nz
Лаунчер для Windows 7 (BAT/CMD) с GitHub

Прочие ссылки

Статья о Roadsend PHP Compiler на Хабр Копия
Исходники лаунчера
BAT/CMD лаунчер на PasteBin

Определение IP и местоположения посетителя сайта 7.

Консольный вариант скрипта.

Т.е. это уже не совсем «определение местоположения посетителя сайта», это просто интерфейс к базе данных Sypex Geo, который можно использовать в консольных приложениях на PHP.

Что переделано:
Переделан изначальный скрипт, для работы под консоль, или, если хотите, а качестве stand-alone скрипта. Для консольного приложения очень важно вернуть код завершения, чтобы далее его могло обработать либо следующая программа в командном файле (BAT/CMD), либо вызвавшая скрипт, как внешний процесс, программа.

Таким же образом был немного подправлен SxGeo.php, распространяемый разработчиками Cypex Geo.

Исправления таковы:

— Везде, где скрипт завершает работу, была добавлена выдача кода завершения
— Таким же образом подправлен класс SxGeo, поставляемый разработчиками Cypex Geo.

Краткая справка скрипта:

Вызов скрипта:
consxgeo.php <ip-address> <database-path> [FIELD_NAME]
consxgeo.php --spec
consxgeo.php --help

--help - Помощь
--spec - Список зарезервированных диапазонов IP-адресов
<ip-address> - Адрес IPv4 (например, 8.8.8.8)
<database-path> - Путь к файлу SxGeoCity.dat
[FIELD_NAME] - Для включения в вывод результата работы скрипта источника IP-адреса. По умолчанию, это значение = MANUAL

Коды завершения:
0 - OK
1 - Предупреждение
3 - Вывод информационных сообщений
4 - Ошибка или неправильные параметры скрипта

Структура ответа:
IP|ISO_CODE|COUNTRY_NAME|CTNR_LAT|CTNR_LON|
REGION_ISO|REGION_NAME|CITY_NAME|CTY_LAT|CTY_LON
|FIELD|MESSAGE|

Пример вывода

Частный IP:


Просто адрес IP:

Сокращенный IP-адрес:

Скрипт на GitHub

Предыдущая часть Копия

PHP. Проверка корректности IP-адреса

Преамбула

[info]ketmar@ljr справедливо заметил, что наши скрипты принимают только IP-адреса в формате xxx.xxx.xxx.xxx, где xxx — десятеричное число от 0 до 255, а IP может быть записан и в виде шестнадцатеричных, и в виде восьмеричных чисел, и даже смешано. Также IP-адрес может быть неполным. Например, адрес 4.0.0.1 можно записать как 4.1
В наших скриптах корректность IP проверялась регулярным выражением, т.к. все равно им же производился поиск IP в полях HTTP_*, в которых IP может передаваться прокси-серверами.
Но валидацию IP можно провести и без использования регулярных выражений. Другое дело, поиск без него уже не произведешь, и это может создать определенные проблемы, если прокси-сервер, например, будет передавать IP в виде шестнадцатеричных чисел или преобразовывать, где возможно, полные адреса в неполные.

Не очень хороший способ валидации IP функцией filter_var()

В PHP 5.2.0 появилась функция filter_var(), которая позволяет проверять строки на соответствие разным форматам, не только IP, но и, например URL или e-mail.
Для проверки IP она вызывается так:

filter_var($ip,FILTER_VALIDATE_IP);
где:
$ip — строка, содержащая IP-адрес
FILTER_VALIDATE_IP — встроенный фильтр для IP-адреса
Функция возвращает TRUE, если строка прошла проверку, и FALSE если нет.

А не очень хорош способ тем, что валидацию проходят только IP, соответствующие формату «четыре десятеричных числа от 0 до 255, разделенных точкой», т.е. работает точно также, как и наша старая функция
Такое ощущение, что разработчики PHP пытаются избавить мир от зоопарка способов записи IP-адреса, и привести все, наконец, к единому знаменателю 🙂

Пример с использованием функции filter_var

Проверка корректности IP-адреса функцией ip2long()

[info]ketmar@ljr предлагал использовать сишную функцию inet_addr(), но где ж я ее возьму-то в PHP, подумал я, и зря подумал. 🙂 Функция ip2long($ip), которая использовалась для проверки попадания IP-адреса в определенный диапазон Копия ее аналог. Если переменная $ip содержит корректный IP-адрес, то функция вернет целое число, если в IP-адресе ошибка, то функция вернет FALSE или -1.

Примечание: Функция ip2long() возвратит FALSE для IP 255.255.255.255 в PHP 5 <= 5.0.2 и -1 в PHP 5 <=5.2.4 на 64-битных системах. Это было исправлено в PHP 5.2.5, теперь возвращается 4294967295. В 32-битных системах будет возвращено -1 из-за целочисленного переполнения.

Так что проверку на корректность IP можно делать в функции-обертке, добавив код-заглушку для IP 255.255.255.255:

function IsIP($ip)
{
	//преобразуем в нижний регистр, на случай шестнадцатиричных чисел
	$ip=strtoupper($ip);
	//ip2long в некоторых версиях php 
	//некорректно реагирует на адрес 255.255.255.255
	//делаем небольшую заглушку
	if ($ip == '255.255.255.255'||$ip == '0xff.0xff.0xff.0xff'||
	   $ip == '0377.0377.0377.0377')
	   {
		   return true;
	   }
	
	$tolong=ip2long($ip);
	
	if ($tolong == -1||$tolong===FALSE) return FALSE;
	else return TRUE;	
}

Преобразование неполных и прочих «необычных» IP-адресов в привычный вид.

В PHP есть функция long2ip(), которая делает обратное преобразование, т.е. преобразует целое число в IP-адрес в привычном виде. Если их совместить, то можно преобразовывать неполные адреса в полные:

function fulladdr($ip)
{
	//преобразует неполные адреса в полные
	//для информации
	$tolong=ip2long($ip);
	return long2ip ($tolong);
}


Пример работы скрипта:
isip.php?ip=4.1

Скрипт на GitHub

Внезапное дополнение

Внедрил последний метод в рабочие скрипты, залил на сервер, и оказалось, что метод не работает. Ну не то, чтобы не совсем не работает, а работает точно так же, как старая функция с регулярным выражением, т.е. возвращает TRUE только если IP-адрес записан в виде четырех десятеричных чисел от 0 до 255, разделенных точкой. Неполные адреса, или адреса в других системах счисления IP-адресами не считаются. Функция ip2long() возвращает FALSE, если ей скормить такой адрес. Уж не знаю, и сходу не нагуглил, отчего такая оказия, то ли такое поведение зависит от настроек PHP, то ли от сервера. На локальном сервере работало, а на том, который в интернете — перестало. Можно сказать, зря делал, но зато сделал валидацию IP без регулярного выражения.

Источники

1. ip2long
2. Ещё раз о filter_var