Reporting Services: составляем отчеты Павел Купцов SELECT OrderID AS 'Номер заказа', OrderDate AS 'Дата заказа', RequiredDate AS 'Дата исполнения', Freight AS 'Стоимость' FROM Orders WHERE CustomerID = (SELECT CustomerID FROM Customers WHERE CompanyName LIKE 'Familia%') SELECT OrderID AS 'Номер заказа', OrderDate AS 'Дата заказа', RequiredDate AS 'Дата исполнения', Freight AS 'Стоимость' FROM Orders WHERE CustomerID = (SELECT CustomerID FROM Customers WHERE CompanyName LIKE @Company+'%') data source=CTX; initial catalog=Northwind ----------------------------------------------------------------------------------------------------------------- Как быстро и эффективно провести учет компьютерной техники Алексей Бережной # Local hosts 192.168.9.31 COMP1 192.168.9.32 COMP2 192.168.9.33 COMP3 # MAC IP Host 0006298FC845 192.168.9.31 COMP1 000A5E6416D2 192.168.9.32 COMP2 00C026AC48DB 192.168.9.33 COMP3 # Static IP-address 192.168.9.31 COMP1 0006298FC845 192.168.9.32 COMP2 000A5E6416D2 192.168.9.33 COMP3 00C026AC48DB ----------------------------------------------------------------------------------------------------------------- Подробное руководство по настройке тонких клиентов на основе дистрибутива Thinstation и протокола NX Часть 2 Евгений Бушков #F8: ShowPopup()\\n\ F12: ShowPopup()\\n\ #"*popupButtonCount: 6", "*popupButtonCount: 2", #"*popup*button1.label: Dismiss popup", "*popup*button1.label: Close", #"*popup*button2.label: Quit viewer", "*popup*button2.label: Send F12", #,: Quit()", ,: SendRFBEvent(key,F12) HidePopup()", xterm -e setxkbmap -rules xorg -model pc105 -layout "us,ru" -variant ",winkeys" -option "grp:ctrl_shift_toggle,grp_led:scroll" ALL ALL = NOPASSWD: /srv/NX/bin/nxserver --list*, !/srv/NX/bin/nxserver [!-]* # We test floppy and HD existing by requesting samba server on thin client name=`whoami` if [ "$name" != nx ] && [ "$name" != "root" ] then ip=$(/usr/bin/sudo /srv/NX/bin/nxserver --list $name|grep 10\\.|tail -n 1|awk '{print $3}') if [ "$ip" != "" ] then # testing for harddisk existence harddisk=`smbclient -NL $ip 2>/dev/null|grep harddisk` if [ "$harddisk" != "" ] then echo "[Desktop Entry]" > ~/Desktop/Harddisk.desktop echo "Encoding=UTF-8" >> ~/Desktop/Harddisk.desktop echo "Icon=HD" >> ~/Desktop/Harddisk.desktop echo "Name=Harddisk" >> ~/Desktop/Harddisk.desktop echo "Name[ru]=Harddisk" >> ~/Desktop/Harddisk.desktop echo "OnlyShowIn=KDE;" >> ~/Desktop/Harddisk.desktop echo "Open=false" >> ~/Desktop/Harddisk.desktop echo "Type=Link" >> ~/Desktop/Harddisk.desktop echo "URL=smb://$ip/harddisk" >> ~/Desktop/Harddisk.desktop echo "X-KDE-KonqSidebarModule=konqsidebar_tree" >> ~/Desktop/Harddisk.desktop echo "X-KDE-TreeModule=Directory" >> ~/Desktop/Harddisk.desktop echo "X-SuSE-translate=true" >> ~/Desktop/Harddisk.desktop else rm -f ~/Desktop/Harddisk.desktop fi # testing for floppy existence floppy=`smbclient -NL $ip 2>/dev/null|grep floppy` if [ "$floppy" != "" ] then echo "[Desktop Entry]" > ~/Desktop/"Floppy Disk"; echo "Encoding=UTF-8" >> ~/Desktop/"Floppy Disk"; echo "Icon=3floppy_mount" >> ~/Desktop/"Floppy Disk"; echo "Name=Floppy Disk" >> ~/Desktop/"Floppy Disk"; echo "Name[ru]=Floppy Disk" >> ~/Desktop/"Floppy Disk"; echo "OnlyShowIn=KDE;" >> ~/Desktop/"Floppy Disk"; echo "Open=false" >> ~/Desktop/"Floppy Disk"; echo "Type=Link" >> ~/Desktop/"Floppy Disk"; echo "URL=smb://$ip/floppy" >> ~/Desktop/"Floppy Disk"; echo "X-KDE-KonqSidebarModule=konqsidebar_tree" >> ~/Desktop/"Floppy Disk"; echo "X-KDE-TreeModule=Directory" >> ~/Desktop/"Floppy Disk"; echo "X-SuSE-translate=true" >> ~/Desktop/"Floppy Disk"; else rm -f ~/Desktop/"Floppy Disk"; fi fi fi ----------------------------------------------------------------------------------------------------------------- Размещаем пользовательские бюджеты в LDAP Часть 1 Алексей Барабанов # L="" ; \ P="openldap2 openldap2-client samba-client samba smbldap-tool perl-ldap nss_ldap pam_ldap" ; \ for i in $P ; \ do rpm -qa | grep $i || L="$L $i" ; done ; \ [ -z "$L" ] || echo yast2 -i $L # rcldap stop # I=/var/lib/ldap ; \ for i in $(ls -1 $I | grep -v ^DB_CONFIG) ; \ do rm -f $I/$i ; done # SUFFIX="dc=office,dc=localnet" ; \ LDAPROOT="ldaproot" ; \ ROOTDN="cn=$LDAPROOT,$SUFFIX" ; \ ROOTPW="secret" ; \ LDAPADMIN="ldapadmin" ; \ ADMINDN="cn=$LDAPADMIN,$SUFFIX" ; \ ADMINPW="admin" ; \ SCHEMA='{SSHA}' ; \ T=$(slappasswd -s $ROOTPW -h $SCHEMA) ; \ cat >/etc/openldap/slapd.conf<$I.$$.tmp ; \ mv $I.$$.tmp $I # rcldap start # LDAPSERVER=127.0.0.1 ; \ LDAPPORT=389 ; \ LDAPINT="$LDAPSERVER:$LDAPPORT" ; \ netstat -apn | grep "LISTEN.*slapd" | \ grep $LDAPINT >/dev/null 2>&1 || echo «увы, не работает!» # strings $(rpm -ql nss_ldap | grep lib) | grep ldap.conf # LDAPSERVER=127.0.0.1 ; \ LDAPPORT=389 ; \ LDAPINT="$LDAPSERVER:$LDAPPORT" ; \ SUFFIX="dc=office,dc=localnet" ; \ cat </etc/ldap.conf host $LDAPINT base $SUFFIX # # Don't try forever if the LDAP server is not reacheable bind_policy soft # RFC2307bis naming contexts nss_base_passwd ou=People,$SUFFIX?one nss_base_shadow ou=People,$SUFFIX?one nss_base_group ou=Group,$SUFFIX?one nss_base_hosts ou=Hosts,$SUFFIX?one nss_base_services ou=Services,$SUFFIX?one nss_base_networks ou=Networks,$SUFFIX?one nss_base_protocols ou=Protocols,$SUFFIX?one nss_base_rpc ou=Rpc,$SUFFIX?one nss_base_ethers ou=Ethers,$SUFFIX?one nss_base_netmasks ou=Networks,$SUFFIX?one nss_base_bootparams ou=Ethers,$SUFFIX?one nss_base_aliases ou=Aliases,$SUFFIX?one nss_base_netgroup ou=Netgroup,$SUFFIX?one # attribute/objectclass mapping # Syntax: nss_map_attribute rfc2307attribute mapped_attribute nss_map_objectclass rfc2307objectclass mapped_objectclass # ldap_version 3 ssl no # # pam pam_password exop pam_filter objectclass=posixAccount pam_login_attribute uid pam_member_attribute memberUid EOT # cat <$/etc/nsswitch.conf.tmp passwd: compat shadow: files group: compat services: files ldap netgroup: files ldap aliases: files ldap passwd_compat: ldap group_compat: ldap EOT # grep -v "^\(#\|$\|passwd\|shadow\|group\|services\|netgroup\|aliases\)" \ /etc/nsswitch.conf >>/etc/nsswitch.conf.tmp # mv /etc/nsswitch.conf.tmp /etc/nsswitch.conf # cat </etc/security/pam_unix2.conf auth: use_ldap account: use_ldap password: use_ldap session: none EOT #!/bin/sh for i in /etc/pam.d/common-* ; do [ -L $i ] || { echo $i | grep -v backup$ >/dev/null && { grep "pam_unix2" $i >/dev/null && { sed '/pam_unix2/s/$/use_ldap/' $i >$i.$$.tmp mv $i.$$.tmp $i } } } done # grep "^+:::" /etc/passwd >/dev/null || echo "+::::::" >>/etc/passwd # grep "^+:::" /etc/group >/dev/null || echo "+:::" >>/etc/group # NT4DOM="Office" ; \ LDAPSERVER=127.0.0.1 ; \ LDAPPORT=389 ; \ SUFFIX="dc=office,dc=localnet" ; \ NBTNAME="SERVER" ; \ MAILDOM="office.localnet" ; \ LOCALSID=$(net getlocalsid | awk 'BEGIN{FS="is: "}{print $2}') ; \ cat >/etc/smbldap-tools/smbldap.conf </etc/smbldap-tools/smbldap_bind.conf <init.ldiff ; \ rm -f $I # SUFFIX="dc=office,dc=localnet" ; \ LDAPROOT="ldaproot" ; \ ROOTDN="cn=$LDAPROOT,$SUFFIX" ; \ ROOTPW="secret" ; \ ldapmodify -v -a -D "$ROOTDN" -H ldap://localhost -x -w $ROOTPW -f init.ldiff # SUFFIX="dc=office,dc=localnet" ; \ LDAPROOT="ldaproot" ; \ ROOTDN="cn=$LDAPROOT,$SUFFIX" ; \ ROOTPW="secret" ; \ LDAPADMIN="ldapadmin" ; \ ADMINDN="cn=$LDAPADMIN,$SUFFIX" ; \ ADMINPW="admin" ; \ SCHEMA='{SSHA}' ; \ cat <$I.tmp ; \ mv $I.tmp $I # cat /etc/default/useradd GROUP=100 HOME=/home INACTIVE=-1 EXPIRE= SHELL=/bin/bash SKEL=/etc/skel GROUPS=video,dialout CREATE_MAIL_SPOOL=no #!/bin/bash SUFFIX="dc=office,dc=localnet" LDAPADMIN="ldapadmin" ADMINDN="cn=$LDAPADMIN,$SUFFIX" ADMINPW="admin" cat /etc/group | grep -v ^+ | awk -F: '{print $1, $3}' | while read GNAME GID ; do cat <dump.ldiff # strings $(rpm -ql nss_ldap | grep lib) | grep ldap.conf ----------------------------------------------------------------------------------------------------------------- Какова в действии система резервирования AMANDA Сергей Яремчук $ sudo apt-get update $ sudo apt-get install amanda-server cdrw-taper $ sudo /usr/lib/amanda/taper /usr/lib/amanda/taper.orig org "DailySet1" # Название организации будет использовано в отчете, будет видно в поле «Subject:», # поэтому есть смысл проставить имя задания mailto "grinder" # Пользователь или адрес, куда будет отправлено e-mail-сообщение dumpuser "backup" # Пользователь, от имени которого будет выполняться задание inparallel 4 # Максимальное количество параллельно резервируемых ресурсов, максимальное число 63 может быть увеличено в параметре # MAX_DUMPERS в server-src/driverio.h netusage 600 # Максимальная сетевая загрузка в Кбайт в сек. dumpcycle 1 weeks # Количество дней, через которое производится полное # резервирование, по умолчанию 10 дней, если установить # в 0, то полное резервирование будет производиться # при каждом запуске runspercycle 5 # Необязательный параметр показывает количество запусков # amdump в одном dumpcycle, ведь в выходные программу # резервирования запускать не обязательно tapecycle 9 tapes # Общее число лент, используемых при резервировании, # в нашем случае это DVD-диски. На каждый день dumpcycle # минимум один диск + резерв, чтобы не перекрывались # до следующего полного копирования bumpsize 20 MB # Минимальный порог для перехода на следующий инкрементный # уровень (по умолчанию 10 Мб), взамен возможно использование # bumppercent для указания размера в процентах bumpdays 1 # Позволяет устранить избыточность, минимальное количество # дней для перехода на следующий инкрементный уровень, # значение по умолчанию 2 дня #tpchanger "no-changer" # Интересная опция, позволяющая подменить или изменить # настройки ленточного накопителя (tape changer). # В каталоге /vat/lib/amanda/ доступно 13 обработчиков, # например, chg-disk позволяет вместо ленты писать # на жесткий диск, но нам он сейчас не нужен. # Далее параметры идут специфично для CDRW-Taper tapedev "/media/cdrom0" # Механизм выбора ленты, но в нашем случае это каталог, # куда монтируется CD/DVD-устройство, совпадающий с /etc/fstab rawtapedev "/dev/hdc:0,0,0" # Указывает на реальный файл устройства, в случае # с CDRW-Taper, плюс номер устройства в понимании cdrecord, # т.е. cdrecord -scanbus tapetype DVD # Тип устройства, его описание дается в отдельной # секции файла labelstr "^local[0-9]*$" # Регулярное выражение, соответствующее меткам, которыми # будут помечаться диски/ленты, т.е. в этом случае # возможно 11 меток/дисков вида local, local0 – local9. # Обратите внимание, что в метке не допускаются пробелы, # табуляция и некоторые другие символы diskdir "/var/cache/cdrw-taper " # Каталог, куда будут складываться резервируемые копии файлов disksize 10 GB # Сколько места можно использовать в diskdir, # лучше когда в него помещается вся информация dumpcycle, # тогда резервные файлы можно будет хранить и там, # не удаляя infofile "/var/lib/amanda/DailySet1/curinfo" # База имен файлов logfile "/var/log/amanda/DailySet1/log" # Журналы indexdir "/var/lib/amanda/DailySet1/index" # Индексные файлы # tapetypes # Устройства хранения информации, описывается скорость, # размер блока и объем define tapetype HP-DAT { comment "DAT tape drives" length 1900 mbytes filemark 100 kbytes speed 500 kbytes } # Для DVD в документации ничего не сказано, # я записал так define tapetype DVD { comment "DVD-RW" length 4700 mbytes speed 1385 kbytes } define dumptype always-full { comment "Full dump of this filesystem always" options no-compress priority high dumpcycle 0 maxcycle 0 } define dumptype comp-user-tar { program "GNUTAR" comment "partitions dumped with tar" options compress-fast, index, exclude-list "/etc/amanda/exclude.gtar" priority medium } define dumptype comp-user { comment "Non-root partitions on reasonably fast machines" options compress-fast priority medium } client1 //client1/backupc comp-user-tar amandaserver //windows1/C$ comp-user-tar amandaserver /home comp-user-tar amandaserver /dev/hda5 comp-user-tar //windows1/C$ p@ssw0rd WORKGROUP amandaserver backup amdump client1 backup amindexd amidxtaped amandaserver backup amdump # это для работы клиента на этом же узле localhost backup amdump amanda 10080/udp amandaidx 10082/tcp amidxtape 10083/tcp service amanda { only_from = amandaserver # добавилось в 2.5.1 socket_type = dgram protocol = udp wait = yes user = backup group = backup groups = yes server = /usr/lib/amanda/amandad server_args = -auth=bsd amdump disable = no } service amanda { only_from = client1 client2 amandaserver socket_type = stream protocol = tcp wait = no user = amandabackup group = disk groups = yes server = /usr/lib/amanda/amandad server_args = -auth=bsdtcp amdump amindexd amidxtaped disable = no } # Местонахождение конфигурационных файлов AMANDA $CONFIG_ROOT = "/etc/amanda"; # Каталог, в котором создаются промежуточные файлы: # diskdir в amanda.conf $DUMP_DIR = "/var/cache/cdrw-taper"; # 1 – удалять или 0 – оставлять промежуточные файлы # после записи на CD/DVD-диск $DELETE_DIRS = 0; # При 1 использование не перезаписываемого диска CD/DVD-R $WRITE_NON_ERASABLE = 0; # Устройство CD/DVD-RW # $CD_DEVICE_RE = "/dev/s(cd|g)\\d+:?.*"; # $CD_DEVICE_RE = "^/dev/(ide|scsi)/host\\d/bus\\d/target\\d/lun\\d/(cd|generic):"; $CD_DEVICE_RE = "/dev/hdc"; # Размер блока $BLOCKSIZE = 2048; # Блоков в устройстве # (650MB CDRW: 650 MB = 650 * 1024k / 2k = 332800) #$MEDIABLOCKS = 332800; # (700MB CD-RW: 700 MB = 700 * 1024k / 2k = 358400) $MEDIABLOCKS = 358400; # Blocks per media (DVD+RW: 4700 MB = 4700 * 1000 * 1000 / 2k = 2294921) $MEDIABLOCKS = 2294921; # Названия исполняемых файлов $MOUNT = "mount"; $UMOUNT = "umount"; $CDRECORD = "cdrecord"; $MKISOFS = "mkisofs"; $SENDMAIL = "/usr/sbin/sendmail"; $GROWISOFS = "growisofs"; $DVDRWMEDIAINFO = "dvd+rw-mediainfo"; # Указание, что все загружено успешно 1; $ sudo mkdir /var/cache/cdrw-taper $ sudo chown backup:backup /var/cache/cdrw-taper $ sudo su backup -c "amcheck DailySet1" $ sudo su backup -c " amadmin DailySet1 disklist" $ sudo /usr/sbin/amlabel-cdrw DailySet1 metka $ sudo /usr/sbin/amlabel-cdrw DailySet1 local1 $ sudo su backup -c "amdump DailySet1" $ sudo ls -al /var/cache/cdrw-taper/local1 $ sudo apt-get install dump $ sudo /usr/lib/amanda/taper DailySet1 -flush local1 local2 $ sudo /usr/lib/amanda/taper DailySet1 -flush local local1 $ sudo crontab -u backup -e 0 10 * * 1-5 /usr/sbin/amcheck -m DailySet1 45 0 * * 2-6 /usr/sbin/amdump DailySet1 $ sudo amrecover amandaserver root amindexd amidxtaped localhost root amindexd amidxtaped $ sudo amrecover DailySet1 amrecover> sethost localhost # Выбираем узел, данные с которого собираемся восстанавливать # Записи localhost нет в disklist, но amrecover разобрался amrecover> setdisk /home # Выбираем восстанавливаемый раздел с узла. Если перейти # каталог, занесенный в disklist перед запуском amrecover, # «cd /home», то раздел будет выбран автоматически amrecover> ls # Смотрим, что есть amrecover> add test_file # Добавляем файл в список восстановления, чтобы добавить # все, ставим точку восстанавливаем amrecover> extract amrecover> quit ----------------------------------------------------------------------------------------------------------------- Устанавливаем и обновляем программное обеспечение в системе FreeBSD Гаспар Чилингаров pkg_add /cdrom/packages/All/имя_пакета-версия.tgz ls /cdrom/packages/All/имя_пакета* pkg_add имя_файла pkg_add -rv имя_порта pkg_add -rv apache13 pkg_add -K -rv apache13 pkg_delete имя_пакета pkg_create -b имя_пакета-версия pkg_info -W абсолютное_имя_файла ls /var/db/pkg pkg_info имя_пакета pkg_info xorg-6.9.0 SUP_UPDATE=YES SUP=/usr/bin/csup SUPFLAGS=-g -L 2 -z SUPHOST=cvsup.uk.FreeBSD.org SUPFILE=/usr/share/examples/cvsup/standard-supfile PORTSSUPFILE=/usr/share/examples/cvsup/ports-supfile SUP=/usr/local/bin/cvsup SUP=/usr/bin/csup pkg_add -rv cvsup-without-gui make update pkg_add -rv portupgrade portinstall имя_порта portupgrade имя_порта portupgrade 'имя_порта*' portupgrade 'php5*' portupgrade -R 'имя_порта' make search key=ключевое_слово make search key=licq make -DWITHOUT_X11=YES portsnap fetch; portsnap extract portsnap fetch; portsnap update portsnap update databases/mysql pkg_which имя_файла portsclean portsclean -C portsclean -D portsclean -DD pkg_version pkg_deinstall 'имя_порта' // или pkg_deinstall 'имя_porta*' pkg_deinstall -r имя_порта pkg_deinstall -R имя_порта ----------------------------------------------------------------------------------------------------------------- Unionfs во FreeBSD: разбираемся в текущей реализации Сергей Супрунов # mount_unionfs /usr/home/src/ usr/src # mount -t unionfs -b /usr/home/src /usr/src $ kldstat options UNIONFS #Union filesystem # mount_unionfs /usr/home/cdrom /mnt/cdrom # mount_mfs -s 50m md /tmp/md1 # mount_unionfs /tmp/md1 /usr/ports/www/apache22 # ls -l md1 # ls -l md2 # ls -l md1/subdir # ls -l md2/subdir # mount_unionfs /tmp/md2 /tmp/md1 # ls -l /tmp/md2 # ls -l /tmp/md1 # ls -l md2/subdir # ls -l md1/subdir # rm md2/file1 # ls -l md1 # ls -l md2 # rm md1/file2 # rm md1/file1 # ls -l md1 # vi md1/file5 # ls -l md1 # umount md1 # ls -l md1 # ls -l md2 ----------------------------------------------------------------------------------------------------------------- FreeBSD в домене Windows: дополнительные возможности Рашид Ачилов # make WITH_ADS=yes WITH_LDAP=yes <другие параметры, если необходимо> security = ads realm = domain.ru workgroup = DOMAIN_INC client use spnego = yes [libdefaults] default_realm = DOMAIN.RU dns_lookup_kdc = yes [realms] DOMAIN.RU = { kdc = win-dc.domain.ru kpasswd_server = win-dc.domain.ru admin_server = win-dc.domain.ru } [logging] default = SYSLOG:INFO:LOCAL1 [domain_realm] .domain.ru = DOMAIN.RU domain.ru = DOMAIN.RU # kinit administrator@DOMAIN.RU # klist # net ads join -U administrator -w domain.ru # net ads testjoin ntlm auth = no lanman auth = no include = /usr/local/samba/conf/smb.conf.%U [global] log level = 5 # Description: Описание сервиса, как оно будет отображаться svcctl list = cups apache mysql ssh2 # smbpasswd -a ftp # net sam createlocalgroup moretest # net sam [myshare1] comment = This is a comment path = /var/ftp/pub/quality write list = %D+user1,%D+user2, root [myshare2] comment = More comments were here path = /usr/local/share/assembly write list = @"Group one", @"Group two", root valid users = %D+user1, %D+user2, root, @"Group one", @"Group two", OTHERDOM_AIN+user3 [backup] comment = There are backup shares for each user path = /usr/share/dmbackup/%u force user = oneuser [backup] force create mode = 0666 account required pam_mkhome.so mode=0700 root preexec = csh -c '/usr/local/sbin/checkuserhome %u %D %U' # configure –prefix=/usr/local # make # make single # make double root=DOMAIN_INC+administrator root=DOMAIN_INC+moreadmin root preexec = csh -c '/usr/local/sbin/checkbackdir %u %D %U' # kinit administrator@DOMAIN.RU # kinit administrator@DOMAIN.RU # /usr/bin/kinit administrator@domain.ru # net ads join -U administrator -w domain.ru .domain.ru = DOMAIN.RU domain.ru = DOMAIN.RU # net ads join -U administrator -w domain.ru # net rpc join -U administrator -w DOMAIN_INC ----------------------------------------------------------------------------------------------------------------- Руткиты режима ядра: алгоритмы работы и защита Артем Баранов typedef struct _SERVICE_DESCRIPTOR_TABLE { SYSTEM_SERVICE_TABLE ntoskrnl; SYSTEM_SERVICE_TABLE win32k; SYSTEM_SERVICE_TABLE Table3; SYSTEM_SERVICE_TABLE Table4; } SERVICE_DESCRIPTOR_TABLE, typedef struct _SYSTEM_SERVICE_TABLE { PNTPROC ServiceTable PDWORD CounterTable; DWORD ServiceLimit; PBYTE ArgumentTable; } SYSTEM_SERVICE_TABLE; ----------------------------------------------------------------------------------------------------------------- bugtraq, стр. 89 POST http://SERVER/projectserver/logon/pdsrequest.asp HTTP/1.0 Accept: */* Accept-Language: en-nz Pragma: no-cache Host: SERVER Content-length: 87 Proxy-Connection: Keep-Alive Cookie: PjSessionID= 1 0 0 theuser 0 {SQLServer} ProjectServer SERVER 1 resglobal MSProjectUser <---- sekretpass <---- SERVER\USER -----------------------------------------------------------------------------------------------------------------