Обзор клиентских приложений под Android
Андрей Бирюков
user@server.loc
server.loc:port
-----------------------------------------------------------------------------------------------------------------
Веб-интерфейс к Cisco IOS DHCP
Гавриил Каримов
ip dhcp pool computers
network 192.168.1.0 255.255.255.0
dns-server 192.168.1.2 192.168.1.3
netbios-name-server 192.168.1.2
domain-name mydomain.ru
default-router 192.168.1.1
lease 3
ip dhcp pool manual_4_pc
host 192.168.1.68 255.255.255.0
client-identifier 0100.19d1.ad23.13
client-name pcname
ip dhcp pool print_server
host 192.168.1.80 255.255.255.0
hardware-address 001b.7811.dc6c
ip dhcp excluded-address 192.168.1.1
show ip dhcp binding
clear ip dhcp binding 192.168.1.77
no ip dhcp pool poolname
-----------------------------------------------------------------------------------------------------------------
История одной тенденции, или Как PowerShell помогает в администрировании MS SQL
Владимир Шамаков
Get-TSQLTableRecordCount -SQLInstanceName 'SERVER\S8R2' -SourceDbName 'DOCsWorks' >C:\countWorks.txt
Get-TSQLTableColumns -SQLInstanceName 'SERVER\S8R2' -SourceDbName 'DOCsWorks' | export-csv С:\tablesWorks.csv encoding UTF8
"s_AuthorID","int","4"
"s_CreationDate","datetime","8"
"FileName","nvarchar","510"
"FileData","varbinary","-1"
Листинг 1. Сценарий замены BLOB-объектов двухмесячной давности
# Имя экземпляра SQL Server
$Instance = 'SERVER\S8R2'
# Имя базы данных
$database = "DOCsWorks"
С:\InitializeSQLProvider.ps1
Set-Variable -scope Global -name SqlServerConnectionTimeout -Value 240
# Получаем текущую дату
$CriticalDate=get-date
# Формируем критическую дату удаления (61 день)
$CriticalDate=$CriticalDate.adddays(-61)
# Формируем SQL-запрос к нужной базе
$sqlQuery = "USE " + $database
$sqlQuery += @"
;
GO
UPDATE dbo.MessageEmbeddedFiles
SET FileData = (
SELECT *
FROM OPENROWSET(BULK 'C:\Sorry.txt', SINGLE_BLOB)AS x )
WHERE (s_CreationDate < '
"@
# Вводим в SQL-запрос вычисленную дату
$sqlQuery += $CriticalDate.tostring("dd\/MM\/yyyy") + "'); " + "`r`n" + "GO`r`n"
# Запускаем SQL-запрос
Try{ $Results = Invoke-SQLCmd -ServerInstance $Instance $Database $database -Query $sqlQuery}
Catch { Write-Host "Error: $Instance - $database Failed!" -Fore red -Back black }
Листинг 2. Сценарий отчета по BLOB-объектам
# Имя экземпляра SQL Server
$Instance = 'SERVER\S8R2'
# Имя базы данных
$Database = "DOCsWorks"
# Сформируем SQL-запрос с сортировкой по автору
$Query = @"
SELECT d.FileData
,d.FileName
,d.s_CreationDate
,d.s_AuthorID
,d.s_ObjectID
,u.FullName
FROM [
"@
$Query += $Database
$Query += @"
].[dbo].[MessageEmbeddedFiles] AS d
JOIN [dbo].[Users] AS u ON d.s_AuthorID=u.s_ObjectID
ORDER BY d.s_AuthorID
"@
# Имя формируемого файла отчета
$BLOBrep="С:\BLOBreport.txt"
[string]$RepStr="AuthorID;FIO;FileName;FileSize; CreationDate;FileId;Total" [string]$OldId = "0"
# Суммарный счетчик по автору
[int64]$SubTotal = 0
[int64]$Lngt = 0
# Открываем файл отчета и пишем заголовок
set-content $BLOBrep -value $RepStr -encoding UTF8
$Connection=new-object System.Data.SqlClient.SQLConnection$Connection.ConnectionString="Server={0};Database={1};Integrated Security=True" -f $In-stance,$Database$Command=new-object System.Data.SqlClient.SqlCommand($Query,$Connection)
$Command.CommandTimeout=240
$Connection.Open()
$Reader = $Command.ExecuteReader()
while ($Reader.Read())
{
$RepStr=""
# Нулевой элемент SQL-запроса – поле FileData
# Чтение BLOB-объекта для определения длины
$sqlBytes = $Reader.GetSqlBytes(0)
$Lngt = $sqlBytes.Length
# Замена скобок в именах файлов
[string]$Nam1 = $Reader.GetValue(1) "\[", "("$Nam1 = $Nam1 -replace "]", ")"
[string]$DtCreate = $Reader.GetValue(2)
[string]$IdAuthor = $Reader.GetValue(3)
[string]$IdFile = $Reader.GetValue(4)
[string]$Uname = $Reader.GetValue(5)
# Если автор поменялся, обнулим счетчик
if ($OldId -ne $IdAuthor) {
$OldId = $IdAuthor; $SubTotal=0}
$SubTotal += $Lngt
# Формируем строку отчета и записываем
$RepStr=$Uname+";"+$Nam1+";"+$Lngt+";"+$DtCreate+";"+$IdFile+";"+$SubTotal+";"
add-content -path $BLOBrep -value $RepStr -encoding UTF8
}
$Reader.Close()
$Connection.Close()
-----------------------------------------------------------------------------------------------------------------
Локальный сервер обновлений Adobe. Установка и настройка
Иван Коробко
Листинг 1. Установка необходимых компонентов IIS для внедрения AUSST
$components = "Web-Server", "Web-WebServer", "Web-Common-Http", "Web-Static-Content", "Web-Default-Doc", "Web-Dir-Browsing", "Web-Http-Errors", "Web-App-Dev", "Web-Asp-Net", "Web-Net-Ext", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Includes", "Web-Health", "Web-Http-Logging", "Web-Request-Monitor", "Web-Security", "Web-Windows-Auth", "Web-Filtering", "Web-Performance", "Web-Stat-Compression", "Web-Mgmt-Tools", "Web-Mgmt-Console"
Write-host "Установка компонентов IIS:`n"
$components |% {
$component = [string]$_
if ((Get-WindowsFeature $component).installed -eq $false)
{Add-WindowsFeature $component
Write-host ("{0}OK" -f $component.padright(60,"."))}
else
{Write-host ("{0}Ошибка" -f $component.padright(60,"."))}
}
Листинг 2. Создание веб-сайта и настройка пула приложения
# Проверка на существование каталога
# Формирование физического пути к сайту
$sitePath=("d:\{0}" -f $siteName)
if ((Test-Path -Path $sitePath) -eq $false)
{
# Создание каталога в файловой системе
New-Item -ItemType directory -Path $sitePath
Write-Host ("{0} ОК" -f ("Создание папки {0}" -f $sitePath).padright(60,"."))
}
else
{
Write-Host ("{0} Ошибка" -f ("Папка {0}" -f $sitePath).padright(60,"."))
}
# Проверка на существование пула приложений
# Определение имени сайта
$siteName="AdobeUpdate"
if ((Get-ChildItem IIS:\AppPools | ? {$_.name -eq $siteName}).count -eq 0)
{
# Создание пула приложений
$appPool = New-WebAppPool -Name $siteName -Force
Write-Host ("{0} ОК" -f ("Создание пула приложений {0}" -f $siteName).padright(60,"."))
}
else
{
Write-Host ("{0} Ошибка" -f ("Пул приложений {0}" -f $siteName).padright(60,"."))
}
#Настройка пула приложений
#1. Установка версии Framework
$appPool | set-itemproperty -Name "managedRuntimeVersion" -Value "v2.0"
#2.Настройка метода конвейеризациии "Integrated"=0,
#"Classic" = 1
$appPool | set-itemproperty -Name "managedPipelineMode" -Value 1
#Проверка на существование сайта приложений
if ((Get-ChildItem IIS:\Sites | ? {$_.name -eq $siteName}).count -eq 0)
{
# Создание веб-сайта с привязкой к пулу приложения
New-Website -Name $siteName -HostHeader $siteName -PhysicalPath $sitePath -ApplicationPool $siteName
Write-Host ("{0} ОК" -f ("Создание веб-сайта {0}" -f $siteName).padright(60,"."))
}
else
{
Write-Host ("{0} Ошибка" -f ("Веб-сайт http://{0}" -f $siteName).padright(60,"."))
}
Листинг 3. Обновление конфигурации веб-сайта
$siteName = "adobeUpdate"
New-WebHandler -Name "XMLFILTERTEST" -Path "xml" -Modules "IsapiModule" -Verb "*" -Location $siteName -ScriptProcessor "C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"
$extensions = "xml", "crl", "dmg", "zip"
$extensions | % {
New-WebHandler -name ("SSINC-{0}" -f $_) -path "*.xml" -Modules "ServerSideIncludeModule" -Verb "*" -Location $siteName -RequiredAccess "Script"
}
"c:\AUSST\Adobe Update Setup Server Tool\AdobeUpdateServerSetupTool2.0.exe" --root=d:\AdobeUpdate
Листинг 4. Формирование файловой структуры и разовая загрузка пакета обновлений
# Управление процессом
function AUSSTWork([int]$mode=4)
{
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = $ausstLocation
$process.StartInfo.Arguments = ("--root={0}" -f $siteName)
$process.StartInfo.UseShellExecute = $false
$process.StartInfo.RedirectStandardOutput = $true
$process.StartInfo.RedirectStandardInput = $true
$process.Start()
$process.StandardInput.WriteLine($mode)
$process.StandardInput.Close()
$outputStr = $process.StandardOutput.ReadToEnd()
}
# Определение имени сайта
$siteName="AdobeUpdate"
# Назначение пути к AUSST
$ausstLocation = "c:\AUSST\Adobe Update Setup Server Tool\AdobeUpdateServerSetupTool2.0.exe"
# Формирование физического пути к сайту
$sitePath=("d:\{0}" -f $siteName)
# Обращение к функции
AUSSTWork -mode 1
"c:\AUSST\Adobe Update Setup Server Tool\AdobeUpdateServerSetupTool2.0.exe" --genclientconf=d:\Config --root=d:\AdobeUpdate --url=http://adobeupdate
Листинг 5. Создание конфигурационного файла
# Управление процессом
function AUSSTConfig()
{
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = $ausstLocation
$process.StartInfo.Arguments = ("--root={0} --genclientconf={1} --url=http://{2}" -f $sitePath, $configPath, $siteName)
write-host $process.StartInfo.Arguments
$process.StartInfo.UseShellExecute = $false
$process.StartInfo.RedirectStandardOutput = $true
$process.StartInfo.RedirectStandardInput = $true
$process.Start()
$outputStr = $process.StandardOutput.ReadToEnd()
Write-Host $outputStr
}
# Определение имени сайта
$siteName="AdobeUpdate"
# Формирование физического пути к сайту
$sitePath=("d:\{0}" -f $siteName)
# Назначение пути к AUSST
$ausstLocation = "c:\AUSST\Adobe Update Setup Server Tool\AdobeUpdateServerSetupTool2.0.exe"
# Название папки, в которой сохранена конфигурация
$config= "config"
# Проверка на существование каталога
# Формирование физического пути к сайту
$configPath=("d:\{0}" -f $config)
if ((Test-Path -Path $configPath) -eq $true)
{
# Удаление папки со всем содержимым
Remove-Item -Path $configPath -Recurse -Force
Write-Host ("Старая папка удалена")
}
# Создание папки каталога в файловой системе
New-Item -ItemType directory -Path $configPath
Write-Host ("{0} ОК" -f ("Создание папки {0}" -f $configPath).padright(60,"."))
# Предоставление сетевого доступа
$Shares=[WMICLASS]"WIN32_Share"
if (!(GET-WMIOBJECT Win32_Share | ? {$_.name -like (('{0}$') -f $config)}))
{ $Shares.Create($configPath,(('{0}$') -f $config),0,65535,"") }
#Установка ACL
$acl = Get-Acl -Path $configPath
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule ("Domain Users","ReadandExecute","ContainerInherit","None","Allow")
$acl.SetAccessRule($AccessRule)
$acl | Set-Acl $configPath
AUSSTConfig
Листинг 6. Сценарий запуска веб-сайта из сценария регистрации пользователей в сети
# Определение имени компьютера
$pcname = [string](Get-Item Env:\COMPUTERNAME).value
# Определение версии установленной ОС по данным из AD
$obj =[ADSISearcher]""
$obj.SearchRoot=[ADSI]""
$obj.Filter = ("(&(objectclass=computer)(name={0}))" -f $pcname)
$result= [System.DirectoryServices.SearchResult] $obj.FindOne()
[string]$verOS=$result.Properties.operatingsystem
# Для windows 7
if ($verOS.Contains("Windows 7"))
{
$Path=Join-Path -Path (get-item env:ProgramData).value -ChildPath "Adobe\AAMUpdater\1.0" #windows 7
}
# Для windows XP
if ($verOS.Contains("Windows XP"))
{
$Path=Join-Path -Path (get-item env:AllUsersProfile).value -ChildPath "Application Data\Adobe\AAMUpdater\1.0" #windows XP
}
$DestinationPath = "\\{0}\{1}" -f $pcname, $Path.replace(":",'$')
# Вызов веб-страницы с параметром
# Чтение списка сайтов из ROOT - IIS - SITE, параметры
# VISIBLE и URL
$obj.root.iis.site | % {
$ie = New-Object -com InternetExplorer.Application #-ErrorAction "silentlycontinue"
$ie.visible =0
$ie.silent=1
while ($ie.busy -eq $true ) {}
$ie.navigate("http://adobeUpdateTransport?DestinationPath=$DestinationPath")
# Назначение времени ожидания
$timeUntil =(Get-Date).AddMinutes($obj.root.part.iis.timeout)
# Контроль времени ожидания
while ($ie.busy -eq $true) {If($timeUntil -lt (Get-Date)){$ie.quit();}}
}
Листинг 7. Перемещение данных с сервера на рабочую станцию
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
public partial class _Default : System.Web.UI.Page
{
System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
string XMLname = "adobecfg.xml";
string DesctinationPath, SourcePath, ConfigName;
protected void Page_Load(object sender, EventArgs e)
{
LoadXML();
try
{
DesctinationPath = Request.QueryString["DestinationPath"].ToString();
if (!System.IO.Directory.Exists(DesctinationPath))
{ System.IO.Directory.CreateDirectory(DesctinationPath); }
System.IO.File.Copy(System.IO.Path.Combine(SourcePath, ConfigName), System.IO.Path.Combine(DesctinationPath, ConfigName), true);
Response.Write(string.Format("Файл {0} успешно скопирован
из {1}
в {2}
",
ConfigName, SourcePath, DesctinationPath));
}
catch (Exception ex)
{
if (DesctinationPath == null)
{
DesctinationPath = "—";
}
Response.Write(string.Format("{0}{1}
", ("Desctination Path:").PadRight(40, ' ').Replace(" ", " "), DesctinationPath));
Response.Write(string.Format("
{0}{1}
", ("Ошибка копирования:").PadRight(40, ' ').Replace(" ", " "), ex.Message));
}
}
void LoadXML()
{
try
{
xDoc.Load(Request.ServerVariables.GetValues(3)[0] + "\\" + XMLname);
ConfigName = xDoc.GetElementsByTagName("config").Item(0).InnerText;
SourcePath = xDoc.GetElementsByTagName("source_win").Item(0).InnerText;
}
catch (Exception ex)
{
Response.Write(string.Format("{0}
", ex.Message));
}
}
}
AUSSTWork -mode 2
-----------------------------------------------------------------------------------------------------------------
Автоматические группы безопасности. Часть 2. Импорт информации из внешнего источника
Вадим Андросов
Листинг 1. CSV: таблица users
samAccountName;birthDate;position
ivanov;15.10.1980;программист
petrov;1.08.1983;дизайнер
sidorov;22.01.1981;бухгалтер
Листинг 2. CSV: таблица teams
name;leader
nerds;ivanov
bulls;ivanov
vikings;petrov
Листинг 3. CSV: таблица teamsMembership
team;member
nerds;ivanov
nerds;petrov
nerds;sidorov
bulls;petrov
bulls;sidorov
vikings;ivanov
vikings;sidorov
%systemroot%\sysWOW64\odbcad32.exe
Листинг 4. Заготовка класса wsc
Set myObject = CreateObject(“LDAPGroup.Engine”)
myObject.onNewUser parameter
REGSVR32.EXE /i:"LDAPGroup.Engine.wsc" "scrobj.dll"
Листинг 5. Инициализация объекта класса надстройки
Option explicit
Const EVENTLOG_WARNING = 2
Const TEAM_CONTAINER_ID = "teams"
Const TEAM_CLASS_ID = "team"
Const OU_CLASS_ID = "organizationalUnit"
Dim domainRootPath
initialize
'Инициализация объекта
Sub initialize()
Dim domainRoot
Set domainRoot = GetObject("LDAP://RootDSE")
domainRootPath = "LDAP://" & _
domainRoot.Get("defaultNamingContext")
End Sub
Листинг 6. Импорт информации из внешнего источника данных
Function databaseToLDAP()
Dim connection, tableData
Set connection = CreateObject("ADODB.Connection")
Set tableData = CreateObject("ADODB.Recordset")
connection.Open "extdb"
tableData.open "SELECT * FROM users.txt", connection
tableData.moveFirst
while Not tableData.EOF
updateUserInformation
tableData.Fields("samAccountName"),tableData.Fields("birthDate"),
tableData.Fields("position")
tableData.moveNext
wend
tableData.Close
tableData.open "SELECT * FROM teams.csv", connection
‘... Загрузка содержимого teams.csv и teamsMembership.csv
connection.Close
End Function
SELECT field1, field2
FROM dataSource
WHERE field1=value1 AND field3=value2
;
(&( field1=value1)( field3=value2));
field1,field2;Subtree
;
(&(objectCategory=user)(samAccountName=ivanov);
ADSPath;Subtree
On Error Resume Next
theObject = GetObject(path)
If (Err <> 0) then
‘Обрабатываем ошибку
End If
On Error Goto 0
path = getObjectPath(samName, "user", "samAccountName")
if (path <> "") then
theObject = GetObject(path)
else
‘Обрабатываем ошибку
end if
Листинг 7. Функция поиска объекта в Active Directory
Function getObjectPath(samName, objectType, idFieldName)
Dim objConnection, objCommand, objRecordSet
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 100
objCommand.CommandText = "<" & domainRootPath & ">; (&(objectCategory=" & objectType & ") (" & idFieldName & "=" & samName & ")); ADSPath;Subtree"
Set objRecordSet = objCommand.Execute
If Not objRecordSet.EOF Then
objRecordSet.MoveFirst
getObjectPath = objRecordSet.Fields(0).Value
Else
getObjectPath = ""
End If
objConnection.Close
End Function
-----------------------------------------------------------------------------------------------------------------
Facebook под микроскопом. Часть вторая
Игорь Савчук
pear config-set auto_discover 1
pear install http://pear.phpunit.de/get/hphpa-1.2.2.tgz
$ hphpa /usr/local/src/code-coverage/PHP
sudo apt-get install git-core cmake g++ libboost-dev libmysqlclient-dev libxml2-dev libmcrypt-dev libicu-dev openssl build-essential binutils-dev libcap-dev libgd2-xpm-dev zlib1g-dev libtbb-dev libonig-dev libpcre3-dev autoconf libtool libcurl4-openssl-dev libboost-system-dev libboost-program-options-dev libboost-filesystem-dev wget memcached libreadline-dev libncurses-dev libmemcached-dev libbz2-dev libc-client2007e-dev php5-mcrypt php5-imagick libgoogle-perftools-dev libcloog-ppl0 libelf-dev libdwarf-dev libunwind7-dev
mkdir dev
cd dev
git clone git://github.com/facebook/hiphop-php.git
cd hiphop-php
export CMAKE_PREFIX_PATH=`/bin/pwd`/..
export HPHP_HOME=`/bin/pwd`
export HPHP_LIB=`/bin/pwd`/bin
export USE_HHVM=1
cd hiphop-php
cmake .
make
$HPHP_HOME/src/hphp/hphp test.php
$HPHP_HOME/src/hphp/hphp test.php --keep-tempdir=1 --log=3
/tmp/ hphp_temp/program
$HPHP_HOME/src/hphp/hphp test.php --keep-tempdir=1 --log=3
sudo /tmp/hphp_temp /program -m server
sudo /tmp/hphp_temp/program -m daemon
$HPHP_HOME/src/hphpi/hphpi -f test.php
sudo $HPHP_HOME/src/hphpi/hphpi -m server
curl localhost/test.php
curl localhost:8088
wget http://wordpress.org/wordpress-3.5.1.tar.gz
tar zxvf wordpress-3.5.1.tar.gz
function &loopback(/* args.. */) {
return func_get_args();
}
function &loopback(/* args.. */) {
$ret = func_get_args();
return $ret;
}
if ( !isset($q['suppress_filters']) )
$q['suppress_filters'] = false;
$q['suppress_filters'] = true;
find . -name "*.php" > flist.txt
$HPHP_HOME/src/hphp/hphp --input-list=files.list -k 1 --log=3 --force=1 --cluster-count=50
sudo /tmp/hphp_temp/program -m server -v "Server.SourceRoot=`pwd`" -v "Server.DefaultDocument=index.php" -c $HPHP_HOME/bin/mime.hdf
-----------------------------------------------------------------------------------------------------------------
Работаем с Active Directory на PHP. Запись данных
Рашид Ачилов
Листинг 1. Конфигурационный файл скрипта phpldapupdate.php
#LDAP-сервер для подключения
ldap_server=10.54.200.1
#Base DN для подключения
ldap_basedn="dc=shelton,dc=int"
#Bind DN для подключения
ldap_binddn=ldapread@SHELTON.INT
#Пароль для пользователя, от имени которого будет выполняться подключение
ldap_password="cXdlcnR5YXNkZgo 1"
#Фильтр отбора пользователей – все объекты типа «Пользователь», у которых нет свойства «Заблокировать учетную запись»
ldap_users_filter="(&!(userAccountControl:1.2.840.113556.1.4.803:=2)(sAMAccountType=805306368)"
#Фильтр отбора групп – все объекты типа «Группа»
ldap_group_filter="(sAMAccountType=268435456)"
# pear install Console_Getopt-1.3.1
Листинг 2. Функция обратного преобразования пароля
/*
* Обратное преобразование пароля
* @param string $converted преобразованный пароль
* @return string $passwd пароль в текстовой форме
*/
function demux_passwd($converted)
{
$_conved = explode(" ", $converted);
$_passwd = "";
if ( $_conved[1] != 0 )
for (;$_conved[1] != 0; $_conved[1]--)
{ $_conved[0] = $_conved[0] . "="; }
$_passwd = base64_decode($_conved[0]);
return rtrim($_passwd);
}
# echo somepassword | mmencode
Листинг 3. Функция перекодировки строки из UTF-8 в KOI8-R
/*
* Перекодировать строку из UTF-8 в KOI8-R
* @param string $source строка в кодировке UTF-8
* @return string $dest строка в кодировке KOI8-R
*/
function _from_utf8($source)
{
$converted = iconv("UTF-8", "KOI8-R", $source);
return($converted);
}
Листинг 4. Функция вывода сообщений в журнал и на консоль с завершением или без завершения работы скрипта
/*
* Вывести сообщение в лог и на консоль
* @param string $msg строка для вывода
* @param string $severity если DIE, то после вывода завершить скрипт
* @global resource $handle идентификатор открытого файла лога
* @global array $_params массив параметров
*/
function safe_logger($msg, $severity)
{
global $handle;
global $_params;
// Отформатировать сообщение
$formatted = sprintf("%s [%s] phpldapquery: %s\n", date("d/m/Y H:i:s"), posix_getpid(), $msg);
// Если серьезность – DIE, то немедленно завершиться
if ($severity == "DIE") die($formatted);
// Обработать условия вывода на консоль и в журнал
if ((($severity == "debug") && ($_params["modes"]["debug"])) || (($severity == "") && (!$_params["modes"]["debug"])))
{
fwrite($handle, $formatted);
if ($_params["modes"]["verbose"]) print $formatted;
}
}
Листинг 5. Функция подключения к серверу AD
require_once $PATH_LIB."/utils.php";
/*
* Подключение к серверу LDAP
* @param array $_config массив параметров конфигурации
* @return resource $ldapconn идентификатор соединения с LDAP-сервером
*/
function ldap_server_connect($_config)
{
// Получить пароль в текстовом виде
$_ldap_pwd = demux_passwd($_config["root"]["ldap_password"]);
// Установить соединение с сервером
if (!$ldapconn = ldap_connect($_config["root"]["ldap_server"]))
safe_logger(sprintf("Невозможно подключиться к LDAP-серверу %s", $_ config["root"]["ldap_server"]), "DIE");
// Для подключения к AD Windows 2003 и выше нужно установить эти опции
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
// Авторизоваться на сервере
ldap_bind($ldapconn, $_config["root"]["ldap_binddn"], $_ldap_pwd);
return $ldapconn;
}
Листинг 6. Запуск программы и подключение к AD
// Журнал, конфигурационный файл, функциональная библиотека
$logfile = "./ldapsetugid.log";
$config = "./ldapsetugid.conf";
$PATH_LIB = "./lib";
// Подключаются необходимые модули
require_once "Console/Getopt.php";
require_once $PATH_LIB."/parseconfig.php";
require_once $PATH_LIB."/ldapconnect.php";
// Строится массив параметров, которые можно передать через командную строку. Их очень мало, фактически используется только verbose
$_params = array( "modes" => array ("debug" => 0, "verbose" => 0));
// Открывается файл журнала
$handle = fopen($logfile, "a") or die(sprintf("Log file %s cannot open", $logfile));
// Разбирается конфигурационный файл, опции командной строки и выдается идентификатор – признак того, что инициализация закончена
$_config = parse_configfile($config);
$rev = parse_options($_config, $_params);
safe_logger(sprintf("PHPSetUGID ver. %s started", $rev), "");
// Выполняется подключение к AD как к серверу LDAP
if (!$ldapconn = ldap_server_connect($_config))
safe_logger(sprintf("Cannot connect to LDAP server %s", $_config["root"]["ldap_server"]), "DIE");
Листинг 7. Получение NIS-имени домена
// NIS-имя будет находиться в атрибуте CN
$nisparam = array("cn");
// Задается фильтр отбора записей из AD
$result = ldap_search($ldapconn, $_config["root"]["ldap_basedn"], "(msSFU30MaxUidNumber=*)", $nisparam);
// Читаются отобранные данные
$info = ldap_get_entries($ldapconn, $result);
// Если прочитано 0 записей, дальше работать нет смысла
if ($info["count"] == 0)
safe_logger(sprintf("Cannot read NIS domain name on LDAP server %s. Install or configure IDMU first", $_config["root"]["ldap_server"]), "DIE");
// Если же что-то прочитано, то получить значение атрибута
$nisdomain = $info[0]["cn"][0];
// Задать начальные значения UID и GID, заносимые в AD.
// Важно, чтобы они не пересекались со значениями, используемыми в UNIX, поэтому нумерацию начинаем с 70000
$lngNextUID = 70000;
$lngNextGID = 70000;
// Здесь будем хранить GID группы Domain Users
$intGIDomainUsers = 0;
Листинг 8. Один элемент массива данных, возвращаемого функцией ldap_get_entries.
[0]=>
array(6) {
["cn"]=> array(2) { ["count"]=> int(1), [0]=> string(13) "Administrator" }
[0]=> string(2) "cn"
["samaccountname"]=> array(2) { ["count"]=> int(1), [0]=> string(13) "Administrator" }
[1]=> string(14) "samaccountname"
["count"]=> int(2)
["dn"]=> string(43) "CN=Administrator,CN=Users,DC=shelton,DC=net" }
Листинг 9. Перебор групп AD и внесение изменений
// Запрашивается sAMAccountName
$ad_params = array("samaccountname");
// Записи отбираются по общему фильтру групп из конфига (обьект – группа)
$result = ldap_search($ldapconn, $_config["root"]["ldap_basedn"], $_config["root"]["ldap_group_filter"], $ad_params);
// Получить сразу все отобранные записи
$info = ldap_get_entries($ldapconn, $result);
// Вывести в журнал (и на консоль, если задано) количество прочитанных записей
safe_logger(sprintf("Read %d group records from server %s", $info["count"],$_config["root"]["ldap_server"]), "");
// Основной цикл обхода полученного многомерного массива
for ($i = 0; $i < $info["count"]; $i++)
{
// В этой операции нет необходимости, она только сокращает написание
$cell = $info[$i];
$attrs = array();
// Формируется массив с новыми значениями атрибутов
$attrs["gidNumber"] = $lngNextGID;
$attrs["msSFU30NisDomain"] = $nisdomain;
// Информация об обрабатываемой группе выводится в журнал (и на консоль)
safe_logger(sprintf("Group %s, assigned GID: %d", _from_utf8($cell["samaccountname"][0]), $lngNextGID), "");
// Собственно запись в AD происходит здесь
if (!(ldap_modify($ldapconn, $cell["dn"], $attrs)))
safe_logger(sprintf("Cannot write group %s attributes to LDAP server %s", $cell["samaccountname"][0],
$_config["root"]["ldap_server"]), "DIE");
// Если это группа Domain Users, то сохранить ее GID
if (preg_match("/domain users/i", $cell["dn"]))
{
safe_logger(sprintf("Found Domain Users group, GID: %d", $lngNextGID), "");
$intGIDomainUsers = $lngNextGID;
}
$lngNextGID++;
}
Листинг 10. Перебор пользователей AD и внесение изменений
// Записи отбираются по общему фильтру пользователей из конфига (обьект – пользователь, и он не заблокирован)
$result = ldap_search($ldapconn, $_config["root"]["ldap_basedn"], $_config["root"]["ldap_users_filter"], $ad_params);
// Получить все отобранные записи в одном массиве
$info = ldap_get_entries($ldapconn, $result);
//Вывести в журнал (и на консоль, если задано) количество прочитанных записей
safe_logger(sprintf("Read %d users records from server %s", $info["count"],$_config["root"]["ldap_server"]), "");
// Основной цикл обхода полученного многомерного массива
for ($i = 0; $i < $info["count"]; $i++)
{
// В этой операции нет необходимости, она просто сокращает написание
$cell = $info[$i];
$attrs = array();
// Формируется массив с новыми значениями атрибутов
$attrs["uidNumber"] = $lngNextUID;
$attrs["msSFU30NisDomain"] = $nisdomain;
$attrs["gidNumber"] = $intGIDomainUsers;
// Информация об обрабатываемом пользователе выводится в журнал (и на консоль)
safe_logger(sprintf("User %s, assigned UID: %d", _from_utf8($cell["samaccountname"][0]), $lngNextUID), "");
// Собственно запись в AD происходит здесь
if (!(ldap_modify($ldapconn, $cell["dn"], $attrs)))
safe_logger(sprintf("Cannot write user %s attributes to LDAP server %s", $cell["samaccountname"][0], $_config["root"]["ldap_server"]), "DIE");
$lngNextUID++;
}
Листинг 11. Запись счетчиков в AD и завершение работы
//Сформировать DN, где расположен объект со счетчиками
$final = sprintf("CN=%s,CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System,%s", $nisdomain, $_config["root"]["ldap_basedn"]);
//Сформировать массив со значениями атрибутов
$counters["msSFU30MaxUidNumber"] = $lngNextUID;
$counters["msSFU30MaxGidNumber"] = $lngNextGID;
// Записать счетчики
if (!(ldap_modify($ldapconn, $final, $counters)))
safe_logger(sprintf("Cannot write counters for NIS domain %s to LDAP server %s", $nisdomain, $_config["root"]["ldap_server"]), "DIE");
//Вывести информацию, сколько записей какого типа было перенумеровано
safe_logger(sprintf("Renumbered %d users and %d groups", $lngNextUID - 70000, $lngNextGID - 70000), "");
//Ну, собственно и все
ldap_unbind($ldapconn);
fclose($handle);
-----------------------------------------------------------------------------------------------------------------
Vibration API есть? А если найду? HTML5 для мобильных устройств
Кирилл Сухов
battery.addEventListener("dischargingtimechange", function (e) {
if (!battery.charging) {
if(battery.level <0.1){
alert("Срочно зарядите батарею!");
}
}
}, false);
Mobile Page
Просто страница
Mobile Page
Не стой под стрелой!
Mobile Page
window.addEventListener("compassneedscalibration", function(event) {
alert('Your compass needs calibrating! Wave your device in a figure-eight motion');
event.preventDefault();
}, true);
navigator.vibrate(1000);
navigator.vibrate([5000, 1000, 3000]);
navigator.vibrate(0);
window.addEventListener( 'devicelight', function(e) {
alert('devicelight: ' + e.value);
}, false );
window.addEventListener( 'lightlevel', function(e) {
alert('lightlevel: ' + e.value);
}, false );
window.addEventListener( "deviceproximity", function(e){
console.log("distance is "+e.value+"sm");
console.log(min = e.min);
console.log( max = e.max)
}, true );
window.addEventListener( "userproximity", function(e){
if( e.near == true){
alert(“Near!”);
}
}, true );
Big image
-----------------------------------------------------------------------------------------------------------------
Система обмена сообщениями на MongoDb. Часть 2. Структура данных
Александр Календарев
{ _id, name, age, city, avatar }
{ _id, fcount, msg : {new, all}, folders : [ folder: { id, name, in, all } ] }
{ owner_id, talker_id, msg: {new, all}, folder_id}
{ key, dir, txt, ts, ts_read }
-----------------------------------------------------------------------------------------------------------------
Создание собственных key/value-хранилищ данных. Часть 5. Статистика и мониторинг
Александр Календарев
$telnet localhost 12313
stats
END
struct {
/* перечислены не все поля */
unsigned connections; // количество активных соединений
unsigned cmd_per; // количество запросов за период
float rps; // производительность опер/сек
float rps_peak; // пиковая производительность
unsigned get; // количество выполненных get
unsigned set; // количество выполненных set/append/prepend/incr/decr
unsigned del; // количество выполненных delete
unsigned inc; // количество выполненных increment/decrement
unsigned miss; // количество отсутствующих ключей (key not found)
time_t uptime; // время работы сервиса
unsigned err; // количество ошибок
...
} stats = {0,0,0,0,0,0,0,0,0,0,0,0,0 };
memcached-tools --server=mymchost:12313 stats | grep all_memory;
static void
memcached_stats(EV_P_ memcache_ctx *mctx) {
int len;
char *statsbuf = malloc(BUFSIZE);
unsigned mem_data = 0;
unsigned mem_all = get_memory(&mem_data);
time_t t;
time(&t);
len = snprintf(statsbuf, BUFSIZE,
"STAT pid %ld\r\n"
"STAT uptime %d\r\n"
"STAT curent connections %u\r\n"
"STAT total connections %u\r\n"
"STAT rps %4.2f\r\n"
"STAT peak rps %4.2f\r\n"
"STAT request %u\r\n"
"STAT get %u\r\n"
"STAT set %u\r\n"
"STAT inc %u\r\n"
"STAT del %u\r\n"
"STAT miss %u\r\n"
"STAT error %u\r\n"
"STAT all_memory %u\r\n"
"STAT data_memory %u\r\n"
"END\r\n",
(long)getpid(), (int)(t-stats.uptime) , stats.connections, stats.cnn_count,
stats.rps, stats.rps_peak, stats.cmd_count, stats.get, stats.set,
stats.inc, stats.del, stats.miss, stats.err, mem_all, mem_data);
memcpy(mctx->value, statsbuf, len);
free(statsbuf);
obuffer_init(&mctx->response, mctx->value, len);
}
static int
get_memory( int * mem_data) {
// char buf [64] = { 0, 0, 0, 0};
int pages=0;
int res=0;
int share=0;
int text = 0;
int lib=0;
// sprintf(buf, "/proc/%u/statm", getpid());
FILE* mfd = fopen( "/proc/self/statm", "r");
fscanf(mfd, "%d %d %d %d %d %d", &pages,&res,&share,&text,&lib,mem_data);
*mem_data *= PAGESIZE;
fclose(mfd);
return pages * PAGESIZE;
}
memcached_process_set( memcache_ctx *mctx, likes_ctx* ctx) {
... // текст процедуры добавления данных
// eсли возвращено FALSE, то смотрим код ошибки
if (!tchdbput2(hdb, mctx->key, mctx->value)) {
ctx->ecode = tchdbecode(hdb);
// eсли код ошибки: «Запись не найдена», то увеличиваем stats.miss
if (ctx->ecode == TCENOREC) {
stats.miss ++;
return NOT_FND;
}
stats.err ++; // другой код ошибки: увеличиваем stats.err
return ERR;
}
// операция завершилась успешно: увеличиваем stats.set
stats.set ++;
return OK;
}
...
} else if (strncmp(mctx->cmd, "stats clear", 11) == 0) {
stats.cmd_count = 0;
stats.get = 0;
stats.set = 0;
stats.del = 0;
stats.miss = 0;
stats.err = 0;
stats.notice = 0;
stats.inc = 0;
stats.cnn_count = 0;
stats.rps_peak = 0;
stats.crw_cycles = 0;
stats.crw_del = 0;
memcached_stats(EV_A_ mctx);
goto send_reply;
// обязательно должна стоять перед командой stats
} else if (strncmp(mctx->cmd, "stats", 5) == 0) {
...
...
ev_timer_init(&timeout_watcher, periodic_watcher, 0., TIME_CHECK_INTERVAL);
ev_timer_again(loop, &timeout_watcher);
// event loop
ev_loop(loop, 0);
void
periodic_watcher(EV_P_ ev_timer *t, int revents)
{
// фиксируем время окончания периода измерения
gettimeofday(&t_end, NULL);
long mtime, seconds, useconds, mtime_sum;
seconds = t_end.tv_sec - t_start.tv_sec;
useconds = t_end.tv_usec - t_start.tv_usec;
mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
mtime_sum = ((second_sum) * 1000 + usecond_sum/1000.0) + 0.5;
// получаем время в миллисекундах
mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
// получаем относительную величину загрузки
stats.upload = mtime? (float)mtime_sum / mtime : 0;
// получаем производительность количество операций в сек (rps)
stats.rps = stats.cmd_per * 1000 /mtime ;
if(stats.rps_peak < stats.rps) stats.rps_peak = stats.rps;
stats.cmd_per = 0;
second_sum=0;
usecond_sum=0;
// фиксируем время начала периода измерения
gettimeofday(&t_start, NULL);
}
-----------------------------------------------------------------------------------------------------------------
Соберем Wi-Fi-точку доступа с WPA2-шифрованием на базе Wi-Fi-карты, hostapd и Linux
Михаил Ушаков
#iwconfig
#ip addr add 192.168.10.1/24 dev wlan0
HOSTAPD_BIN=/usr/sbin/hostapd
HOSTAPD_PID=/var/run/hostapd.pid
HOSTAPD_ARGS="-B -P $HOSTAPD_PID"
HOSTAPD_CONF="/etc/gostapd.conf"
. /etc/rc.status
rc_reset
case "$1" in
start)
echo –n "Starting hostapd"
/sbin/start_daemon –p $HOSTAPD_PID $HOSTAPD_BIN $HOSTAPD_ARGS $HOSTAPD_CONF
rc_status –v
;;
stop)
echo –n "Shutdown hostapd"
/sbin/killproc $HOSTAPD_BIN
rc_status –v
;;
try-restart|condrestart)
$0 status
if test $?=0; then
$0 restart
else
rc_reset
fi
rc_status
;;
restart)
$0 stop
$0 start
rc_status
;;
force-reload)
echo -n "Reload service hostapd "
/sbin/killproc -HUP $HOSTAPD_BIN
touch $HOSTAPD_PID
rc_status -v
;;
reload)
echo -n "Reload service hostapd "
/sbin/killproc -HUP $HOSTAPD_BIN
touch $HOSTAPD_PID
rc_status -v
;;
status)
echo -n "Checking for service hostapd "
/sbin/checkproc $HOSTAPD_BIN
rc_status -v
;;
probe)
test $HOSTAPD_CONF -nt $HOSTAPD_PID && echo reload
;;
*)
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
exit 1
;;
esac
rc_exit
#chmod ug+x hostapd
#chkconfig --level 35 hostapd on
service hostapd stop
service hostapd restart
interface=wlan0
driver=nl80211
bridge=br0
ssid=MyAccessPoiut
utf8_ssid=1
country_code=RU
ieee80211d=1
hw_mode=g
channel=11
auth_algs=1
wpa=2
interface=wlan0
ieee80211d=1
ssid=MyAccessPoint
hw_mode=g
channel=11
auth_algs=1
wpa=2
wpa_passphrase=MyAccessPointPassword~^&653
# /usr/sbin/hostapd –d /etc/hostapd.conf
#ifconfig –a | grep HWaddr
# ifconfig wlan0 down
# ifconfig wlan0 hw ether 02:E6:BA:D0:E0:A0
# ifconfig wlan0 up
interface=wlan0
bssid=02: E6:BA:D0:E0:A0
driver=nl80211
ssid= MyAccessPoint
channel=11
wpa=2
wpa_passphrase=MyAccessPointPassword1~^&653
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
bss=wlan0_0
ssid= MyAccessPoint2
bss=wlan0_1
ssid= MyAccessPoint3
bss=wlan0_2
ssid= MyAccessPoint4
wpa=2
wpa_passphrase=AnotherStrongPassWord~~~480
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP