Piter Punk's HomePage - Artigos
 
English version
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


Links Principal Artigos Piter Punk Dicas Programas
 
Powered by Slackware Linux - Written in VIm (the best one!) Last Update: 30 Oct 2004