Windows 2008 Server Core: Windows без окон Андрей Бирюков netsh interface ipv4 show interfaces netsh interface ipv4 set address name="" source=static address=<Статический_адрес> mask=<Маска_подсети> gateway=<Шлюз_по_умолчанию> netsh interface ipv4 add dnsserver name=""" address=index=1 netsh interface ipv4 set address name="" source=dhcp Netdom renamecomputer <Имя_компьютера> /NewName:<Новое_имя_компьютера> net user administrator * Netsh advfirewall Set machine <Имя_сервера> Slmgr.vbs -ato netdom join <Имя_компьютера> /domain:<Имя_домена> /userd:<Имя_пользователя> /passwordd:* net localgroup administrators /add <Имя_домена>\<Имя_пользователя> Shutdown /r /t 0 Dcpromo /unattend:<Файл_ответов> start /w ocsetup DHCPServerCore start /w ocsetup DHCPServerCore /uninstall start /w ocsetup FRS-Infrastructure start /w ocsetup DFSN-Server start /w ocsetup DFSR-Infrastructure-ServerEdition start /w ocsetup ServerForNFS-Base start /w ocsetup ClientForNFS-Base Start /w ocsetup Printing-ServerCore-Role Oclist start /w ocsetup <Имя_компонента> ----------------------------------------------------------------------------------------------------------------- Оптимизируем работу MS SQL Server Алексей Бережной DBCC SHRINKDATABASE ( {имя базы данных} [ , {необходимый процент} ] [ , { NOTRUNCATE | TRUNCATEONLY } ] ) DBCC SHRINKFILE ( { имя файла/ID файла } { [ , {необходимый размер} ] | [ , { EMPTYFILE | NOTRUNCATE | TRUNCATEONLY } ] } ) EXEC sp_attach_db @dbname = N'{имя базы данных}', @filename1 = N'{полный путь к файлу.mdf}', @filename2 = N'{полный путь к файлу.ldf}' ALTER DATABASE {имя базы данных} MODIFY FILEGROUP {имя файловой группы} DEFAULT CREATE DATABASE Sales ON PRIMARY ( NAME = SPri1_dat, FILENAME = '{полный путь к файлу.mdf}', SIZE = 10, MAXSIZE = 50, FILEGROWTH = 15% ), FILEGROUP SalesGroup1 ( NAME = SGrp1Fi1_dat, FILENAME = '{полный путь к файлу.ndf}', SIZE = 10, MAXSIZE = 50, FILEGROWTH = 5 ) LOG ON ( NAME = 'Sales_log', FILENAME = '{полный путь к файлу.ldf}', SIZE = 5MB, MAXSIZE = 25MB, FILEGROWTH = 5MB ) GO ----------------------------------------------------------------------------------------------------------------- Дао DTrace Часть II Евгений Ильин, Филипп Торчинский # mdb -k > ::sizeof struct sysent > sysent+7*0x20::array struct sysent 1 |::print struct sysent > sysent+7*0x20::array struct sysent 1 |::print struct sysent #pragma D option quiet proc:::exec { self->parent = execname; } proc:::exec-success /self->parent != NULL/ { @gs[self->parent, execname] = count(); self->parent = NULL; } proc:::exec-failure /self->parent != NULL/ { @gf[self->parent, execname] = count(); self->parent = NULL; } END { printa(" %s -> %s (%@d)\n", @gs ); } joda#dtrace -s exec-chain.d -c 'su – obi-wan' obi-wan#exit BEGIN { self->start = timestamp; } timestamp-self->start END { printf( "digraph ExecGraph {\n" ); printa(" \"%s\" -> \"%s\" [weight=%@d];\n", @gs ); printa(" \"%s\" -> \"%s\" [color=red,weight=%@d];\n",@gf ); printf("}\n"); #dot -Tjpg graph.dot -o graph.jpg #dtrace -n 'proc:::exec-success { trace(curpsinfo->pr_psargs); }' #dtrace -P pid'$target' -c dtrace -l #!/usr/sbin/dtrace -s pid$target:$1::entry { @func[probefunc] = count(); } #!/usr/sbin/dtrace -s pid$target:libc:malloc:entry { ustack(); } pid$target:libc:malloc:return { printf("alloc: %x\n", arg1); @memu[ arg1 ] = count(); } pid$target:libc:free:entry { printf("free: %x\n", arg0); @memu[ arg0 ] = count(); } END { printa(@par); } # dtrace -l -n 'javascript*:::'|more javascript*::: function-args javascript* :::function-rval dtrace -l -v -n 'javascript*:::function-args' Input form
# dtrace -n 'javascript*:::function-args /copyinstr(arg2) == "testDate"/ {printf("%s %s %d %s",copyinstr(arg0),copyinstr(arg2),arg3,copyinstr(arg5));}' ----------------------------------------------------------------------------------------------------------------- Fedora Directory Server – сервер каталогов уровня предприятия Андрей Маркелов yum install fedora-ds /usr/bin/fedora-idm-console ----------------------------------------------------------------------------------------------------------------- Безопасный FTP – это легко! Иван Максимов # aptitude update # aptitude upgrade # aptitude search pure-ftpd # apt-get source pure-ftpd # aptitude install openssl # aptitude install libssl-dev # openssl req -x509 -nodes -newkey rsa:1024 -keyout /etc/ssl/private/pure-ftpd.pem -out /etc/ssl/private/pure-ftpd.pem # ./configure --with-rfc2640 --with-puredb --with-tls --with-certfile=/etc/ssl/private/pure-ftpd.pem --with-ftpwho –with-altlog # make & make install # groupadd ftpgroup # useradd -m -g ftpgroup -d /dev/null -s /etc ftpuser # getent passwd ftpuser # pure-pw useradd max -u ftpuser -d /home/ftpusers/max # cat /etc/pureftpd.passwd # pure-pw show max # pure-pw mkdb # /usr/local/sbin/pure-ftpd -4 -A -B -E -j -U 022:022 -O clf:/var/log/pureftpd.log --fscharset=utf8 --clientcharset=cp1251 -lpuredb:/etc/pureftpd.pdb --tls=2 # netstat -apn | grep ftp # /usr/local/sbin/pure-ftpd -4 -A -B -E -U 022:022 -p 50000:51000 -O clf:/var/log/pureftpd.log --fscharset=utf8 --clientcharset=cp1251 -lpuredb:/etc/pureftpd.pdb –tls=2 # iptables -I INPUT -p tcp --dport 50000:51000 -j ACCEPT # iptables -L iptables -I FORWARD -i eth0 -s 192.168.0.20 -o eth1 -p tcp --dport 1024:4096 -j ACCEPT iptables -I FORWARD -i eth0 -s 192.168.0.20 -o eth1 -j ACCEPT # chmod 755 pure-config.pl # pure-config.pl /etc/pure-ftpd.conf #!/bin/bash /usr/local/sbin/pure-ftpd -4 -A -B -E -U 022:022 -p 50000:51000 -O clf:/var/log/pureftpd.log --fscharset=utf8 --clientcharset=cp1251 -lpuredb:/etc/pureftpd.pdb –tls=2 # update-rc.d ftpes start 20 3 4 . # update-rc.d -f ftpes remove # pure-pw --help ----------------------------------------------------------------------------------------------------------------- Балансировка исходящего веб-трафика между двумя провайдерами для небольших и средних организаций Squid+ipvs+keepalived Кирилл Хорошилов # rpm -ihv squid-2.6.STABLE4-1.fc6.i386.rpm ipvsadm-1.24-8.1.i386.rpm keepalived-1.1.13-6.fc6.i386.rpm # rpm -ihv kernel-2.6.22.5-49.fc6.src.rpm ---------kernel-2.6.spec--------- ... Patch1400: linux-2.6-ipvs.patch ... ApplyPatch linux-2.6-ipvs.patch ... ---------kernel-2.6.spec--------- # Whether or not to gpg sign modules %define with_modsign 0 # cd /usr/src/redhat/SPECS # rpmbuild -bb --target=i686 --with baseonly kernel-2.6.spec # cd /usr/src/redhat/RPMS/i386 # rpm -ihv kernel-2.6.22.5-49.i386.rpm # ifconfig eth0:0 192.168.1.20 netmask 255.255.255.0 -------squid.conf------- acl lhost1 myhost 192.168.1.10 acl lhost2 myhost 192.168.1.20 tcp_outgoing_address 172.16.1.10 lhost1 tcp_outgoing_address 10.0.0.20 lhost2 # Допишем еще параметр transparent к директиве http_port http_port 3128 transparent # Это добавит к обычному режиму transparent (прозрачный) # режим, когда Squid проксирует http-трафик, проходящий # через сервер не заметно для клиентов. Данный режим прокси # требуется для корректного прохождения запросов # на доступность каналов от keepalived. # Так же нужно указать Squid не использовать серверные # persistent connections (persistent connections – # постоянные соединения, когда для нескольких http-запросов # используется одно и то же tcp-соединение). В нашем случае # опцию отключаем, чтобы squid закрывал сокет после # http-запроса, иначе в случае падения канала Squid # по-прежнему будет отправлять запросы в уже не работающий # канал, используя открытые сокеты на интрефейсе # этого канала. server_persistent_connections off # echo 200 T1 >> /etc/iproute2/rt_tables # echo 201 T2 >> /etc/iproute2/rt_tables # ip rule add from 172.16.1.10 table T1 # ip rule add from 10.0.0.20 table T2 # ip route add default via 172.16.1.1 table T1 # ip route add default via 10.0.0.1 table T2 # ip ru sh # ip ro sh t T1 # ip ro sh t T2 -------------/etc/keepalived/keepalived.conf---------- global_defs { # Определим параметры e-mail для извещения о работе # health-checker – это полезно, при падении одного # из каналов вам придет письмо с новостью об этом notification_email { root@host.domain } notification_email_from keepalived@yourhost.domain smtp_server 127.0.0.1 smtp_connect_timeout 30 } # Настройки относительно VRRP из дефолтного конфигурационного # файла следует оставить, они необходимы для работы # keepalived. Подправим их следующим образом vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.1 } } # При старте keepalived поднимет виртуальный интерфейс # с адресом 192.168.1.1, который не будет виден через # ifconfig (он виден через команду «ip address show»), # но будет доступен из сети. Этот адрес нужно указать # в качестве прокси, это VIRTUAL IP балансировщика, # с которого он будет разбрасывать трафик на реальные # адреса, слушаемые Squid # Далее описывается этот виртуальный сервер и 2 реальных virtual_server 192.168.1.1 3128 { delay_loop 6 # Алгоритм балансировки - round-robin lb_algo rr # Способ форварда пакетов на real-сервера - NAT lb_kind NAT nat_mask 255.255.255.0 # Здесь задается таймаут (в секундах) работы одного клиента # через одного и того же провайдера (для поддержки # веб-сессий). Клиент по истечении заданного здесь времени # бездействия может быть переключен на другой канал persistence_timeout 600 protocol TCP # Для проверки работоспособности каналов будем проверять # доступность http://yandex.ru/white.html через каждый # канал. Страничка достаточно легкая и доступная. # Можете прописать какую-нибудь свою virtualhost yandex.ru # Real-server – в нашем случае первый адрес, на котором # слушает Squid real_server 192.168.1.10 3128 { weight 1 # Для проверки будем слать HTTP GET-запрос и считать, # что канал доступен, если через него пришел ответ 200 # от сервера HTTP_GET { url { path /white.html # Проверяем http-код ответа сервера при запросе данной # страницы, этого достаточно, чтобы убедиться, что канал # работает status_code 200 } # Время на установление соединения (сек.) connect_timeout 10 # Количество попыток соединиться (сек.) nb_get_retry 3 # Соответственно задержка между попытками (сек.) delay_before_retry 8 # Возможно, вы захотите использовать другие тайм-ауты } } # Аналогично для второго Real-server real_server 192.168.1.20 3128 { weight 1 HTTP_GET { url { path /white.html status_code 200 } connect_timeout 10 nb_get_retry 3 delay_before_retry 8 } } } # /etc/init.d/keepalived start # ipvsadm -L # ipvsadm -L –-stats ----------------------------------------------------------------------------------------------------------------- Создаем интернет-магазин на osCommerce Сергей Яремчук $ sudo apt-get install php5 php5-mysql $ sudo a2enmod php5 $ sudo /etc/init.d/apache2 restart $ mysqladmin --user=root password 'mysql_root_password' $ mysqladmin --user=root -p create oscommerce $ mysql --user root -p mysql> GRANT ALL PRIVILEGES ON oscommerce.* TO oscommerce@localhost IDENTIFIED BY 'db_passwd'; mysql> flush privileges; mysql> quit; $ sudo chmod 777 /var/www/catalog/includes/configure.php /var/www/catalog/admin/includes/configure.php $ sudo apt-get install php5-curl php5-gd $ sudo rm –Rf /var/www/catalog/install $ sudo chmod 444 /var/www/catalog/includes/configure.php define('LANGUAGE_CURRENCY', 'USD'); define('LANGUAGE_CURRENCY', 'RUB'); # Локаль @setlocale(LC_TIME, 'ru_RU.CP1251'); # Формат даты define('DATE_FORMAT_SHORT', '%d/%m/%Y'); // this is used for strftime() define('DATE_FORMAT_LONG', '%A %d %B, %Y'); // this is used for strftime() define('DATE_FORMAT', 'd/m/Y'); // this is used for date() define('DATE_TIME_FORMAT', DATE_FORMAT_SHORT . ' %H:%M:%S'); # Кодировка веб-страниц и e-mail define('CHARSET', 'windows-1251'); # Заголовок страницы define('TITLE', 'OsCommerce - Русская Версия'); $ sudo chmod 777 /var/www/catalog/images $ sudo chmod 777 /var/www/catalog/admin/images/graphs $ sudo mkdir /var/www/catalog/admin/backups $ sudo chmod 777 /var/www/catalog/admin/backups AllowOverride None AuthUserFile /etc/apache2/.htpasswd AuthName "Secure Zone" AuthType Basic Require valid-user htpasswd -c /etc/apache/.htpasswd user1 htpasswd /etc/apache/.htpasswd user2 ----------------------------------------------------------------------------------------------------------------- Синхронизация ACL и структуры организации Часть 2 Вадим Андросов const SOME_CONST = 3 function add(a, b) add = a + b end function cscript my_script.wsf //Job:some_job msgbox "I like set accumObj = Createobject("DynamicGroup.Accumulator") set accumObj = Createobject("DynamicGroup.Accumulator") Msgbox accumObj.Value accumObj.Add(3) accumObj.Add(4) Msgbox accumObj.Value function getOU(dn) getOU = "LDAP://" & right(dn, len(dn) - instr(1, dn, ",", vbTextCompare)) end function function getParent(dn) if UCase(Left(dn, 2))="DC" then getParent = "" else getParent = getOU(dn) end if end function Function isBadLink(aLink) on Error Resume Next Getobject("LDAP://") isBadLink = Err<>0 On Error Goto 0 end Function function isBadSingle(ou) isBadSingle = isBadLink(ou.groupSingle) end function function isBadTree(ou) isBadTree = isBadLink(ou.groupTree) end function function addToAttached(groupObj) if groupObj.isMember(dn) then exit function groupObj.add(dn) groupObj.setInfo end function set handler = createObject("DynamicGroup.EventHandler") handler.dn = targetEvent.TargetInstance.ADSIPath handler.on... function extractCN() pos = instr(1, UCase(dn), "CN=", vbTextCompare) if pos = 0 then extractCN = "" exit Function end if extractCN = right(dn, len(dn) - pos - 3 + 1) pos = instr(1, extractCN, ",", vbTextCompare) extractCN = Left(extractCN, pos - 1) end Function function userDNInGroup(groupObj) userDNInGroup = "" cn = extractCN for each userObj in groupObj.members if userObj.cn = CN then userDNInGroup = userObj.ADSPath exit function end if next end function function removeFromAttached(groupObj) newDN = userDNInGroup(groupObj) if isEmpty(newDN) then exit function groupObj.remove(newDN) groupObj.setInfo end function function unRegisterInParent(treeGroupGUID, parentOU) if not isGroupExist(parentOU.groupTree) then exit function set treeGroup = getObject("LDAP://") set ou2Delete = getObject("LDAP://") treeGroup.remove(ou2Delete.ADSPath) treeGroup.setInfo end function Function unattachTreeGroup(ou) parentPath = getParent(ou.distinguishedName) if not isEmpty(parentPath) Then set parentOU = getObject(parentPath) if not isEmpty(parentOU.groupTree) then ou.groupTree = parentOU.groupTree ou.setInfo set parentGroup = getObject("LDAP://") attach parentGroup, ou end if Else ou.putEx ADS_PROPERTY_CLEAR, "groupTree", "" ou.setInfo end If end Function set handler = createObject("DynamicGroup.EventHandler") handler.dn = targetEvent.TargetInstance.ADSIPath handler.onUserEvent(targetEvent.path_.class) const EVENT_CREATE_INSTANCE = "__InstanceCreationEvent" const EVENT_DELETE_INSTANCE = "__InstanceDeletionEvent" function onUserEvent(eventType) set ouObj = getObject(getOU(dn)) if isGroupExist(ouObj.groupSingle) then set grSingle = getObject("LDAP://") if eventType = EVENT_CREATE_INSTANCE then addToAttached grSingle elseif eventType = EVENT_DELETE_INSTANCE then removeFromAttached grSingle end if end if end function handler.onGroupDelete() function onGroupDelete() set ou = getObject(getOU(dn)) if isBadSingle(ou) then ou.putEx ADS_PROPERTY_CLEAR, "groupSingle", "" ou.setInfo end If if isBadTree(ou) then unattachTreeGroup ou end if end function handler.onOuCreate() function onOuCreate() set ouObj = getObject(dn) if not isGroupExist(ouObj.groupTree) then exit function parentPath = getParent(dn) if isEmpty(parentPath) then exit function set parentOU = getObject(parentPath) registerInParent ouObj, parentOU end function handler.onOuDelete(targetEvent.TargetInstance.DS_groupTree) function onOuDelete(treeGroupGUID) if not isGroupExist(treeGroupGUID) then exit function parentPath = getParent(dn) if isEmpty(parentPath) then exit function set parentOU = getObject(parentPath) unRegisterInParent treeGroupGUID, parentOU end function ----------------------------------------------------------------------------------------------------------------- A2Billing – система отчетов и биллинга для Asterisk Сергей Яремчук # rpm -qa | grep php $ sudo dpkg –l php* extension=mysqli.so extension=gd.so $ mysqladmin create mya2billing -u a2billinguser -p $ mysql –u root –p mysql> GRANT ALL PRIVILEGES ON mya2billing.* TO 'a2billinguser'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION; mysql> GRANT ALL PRIVILEGES ON mya2billing.* TO 'a2billinguser'@'localhost' IDENTIFIED BY ' password' WITH GRANT OPTION; mysql>GRANT ALL PRIVILEGES ON mya2billing.* TO 'a2billinguser'@'localhost.localdomain' IDENTIFIED BY 'password' WITH GRANT OPTION; mysql> flush privileges; mysql> quit $ mkdir a2billing $ cd a2billing $ tar xzvf A2Billing_1.3.1.tar.gz3 $ cd Database/mysql/Mysql-5.x/ $ mysql mya2billing -u a2billinguser -p < a2billing-mysql-schema-MYSQL.5.X-v1.3.0.sql $ mysql mya2billing -u a2billinguser –p mysql> SELECT * FROM cc_ui_authen; $ sudo cp –v a2billing.conf /etc/asterisk $ sudo vi /etc/asterisk/a2billing.conf [database] hostname = localhost port = 5432 user = a2billinguser password = password dbname = mya2billing ;dbtype = postgres dbtype = mysql [global] ; Базовая валюта для расчетов, по умолчанию использован ; доллар. Конвертация и другие доступные валюты можно найти ; в таблице cc_curencies. Для рубля запись выглядит так: ; | id | currency | name | value | lastupdate | basecurrency | ; | 112 | RUB | Russian Rouble (RUB) | 0.03563 | 2008-01-22 21:02:59 | USD | ; можно настроить автоматическое обновление котировок ; с finance.yahoo.com base_currency = usd ; Рисунок, который будет показан на верху счета, ; это JPEG-файл в каталоге templates/default/images/ invoice_image = asterisk.jpg ; Электронный адрес администратора admin_email = admin@server.com ; Настройки менеджера из /etc/asterisk/manager.conf manager_host = localhost manager_username = myasterisk manager_secret = mypassword [webui] ; Доступная валюта currency_choose = usd, eur, rub ; или all ; Файлы, в которые будут сохраняться новые настройки SIP ; и IAX сделанные в A2Billing buddy_sip_file = /etc/asterisk/additional_a2billing_sip.conf buddy_iax_file = /etc/asterisk/additional_a2billing_iax.conf ; Каталог MOH (Music on Hold) dir_store_mohmp3 = /var/lib/asterisk/mohmp3 ; И класс MOH classes в musiconhold.conf num_musiconhold_class = 10 ; Показ секции help в интерфейсе администратора (YES - NO) show_help = YES ; Максимальный размер загружаемого файла, следует ; учитывать также параметр upload_max_filesize в Ubuntu, ; по умолчанию здесь установлено 2 Мб my_max_file_size_import = 1024000 ; 1 Mб ; Каталог для загрузки мелодий MOH dir_store_audio = /var/lib/asterisk/sounds/a2billing ; Максимальный их размер my_max_file_size_audio=3072000 ; в байтах ; Разрешенные расширения файлов file_ext_allow = gsm, mp3, wav file_ext_allow_musiconhold = mp3 $ sudo mkdir /var/lib/asterisk/mohmp3/ $ sudo mkdir /var/lib/asterisk/sounds/a2billing $ sudo chmod 777 /var/lib/asterisk/sounds/a2billing $ sudo chmod 777 /etc/asterisk #include additional_a2billing_sip.conf #include additional_a2billing_iax.conf $ sudo touch /etc/asterisk/additional_a2billing_sip.conf $ sudo chmod 777 /etc/asterisk/additional_a2billing_sip.conf $ sudo touch /etc/asterisk/additional_a2billing_iax.conf $ sudo chmod 777 /etc/asterisk/additional_a2billing_iax.conf [general] enabled = yes port = 5038 bindaddr = 0.0.0.0 [myasterisk] secret = mypassword read = system,call,log,verbose,command,agent,user write = system,call,log,verbose,command,agent,user $ sudo cp -rf A2Billing_UI /var/www $ cat /etc/apache2/apache2.conf | grep User $ sudo chown –R www-data /var/www/A2Billing_UI $ sudo chmod 777 /var/www/A2Billing_UI/templates_c $ sudo cp -rf A2BCustomer_UI /var/www $ sudo chown –R www-data /var/www/ $ sudo chmod 777 /var/www/A2BCustomer_UI/templates_c $ cd A2Billing_AGI $ sudo cp a2billing.php /var/lib/asterisk/agi-bin/ $ sudo chmod +x /var/lib/asterisk/agi-bin/a2billing.php $ sudo cp -rf libs_a2billing /var/lib/asterisk/agi-bin/ [a2billing] exten => _X.,1,Answer exten => _X.,2,Wait,2 exten => _X.,3,DeadAGI,a2billing.php exten => _X.,4,Wait,2 exten => _X.,5,Hangup ----------------------------------------------------------------------------------------------------------------- Начинаем работать с Zend Framework Кирилл Сухов RewriteEngine on RewriteRule .* index.php RewriteEngine off setControllerDirectory('./application/controllers'); //запуск приложения $frontController->dispatch(); ?> USE records CREATE TABLE ‘Records’ id int(11) NOT NULL auto_increment, group varchar(100) NOT NULL, notes text NOT NULL, PRIMARY KEY (id) ); zend/application/config.ini [general] db.adapter = PDO_MYSQL db.config.host = localhost db.config.username = geol db.config.password = fig_podberesh db.config.dbname = records Zend_Loader::loadClass('Zend_Db'); Zend_Loader::loadClass('Zend_Db_Table'); Zend_Loader::loadClass('Zend_Config_Ini'); Zend_Loader::loadClass('Zend_Registry'); $config = new Zend_Config_Ini('./application/config.ini','general'); $registry = Zend_Registry::getInstance(); $registry->set('config', $config); $db = Zend_Db::factory($config->db->adapter, $config->db->config->toArray()); Zend_Db_Table::setDefaultAdapter($db); http://localhost/zend/records/delete zend/application/controllers/IndexController.php: view->baseUrl = $this->_request->getBaseUrl(); Zend_Loader::loadClass('Records'); } function indexAction() { print “list”; } function addAction() { print “add”: } function editAction() { … } function deleteAction() { … } } http://localhost/zend/index/add $view = new Zend_View(); echo $view->render('view.php'); function indexAction() { $this->view->title = "Records"; $this->view->capitin = "Моя коллекция"; } zend/application/views/scripts/index/add.phtml: <?php echo $this->escape($this->title); ?>

escape($this->capiton); ?>

zend/application/views/scripts/index/add.phtml: <?php echo $this->escape($this->title); ?>

escape($this->capiton); ?>

----------------------------------------------------------------------------------------------------------------- Проводим отладку JavaScript-приложений Андрей Уваров ... ... ... ... <полный путь>testRunner.html?testpage=<путь>testSuite.html file:///users/dashin/Documents/work/articles/samag/debugging-js/examples/jsunit/testRunner.html?testpage=/users/dashin/Documents/work/articles/samag/debugging-js/examples/testSuite.html Log4js example ----------------------------------------------------------------------------------------------------------------- SOAP и веб-сервисы XML на платформе .Net Алексей Бойко Листинг 1. Структура SOAP-сообщения Листинг 2. Пример SOAP-запроса Листинг 3. Пример SOAP-ответа Здравствуй, мир! <%@ WebService Language="C#" CodeBehind="~/App_Code/Service.cs" Class="Service" %> Листинг 5. Файл Service.cs, реализующий метод HelloWorld() using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class Service : System.Web.Services.WebService { public Service () { } [WebMethod] public string HelloWorld() { return "Hello World"; } } Листинг 6. Service.asmx без внешнего кода поддержки <%@ WebService Language="C#" Class="Service" %> using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class Service : System.Web.Services.WebService { public Service () { } [WebMethod] public string HelloWorld() { return "Hello World"; } } Листинг 7. «Старый» и новый ответы web-сервиса XML Hello World зашифрованный текст Листинг 8. Создание класса, наследуемого от SoapExtension using System; using System.Web.Services; using System.Web.Services.Protocols; using System.IO; using System.Net; using System.Xml; public class TraceExtension : SoapExtension { } Листинг 9. Реализация метода ChainStream public class TraceExtension : SoapExtension { Stream wireStream; Stream appStream; // метод в качестве входного параметра // получает поток, содержащий передаваемый объект public override Stream ChainStream(Stream stream) { wireStream = stream; appStream = new MemoryStream(); return appStream; } … } Листинг 10. Реализация метода ProcessMessage, не модифицирующего SOAP-сообщения // ProcessMessage, выполняющий обязательное копирование // потоков в двух точках (BeforeDeserialize и AfterSerialize) public override void ProcessMessage(SoapMessage message) { switch (message.Stage) { // в точке BeforeDeserialize необходимо передать // SOAP-запрос из потока сети (wireStream) // в поток приложения (appStream) case SoapMessageStage.BeforeDeserialize: Copy(wireStream, appStream); appStream.Position = 0; break; // в точке AfterSerialize необходимо передать // SOAP-ответ из потока приложения в поток сети case SoapMessageStage.AfterSerialize: appStream.Position = 0; Copy(appStream, wireStream); break; } } void Copy(Stream from, Stream to) { TextReader reader = new StreamReader(from); TextWriter writer = new StreamWriter(to); writer.WriteLine(reader.ReadToEnd()); writer.Flush(); } Листинг 11. Реализация метода ProcessMessage, модифицирующего SOAP-ответ public override void ProcessMessage(SoapMessage message) { switch (message.Stage) { case SoapMessageStage.AfterSerialize: WriteOutput(message); break; // часть кода вырезана для экономии места { { // перепишем SOAP-ответ public void WriteOutput(SoapMessage message) { appStream.Position = 0; // создадим XML документ из потока XmlDocument document = new XmlDocument(); document.Load(appStream); // Для использования XPath нужно определить // NamespaceManager XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable); nsmgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/"); // получим ссылку на узел XmlNode ResultNode = document.SelectSingleNode("//soap:Body", nsmgr); // заменем содержимое узла ResultNode.InnerText = "зашифрованный текст"; // очистим поток и запишем в него новый SOAP-ответ appStream.SetLength(0); appStream.Position = 0; document.Save(appStream); // ОБЯЗАТЕЛЬНОЕ ДЕЙСТВИЕ // передадим SOAP-ответ из потока приложения (appStream) // в поток сети (wireStream) appStream.Position = 0; Copy(appStream, wireStream); } Листинг 12. Другие обязательно реализуемые методы // В соотвествии с правилами наследования мы обязаны // определить эти методы, однако мы их никак не используем public override object ? GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute) { return null; } public override object GetInitializer(Type WebServiceType) { return null; } public override void Initialize(object initializer) { return; } Листинг 13. Файл Web.Config Листинг 14. Секция webServices в файле Web.Config Листинг 15. Пример использования собственного атрибута [WebMethod] [MyExtension] public string HelloWorld() { return "Hello World"; } -----------------------------------------------------------------------------------------------------------------