Tecnologias Web 2010/11



Documentos relacionados
CGI Common Gateway Interface. É um standard para transmitir dados entre um servidor web e uma aplicação externa

Internet e protocolos web. A Internet é uma rede descentralizada de recursos computacionais. Topologia tem de fornecer caminhos alternativos

Programação para Internet I

Programação para Internet I. 2. O protocolo HTTP. Nuno Miguel Gil Fonseca nuno.fonseca@estgoh.ipc.pt

COMO FUNCIONA UM FORMULÁRIO

Mais sobre uso de formulários Site sem Ajax

3 SERVIÇOS IP. 3.1 Serviços IP e alguns aspectos de segurança

1.264 Lição 11. Fundamentos da Web

INTRODUÇÃO AO DESENVOLVIMENTO WEB

PHP. Hypertext Pre-Processor


Impressão do Manual do Utilizador

Programação para Internet I

Conteúdo Dinâmico. Introdução. Interação Browser x Servidor Web. Interação Browser x Servidor Web

Universidade Federal do Espírito Santo CCA UFES. Centro de Ciências Agrárias CCA UFES Departamento de Computação. Programação WEB

MANUAL DO UTILIZADOR DE REDE

COLIBRI Ambiente Colaborativo Multimédia MÓDULO MOODLE. Rui Ribeiro FCCN - Dezembro 2010

Escola Superior de Tecnologia de Setúbal. Projecto Final

Web. Até a década de 1990, a Internet era utilizada. por pesquisadores, acadêmicos e universitários, para troca de arquivos e para correio eletrônico.

Programação Web Prof. Wladimir


7. Formulários em XHTML

Java Mail Server. Manual do Utilizador

Ajax Asynchronous JavaScript and Xml

Manual de Utilizador. Disciplina de Projecto de Sistemas Industriais. Escola Superior de Tecnologia. Instituto Politécnico de Castelo Branco

O código acima descreve o formulário com uma caixa de texto e dois botões

PACWEB Módulo de Pesquisa MANUAL DO UTILIZADOR

Um sistema SMS 1 simplificado

PHP (Seções, Cookies e Banco de Dados)

O que é o JavaScript?

Programação web Prof. Wladimir

MANUAL DE CONFIGURAÇÃO -ZIMBRA- Ajuda na configuração e utilização do cliente de correio eletrónico

Desenvolvimento de uma Aplicação WEB para monitorização de BD Oracle

Forms Authentication em ASP.NET

O protocolo HTTP. O que é o protocolo HTTP?

Aplicação Prática de Lua para Web

PHP: Cookies e Sessões

Os componentes de um formulário são: Form, Input, Select e AreaText

Ajax Asynchronous JavaScript and Xml

Introdução. História. Como funciona

Linguagem de Programação III Aula 2 Revisão Parte II

Cookies. Krishna Tateneni Jost Schenck Tradução: José Pires

Desenvolvimento de Aplicações Web. Prof. José Eduardo A. de O. Teixeira / j.edu@vqv.com.br

Programação Orientada a Objetos com PHP & MySQL Cookies e Sessões. Prof. MSc. Hugo Souza

EMULADOR 3270 VIA WEB BROWSER

P S I 2. º A N O F 5 M E S T R E / D E T A L H E E P E S Q U I S A. Criar uma relação mestre-detalhe. Pesquisa de informação

2.3. PHP Tipos de dados e operadores

Acronis Servidor de Licença. Manual do Utilizador

Comunicação entre Processos

Ferramentas para Multimídia e Internet

Guia de Instalação do "Google Cloud Print"

Agentes Inteligentes segundo o Chimera

Formador: Paulo Ramos IGRI13: Rui Bárcia Nº15. Windows 2008 Server. Módulo 16. Instalação e configuração

1.1 Porque um nível de aplicação proxy?

CONFIGURAÇÃO DO ACESSO REMOTO PARA HS-DHXX93 E HS-DHXX96

LAB08 Protocolo HTTP Servidor Apache


O sistema está pedindo que eu faça meu login novamente e diz que minha sessão expirou. O que isso significa?

World Wide Web e Aplicações

ZS Rest. Manual Avançado. Ementas : e SMS. v2011

JSP trata-se de uma tecnologia que possibilita o desenvolvimento de páginas web dinâmicas utilizando todas as potencialidades do Java como linguagem

INTRODUÇÃO: 1 - Conectando na sua conta

O Manual do Desktop Sharing. Brad Hards Tradução: Pedro Morais

Programação WEB II. Sessions e Cookies. progweb2@thiagomiranda.net. Thiago Miranda dos Santos Souza

Entendendo como funciona o NAT

Lista de Erros Discador Dial-Up

Editor Eclipse para Programas F

Módulo 3936 ASP.NET. Financiado pelo FSE

TUTORIAL: MANTENDO O BANCO DE DADOS DE SEU SITE DENTRO DO DOMÍNIO DA USP USANDO O SSH!

Introdução. HyperText Markup Language HTML. Formulário. Fluxo do Formulário. Fluxo do Formulário. Fluxo do Formulário. Fluxo do Formulário

