|
||||||
Практические примеры программирования cgi-скриптов на Perl: работа с файлами и каталогами.
Работа с файлами и каталогами.Чтение и запись файлов и каталогов является едва ли не главным достоинством Perl. Практически любой Perl-скрипт использует либо запись в файлы,либо поиск определенных строк в файле,либо запись или загрузку файлов в каталоги. Кратко напомню основные положения: Файл можно открывать для чтения,записи,добавления либо поиска определенных строк. Где FILE-это дескриптор или описатель файла,т.е. имя,под которым он фигурирует в программе.Может быть любым набом символов,рекомендуется набирать прописными буквами во избежание неоднозначностей. $file-переменная для файла,содержит обычно имя файла и путь к нему.Предпочтительно объявить эту переменную в начале скрипта.Это удобно,если файл находится где-то глубоко в подкаталогах,к примеру,неудобно все время набирать /usr/local/htdocs/main/pages/file.html. Думаю,с этим особых вопросов не возникнет.Еще нужно отметить,что содержимое файла можно читать построчно или в массив: #!/usr/local/bin/perl open (STAT,"$file");#Прочесть одну строку из файла. $count= Что касается каталога,то его тоже можно открывать для чтения командой readdir.Для того,чтобы понять как все это происходит,рассмотрим практические примеры.
Пример 1.Рассмотрим сценарий регистрации пользователя на веб-сервере.Имя пользователя и его пароль записываются в текстовый файл и используются для его последующей аутентификации. #!/usr/local/bin/perl #Объявляем глобальные переменные. $request=$ENV{'REQUEST_METHOD'}; $content=$ENV{'CONTENT_LENGTH'}; $basedir="http://www.mydomain.com/~"; $userdir="f:/home"; #Подпрограммы для декодирования данных из формы. sub urldecode { local($val)=@_; $val=~ s/\+/ /g; $val=~ s/%[0-9a-hA-H] {2}/pack('C',hex($1))/ge; return $val; } sub strhtml { local($val)=@_; $val=~s//>/g; $val=~s/(http:\/\/\+S)/<A href="$1">$1<\/A>/g; return $val; } ###################################################################### if ($request eq 'GET') { $query=$ENV{'QUERY_STRING'}; } else { sysread(STDIN,$query,$content); } #Генерируем форму,если никакие данные не введены. print "Content-type:text/html\n\n"; print <<HTML_gen; <HTML><BODY bgcolor="e6e8fa"> HTML_gen if ($query eq '') { print <<HTML; <h2 align=center><font color="ff0000">Registration.</font></h2> <p><font face="serif" size=2> Please,fill in the form below. <p>After registration you will receive your personal directory and unique URL.Fill all fields carefully. Form fields marked as <font color="ff0000">*</font>are required.</font> <p><FORM ACTION="../cgi-bin/addlogin.cgi" METHOD="POST" name="reg"> <center><TABLE BGCOLOR="bfbfbf"> <TR><td><font color="ff0000">*</font> <TD><b>Login:</b><TD><INPUT TYPE="text" NAME="login" SIZE="20"> <TR><td><font color="ff0000">*</font> <TD><b>Password:</b> <TD><INPUT TYPE="password" NAME="pass" SIZE="20"> <TR><td><font color="ff0000">*</font><TD><b>E-mail:</b> <TD><INPUT TYPE="text" NAME="email" SIZE="20"> <TR><TD colspan=3><p><center> <INPUT TYPE="submit" VALUE="Submit"></center> </TABLE></center> </FORM> HTML #Декодируем поля формы else { foreach (@fields=split(/&/,$query)) { if (/^login=(.*)/) { $login=&urldecode ($1); } if (/^pass=(.*)/) { $password=&urldecode ($1); } if (/^email=(.*)/) { $email=&urldecode ($1); } } #Проверяем,не существует ли данное имя в системе. open(INFO,"login.txt") ||die; @data=<INFO>;#Читаем строки в массив. close(INFO); foreach $string(@data) { @item=split(/&/,$string);#Разбиваем строку на части. foreach (@item) { if ($item[0] eq $login) { #Сравниваем полученное имя с первым полем файла #для каждой строки и если такое найдено выдаем #ошибку. print <<HTML; <h2 align=center><font color="ff0000">Error!</font></h2> <p><center><b>The name <font color="ff0000">$login</font> already exists in the system. <p>Please,go back and choose another name.</b> <p><form><input type="button" value="Back" onClick="history.back()"></form> </center> HTML exit; } } } #Если имя не найдено,открываем базу данных и добавляем информацию. if ($item[0] ne $login) { open(DATA,">>login.txt"); $string=join('&',$login,$password,$email,scalar localtime,$ENV {'REMOTE_ADDR'}; print DATA "$string\n"; close(DATA); #Создаем домашний каталог пользователя и переходим в него. mkdir("$userdir/$login",0700); chdir("$userdir/login"); opendir(USER,"$userdir/$login"); #Помещаем файл index.html в каталог пользователя. open(IN,">$userdir/$login/index.html"); print IN "This is the test!\n"; close(IN); closedir(USER); #Содержание файла может быть любым,это только для примера. #Генерируем ответ пользователю. print <<HTML; <p><h1 align=center><font color="ff0000">Congratulations!</font></h1> <p><b>Your registration was successful and your data were added to our database.Thank you for your time.</b> <p><center><b><font color="ff0000"> You entered:</font>(print this page and keep it in safe place)</b> <p><table> <tr><td><b>Your login name:</b><td><font color="0000ff">$login</font> <tr><td><b>Your password:</b><td><font color="0000ff">$password</font> <tr><td><b>Your e-mail address:</b><td><font color="0000ff">$email</font> </table></center> HTML } } Скрипт выдает ответ в виде html-страницы,содержащей всю информацию,введенную пользователем.
Пример 2.Рассмотрим пример открытия и чтения каталога и вывод списка файлов,содержащихся в нем.Начало скрипта можно взять из предыдущего примера.Предположим,что пользователь,зарегистрированный на веб-сервере,хочет войти в свой домашний каталог. #!/usr/local/bin/perl #Объявляем глобальные переменные. $request=$ENV{'REQUEST_METHOD'}; $content=$ENV{'CONTENT_LENGTH'}; $basedir="http://www.mydomain.com/~"; $file="login.txt"; $url="http://www.mydomain.com"; $dir="f:/home/"; $cgi="f:/usr/local/apache/cgi-bin"; #Подпрограммы для декодирования данных из формы. sub urldecode { local($val)=@_; $val=~ s/\+/ /g; $val=~ s/%[0-9a-hA-H] {2}/pack('C',hex($1))/ge; return $val; } sub strhtml { local($val)=@_; $val=~s//>/g; $val=~s/(http:\/\/\+S)/<A href="$1">$1<\/A>/g; return $val; } ###################################################################### if ($request eq 'GET') { $query=$ENV{'QUERY_STRING'}; } else { sysread(STDIN,$query,$content); } #Генерируем форму,если никакие данные не введены. print "Content-type:text/html\n\n"; print <<HTML_gen; <HTML><BODY bgcolor="e6e8fa"> HTML_gen if ($query eq '') { print "Content-type:text/html\n\n"; print <<HTML; <HTML><HEAD> </HEAD><BODY bgcolor="e6e8fa"> <FORM ACTION="../cgi-bin/fileman.cgi" name="form1" METHOD="POST"> <h2 align=center><font color="ff0000">System login.</font></h2> <p><center>Please,enter your login name and password: <p><TABLE BGCOLOR="cccccc"> <tr><td colspan=2 align=center bgcolor="99cccc"><b><font color="ff0000"> I am registered user</font></b> <TR><TD><p><b>Login:</b><TD><INPUT TYPE="text" NAME="login" SIZE="20"> <TR><TD><p><b>Password:</b><TD><INPUT TYPE="password" NAME="pass" SIZE="20"> <tr><td colspan=2 align=center><input type=submit value="Submit"></center> HTML } #Если информация получена,декодируем поля формы. else { foreach (@fields=split(/&/,$query)) { if (/^login=(.*)/) { $login=&urldecode ($1); } if (/^pass=(.*)/) { $password=&urldecode ($1); } } #Открываем базу данных и проверяем логин и пароль. open(INFO,$file) ||die; @data= Надеюсь,я объяснил все достаточно подробно.Я выбрал намеренно сложные примеры,чтобы показать все операции,которые можно производить с файлами и каталогами.Файлы еще можно загружать на сервер через веб.Этому посвящен следующий раздел. Загрузка файлов на сервер через Интернет.
Файлы можно загружать на веб-сервер через Интернет,используя формы.Вы,наверное,сами не раз это делали.Разберем более подробно,как это делается. Нужно создать форму с полем типа file и методом кодировки multipart/form-data.
#!/usr/local/bin/perl print "Content-type:text/html\n\n"; print <<HTML; <html><head> <script language="javascript"> <!-- function fill () { if (fn==document.form.entry.value) { document.form.file.value=fn; } } //--> </script> </head> <body bgcolor="e6e8fa"> HTML print "<p><table width=300 bgcolor=\"bfbfbf\">\n"; print "<h3 align=center><font color=\"0000ff\">File upload:</font></h3>\n"; print "<center><FORM action=\"../cgi-bin/upload.cgi\" name=\"form\" METHOD=\"POST\" ENCTYPE=\"multipart/form-data\">\n"; print "<tr><td align=center><b>Select file:</b></td>\n"; print "<tr><td><input type=\"file\" name=\"entry\" onBlur=\"fill()\"></td>\n"; print "<tr><td><input type=\"hidden\" name=\"file\" value=\"1\"></td>\n"; print "<tr><td align=center><input type=\"Submit\" value=\"Upload\"></td></table>\n"; print "</form></center></table></body></html>\n"; Функция Javascript использована для того,чтобы передать на сервер имя загружаемого файла, включая полный путь.Далее,скрипт декодирует его,отбросит путь и загрузит файл под его именем. Функцию для декодирования в этом случае я использую готовую,нашел в Интернете,за что большое спасибо ее разработчику. $content_type = $ENV{'CONTENT_TYPE'}; binmode STDIN; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); if ((!$content_type) || ($content_type =~ m#^multipart/form-data#)){ ($boundary = $content_type) =~ s/^.*boundary=(.*)$/\1/; @pairs = split(/--$boundary/, $buffer); @pairs = splice(@pairs,1,$#pairs-1); for $part (@pairs) { ($dump,$fline,$value) = split(/\r\n/,$part,3); next if $fline =~ /filename=\"\"/; $fline =~ s/^Content-Disposition: form-data; //; (@columns) = split(/;\s+/, $fline); ($name = $columns[0]) =~ s/^name="([^"]+)"$/\1/g; if ($#columns > 0) { if ($value =~ /^Content-Type:/) { ($dump,$dump,$value) = split(/\r\n/,$value,3); } else {($dump,$value) = split(/\r\n/,$value,2);}} else {($dump,$value) = split(/\r\n/,$value,2); if (grep(/^$name$/, keys(%CGI))) { if (@{$FORM{$name}} > 0) { push(@{$FORM{$name}}, $value);} else { $arrvalue = $FORM{$name}; undef $FORM{$name}; $FORM{$name}[0] = $arrvalue; push(@{$FORM{$name}}, $value);}} else { next if $value =~ /^\s*$/; $FORM{$name} = $value;} next;} $FORM{$name} = $value;}} Как видите,довольно сложная и громоздкая,зато загрузка проходит без проблем.Далее нужно получить имя файла и отбросить путь,оставив только имя. $upfile=$FORM {'entry'}; #Имя загружаемого файла. $destfile=$FORM {'file'}; #Имя,под которым он будет записан в каталог назначения. $destdir="/home/upload"; #Имя каталога для загрузки. chdir ("$destdir"); #Отбрасываем путь,оставляя только имя. $destfile=~s/\w+//; $destfile=~s/([^\/\\]+)$//; $destfile=$1; #Далее записываем файл в каталог назначения. open(FILE, ">$destdir/$destfile"); #Открываем на запись новый файл. binmode FILE; #Устанавливаем бинарный режим. print FILE $upfile; #Записываем в него содержимое загруженного файла. close(FILE); #Закрываем файл. Все,загрузка завершена.Таким способом можно загружать сразу несколько файлов-5 или 10,создав для каждого элемент формы и,само собой,добавив в скрипте нужное количество обработчиков.
|
||||||
|