como programar um wiki no linux.pdf
TRANSCRIPT
-
Os wikis vm revolucionando a Internet. Saiba como
programar um com apenas 150 linhas de cdigo.
por Jos Pedro Orantes e Jos Mara Ruz
Como programar um wiki
Wiki Python
Nesta edio vamos construir um wiki simples, base-ado no site pioneiro do tipo, de Ward Cunningham. Seu wiki (ou mais corretamente, WikiWiki) o mais antigo do mundo: Cunningham & Cunningham, Inc. [1] (por falar nisso, consulte o maior wiki do planeta para obter
informaes sobre ele em [2] ). O site bastante simples. Seu sistema foi criado com o
objetivo de que as pessoas pudessem acrescentar informa-
o. Assim o site poderia crescer sozinho. Vamos reproduzir
grande parte dele com um programa em Python de apenas
150 linhas, que deve ser baixado em [3] . Novamente, essa linguagem demonstra todo seu poder.
Nosso prprio WikiWiki Criar um wiki no Python no to complicado como pode
parecer. A receita :
01 Muito CGI
02 Um pouco de expresses regulares
03 Um pouco de manipulao de diretrios
04 Um servidor Web ao gosto do leitor (mas que suporte CGI)
Com esses ingredientes vamos programar um wiki completo,
que pode ser ampliado de acordo com a necessidade.
roger stoll ww
w.sxc.hu
Figura 1: O pai de todos os wikis, criado por Ward Cunningham.
Funcionamento Vamos ao primeiro passo para desenvolver qualquer programa:
saber exatamente o que queremos. Seguindo as regras do c2.com, o wiki ser composto por pginas interligadas. Os links sero
palavras-chave com um formato especial: elas sero formadas por
duas palavras juntas (sem espaos ou separadores), cada uma
comeando com uma letra maiscula. Isso pode parecer confuso,
como veremos em alguns exemplos. Primeiro, con ra as palavras
erradas, que no vo ser consideradas palavras-chave:
P Ol
P Uma Coisa
www.linuxmagazine.com.br
junho 2006 edio 20 67
Programao
-
P Outra-Coisa
P softwareLivre
P 3porquinhos
Nenhuma delas corresponde ao nosso padro. A seguir, as
que se enquadram:
P OlMundo
P UmDoisTrs
P LinuxMagazine
P FreeBsd
por isso que o termo original WikiWiki, em vez de
simplesmente wiki.
Agora que j vimos as palavras-chave, vamos ver como elas
so utilizadas. A verdade que no h muito o que explicar, elas
simplesmente devem ser digitadas e pronto! Por exemplo:
Este um texto de um WikiWiki para a LinuxMagazine. Neste U
exemplo, as palavras WikiWiki e LinuxMagazine devem se U
converter automaticamente em palavras-chave.
Cada palavra-chave digitada pode virar uma pgina. Caso ela
no contenha nenhum texto associado com ela, um ponto de inter-
rogao surge ao lado da palavra. Basta clicar nele para acrescentar
o texto. Em textos prontos, basta clicar no boto Editar.
O texto que vamos editar vai estar em formato HTML, assim pode-
mos introduzir formataes como, por exemplo, listas ou negrito.
Uma vez editadas, as pginas podero ser armazenadas e, a
partir de ento, a verso modi cada j estar disponvel. Na teoria,
no deveria ser possvel apagar pginas, j que o objetivo de um
wiki acumular informao. Como a nica maneira de criar
novas pginas adicionar palavras-chave a pginas existentes,
assim asseguramos que qualquer pgina ser acessvel a partir
de outra. Tudo estar interligado, no haver pginas soltas.
CGI CGI (Common Gateway Interface) um protocolo que
permite a um servidor web enviar e receber informaes
de um programa externo. Basicamente, o servidor web
delega a gerao das pginas a programas externos (que
obtm parmetros para a criao de pginas a partir do
servidor web).
Esses parmetros podem ser enviados de duas maneiras
distintas: GET e POST. Esses so os modos usados para a
troca de informaes entre o navegador e o servidor de web.
O GET simplesmente passa os parmetros atravs da URL
(na barra de endereo do navegador) para o servidor.
Quando visitamos muitas das pginas da Internet, pode-
mos ver que a URL tem um formato parecido com http://www.algumaweb.org/algo.algo?variavel1=valor1&variavel2=valor.
Nesse exemplo, o navegador est passando 2 variveis ao
servidor ( variavel1 e variavel2 ). A URL usa o smbolo &
para separar variveis entre si. No muito complicado.
J o POST diferente: o navegador e o servidor trocam
informaes usando o protocolo HTTP, de modo que no
vemos as variveis sendo passadas.
Para o nosso programa, o que importa no usar GET ou
POST, mas o conceito de CGI. Nosso programa recolher
variveis e gerar pginas dependendo delas.
Para isso, usaremos o mdulo cgi do Python:
import cgi
Esse mdulo permite recolher as variveis passadas pelo
servidor web. Para isso, temos que usar a funo cgi.Fiel-
dStorage() . Ela fornece um dicionrio de objetos do tipo
FieldStorage. Cada um contm a informao de uma das va-
riveis. De toda essa informao, s nos interessa o valor da
varivel, que podemos acessar com:
variables = cgi.FieldStorage()
valor = variables["nome"].value
Assim poderemos obter o valor da varivel. Se for oferecido
um dicionrio, poderemos consultar se h alguma vari-
vel em particular usando o mtodo has_key() : variables.
has_key(nome) .
Formulrios A parte vital de um wiki o poder de editar o contedo das
pginas. Para isso, usaremos formulrios em HTML para
recolher as informaes e envi-las ao servidor web. Figura 2: Nosso formulrio de edio do wiki em Python.
Programao
68
Python
www.linuxmagazine.com.br
junho 2006 edio 20
-
Os formulrios so compostos de muitos controles, como,
por exemplo, botes, campos de texto, rtulos e arquivos.
Precisamos de um formulrio com um campo extenso de texto
e um boto para guardar o texto editado. Vamos ao bsico.
Um formulrio HTML ca entre duas tags: e
. A primeira delas leva a uma srie de dados que
de nem o comportamento do formulrio. Queremos con-
trolar o mtodo de envio (POST ou GET) e o programa que
receber os dados (wiki.py).
...
Dentro do formulrio so de nidos os controles que sero
mostrados. Cada um deles, por sua vez, de ne uma srie de
parmetros. O primeiro deles ser uma textarea.
...
...
cols indica o nmero de colunas (de um tipo de largura)
e rows , o nmero de linhas. O parmetro name de ne o
nome com que o contedo da textarea ser enviado ao
servidor web. Para simpli car, vamos usar o pouco ori-
ginal nome de texto.
O segundo tipo de controle de que necessitaremos input:
...
...
Aqui vemos os dois tipos de que necessitamos. O parme-
tro type usado para especi car o tipo, pois existem vrios
diferentes. No nosso caso, teremos:
submit , que gera um boto cujo ttulo recolhido do par-
metro value . Esse boto, ao ser pressionado, envia os dados
ao servidor; e hidden , que usado para passar ao servidor
dados relacionados com controles. Em nosso caso, passamos
a varivel editar=algo .
Estrutura Nosso wiki funcionar assim: ao ser acessado pela primeira vez,
no havendo variveis, ser gerada uma pgina de apresentao.
Essa pgina ter um boto que nos permitir edit-la.
Para isso, incluiremos um boto dentro do formulrio HTML,
que enviar uma varivel editar , com a cadeia de caracteres
WikiWiki como valor.
Ao ser iniciado novamente, teremos uma varivel editar
e, ao invs de gerar uma pgina, a aplicao buscar em seu
diretrio por um arquivo WikiWiki.txt. Se ele exisitir, o texto
ser carregado em uma textarea, que nos permitir edit-lo.
Ele vir acompanhado de um boto armazenar, que, ao ser
pressionado, envia duas variveis: armazenar, com o nome
da pgina (WikiWiki, nesse caso); e texto, com o texto que
editamos. Quando o wiki.py detectar as duas variveis, ir
guardar o contedo do texto em um arquivo com o nome que
contenha a varivel armazenar, concatenado com o .txt.
O texto, antes de ser armazenado, analisado em uma busca
por palavras-chave. No caso de elas existirem, ser realizada
a seguinte alterao, no caso de existir a pgina (ou seja, o
arquivo WikiWiki.txt ):
....WikiWiki... en ... U
WikiWiki...
ou realizar a seguinte alterao:
...WikiWiki... en ...WikiWiki ?...
N o caso de no existir uma pgina, um ? deve ser colocado
ao lado da palavra-chave para indicar que essa pgina deve
ser criada. Para isso, teremos apenas que clicar sobre o ?,
digitar o texto e clicar em Armazenar (como antes).
Assim, teremos que controlar 4 situaes:
P Se no houver variveis, geraremos a pgina de boas-vindas.
Figura 3: Muito bem! Nossa pgina foi armazenada.
www.linuxmagazine.com.br
junho 2006 edio 20 69
Python Programao
-
P Se houver a varivel pagina, carregaremos a correspondente.
P Se existir a varivel editar, ento carregaremos a pgina
indicada em modo de edio.
P Se existirem as variveis armazenar e texto, vamos arma-
zenar o texto enviado.
Anlise do texto Para localizar as palavras-chave, usaremos expresses regula-
res (abordadas na edio n 17 ). O importante agora localizar
a expresso regular adequada ao formato palavra-chave. J
vimos que elas so compostas de duas ou mais palavras, cada
uma delas com a primeira letra em maiscula.
Para indicar que queremos uma palavra com a primeira letra
maiscula e pelo menos duas palavras, usamos a seguinte
expresso regular: [A-Z][a-z]+ . Se quisermos indicar que
so duas palavras, usaremos [A-Z][a-z]+[A-Z][a-z]+ . Para
a possibilidade de mais de duas palavras, basta colocar a
segunda parte entre parnteses e um +. Assim, chegamos
nossa expresso regular:
([A-Z][a-z]+[A-Z][a-z]+)+[A-Z]*[a-z]*
Agora que j podemos localizar as palavras-chave, vamos
substitu-las no texto por links para suas respectivas pginas.
Para isso, preciso gerar uma lista a partir dos resultados da
expresso regular. a que entra a funo findall() , que
fornece uma lista com todas as cadeias de caracteres que se-
guem o padro de palavra-chave. Mas teremos um problema:
algumas das cadeias de caracteres vo estar duplicadas.
Como vamos limpar os valores duplicados da lista? Isso pode
ser feito de muitas maneiras (algum na Internet bolou essa
soluo: reduce(lambda 1, x: x not in 1 and 1.append(x)
or 1, a, []) , sendo a a cadeia de caracteres. Mas explicar
essa simples linha levaria um artigo inteiro). Mais simples
empregar um pouco de matemtica.
O Python permite a gerao de um conjunto a partir de
uma lista. Um conjunto pode conter diversos elementos,
mas sua quantidade no importa, o importante apenas
que estejam presentes.
Vamos supor que temos a lista: [1,1,1,3,4,5,5,6]
e que geraremos um conjunto usando a funo
set([1,1,1,3,4,5,6]). O resultado ser o conjunto
{1,3,4,5,6}. O Python permite interferir sobre um con-
junto, extraindo um elemento diferente de cada vez. Isso
nos permite realizar o seguinte truque:
01 >>> lista = [1,1,1,3,4,5,5,6]
02 >>> conj = set(lista)
03 >>> for elemento in conj:
04 ... print "Elemento: ", elemento
05 ...
06 Elemento: 1
07 Elemento: 3
08 Elemento: 4
09 Elemento: 5
10 Elemento: 6
11 >>>
assim que converteremos nossa lista de palavras em
um conjunto para coletarmos. Como j temos as palavras,
teremos apenas que substitu-las pelos links correspon-
dentes. Mas a pgina pode no existir. Ento, teremos que
testar essa condio com um if. A sim substituiremos a
palavra-chave no contedo da pgina pelo link.
Usaremos a funo replace() do string.replace() , que
aceita 2 parmetros. O primeiro a cadeia a ser substituda
e o segundo, a cadeia que ser usada para substituio.
Apenas uma execuo de replace() j vai realizar todas as
substituies de uma vez. Essa a razo pela qual fizemos
o truque do conjunto: se alguma cadeia de caracteres se
repetisse na lista de palavras-chave, ocorreria o seguinte.
Com a primeira, realizaramos a alterao:
...WikiWiki... -> ...WikiU
Wiki...
Mas, ao encontrar outra vez a palavra-chave WikiWiki
na lista, substituiramos os WikiWiki recm-inseridos no-
vamente pelo link: Figura 4: A criao de uma pgina com o formulrio vazio.
Programao
70
Python
www.linuxmagazine.com.br
junho 2006 edio 20
-
...WikiWiki... ->
......WikiWiki......"
Esses mtodos so usados na funo analise() do arquivo
wiki.py , vital para nosso programa.
Gerao de HTML Bem, agora nos encarregaremos de gerar o HTML. Graas ao
CGI, a tarefa consiste apenas em imprimir o cdigo HTML
com print. O HTML devolvido pelo CGI tem uma peculia-
ridade: deve ser enviado com uma tag que indica o tipo de
informao que ele contm. Alm disso, essa tag tem que ir
separada por dois carriage returns (enters) do resto da pgina.
O cdigo em questo :
print "Content-Type:text/html"
print
print
Os prints sem parmetros imprimem os enters. Para faci-
litar o design do cdigo, dividimos a gerao da pgina em
3 funes:
def cabealho(titulo)
def corpo(titulo, texto)
def editarCorpo(titulo,texto)
def rodape()
Toda pgina ter um cabealho, que imprime a parte no
visvel, como as tags , e um rodap, que fechar a
pgina HTML ( ). No meio estar o corpo,
que pode ser gerado por corpo() ou por editarCorpo() .
Essa segunda funo abre um formulrio para a edio do
contedo da pgina.
O texto da funo corpo() gerado normalmente usando
uma varivel conteudo do tipo string . Dependendo das
circunstncias, conter uma informao ou outra.
As funes
def pagina(titulo, texto)
def editarPagina(titulo, texto)
se encarregam de gerar as pginas usando as 3 funes an-
teriores. Isso simpli ca muito o cdigo e nos permite gerar
pginas de maneira simples.
Cada vez que temos que interagir com o sistema de arqui-
vos, usamos:
def carregaPagina(titulo)
def armazenaPagina(titulo,texto)
A funo carregaPagina() devolve o contedo da pgina
que passada como parmetro.
ltimos detalhes Temos que levar em considerao que o programa wiki.py
deve ter permisses para escrita no diretrio onde ele se
encontra, visto que a que os arquivos so depositados.
Tambm temos que lhe dar permisso de execuo (basta o
comando chmod + x wiki.py ).
Resta apenas copiar o wiki.py para o diretrio referente
ao localhost/cgi-bin , para que ele seja executado quando
digitamos no navegador: http//localhost/cgi-bin/wiki.py. Aparecer ento uma pgina como a mostrada na gura 4 .
Au
tore
s Jos Pedro Orantes Casado cursa o 3 ano de Engenharia Tcnica em Informtica de Sistemas e, h muitos anos, usa linux como ferramen-ta de trabalho e sistema operacional de escritrio. Jos Mara Ruz est nalizando seu projeto de concluso de curso de Engenharia Tcnica em Informtica de Sistemas e est h mais de 7 anos usando e desenvolvendo Software Livre (h dois anos no FreeBSD).
Informaes [1] Cunningham & Cunningham, Inc.: http://c2.com
[2] Ward Cunningham, Wikipdia: pt.wikipedia.org/wiki/Ward_Cunningham
[3] Download do cdigo wiki.py: www.linuxmagazine.com.br/issue/20/wiki.zip
Figura 5: A pgina de boas-vindas do nosso wiki.
www.linuxmagazine.com.br
junho 2006 edio 20 71
Python Programao