WEBDESIGN. Professor: Paulo Trentin Escola CDI de Videira

Mini-curso de PHP. Aulas ministradas por: André Luis de Paula Arthur Kalsing Diego Silva


Manual de Administração Intranet BNI

PROGRAMAÇÃO WEB DO LADO DO CLIENTE

A autoria - II. A autoria - II. Tecnologias básicas da Web. A autoria - II Wilson de Pádua Paula Filho. Tópicos:

INSTALANDO E CONFIGURANDO O MY SQL

Internet Update de PaintManager TM. Manual de instalação e utilização do programa de actualização

ENHANCED SERVER FAULT- TOLERANCE FOR IMPROVED USER EXPERIENCE. André Esteves nº3412 David Monteiro

J820. Testes de interface Web com. HttpUnit. argonavis.com.br. Helder da Rocha

Conceitos de Ajax Exemplos de uso do Ajax no braço, muitos exemplos, muito código (HTML, CSS, JavaScript, PHP, XML, JSON)

Sistema de impressão da Divisão de Informática

Conteúdo Programático de PHP

SAFT para siscom. Manual do Utilizador. Data última versão: Versão: Data criação:

Comunicação de Dados de Autenticação e Credenciais de Acesso para Resposta ao Inquérito

4.1. TRABALHAR COM O CALENDÁRIO

Linux - Servidor de Redes

AULA APLICAÇÕES PARA WEB SESSÕES E LOGIN E SENHA

Organizar a estrutura do site

Os objetivos indicados aplicam-se a duas linguagens de programação: C e PHP

EAmb V.1 ESPOSENDE AMBIENTE. GestProcessos Online. Manual do Utilizador

Transcrição:

Tecnologias Web 2010/11 Comon Gateway Interface (CGI) Departamento de Ciência de Computadores Faculdade de Ciências da Universidade do Porto Rui Prior CGI 1

CGI O que é? Common Gateway Interface Interface standard para a execução de programas via web (server-side scripts) RFC 3875 Define aspectos como Directório em que o script é executado Variáveis de ambiente Tratamento dos descritores de ficheiro standard Etc. Não necessariamente em Perl Módulo CGI.pm simplifica o desenvolvimento CGI 2

CGI Como funciona? O servidor web recebe um pedido HTTP com URL que identifica como recurso dinâmico gerado por CGI E.g., através da extensão ".cgi" ou por estar no directório cgi-bin O servidor lança um novo processo para executar o programa CGI Se for um executável nativo é corrido normalmente Se for um script é corrido o interpretador da linguagem respectiva Se for bytecode Java é corrida a JVM Os parâmetros são passados através de variáveis de ambiente Query string Cabeçalhos HTTP Parâmetros do servidor CGI 3

CGI Como funciona? O corpo do pedido HTTP é passado através da entradapadrão Apenas se existir (e.g., no método POST) O programa CGI gera a resposta na saída-padrão Cabeçalhos (parciais) Corpo da resposta O servidor recebe a saída-padrão do CGI e envia-a para o cliente (navegador) Se necessário, completando os cabeçalhos CGI 4

Exemplo simples #!/usr/bin/perl -wt print << "END_OF_HTML"; Content-type: text/html <html> <head><title>hello, World!</title></head> <body> <h1>about this server</h1> <ul> <li>server name: $ENV{SERVER_NAME}</li> <li>running on port: $ENV{SERVER_PORT}</li> <li>server software: $ENV{SERVER_SOFTWARE}</li> <li>server protocol: $ENV{SERVER_PROTOCOL}</li> <li>cgi revision: $ENV{GATEWAY_INTERFACE}</li> </ul> </body> </html> END_OF_HTML CGI 5

Descritores standard STDIN Usado para obter o corpo do pedido (se existir) Não existe marcador de fim de ficheiro tentativas de ler mais do que foi recebido bloqueiam o script STDOUT Não tentar ler quando o método for GET Quando o método for POST, deve obter-se o valor de Content-length: e ler apenas esse número de bytes Resposta a devolver Alguns cabeçalhos, uma linha em branco e o corpo da resposta CGI 6

STDERR Descritores standard CGI não impõe tratamento do STDERR A escrita para STDERR normalmente induz um erro 500 Internal Server Error Alguns servidores (e.g., Apache) guardam saída nos logs Útil para debugging Pedido v.a. e stdin Resposta Servidor Web stdout CGI stderr CGI 7

Variáveis de ambiente standard AUTH_TYPE Variável CONTENT_LENGTH CONTENT_TYPE DOCUMENT_ROOT Descrição Método de autenticação (vazio se o pedido não requeria autenticação) Comprimento em bytes do corpo da mensagem Tipo do corpo (e.g., application/x-www-form-urlencoded ) Directório-base a partir de onde se servem os documentos GATEWAY_INTERFACE Versão da interface CGI usada pelo servidor PATH_INFO PATH_TRANSLATED Informação adicional de caminho passada ao script CGI (e.g., sub-recurso) Pathname do recurso no sistema de ficheiros QUERY_STRING Pergunta no URL pedido (tudo a seguir ao "?"). REMOTE_ADDR REMOTE_HOST Endereço IP do cliente que fez o pedido (navegador ou proxy HTTP) Nome do cliente que fez o pedido (navegador ou proxy) CGI 8

