Покажи Публикации - PhrozenCrew
* Виж публикациите на потр. | Виж темите на потр. | Виж прикачените файлове на потр
Страници: 1 2 3 [4]
46  Програмиране / Общ форум / Perl irc bot programming -: May 03, 2006, 20:03
Педалите от оня ФТП сървар са спряли тегленето на линковете..Хм ако искате да си изтеглите тутора и скрипта ето ви 2 алтернативни адреса:

http://nediko.centrum-group.com/Program....erl.zip

http://nediko.centrum-group.com/Program.....pl.zip
47  Програмиране / Общ форум / Perl ftp tutorial, static blog site -: May 02, 2006, 21:09
Perl FTP tutorial, static blog site

Свързване с FTP сървар през Perl, създаване на статичен блог сайт

Ето и идеята на програмирането за FTP под Perl. На първо място е необходимо да се регистрирате в някой free сървар за да си получите безплатното интернет пространство. Такива сървари с лопата да ги ринеш в БГ – hit.bg, bol.bg(казват ,че е видим от цял свят), centrum-group.com и още знайни и незнайни. След като вече имате акаунт към някой от фрее сърварите е добре да знаете как да се свържете с него. Ако сте си направили акаунт например към free.techno-link.com и името на акаунта ви е pen4o, а паролата pencho17, тогава значи за да се свържете ще трябва да стартирате някой FTP клиент и данните за връзка ще са:

ftp pen4o.centrum-group.com
user: pen4o
pass: pencho17
Направете си директория tutorials на този адрес и сложете някакви файлове в нея. Например: Perl_FTP_Tutorial.pdf и my_CV.doc

Пиша тези неща за да ми е по лесно по-късно в тутора. Приемам , че вече сте си изтеглили Perl. Аз ползвам Perl 5.6. В тази дистрибуция е включен необходимия ни за работа модул NET::FTP. Да преминем директно към същността. Ще напиша скрипта и ще го коментирам между редовете. Така мисля, че ще ви е по-ясно. Скрипта по долу можете да го напишете в най-обикновен текстов редактор, например Notepad (има го във всички Windows или cat – всички Linux, Unix), и го съхранете като PerlFTP.pl

#!/usr/bin/perl
use Net::FTP; # да заредим модула, който ни трябва

my $host="pen4o.centrum-group.com"; #FTP сървара ви
my $directory="tutorials"; # някоя от директориите

# нека създадем една ftp връзка
$ftp=Net::FTP->new($host,Timeout=>240) or $newerr=1;

  # нека направим семпла проверка за грешки и да изкараме
  # съобщение, ако има такива
  # с push добавяме грешката към масив @ERRORS
  push @ERRORS, "Can't ftp to $host: $!\n" if $newerr;
  # стартиране на подпрограмата за грешки, ако има такива
  myerr() if $newerr;

# ако всичко е нормално
print "Connected\n";

# сега нека да се логнем в сървара
$ftp->login("pen4o","pen4o17") # логваме се с нашите данни
    or $newerr=1; # проверка дали сме логнати

# да изпише съобщение когато се свържем
print "Getting file list";

  # отново да проверим за грешка
  # и да излезем от сървара ако има такава
  push @ERRORS, "Can't login to $host: $!\n" if $newerr;
  $ftp->quit if $newerr;
  myerr() if $newerr;

# ако всичко е нормално
print "Logged in\n";

$ftp->cwd($directory)    # нека да идем директно в директорията,
         # която искахме по-горе – tutorials

    or $newerr=1; # отново да проверим за грешка

 # нека скрипта да ни изпише нещо ако
 # намери грешка в името на директорията или друга
 push @ERRORS, "Can't cd  $!\n" if $newerr;
  myerr() if $newerr;
  # разкачи връзката ако има грешка
  $ftp->quit if $newerr;

# да зададем команда на FTP сървара
# в случая аз си избирам ‘dir’, но може да е всяка
# друга команда която поддържа този FTP сървар
@files=$ftp->dir
   # нова проверка за грешки
   or $newerr=1;
  
  # нека изпечата съобщение за грешката
  # с push добавяме грешката към масив @ERRORS
  push @ERRORS, "Can't get file list $!\n" if $newerr;
  myerr() if $newerr;

