Обзор клиентских приложений под 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