Variáveis de ambiente standard Variável REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME SERVER_NAME SERVER_PORT SERVER_PROTOCOL SERVER_SOFTWARE Descrição Utilizador que fez o pedido (indicado pelo identd) Login do utilizador (se autenticado pelo servidor web) Método HTTP usado para fazer o pedido (GET ou POST) Caminho no URL (e.g., /cgi-bin/program.cgi) do script Nome ou endereço IP do servidor web Porta na qual o servidor web está à escuta Nome e versão do protocolo do pedido (e.g., "HTTP/1.1") Nome e versão do servidor web CGI 9

Cabeçalhos do pedido HTTP Todos os cabeçalhos do pedido HTTP que não estão em variáveis standard podem ser acedidos através de HTTP_* HTTP_ACCEPT, HTTP_ACCEPT_CHARSET, HTTP_ACCEPT_ENCODING, HTTP_ACCEPT_LANGUAGE, HTTP_COOKIE, HTTP_FROM, HTTP_HOST, HTTP_REFERER, HTTP_USER_AGENT, Também cabeçalhos desconhecidos Variável HTTPS indica se a conexão é segura ( on ou ON se for, ou OFF se não for) Geralmente é possível configurar o servidor web para passar variáveis adicionais que possam ser úteis CGI 10

Saída O programa tem que gerar pelo menos um cabeçalho um dos seguintes é obrigatório Content-type: especificando o conteúdo do corpo gerado Location: especificando um URL para redireccionamento Status: com um código de estado que não requeira dados adicionais (e.g., 204 No Response) A mensagem em texto pode diferir da standard, mas um código deve ser usado só no contexto para o qual foi definido CGI 11

Saída Geração de um documento É necessário especificar o tipo de documento gerado print "Content-type: text/html\n\n"; As duas mudanças de linha correspondem à linha vazia que separa os cabeçalhos do corpo O servidor web converte cada mudança de linha em CR-LF, confome especificado pelo HTTP CGI 12

Saída Redireccionamento É necessário um cabeçalho Location: para especificar o alvo do redireccionamento print "Location: static_response.html\n\n"; Se o URL for absoluto ou se for relativo com um caminho relativo, é devolvida a resposta ao cliente que faz outro pedido para o novo URL So o URL for relativo com caminho absoluto ocorre um redireccionamento interno O servidor web vai buscar o recurso indicado e retorna-o como se fosse a resposta do CGI mais rápido CGI 13

Saída Especificação do código de resposta Feita através do pseudo-cabeçalho Status: Script indica código e descrição O servidor web intercepta este pseudo-cabeçalho e gera a linha de estado em conformidade Este pseudo-cabeçalho é opcional: Se for gerado um Content-type:, o servidor web gera automaticamente uma resposta 200 OK Se for gerado um Location:, o servidor gera automaticamente uma resposta 302 Found CGI 14

Cabeçalhos completos Normalmente não é necessário o script gerar todos os cabeçalhos O servidor web interpreta os cabeçalhos emitidos e completa-os conforme necessário Contudo, é possível ser o script a gerar a totalidade dos cabeçalhos Modo NPH (Non-Parsed Headers) Seleccionado iniciando o nome do script por nph- (e.g., nph-mycgi em vez de mycgi) Neste modo, o script tem que gerar também a linha de estado da resposta HTTP CGI 15

Exemplo simples com NPH #!/usr/bin/perl -wt print << "END_OF_HTML"; $ENV{SERVER_PROTOCOL} 200 OK Content-type: text/html <html> <head><title>hello, World!</title></head> <body> <h1>about this server</h1> <ul> <li>server name: $ENV{SERVER_NAME}</li> <li>running on port: $ENV{SERVER_PORT}</li> <li>server software: $ENV{SERVER_SOFTWARE}</li> <li>server protocol: $ENV{SERVER_PROTOCOL}</li> <li>cgi revision: $ENV{GATEWAY_INTERFACE}</li> </ul> </body> </html> END_OF_HTML CGI 16

Exemplo 1 Devolução de uma imagem num formato suportado pelo navegador #!/usr/bin/perl -wt use strict; my $image_type = $ENV{HTTP_ACCEPT} =~ m image/png? "png" : "jpeg"; my $basename = $ENV{PATH_INFO} =~ /^(\w+)/; my $image_path = "$ENV{DOCUMENT_ROOT}/images/$basename.$image_type"; unless ( $basename and -B $image_path and open IMAGE, $image_path ) { print "Location: /errors/not_found.html\n\n"; exit; } my $buffer; print "Content-type: image/$image_type\n\n"; binmode; while ( read( IMAGE, $buffer, 16_384 ) ) { print $buffer; } CGI 17