# ако всичко е ок нека видим файловете в директорията
print "Got  file list\n";  
foreach(@files) # правим листата с файловете на масив @files
  {
  print "$_\n"; # принтваме на екрана файл по файл
       # със специалната променлива на Perl,
       # която обслужва елементи на масиви
  }
# след като сме изпечатали всичко, което ни е необходимо
# излизаме нормално от сървара
$ftp->quit;

# нека да създадем подпрограмата за грешки,
# за която споменах по-горе
sub myerr {
  print "Error: \n";
  print @ERRORS;
  exit 0;
}

Уххх, че много коментари! Да вземем малко да ги делнем а ?? И да видим как би изглеждал скрипта:

#!/usr/bin/perl
use Net::FTP;
my $host="pen4o.centrum-group.com";
my $directory="tutorials";
$ftp=Net::FTP->new($host,Timeout=>240) or $newerr=1;
  push @ERRORS, "Can't ftp to $host: $!\n" if $newerr;
  myerr() if $newerr;
print "Connected\n";
$ftp->login("pen4o","pen4o17") or $newerr=1;
print "Getting file list";
  push @ERRORS, "Can't login to $host: $!\n" if $newerr;
  $ftp->quit if $newerr;
  myerr() if $newerr;
print "Logged in\n";
$ftp->cwd($directory) or $newerr=1;
 push @ERRORS, "Can't cd  $!\n" if $newerr;
  myerr() if $newerr;
  $ftp->quit if $newerr;
@files=$ftp->dir or $newerr=1;
  push @ERRORS, "Can't get file list $!\n" if $newerr;
  myerr() if $newerr;
print "Got  file list\n";  
foreach(@files) { print "$_\n"; }
$ftp->quit;
sub myerr {
  print "Error: \n";
  print @ERRORS;
  exit 0; }

Мдам, на 28 реда събрахме програмка, която прави всички проверки за грешки и прави някакви мизерии в FTP сървар '<img'>. Аз лично не знам друг език, който толкова елегантно и ясно да направи това. Като се зачетете в кода може наистина да усетите какво означават думите на Larry Wall (създателя на Perl), който казва: “Пърл е като говоримите езици – рационален, простичък и невероятно богат откъм изразни средтва..”.

Нека ви дам една идея. Можете да накарате този скрипт да прави backup на важните ви файлове които сте поставили в някоя директория или по-точно да съхраните данните(файлове, които е добре да бъдат защитени по някакъв начин – например като архиви или PDF-и с парола) в internet пространството. Нека погледнем реда :

@files=$ftp->dir or $newerr=1;

Спокойно можете да използвате не ‘dir’, а някоя друга команда (put, get ...). Да видим как се прави това. Първо е добре да познавате FTP командите които ви позволява вашия сървар. Всички FTP сървари позволяват командата put. Това е команда с която казвате на сървара да качи някой файл от хард диска ви на FTP директорията ви.

Аз заменям:

@files=$ftp->dir or $newerr=1;

със:

$blog = 'C:\blog\index.html'; # ако сте под Windows
$ftp->put($blog)  or $newerr=1;
@files=$ftp->dir or $newerr=1;

Така качихме файл на FTP сървара ни. Ако искате да качите всички файлове от директорията:

 C:\blog

Можете да го направите като замените горните редове така:

for (glob('C:\blog\*.*''<img'>) { # ако сте под Windows
$ftp->put($_);
}
@files=$ftp->dir or $newerr=1;

Използвах папката блог, защото ми дойде на ум, че така можете да си направите собствен статичен блог сайт който да оновявате по много лесен начин '<img'>). Много Хитро, нали. А има блогерски програми, които ви карат да плащата сума левчета за да им ползвате тъпнята, която дoри не знаете какво прави с вашите данни. Да е жива и здрава идеята OpenSource.

Тъй като сайто може да промени символите от кода прилагам тутора като PDF тук:
http://nediko.fortunecity.com/perl/Perl_Net_FTP_tutorial_ned.zip
И целия код с блогерската програмка тук:
http://nediko.centrum-group.com/Program....erl.zip
Не забравяйте да експериментирате. Например добре би било да изтривате качените файлове за да не ги чакатe да се качат отново и да не ви объркват.  Файловете с Perl се изтриват с командата unlink. Пример:

unlink "index.html";

