Um gerador de PDFs
Piter PUNK
Muitas vezes precisamos trocar documentos com outras pessoas.
Para isso, o formato destes documentos tem que ser visualizável
com facilidade e, muitas vezes, a formatação é muito importante.
Nesses casos, documentos do tipo PDF são ideiais, este artigo
ensina como fazer um gerador de PDFs, capaz de transformar
qualquer saída impressa em um arquivo PDF.
1. Introdução
Iremos demonstrar várias maneiras de imprimir documentos
diretamente para um arquivo PDF. Este artigo foi fortemente
baseado em outro artigo publicado na Linux Gazette (edição
72) por John Bright, e recomendamos a leitura dele.
Normalmente podemos encontrar as seguintes situações:
- Máquina isolada usando LPR/LPRng;
- Servidor para máquinas Windows/Linux usando SAMBA e;
- Máquina ou Servidor usando CUPS.
Para cada uma destas situações foi encontrado um método diferente
para implementar o serviço de impressão para PDFs.
2. Criando os diretórios necessários
Independente do método utilizado, serão necessários um diretório
para conter os PDFs gerados e outro diretório para servir
como spool de impressão.
Vamos lembrar que o usuário deve ser capaz de conseguir mover
o arquivo gerado do repositório para o seu próprio $HOME
(ou outro local do tipo). Por isso, vamos criar este diretório
com permissão de escrita para todos. Execute os seguintes
comandos:
# mkdir /home/pdf
# chown nobody.users /home/pdf
# chmod 777 /home/pdf
Com isso foi criado o nosso repositório, com o nome de /home/pdf.
O outro diretório que devemos criar é o spool de impressão.
Apenas cuidado com o comando checkpc -f do LPRng, ele irá
bagunçar todas as permissões do diretório que iremos criar
e será necessário arrumar depois.
# mkdir /var/spool/lpd/pdf
# chown root.root /var/spool/lpd/pdf
# chmod 1777 /var/spool/lpd/pdf
# chmod 755 /var/spool/lpd
Isso irá criar o spool em /var/spool/lpd/pdf tendo como proprietário
o root e com permissão de leitura escrita para todos. Estas
permissões especiais são para que o SAMBA possa acessar
o diretório. Se você quiser apenas usar o LPR/LPRng, pode
fazer apenas o mkdir e executar o checkpc -f depois de editar
o /etc/printcap.
3. Usando LPR/LPRng
O Slackware utiliza normalmente o LPRng (no 8.0 e anteriores
é utilizado o BSD lpr), nada mais natural que este seja
o primeiro sistema tratado -;). O que nós vamos precisar
para montar o nosso sistema? Poucas coisas, como podemos
ver pela lista abaixo:
- Uma entrada no /etc/printcap;
- Um filtro para a impressora e;
3.1. A entrada no /etc/printcap
Coloque no seu /etc/printcap as seguintes linhas:
pdf:\
:lp=/dev/null:\
:if=/usr/local/bin/pdfprint:\
:sd=/var/spool/lpd/pdf:\
:af=/var/spool/lpd/pdf/acct:\
:mx#0:\
:sh:
Muito cuidado com as barras invertidas no final de cada linha,
elas são necessárias. Esta entrada diz que a impressora
com o nome de pdf irá utilizar o dispositivo /dev/null e
o filtro /usr/local/bin/pdfprint.
3.2. O filtro de impressão
Nosso filtro de impressão será um shell script chamado pdfprint
e vamos colocá-lo no /usr/local/bin. Ele foi feito para
converter diretamente PostScript para PDF, ou então converter
arquivos texto para PostScript e então para PDF. Qualquer
entrada que seja diferente de um arquivo texto e de um PostScript
gerará um erro.
O código do filtro em si está bem documentado, um detalhe
para a variável PDFHOME, será neste diretório que o filtro
irá colocar o PDF gerado. O nome do PDF será composto pelo
nome do usuário e a data e hora correntes.
Depois do PDF gerado, o usuário poderá movê-lo para o seu
próprio $HOME sem maiores problemas. Para os que utilizam
o BSD lpr, é possível alterar o filtro para fazer isso automaticamente,
assim como para trocar o dono do trabalho para a pessoa
que enviou o documento a ser convertido.
#!/bin/sh
#
# pdfprint - Converte a entrada (em PostScript ou Texto puro em PDF)
#
# DATE = Data no formato Mês/Dia - Hora Minuto Segundo
# PDFUSER = Usuário que mandou imprimir o arquivo
# FILENAME = Nome do Arquivo convertido
# PDFHOME = Local onde devem ficar os arquivos convertidos
#
DATE=`date +%b%d-%Hh%Mm%Ss`
PDFUSER=`echo $CONTROL | tr " " "\n" | grep "^P" | tr -d "P"`
FILENAME="${PDFUSER}-${DATE}"
PDFHOME="/home/pdf"
#
# Copia o stdin para um arquivo.
#
# TYPE = Tipo do arquivo criado
#
cat > $PDFHOME/${DATE}.temp
TYPE=`file -b $PDFHOME/${DATE}.temp | cut -f 1 -d " "`
#
# Se o arquivo for do tipo ISO-8859 ou ASCII utiliza o enscript para converter
# em PostScript e depois converte em PDF
# Se o arquivo estiver em formato PostScript converte-o para PDF
# Se não estiver em nenhum destes dois formatos, emite uma mensagem de erro.
#
if [ "$TYPE" = "ISO-8859" ]||[ "$TYPE" = "Bourne" ]||[ "$TYPE" = "ASCII" ]; then
enscript $PDFHOME/${DATE}.temp -o - | ps2pdf - $PDFHOME/${FILENAME}.pdf
elif [ "$TYPE" = "PostScript" ]; then
ps2pdf $PDFHOME/${DATE}.temp $PDFHOME/${FILENAME}.pdf
else
echo -e "\tArquivo do tipo $TYPE não é suportado.\n\t\
Por favor, converta-o para ASCII ou PostScript." > $PDFHOME/${FILENAME}.error
fi
#
# Apaga o arquivo temporário e altera as permissõs do arquivo criado para que
# possa ser lido e copiado pelo usuário que enviou o arquivo.
#
rm $PDFHOME/${DATE}.temp
chmod 666 $PDFHOME/${FILENAME}.*
3.3. Modo de usar
O modo de usar é extremamente simples, basta mandar imprimir
o documento para uma impressora com o nome de pdf. Na linha
de comando isso é feito com:
$ lpr -Ppdf arquivo
No modo gráfico, basta você selecionar a impressora pdf e
mandar imprimir para ela. Se você não possuir outra impressora,
ou desejar colocar esta impressora como padrão, no seu /etc/printcap,
troque o nome da entrada de pdf para lp.
4. Imprimindo via SAMBA
Configurar via SAMBA é até mais simples do que configurar
unicamente para imprimir via LPRng. Para fazer isso precisaremos
apenas editar o /etc/samba/smb.conf.
Este método pode ser utilizado para quem possui um Servidor
para uma Rede Windows/Linux sem problemas. Os clientes Windows
devem utilizar um driver PostScript para essa impressora
(geralmente uso o HP LaserJet PS), os clientes Linux podem
utilizar o apsfilter para configurar uma impressora SAMBA
remota, com o driver PostScript (driver 1). Se você possui
apenas uma máquina (a sua) e não quer manter o serviço do
SAMBA rodando, utilize o primeiro método apresentado.
Para fazer este nosso gerador de PDFs, acrescente as seguintes
linhas no seu /etc/samba/smb.conf:
[pdfs]
comment = PDFs Gerados
path = /home/pdf
force group = users
read only = No
create mask = 0777
directory mask = 0777
guest ok = Yes
[pdf]
comment = Gerador de PDFs
path = /var/spool/lpd/pdf
printable = Yes
print command = /usr/bin/gs -dNOPAUSE -sDEVICE=pdfwrite
-q -dBATCH
-sOut putFile=/home/pdf/%m_`datetime`.pdf %s ; rm %s
guest ok = Yes
O primeiro compartilhamento [pdfs] será onde os PDFs gerados
estarão disponíveis aos usuários. O [pdf] é o nosso gerador
propriamente dito. Como comando de impressão ele chama diretamente
o ghostscript para transformar a entrada em um PDF.
A última coisa que falta é um pequeno script para colocar
a data e hora, crie-o com o nome de datetime, dentro do
diretório /bin. Não podemos utilizar diretamente o comando
date dentro do smb.conf pois este substitui tudo que começa
com % pelas suas próprias variáveis.
#!/bin/sh
date +%b%d-%Hh%Mm%Ss
Com isso está terminada a configuração para quem quer usar
o SAMBA -:).
4.1. Usuários do CUPS
Se você é usuário do CUPS, e não possui uma impressora real
conectada ao seu computador, você poderá utilizar as linhas
já mostradas no /etc/samba/smb.conf. Você irá gerar normalmente
os seus PDFs via SAMBA. Porém, se você já possuir uma impressora
real e quiser acrescentar o nosso gerador de PDFs, será
necessário utilizar o método descrito na seção 5.
Para o método da seção 5 funcionar corretamente no SAMBA,
o compartilhamento [pdf] (a nossa impressora) deverá ser
feito de outra maneira. O compartilhamento [pdfs] (o nosso
repositório) pode continuar da mesma maneira. As seguintes
linhas devem ser colocadas no seu /etc/samba/smb.conf:
[pdf]
path = /var/spool/lpd/pdf
comment = Gerador de PDFs
printer name = pdf
writable = yes
printable = Yes
guest ok = Yes
public = yes
create mask = 0775
E devem ser seguidos os passos da seção 5 para configurar
corretamente o backend e adicionar a nossa impressora.
5. Usando o CUPS
O Slackware possui o CUPS pronto para ser instalado, no CD
Extra. Particularmente eu prefiro utilizar o LPRng, mas
tem gente que por algum motivo é obrigado (ou gosta) de
usar o CUPS.
Se você não tem uma impressora real no seu computador e quer
apenas utilizar como um serviço de geração de PDFs via samba,
basta fazer o que foi dito na seção 3. Infelizmente, se
você precisa imprimir localmente OU se você possui uma impressora
real na sua máquina, o método anterior não irá funcionar,
e teremos de usar um terceiro método muito mais complicado...
Para isso iremos precisar:
- Um novo backend para o cups;
- Um filtro;
- Um PPD com a descrição da nossa impressora.
O backend e o filtro são dois shell scripts. E o arquivo
PPD é uma descrição da impressora. Ele é imprescindível.
Podemos utilizar o destiller.ppd da própria Adobe. Basta
copiar este arquivo para o /usr/share/cups/models.
Depois de feitos os shell scripts e copiado o PPD para o
local correto, será necessário reiniciar o CUPS e adicionar
a nossa nova impressora.
5.1. O nosso PDF backend
Crie um arquivo em /usr/lib/cups/backend com o nome de pdf
e com o seguinte conteúdo:
#!/bin/sh
#
# PDF - Novo backend para o CUPS
#
# PDFBIN = Filtro a ser utilizado
# PDFHOME = Repositório onde irão ficar os PDFs gerados
# PRINTTIME = Mês/Dia e Hora/Minuto/Segundo do arquivo
#
PDFBIN=/usr/local/bin/ps2pdf.cups
PDFHOME=/home/pdf
PRINTTIME=`date +%b%d-%Hh%Mm%Ss`
#
# Verifica se a impressão é local ou remota
# Se for local, coloca apenas localhost na frente do nome do PDF.
# Se for remota, coloca o nome do usuário.
#
if [ "$2" = "" ]; then
OUTPUTFILENAME="$PDFHOME/localhost_$PRINTTIME.pdf"
else
OUTPUTFILENAME="$PDFHOME/$2_$PRINTTIME.pdf"
fi
#
# Quando a impressão é local, ou quando o cliente é Linux, o arquivo
# vem pelo stdin (e não existe o sexto argumento). Quando o cliente
# é Windows, é enviado o sexto argumento.
#
if [ "$6" = "" ]; then
$PDFBIN - $OUTPUTFILENAME >& /dev/null
else
$PDFBIN $6 $OUTPUTFILENAME >& /dev/null
fi
#
# Corrige as permissões do arquivo
#
chown nobody.nobody $OUTPUTFILENAME
chmod 777 $OUTPUTFILENAME
exit 0
Além disso, deve ser criado um link simbólico (se ainda não
existir) de /usr/bin/smbspool para /usr/lib/cups/backend/smb.
Muita atenção para a variável PDFHOME que é o diretório
onde irão estar os PDFs gerados. O conteúdo dela deve ser
o caminho para o nosso repositório.
>5.2. O filtro
O filtro deverá ser colocado no diretório /usr/local/bin
e com o nome de ps2pdf.cups (para ficar compatível com a
variável PDFBIN do backend).
O conteúdo do filtro é o seguinte script:
#!/bin/sh
# ps2pdf.cups - Converte PostScript para PDF.
exec gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
-sOutputFile=$2 -c save pop -f $1
O filtro está separado do backend por questões de modularidade.
Podemos utilizar como filtro (com algumas modificações) o próprio
pdfprint (afinal, é necessário receber dados diretamente
pelo stdin (o que o pdfprint já faz) e via arquivo (o que
o pdfprint não faz). Ou podemos integrar o filtro dentro
do próprio backend.
5.3 Adicionando a Impressora
Você pode utilizar a interface web para adicionar a sua impressora,
para isso utilize um browser e conecte-se em seu servidor
na porta 631 (http://servidor:631). Selecione a opção Printers
e depois Add Printer. Chame a sua impressora de pdf e escolha
o dispositivo PDF Creator. Quando for perguntando sobre
o caminho (URI), coloque pdf:/home/pdf e, como driver utilize
Adobe - Destiller. Finalmente acabou.
6 Conclusão
Com este artigo foi possível fazer um gerador de PDFs simples
de usar, bastando apenas mandar imprimir o documento para
termos o PDF gerado automaticamente. E, no caso de estar
sendo implementado em rede, funcionar tanto para clientes
Windows como para clientes Linux.
Os testes com o LPR/LPRng foram realizados em dois computadores
utilizando o Slackware 8.1, os testes com o CUPS foram em
uma máquina rodando Debian. Como clientes foram utilizados
máquinas rodando Slackware 8.1, Windows XP e Windows NT.
Qualquer dúvida, comentário ou sugestão sobre este artigo,
envie e-mail para piterpk@terra.com.br
|