Exemplo 2 Geração da resposta de acordo com a autenticação feita pelo servidor $remote_user = $ENV{REMOTE_USER}; if ( $remote_user eq "mary" ) { print "Welcome Mary, how is your company doing these days?\n"; } elsif ( $remote_user eq "bob" ) { print "Hey Bob, how are you doing? I heard you were sick.\n"; } CGI 18

Descodificação da entrada de formulários Frequentemente, a entrada para um CGI é obtida a partir de formulários Estes formulários podem estar em páginas estáticas ou ser gerados pelo mesmo ou por outro CGI Se o método for GET, os pares <chave>=<valor> são colocados na query string Se o método for POST, são colocados no corpo do pedido Content-type: application/x-www-form-urlencoded CGI 20

Descodificação da entrada de formulários 1. Ler a query string de $ENV{QUERY_STRING} 2. Se $ENV{REQUEST_METHOD} é POST, determinar o tamanho do pedido usando $ENV{CONTENT_LENGTH} e ler essa quantidade de bytes de STDIN. Acrescentar estes dados aos lidos da query string (se presente); a junção faz-se com & 3. Separar os resultados pelo carácter " &" character, que separ os diferentes pares <chave>=<valor> 4. Separar cada par <chave>=<valor> pelo carácter = 5. Descodificar os caracteres URL-encoded no nome (chave) e no valor 6. Associar cada nome com o(s) respectivo(s) valore(s), recordando que cada opção pode ter múltiplos valores Que trabalheira, fazer isto à mão!!! CGI 21

Descodificação da entrada de formulários sub parse_form_data { my %form_data; my $name_value; my @name_value_pairs = split /&/, $ENV{QUERY_STRING}; if ($ENV{REQUEST_METHOD} eq 'POST') { my $query = ""; read(stdin, $query, $ENV{CONTENT_LENGTH}) == $ENV{CONTENT_LENGTH} or return undef; push @name_value_pairs, split /&/, $query; } foreach $name_value (@name_value_pairs) { my($name, $value) = split /=/, $name_value; $name =~ tr/+/ /; $name =~ s/%([\da-f][\da-f])/chr(hex($1))/egi; $value = [] unless defined $value; $value =~ tr/+/ /; $value =~ s/%([\da-f][\da-f])/chr(hex($1))/egi; push @{$form_data{$name}}, $value; } return %form_data; } CGI 22

O módulo CGI.pm Simplifica muito as tarefas necessárias num CGI É uma das razões para o Perl ser tão popular para CGIs Tratamento da entrada Informação de ambiente (cabeçalhos, etc.) Parsing da entrada de formulários Gestão de uploads Geração da saída Geração de cabeçalhos Geração de código HTML Controlo de erros CGI::Carp permite apanhar die e outras condições de erro que poderiam terminar abruptamente o script CGI 23

CGI.pm exemplo simples #!/usr/bin/perl -Tw use strict; use CGI; my $q = new CGI; my $name = $q->server_name(); print $q->header("text/html"), $q->start_html("welcome"), $q->p("hi there! Server at $name speaking."), $q->end_html; Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en-us" xml:lang="en-us"> <head> <title>welcome</title> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> </head> <body> <p>hi there! Server at localhost speaking.</p> </body> </html> CGI 24

Métodos e variáveis correspondentes Método CGI.pm auth_type N/D content_type N/D N/D path_info path_translated query_string remote_addr remote_host remote_ident remote_user Variável de Ambiente CGI AUTH_TYPE CONTENT_LENGTH CONTENT_TYPE DOCUMENT_ROOT GATEWAY_INTERFACE PATH_INFO PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST REMOTE_IDENT REMOTE_USER CGI 25

Métodos e variáveis correspondentes Método CGI.pm request_method script_name self_url server_name server_port server_protocol url Accept * http("accept-charset") Variável de Ambiente CGI REQUEST_METHOD SCRIPT_NAME Indisponível SERVER_NAME SERVER_PORT SERVER_PROTOCOL Indisponível HTTP_ACCEPT HTTP_ACCEPT_CHARSET http("accept-encoding") HTTP_ACCEPT_ENCODING * Quando um método do CGI.pm tem o mesmo nome de uma função interna ou palavra-chave do Perl, a primeira letra do método é maiúscula. CGI 26

Métodos e variáveis correspondentes Método CGI.pm Variável de Ambiente CGI http("accept-language") HTTP_ACCEPT_LANGUAGE http("from") HTTP_FROM raw_cookie HTTP_COOKIE virtual_host HTTP_HOST referer HTTP_REFERER user_agent HTTP_USER_AGENT https HTTPS https("cipher") HTTPS_CIPHER https("keysize") HTTPS_KEYSIZE https("secretkeysize") HTTPS_SECRETKEYSIZE CGI 27