Можете да замените еденичните кавички с двойни, но тогава внимавайте с шпациите в файловете. Ще трябва да използвате двойно наклонени черти. Пример:


for (glob("C:\\blog\\*.*")) { # ако сте под Windows
$ftp->put($_);
}
@files=$ftp->dir or $newerr=1;

Айде стига толква. Perl е толкова лесен и необятен, че човек като почне да пише за него и няма спирачки. Дано ви хареса тутора. В следващия тутор може да закачим и малко сериозното програмиране с Perl, макар, че с тоя език няма сериозност, всичко става като на майтап. Все пак не се заблуждавайте, всички C unix/linux гурота ползват доволно Perl като алтернативен език.

ПС: Не забравяйте да смените сървара с вашия и да си попълните всички ваши данни. Скриптовете са тествани и работят с:
perl, v5.6.1 built for MSWin32-x86-multi-thread
Видях, че има проблеми с копирането на кавичките в PDF-a, заменете ги ръчно с кавички под английска клавиатура.
48  Програмиране / Общ форум / Perl irc bot programming -: May 01, 2006, 19:59
Прост Perl IRC бот

Програмиране на семпъл IRC робот, който да се свързва с IRC сървар и след това да влиза в канал по Ваш избор.

В този туториал ще се опитам в лесни стъпки да ви покажа как можете да се свържете с IRC сървар, да влезете в някой канал и да манипулирате в него. Думата бот, която често се използва в IRC, всъщност е съкращение на робот. IRC ботовете могат да имат много предназначения – съхраняват информация (логинг), следят за чистотата на канала (административни ботове), ботове за игри, бойни ботове (с цел завземане на чужди канали, флоодинг, нюкинг, порт-сканинг...). В този туториал е невъзможно да се обобщят всички приложения на IRC ботовете, а и нашата цел днес не е такава.

Много хора мислят, че Perl е най-добрия език за писане на IRC ботове, тъй като една от най-силните му страни е перфектната поддръжка на регулярни изрази и лесната обработка на големи обеми текст. Съществува още един много разпространен език за писане на ботове – TCL. Като възможности TCL доста отстъпва пред Perl, но се е наложил поради първоначалния замисъл на езика – създаване на теоретични модели на физични процеси. Всъщност един IRC бот може да бъде написан почти на всички съществуващи езици, които поддържат работа с сокети, но нека не се отклоняваме от темата.
 За да създадем нашия прост робот трябва да сте наясно, че IRC RFC изисква всяка команда или съобщение да завършва “return” и нов ред (ето така \r\n), а също трябва да отговаря адекватно на PING съобщението на сървара!

Стартиране на нашия IRC робот
 Просто извикайте скрипта без никакви аргументи, ето така:
   % perl irc.pl

Резултат

В резултат на стартирането трябва да видите нещо от сорта:

:irc.del.bg 005 simple_r WALLCHOPS KNOCK EXCEPTS INVEX MODES=4 MAXCHANNELS=15 MAXBANS=120 MAXTARGETS=4 NICKLEN=15 TOPICLEN=150 KICKLEN=150 :are supported by this server
:irc.del.bg 005 simple_r CHANTYPES=#& PREFIX=(ohv)@%+ CHANMODES=eIb,k,l,imnpsta NETWORK=ShakeIT CASEMAPPING=rfc1459 CALLERID :are supported by this server
:irc.del.bg 251 simple_r :There are 5 users and 2350 invisible on 27 servers
:irc.del.bg 252 simple_r 56 :IRC Operators online
:irc.del.bg 254 simple_r 2622 :channels formed
:irc.del.bg 255 simple_r :I have 576 clients and 1 servers
:irc.del.bg 265 simple_r :Current local  users: 576  Max: 1398
:irc.del.bg 266 simple_r :Current global users: 2355  Max: 4883
:irc.del.bg 250 simple_r :Highest connection count: 1399 (1398 clients) (431982 connections received)
...
:irc.del.bg 372 simple_r :-  Priaten chat vi jelae equipat na Davidov Net! ;-)
...

Това може да изглежда малко объркващо отначало, но ако разгледате отговора на сървара линия по линия ще ви стане по-ясно. Накратко – сървара отговаря, че ви е разпознал като клиент и е готов за работа.
Ако желаете може спокойно да използвате регулярните изрази за да филтрирате цялата тази информация и да покажете само това което ви интересува.

