Um gerador de PDFs
Descubra como montar um sistema que converte qualquer arquivo enviado para a impressora em um arquivo PDF, ideal para a troca de documentos do dia-a-dia
Neste artigo, iremos demonstrar várias maneiras de imprimir documentos diretamente para um arquivo PDF. Este artigo foi baseado em outro artigo publicado na Linux Gazette (edição 72) por John Bright, cuja leitura recomendamos. Podemos, normalmente, encontrar as seguintes situações:
- Máquina isolada usando LPR/LPRng;
- Servidor para máquinas Windows/Linux usando SAMBA;
- 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.
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 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 arrumá-las 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 e escrita para todos. Estas permissões especiais são para que o SAMBA possa acessar o diretório. Se quiser apenas usar o LPR/LPRng, você pode simplesmente criar o diretório e executar o checkpc -f depois de editar o /etc/printcap.
Usando LPR/LPRng
Do que vamos precisar para montar o nosso sistema em uma distribuição que utilize o LPRng como servidor de impressão? Basicamente, de duas coisas: uma entrada no /etc/printcap e um filtro para a impressora.
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.
O filtro de impressão
Nosso filtro de impressão será um shell script chamado pdfprint, colocado no diretório /usr/local/bin. Ele foi feito para converter diretamente PostScript para PDF, ou então converter arquivos texto para PostScript e depois para PDF. Qualquer entrada que seja diferente de um arquivo texto ou PostScript gerará um erro.
O código do filtro em si está bem documentado, preste atenção à variável pdfhome, que especifica o diretório onde 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 ter sido 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, bem como para trocar o dono do trabalho pela pessoa que enviou o documento a ser convertido. Veja a listagem 1.
Modo de usar
O modo de usar é extremamente simples, basta mandar imprimir o documento para a impressora chamada pdf. Na linha de comando isso é feito com:
$ lpr -Ppdf arquivo
No modo gráfico, basta você selecionar a impressora pdf e mandar imprimir nela. Se você não tiver outra impressora ou desejar colocar esta impressora como padrão, edite o arquivo /etc/printcap e troque a entrada pdf:\ por lp:\.
SAMBA
Configurar a impressão de PDFs via SAMBA é até mais simples do que 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. 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ê tem apenas uma máquina (a sua) e não quer manter o serviço do SAMBA rodando, utilize a primeira opção.
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 vão estar disponíveis aos usuários. O [pdfs] é 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 a 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 isto, está terminada a configuração para quem quer usar o SAMBA.
CUPS
Se você é usuário do CUPS e não tem uma impressora real conectada ao seu computador, poderá utilizar as linhas já mostradas no /etc/samba/smb.conf. Você irá gerar normalmente os seus PDFs via SAMBA. Porém, se já tiver uma impressora real e quiser acrescentar o nosso gerador de PDFs, será necessário utilizar o método descrito na seção Usando o CUPS.
Para o método 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
Siga os passos da seção Usando o CUPS para configurar corretamente o backend e adicionar a nossa impressora.
Usando o CUPS
Se você não tem uma impressora real no seu computador e quer apenas utilizar um serviço de geração de PDFs via Samba, basta fazer o que foi dito na seção Usando LPR/LPRng. Infelizmente, se precisar imprimir localmente ou se tiver uma impressora real na sua máquina, o método anterior não vai funcionar, e teremos de usar um terceiro método muito mais complicado. Para isso vamos precisar de:
~U Um novo backend para o cups;
~U Um filtro;
~U 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 ter feito os shell scripts e copiado o PPD para o local correto, será necessário reiniciar o CUPS e adicionar a nossa nova impressora.
O nosso PDF backend
Crie um arquivo em /usr/lib/cups/backend com o nome de pdf e com o conteúdo da listagem 2.
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 serão colocados os PDFs gerados. O conteúdo dela deve ser o caminho para o nosso repositório.
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.
Adicionando a Impressora
Você pode utilizar a interface web para adicionar sua impressora. Para isto, utilize um browser e conecte-se ao 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 perguntado sobre o caminho (URL), coloque pdf:/home/pdf e, como driver, utilize Adobe - Distiller. Finalmente acabou.
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 utilizadas máquinas rodando Slackware 8.1, Windows XP e Windows NT.
Listagem 1
#!/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ões 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}.*
Listagem 2
#!/bin/sh
#
# PDF - Novo backend para o CUPS
#
# PDFBIN = Filtro a ser utilizado
# PDFHOME = Repositório onde ficarão
# 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
Piter Punk - piterpk@terra.com.br