Notas sobre alguns métodos O funcionamento standard para os métodos de acesso a variáveis de ambiente é ser invocados sem parâmetros e devolver o conteúdo da variável correspondente; no entanto há excepções a esta regra. Accept http Invocado sem argumentos retorna a lista de tipos aceites Invocado com um argumento (e.g., text/plain ), devolve o factor de preferência associado Invocado sem argumentos devolve a lista de variáveis de ambiente HTTP_* disponíveis Invocado com o nome de uma variável HTTP_* ou do cabeçalho correspondente devolve o valor desse cabeçalho https Invocado sem argumentos devolve o conteúdo da variável HTTPS, inicializada pelo servidor se a conexão é segura Invocado com um parâmetro, funciona de forma semelhante ao http, mas para HTTPS_* CGI 28

Notas sobre alguns métodos query_string Se o método for GET devolve a query string, incluindo quaisquer alterações que entretanto lhe tenham sido feitas, ao contrário de $ENV{QUERY_STRING} Se o método for POST, retorna os parâmetros POST enviados no corpo da mensagem self_url url Neste caso, não inclui a query string (que normalmente não existe com o POST) Devolve um URL que pode ser usado para invocar o CGI com o método GET com os mesmos parâmetros com que foi invocado Ainda que tenha sido invocado com o método POST Semelhante ao anterior, mas sem parâmetros (informação de caminho ou query string) virtual_host Retorna o conteúdo do cabeçalho Host:, se este existir (i.e., HTTP/1.1), ou SERVER_NAME no caso contrário CGI 29

Acesso aos parâmetros do formulário O acesso aos parâmetros é feito usando o método param Independentemente de o formulário ter sido submetido por GET ou POST Invocado sem argumentos, param retorna a lista de todos os parâmetros Invocado com o nome de um parâmetro, param devolve A lista de valores para esse parâmetro, se invocado em contexto de lista O primeiro (ou único) valor, se invocado em contexto escalar undef se não existir esse parâmetro no formulário CGI 30

Alteração dos parâmetros do formulário É possível alterar o valor de um parâmetro invocando param com dois ou mais argumentos $q->param(name => "John Doe"); $q->param(hobbies => "Biking", "Windsurfing", "Music"); Também é possível apagar um parâmetro específico ou todos os parâmetros $q->delete("age"); $q->delete_all; Pode ser útil para definir valores-padrão para os parâmetros de um formulário CGI 32

Exportação de parâmetros para um espaço de nomes Método param não permite a interpolação em strings de forma simples Em alternativa é possível exportar todos os parâmetros para variáveis de um dado espaço de nomes $q->import_names("q"); print "Hi, $Q::user!"; Único senão: maior consumo de memória CGI 33

Submissão de ficheiros É possível efectuar a submissão de ficheiros usando formulários com enctype= multipart/form-data O valor fornecido é o nome do ficheiro tal como aparecia no servidor Os delimitadores de directórios são diferentes nos diferentes sistemas operativos Os caracteres válidos num nome também Alguns browsers fazem tradução do nome O conteúdo é guardado num ficheiro temporário Pode obter-se um handle para este temporário usando o método upload com o nome do ficheiro como argumento É possível obter o nome do ficheiro temporário usando o método tmpfilename (método não-documentado, deve evitar-se) Pode pedir-se no formulário o nome com o qual o ficheiro deve ser guardado no servidor CGI 34

Prevenir ataques DoS Na configuração standard, o módulo CGI permite upload de ficheiros e não limita o tamanho de um POST Seria possível lançar um DoS que enchesse o disco ou a memória do servidor Para evitar este problema, é conveniente usar o seguinte código antes de criar o objecto CGI: $CGI::DISABLE_UPLOADS = 1; $CGI::POST_MAX = 102_400; # 100 KB CGI 35

Submissão de ficheiros #!/usr/bin/perl -wt use strict; use CGI; use Fcntl qw( :DEFAULT :flock ); use constant UPLOAD_DIR => "/usr/local/apache/data/uploads"; use constant BUFFER_SIZE => 16_384; use constant MAX_FILE_SIZE => 1_048_576; # Limit each upload to 1 MB use constant MAX_DIR_SIZE => 100 * 1_048_576; # Limit total uploads to 100 MB use constant MAX_OPEN_TRIES => 100; $CGI::DISABLE_UPLOADS = 0; $CGI::POST_MAX = MAX_FILE_SIZE; my $q = new CGI; $q->cgi_error and error( $q, "Error transferring file: ". $q->cgi_error ); my $file = $q->param( "file" ) error( $q, "No file received." ); my $filename = $q->param( "filename" ) error( $q, "No filename entered." ); my $fh = $q->upload( $file ); my $buffer = ""; if ( dir_size( UPLOAD_DIR ) + $ENV{CONTENT_LENGTH} > MAX_DIR_SIZE ) { error( $q, "Upload directory is full." ); } CGI 36

Submissão de ficheiros (cont.) # Conversão do nome do ficheiro de destino $filename =~ s/[^\w.-]/_/g; if ( $filename =~ /^(\w[\w.-]*)/ ) { $filename = $1; } else { error( $q, "Invalid file name; files must start with a letter or number." ); } # Abrir ficheiro de destino, garantindo que o nome é único until ( sysopen OUTPUT, UPLOAD_DIR. $filename, O_WRONLY O_CREAT O_EXCL ) { $filename =~ s/(\d*)(\.\w+)?$/($1 0) + 1. $2/e; $1 + 0 >= MAX_OPEN_TRIES and error( $q, "Unable to save your file." ); } # Necessário em sistemas não-unix; não faz nada em sistemas Unix binmode OUTPUT; binmode $fh; # Copiar conteúdo do ficheiro temporário para o de destino por blocos while ( read( $fh, $buffer, BUFFER_SIZE ) ) { print OUTPUT $buffer; } close OUTPUT; CGI 37