А сега нека да напишем робота

За да пишете Perl програми ви е напълно достатъчен и най-простия текстови редактор, който имате (ed - unix, cat - *x, notepad – win...). Ще съхраним нашия робот с разширението .pl. За да ми е по-лесно ще изпиша целия код и ще го коментирам между редовете.

#!/usr/local/bin/perl -w
# irc.pl
# Простичък IRC robot.
# Стартиране: perl irc.pl

use strict;

# Ще използваме сокет за да се свържем с IRC.
# Модулът по-долу би трябвало да присъства
# по подразбиране във вашата Perl дистрибуция
use IO::Socket;

# Сървар за връзка и нашите данни.
my $server = "irc.del.bg";   # любимия ви сървар
my $nick = "simple_r";   #  прякор с който желате да влезете
my $login = "ne6to_si";

#  Канал в който искате да влезе бота.
my $channel = "#sladur";

# Свързване с IRC сървара.
my $sock = new IO::Socket::INET(PeerAddr => $server,
                                PeerPort => 6667,
                                Proto => 'tcp''<img'> or
                                    die "Can't connect\n";

# Логване в сървара.
print $sock "NICK $nick\r\n";
print $sock "USER $login 8 * :Perl IRC Hacks Robot\r\n";

# Изчитане на редовете гот сървара,
# докато не ни каже, че сме се свързали.
while (my $input = <$sock>) {
        if ($input =~ /^PING(.*)$/i) {
            print $sock "PONG $1\r\n";
            #сървара обича да ни проверява с ping, затова му отговаряме
        }
    # Проверка на числовия отговор от сървара.
    if ($input =~ /004/) {
        # Сега вече сме логнати.
        last;
    }
    elsif ($input =~ /433/) {
        die "Nickname is already in use.";
    }
}

# Свързване с канал.
print $sock "JOIN $channel\r\n";

# Продължаваме да четем редовете от сървара.
while (my $input = <$sock>) {
    chop $input;
    if ($input =~ /^PING(.*)$/i) {
        # Трябва да отговоряме на PING-а за да не ни изхвърли.
        print $sock "PONG $1\r\n";
    }
    else {
        # Принтване на съобщенията от канала.
        print "$input\n";
    }
}

Надграждане на бота

След като имаме базовия бот, който се свързва с някой канал, вече можем да градим върху този бот по-голяма функционалност. Погледнете редa:

        # Принтване на съобщенията от канала.
        print "$input\n";

Този ред е онова което можем да разработим колкото си искаме. Например можем да накараме съобщенията от канала да се логват в някой текстови файл, който по-късно да разгледаме за интересни уеб адреси. Ето как:
Заместваме реда:

print "$input\n";

със

#----------------часта която ще замени реда
# създаваме файл в който логваме съобщенията
open (LOG, ">>$channel.log");
# >> означава, че файла ще се допълва
# и няма да се изгуби предишната информация в него

# филтрираме леко информацията
# с регулярен израз
$input =~ s/!.*PRIVMSG $channel :/:  /i;
# s/нещо-което-искаме-да-заменим/с-това/
# i-то накрая е за да укажем, че е без значение м. и гол. букви

#принтираме съобщенията от канала в този файл
print LOG "$input\n";

#затваряме файла
close LOG;
#-----------------край

Изчакайте малко и отворете файла, който се намира в директорията на скрипта channel.log. Когато вмъквате тези редове на конзолния ви прозорец няма да се показват никакви съобщения, тъй като принтваме директно във файл. Колко готино и лесно го прави Perl, нали '<img'>.  От тук нататък можем да накараме файла, който се логва да бъде HTML, но сега ме мързи да пиша. Все пак има много простичък начин да логваме директно в някоя статична уеб страничка с NET::FTP модула. Може би ще напиша скоро и за него едно семпло туторче.


Заключение

За да напишете подобен бот Perl ще ви предложи много начини. Философията на езика е, че “има повече от един начин за да направиш това...”. Можете да използвате доста модули подходящи за писане на IRC ботове. Някои от тях са NET::IRC и POE.
Тъй като сайта трие някои символи качвам тутора като PDF тук:
http://nediko.fortunecity.com/perl/Prost_IRC_bot_pod_Perl.zip
Целия скрипт можете да си свалите от тук:
http://nediko.fortunecity.com/perl/irc.pl.zip
Тествано с:
perl, v5.6.1 built for MSWin32-x86-multi-thread
Не забравяйте да смените сървара, ника, канала и там каквото си искате!
Спокойно можете да изтриете всички линии, които започват с # - знака за коментар. Може би така ще видите простотата в цял вид. Ето така:

use strict;
use IO::Socket;
my $server = "irc.del.bg";
my $nick = "simple_r";
my $login = "ne6to_si";
my $channel = "#sladur";
my $sock = new IO::Socket::INET(PeerAddr => $server,
                                PeerPort => 6667,
                                Proto => 'tcp''<img'> or
                                    die "Can't connect\n";
print $sock "NICK $nick\r\n";
print $sock "USER $login 8 * :Perl IRC Hacks Robot\r\n";
while (my $input = <$sock>) {

    if ($input =~ /^PING(.*)$/i) {
            print $sock "PONG $1\r\n";
        }

    if ($input =~ /004/) {
        last;
    }
    elsif ($input =~ /433/) {
        die "Nickname is already in use.";
    }
}
print $sock "JOIN $channel\r\n";
while (my $input = <$sock>) {
    chop $input;
    if ($input =~ /^PING(.*)$/i) {
        print $sock "PONG $1\r\n";
    }
    else {
   open (LOG, ">>$channel.log");
   $input =~ s/!.*PRIVMSG $channel :/:\t  /i;
   print LOG "$input\n";
   close LOG;
    }
}

редакцията по-долу от 24.08.06


Разбира се бихте могли да направите и друг бот, примерно инфо-бот, който да информира посетителите на канала ви за някоя irc команда (а защо не и linux-команда). В този случай бота би изглеждал така ако е писан за unibg.org, не че има значение от мрежата де:


use strict;
use IO::Socket;
my $server = "irc.techno-link.com";
my $nick = "sim_perl_b0t";
my $login = "lapaiks";
my $channel = "#help";
my $sock = new IO::Socket::INET(PeerAddr => $server,
                                PeerPort => 6667,
                                Proto => 'tcp''<img'> or
                                    die "Can't connect\n";
print $sock "NICK $nick\r\n";
print $sock "USER $login 8 * :Perl IRC Hacks Robot\r\n";
while (my $input = <$sock>) {
        if ($input =~ /^PING(.*)$/i) {
            print $sock "PONG $1\r\n";
        }
    if ($input =~ /004/) {
        last;
    }
    elsif ($input =~ /433/) {
        die "Nickname is already in use.";
    }
}
print $sock "JOIN $channel\r\n";
while (my $input = <$sock>) {
    chop $input;
    if ($input =~ /^(.*)$/i) {
        print $input;
    }

    if ($input =~ /^PING(.*)$/i) {
        print $sock "PONG $1\r\n";
    }
##### tuk ve4e moje da se omajete zdrawo, kwoto vi e kef
   #registrirane na nick
    if ($input =~ /^.*!bot regnick(.*)$/i) {
        print $sock ("PRIVMSG $channel :./msg ns reg <parola> <postoianna_parola>\r\n");
    }
    
       #registrirane na chan
    if ($input =~ /^.*!bot regchan(.*)$/i) {
        print $sock ("PRIVMSG $channel :./msg cs reg #chan pass1 pass2\r\n");
    }
    
       #gledane za posledni nicks ot IP
    if ($input =~ /^.*!bot nicksIP(.*)$/i) {
        print $sock ("PRIVMSG $channel :./msg seen seen *\@ip d5\r\n");
    }
    
       #ghost  
    if ($input =~ /^.*!bot ghost(.*)$/i) {
        print $sock ("PRIVMSG $channel :./msg ns ghost nick parola\r\n");
    }
    
    
    if ($input =~ /^.*!bot superop(.*)$/i) {
        print $sock ("PRIVMSG $channel :./msg cs set \$kanal Secureops on/off\r\n");
    }

    if ($input =~ /^.*!bot наздраве(.*)$/i) {
        print $sock ("PRIVMSG $channel :Наздраве, да го еба..\r\n");
    }
    if ($input =~ /^.*bot ща шибам(.*)$/i) {
        print $sock ("PRIVMSG $channel :Що бе'<img'> Майка ти спря ли да ти дава?!\r\n");
    }
    if ($input =~ /^.*kak da.*(.*)$/i) {
        print $sock ("PRIVMSG $channel :Pi4 ia pitai google.com : HowTo se precakam... am ako moje da mi wleze do iaia-ta! Ebavam se estestweno.. sa 6e izmislim ne6to, trai\r\n");
    }
      
#### do tuk    
    else {
        # Print the raw line received by the bot.
        print "$input\n";
    }
}

##############################
Знам, че може да се отнесе кода когато се публикува в интернет, затова ето ви и адресче на тоя инфобот само за БГ:
http://nediko.centrum-group.com/Program...._Bot.pl

Приятно кодиране '<img'>!

ПС: За тутора съм ползвал и чужди идеи, но убийте ме не знам точно от къде съм си свалял скриптовете.
Недялко Войняговски
Пловдив
01.05.06



49  Linux секция за начинаещи / Настройка на програми / IRC -: Oct 21, 2005, 20:03
Мдам ... благодарен... ще черпиш казваш... хмм.. ще ти дам идея - не се назландисвай на UniBG и сие - там няма канал дето  да има свястен админ и да не те изхвърлят ако питаш най-елементарни неща.. Например аз вчера попитах "Абе хора как да си заредя Proxy IP-тата под FreeBSD на програмката BitchX, че не ми се четат ман-ове за IRC"... тотално напъждане'<img'>
После пробвеах със същия въпрос на кирилица в UnderNet #bsd и некво копеленце от Испания - българ4е (естествено) се зариби да ми отговаря... Пробвах му инструкциите и се намъкнах с 10-15 IP-та в irc.techno-link.com.. Идеята е, че май тия дето са извън БГ са мноо по-зарибени да ти помогнат от колкота тукашните надъхани гомненца.. Жив и здрав... Пътеките са тесни ам не се отказвай '<img'>
50  Linux секция за начинаещи / Настройка на програми / net -: Oct 20, 2005, 20:03
По-горе съм писал на шльокавица и наистина съжалявам... едва ли може да се напи6е и разчете свястно името Йордан Йовков или Ясен Атанасов (дори '<img'>... Искам да кажа, че много сажалявам за смотания пост. Както и да е , до сега се карах с майка ми къде трябва да слагам пълния член на думите и интересно, 4е дори тя дне знаеше за тарикатлъка със непрякото допълнение(той, тя, то)... ще дам лесен пример: "Магазин@ се отваря от магазинер@" ... заместете правилно пълния член '<img'>)). Другия път ще ви пи6а къде е шльокавицата... А сега за хакането на Win NTFS и сие - Austrumi имат още по добра версия на Линукса си ... и друго - много тарикатски са ре6или проблема за зяпането на филми със слаб процесор, моя процесор на дома6ната ми машина (PC-то, не ноутбука) е на 630 Мхц обаче няма и да се замисля да инсталирам и един декодек под тъпия ми Winblows98... Филмите си кесат с перфектно качество... Пак се омазах за free LiveCD-тата.. бтв: QNX имат перфектно лайв СД, и с него също може6 да кърти6 паролки на Win Админа, стига да зареди6 модула '<img'>))
51  Linux секция за начинаещи / Настройка на програми / net -: Aug 22, 2005, 20:24
Pi4agata deto ti gowori za AUSTRUMI ne se ebava, probwaj go , trqbwa da stane s nego, dori i priqtek4eto ti da polzwa Linux '<img'>)... ako ne stane s towa probwaj Slax - kato root (pass: toor) pri men wyr6i rabota da krakwam parolki... ako ne6to ne ti e iasno pi6i, no mislq , 4e 6te se oprawi6. Lin distrotata niamat granici, osobeno LiveCD-tata, te se praviat za takiwa kato teb ot nai-pe4enite, za da te wpe4atliawat, a towa , 4e si pod Mandrake niakoj moje da kaje , 4e ne e got, am ne mu obry6tai vnimanie, kernela si e 2.6.x... taka, 4e ti si ot onia deto minawat i prez tesni vrati - derzai. Sled vreme probwaj i Unix - istinata '<img'>)). Ako se zaribi6 po Unix - ima live CD-ta i na BSD, a ot skoro i na ... 6te se 4ue '<img'>
Страници: 1 2 3 [4]