Submissão de ficheiros (cont.) sub dir_size { my $dir = shift; my $dir_size = 0; } # Somar o tamanho de todos os ficheiros no directório opendir DIR, $dir or die "Unable to open $dir: $!"; while ( readdir DIR ) { $dir_size += -s "$dir/$_"; } return $dir_size; sub error { my( $q, $reason ) = @_; } print $q->header( "text/html" ), $q->start_html( "Error" ), $q->h1( "Error" ), $q->p( "Your upload was not procesed because the following error ", "occured: " ), $q->p( $q->i( $reason ) ), $q->end_html; exit; CGI 38

Submissão de ficheiros com hook #!/usr/bin/perl use CGI; # Questões de segurança / prevenção de DoS omitidas my $q = CGI->new(\&hook, undef, 0); # $hook, $data, $use_tempfile sub hook { # Invocado antes de CGI->new() retornar => objecto $q não existe my ($filename, $buffer, $bytes_read, $data) = @_; our $fh; unless (defined($fh)) { open $fh, '>', $filename; binmode $fh; } print $fh $buffer; } print $q->header("text/html"); if (defined($fh)) { # Invocado pela submissão dum ficheiro print $q->start_html("upload finished!"), $q->h1("well Done!"), $q->end_html; } else { # Invocado sem submissão => gerar formulário print $q->start_html("testing upload using hooks"), $q->start_multipart_form, $q->filefield(-name => 'uploaded_file'), $q->submit, $q->end_form, $q->end_html; } CGI 39

Geração de saída com o CGI.pm O módulo CGI.pm simplifica grandemente a geração de respostas Cabeçalhos HTTP Código HTML Incluindo formulários CGI 40

Geração de cabeçalhos HTTP Tipo de media print $q->header( "text/plain" ); print $q->header( -type => "text/plain" ); Código de estado print $q->header( -type => "text/html", -status => "404 Not Found" ); Expiração do documento gerado p/ caching Instante absoluto, relativo ou now print $q->header( -type => "text/html", -expires => "+30m" ); Especificação do alvo (frame, janela) print $q->header( -type => "text/html", -target => "main_frame" ); CGI 41

Geração de cabeçalhos HTTP Redireccionamento print $q->redirect( "http://localhost/survey/thanks.html" ); Outros cabeçalhos Basta passar o par nome/valor ao método header; os sublinhados são automaticamente convertidos para hífenes print $q->header( -content_encoding => "gzip" ); CGI 42

Geração de (X)HTML O método start_html gera a parte inicial do documento, até à etiqueta <body> (inclusive) Algumas opções possíveis: Especificação de meta-informação com -meta Inclusão de script com script Código do script numa string ou Referência a hash com chaves possíveis language, -src, ou code Alternativa se o browser não suportar JavaScript com -noscript CGI 43

Geração de (X)HTML Algumas opções possíveis (cont.): Especificação de folha de estilos CSS com style Código CSS numa string ou Referência a hash com chaves possíveis code ou src Título do documento com title Especificação de URL-base como o URL do script com base e valor true Útil com sub-recursos Especificação de URL-base passado como argumento seguinte com -xbase CGI 44

Geração de (X)HTML Elementos HTML standard Linha horizontal print $q->hr; Mudança de linha print $q->br; Parágrafo print $q->p( "This is a paragraph." ); print $q->p( "The server name is:", $q->em( $q->server_name ) ); { } Sem espaço adicional local $" = ""; print $q->p( "Server=", $q->server_name ); CGI 45

Geração de (X)HTML Elementos HTML standard (cont.) Âncora (link) print $q->a( { -href => "/downloads" }, "Download Area" ); Listas Propriedade distributiva print $q->ol( $q->li( [ "First", "Second", "Third" ] ) ); <ol> <li>first</li> <li>second</li> <li>third</li> </ol> CGI 46

Geração de (X)HTML Elementos HTML standard (cont.) Tabelas print $q->table( { -border => 1, -width => "100%" }, $q->tr( [ $q->th( { -bgcolor => "#cccccc" }, [ "Name", "Age" ] ), $q->td( [ "Mary", 29 ] ), $q->td( [ "Bill", 27 ] ), $q->td( [ "Sue", 26 ] ) ] ) ); <table border="1" width="100%"> <tr> <th bgcolor="#cccccc">name</th> <th bgcolor="#cccccc">age</th> </tr> <tr> <td>mary</td> <td>29</td> </tr> <tr> <td>bill</td> <td>27</td> </tr> <tr> <td>sue</td> <td>26</td> </tr> </table> CGI 47

Geração de formulários A geração de formulários também é facilitada pelo módulo CGI.pm A tabela mostra os métodos disponíveis, bem como as etiquetas (X)HTML por eles geradas Método CGI.pm start_form, start_multipart_form end_form textfield password_field filefield button Etiqueta (X)HTML <form> </form> <input type="text"> <input type="password"> <input type="file"> <input type="button"> CGI 48

Geração de formulários (cont.) Método CGI.pm Etiqueta (X)HTML image_button <input type="image"> submit <input type="submit"> reset <input type="reset"> checkbox, checkbox_group <input type="checkbox"> radio_group <input type="radio"> popup_menu <select size="1"> scrolling_list <select size="n"> (n > 1) textarea <textarea> hidden <input type="hidden"> CGI 49

Geração de formulários (cont.) O método HTTP normalmente usado para submissão por start_form é o POST Possível especificar GET com method => 'GET' Nos métodos que geram elementos do formulário é possível especificar o valorpadrão com a opção default Se o CGI tiver sido invocado pela submissão de um formulário com esse elemento, o valor submetido é usado em vez do padrão Possível forçar uso do padrão com override => 1 CGI 50

Formulários Exemplo use CGI; my $q = CGI->new(); print $q->header('text/html'), $q->start_html(-title => 'Register'), $q->h1('registration form'), $q->start_form, $q->start_table, $q->tr([ $q->td([ 'Name:', $q->textfield(-name => 'name') ]), $q->td([ 'Email:', $q->textfield(-name => 'email') ]), $q->td([ 'Password:', $q->password_field(-name => 'pass') ]), $q->td([ 'Confirm password:', $q->password_field(-name => 'cpass') ]), $q->td([ 'Receive newsletter:', scalar ($q->radio_group(-name => 'rcvnl', -values => [ 'yes', 'no' ], -default => 'no')) ]), ]), $q->end_table, $q->submit(-value => 'Register'), $q->end_form, $q->end_html; CGI 51

Formulários Exemplo CGI 52

Formulários Exemplo 2 print $q->start_form; print $q->table( { -border => 0, -width => 550 }, $q->tr( $q->td($q->textfield(-name => 'fname', -default => 'John', -size => 25), $q->br, "First Name"), $q->td($q->textfield(-name => 'mi', -size => 2, -default => 'A'), $q->br, "M.I."), $q->td($q->textfield(-name => 'lname', -default => 'Doe', -size => 25), $q->br, "Last Name") ), $q->tr( $q->td({ colspan => 3 }, $q->textfield(-name => 'address', -size => 75), $q->br, "Street Address") ), $q->tr( $q->td($q->textfield(-name => 'city', -size => 25), $q->br, "City"), $q->td($q->textfield(-name => 'state', -size => 2), $q->br, "State"), $q->td($q->textfield(-name => 'zip', -size => 10), $q->br, "Zip Code") ) ), $q->hr; Pode testar-se em http://www.dcc.fc.up.pt/~rprior/cgi-bin/formtest CGI 53

Formulários Exemplo 2 print $q->table( { -border => 0, -width => 550 }, $q->tr( $q->td($q->em("what Operating Systems Do You Use?"), $q->br, $q->checkbox_group( -name => 'Operating Systems', ) ) ) ), $q->hr; -values -linebreak => 'yes', -defaults => ['Linux', 'Windows'] => ['Linux', 'MacOS', 'Windows', 'Other'], ) ), $q->td($q->em("what Platform is used most?"), $q->br, $q->radio_group( -name -values -linebreak => 'yes', -default => 'PC' => 'platform', => ['PC', 'Mac', 'Sun', 'Other'], print $q->hidden('hidden Reference', 'Bet you did not see me'); CGI 54

Formulários Exemplo 2 print $q->p( $q->em("how are you connected to the Internet?"), $q->br, $q->popup_menu( -name => 'Connection', -values => ['ADSL', 'Cable', 'T-1/E-1', 'Dial-up', 'Satellite'], -default => 'Dial-up' ) ); print $q->p( $q->em("what Peripherals are connected to your computer?"), $q->br, $q->scrolling_list( -name => 'configuration', -values => ['CDROM', 'Sound Card', 'Video Camera', '3D Graphics'], -size => 4, -multiple => 'true' ) ); print $q->p($q->em("what do you like about the World Wide Web?"), $q->br, $q->textarea(-name => 'Comments', -rows => 8, -columns => 60)); print $q->p($q->checkbox('add me to your mailing list')); CGI 55

Formulários Exemplo 2 print $q->p( $q->reset, $q->submit('action', 'Send Free Catalog'), $q->submit('action', 'No Free Catalog') ); print $q->endform, $q->hr; # Imprime valores recebidos da submissao anterior if ($q->param) { my (@values, $key); print $q->h2("here are the current settings:"); foreach $key ($q->param) { print $q->strong("$key : "); @values = $q->param($key); print join(", ",@values), $q->br; } print $q->hr; } else { print $q->strong("no query submitted yet."); } CGI 56

Tratamento de erros Um CGI não deve morrer, pois originaria um erro 500 Internal Server Error Um simples warn gera esse erro No entanto, existe muito código que invoca die, warn ou funções relacionadas Pode-se colocar código perigoso dentro de blocos eval, mas não é muito prático Módulo CGI::Carp simplifica o tratamento de erros Adiciona informação (timestamp e nome do CGI) às mensagens de erro Permite gerar páginas de erro personalizadas CGI 57

Tratamento de erros CGI::Carp Parâmetro fatalstobrowser para apanhar os erros e warnings Ajuda de valor incalculável na fase de desenvolvimento CGI::Carp::set_message para personalizar a página de erro use CGI; $CGI::HEADERS_ONCE = 1; use CGI::Carp 'fatalstobrowser'; BEGIN { sub carp_error { my $error_message = shift; my $q = new CGI; print $q->start_html( "Error" ), $q->h1( "Error" ), $q->p( "Sorry, the following error has occurred: " ); $q->p( $q->i( $error_message ) ), $q->end_html; } CGI::Carp::set_message( \&carp_error ); } CGI 58

Modularização do código Para simplificar a manutenção do código e a uniformidade do site é conveniente criar código modular Criação de módulo Definir package com o nome do módulo sequência de identificadores separados por :: Dar ao ficheiro o nome do último desses identificadores e a extensão.pm Guardar esse ficheiro num subdirectório constituído pelos restantes identificadores separados por / em vez de :: Este subdirectório deve estar num directório em @INC O ficheiro deve terminar com 1; para ser incluído com sucesso É comum definir a versão em $VERSION Exemplo: o módulo MyMods::CGI::Login deve pertencer a um package com o mesmo nome e ser guardado no ficheiro Login.pm dentro, e.g., do directório /usr/lib/perl5/vendor_perl/5.8.8/mymods/cgi CGI 59

Modularização do código: Exemplo #!/usr/bin/perl -wt package MyMods::CGI::Login; use CGI; use base Exporter; our @EXPORT = qw( login_form ); # Exporta a subrotina login_form() our $VERSION = "0.1"; # Versão do módulo sub login_form { my $q = shift; # Objecto CGI passado como primeiro argumento print $q->header(-type => 'text/html'), $q->start_html('login'), $q->start_form(-action => $scriptname), # Processado pelo próprio script $q->p('username:', $q->textfield(-name => 'user')), $q->p('password:', $q->password_field(-name => 'pass', -default => '', -override => 1)), $q->p($q->submit(-value => 'Login')), $q->end_form(), $q->end_html(); } 1; CGI 60

Manutenção de estado HTTP é stateless (mesmo com conexões permanentes) Por vezes é necessário manter estado entre diversos ciclos pedido/resposta. Técnicas possíveis: Técnica Aplicação Fiabilidade e desempenho Requisitos do cliente Query strings Extra path info Grupo de páginas ou site inteiro; perde-se se o utilizador deixar o site e voltar mais tarde Difícil interceptar de forma fiável todos os links; é pesado passar conteúdos estáticos através de CGIs Nenhuns Hidden fields Sequência de submissões de formulários Fácil implementação; não afecta o desempenho Nenhuns Cookies Sempre, mesmo que o utilizador saia do site e regresse mais tarde Fácil implementação; não afecta o desempenho Suporte para cookies implementado e activo CGI 61

Query strings & extra path information Necessário configurar servidor web para invocar CGI quando se acede a determinadas zonas do sistema de ficheiros <Directory /usr/local/apache/htdocs/store> AddType text/html.html AddType Tracker.html Action Tracker /cgi/track.cgi </Directory> Quando é feito um pedido de http://example.com/store/index.html o CGI (query track) é invocado como http://example.com/cgi/track.cgi/store/index.html O script atribui ao utilizador um identificador único e altera todos os links para incluir esse identificador E.g., http://example.com/store/.cc7e2bmb_h6udk9kfptr1g/faq.html CGI 62

Query strings & extra path information Este método implica a intercepção de todos os links nos documentos estáticos servidos para introduzir o ID Pode utilizar-se o módulo HTML::Parser para o efeito Parsing é tarefa pesada penalização em termos de desempenho Em alternativa podem pré-processar-se os documentos para agilizar o processo (e.g., colocar em todos os links #SESSID# no sítio onde deve introduzir-se o ID) sub parse { my( $filename, $id ) = @_; local *FH; open FH, $filename or die "Cannot open file: $!"; } while (<FH>) { s/#sessid#/$id/g; print; } CGI 63

Cookies Geração do cabeçalho Set-cookie: my $cookie = $q->cookie( -name => 'cart_id', -value => 12345, -domain => '.oreilly.com', -expires => '+1y', -path => '/cgi', -secure => 1 ); print $q->header( -type => 'text/html', -cookie => $cookie ); Recuperação de uma cookie recebida my $cookie = $q->cookie( 'cart_id' ); Problema: se houver várias cookies com o mesmo nome apenas retorna a primeira Possível desde que tenham path ou domain distintos Podem recuperar-se as restantes através de $ENV{HTTP_COOKIE} CGI 64