Protheus e AdvPL ASP – Parte 01

Introdução

Nos posts anteriores sobre O Protheus como servidor HTTP – Parte 01O Protheus como servidor HTTP – Parte 02 , vimos como configurar o Protheus Application Server como servidor HTTP de páginas estáticas. Agora, vamos ver como fazer ele processar páginas dinâmicas — o AdvPL ASP. É importante ler os posts anteriores para partir para o AdvPL ASP.

AdvPL ASP

ASP, acrônimo para Active Server Pages, foi o primeiro tipo de script criado pela Microsoft para gerar conteúdo dinâmico de páginas para Internet, onde o script é processado no servidor mediante a requisição do Browser, e a página HTML é gerada no servidor ao executar o script, e retornada ao Browser. O arquivo que contém o Script é composto por conteúdo HTML, e dentro dele separadores especiais delimitam as partes de código / programa que são executadas.

O AdvPL ASP é uma forma similar ao ASP de criação de páginas dinâmicas proprietária do Protheus Server. As duas diferenças básicas são: O código delimitado para execução dentro da página é AdvPL, e uma página (ou arquivo) AdvPL ASP é compilado no repositório de objetos, sendo executado internamente como uma função AdvPL, ao invés de ser interpretado no momento em que for solicitado. Isso inclusive não “expõe”o arquivo original na pasta de publicações do HTTP. Isso mesmo, o arquivo contendo AdvPL ASP pode ficar em uma pasta não publicada na WEB, como uma pasta de fontes do Projeto.

Arquivo APH

Um arquivo contendo AdvPL ASP deve possuir a extensão “.aph“, para ele ser compilado diferenciadamente pelo IDE/TDS e pelo Application Server Protheus. Dentro dele, usamos as tags <% e %> para delimitar código AdvPL que deve ser executado, e <%= <expressão %> para qualquer expressão AdvPL que deve ser acrescentada na página final a ser retornada ao Browser.

Um arquivo chamado teste.aph, ao ser acrescentado em um projeto do AdvPL e compilado, vai virar dentro do repositório uma nova função, chamada H_TESTE() — Prefixo H_ seguido do nome do arquivo. Portanto, atenção ao dar nomes para os arquivos APH, por hora eles não devem ter mais que 8 letras no nome, devem sempre começar com uma letra alfabética, e pode conter a partir de então apenas letras e números — a mesma regra usada para nomear funções do AdvPL.

A função criada a partir da compilação do arquivo APH basicamente cria um retorno em uma variável string, declarada internamente na função, e concatena dentro tela todo o conteúdo estático e dinâmico gerado durante a chamada da função. Isto também significa que, eu posso usar um arquivo APH não apenas para HTML, mas para qualquer outra geração de string dinâmica, mas isso veremos mais para a frente. Por hora, apenas crie um arquivo index.aph no seu ambiente, com o seguinte conteúdo:

<html><body>
<p>Olá Mundo AdvPL ASP</p>
<p>Agora são <%=Time()%></p>
</body></html>

Configuração do Protheus Server para AdvPL ASP

Legal, vamos lembrar como configuramos o nosso site estático no Protheus Server como HTTP:

[http]
enable=1
port=80
path=c:\Protheus12LG\Http
defaultpage=index.html

Com esta configuração — sem configurar hosts ou pastas virtuais — qualquer requisição que chegar na porta HTTP (80) do Protheus Server será atendida considerando o path raid de publicação WEB  a partir da pasta C:\Protheus12LG\Http

Agora, vamos acrescentar uma chave a mais na seção http, e uma nova seção no appserver.ini, para ele ficar assim:

[http]
enable=1
port=80
path=c:\Protheus12LG\Http
defaultpage=index.html
responsejob=webaspthreads

[webaspthreads]
type=webex
environment=envlight
instances=1,2
onstart=U_ASPInit
onconnect=U_ASPConn

Muito bem, vamos por partes: webaspthreads foi o nome que eu dei para a seção de configuração de um POOL de processos AdvPL — também chamado de Working Threads — do tipo WEBEX — para processamento de AdvPL ASP — que vai atender a todas as requisições de AdvPL ASP que o HTTP Server receber. Eu poderia chamar ela de outros nomes, como poolwebjob01 ou o que lhe for conveniente, apenas não pode ser usado nenhum nome de configuração reservada ou outro que conflite com outra seção já existente no arquivo de configuração.

No meu servidor, meu environment de compilação e execução de código AdvPL chama-se “envlight“. Ao usar esta configuração no seu Protheus Server, use o nome do seu environment.

A configuração de instances indica qual é o número de processos AdvPL mínimo e máximo que serão gerenciados internamente pelo POOL de atendimento de requisições de páginas dinâmicas do AdvPL ASP. Por hora, minimo de 1 e máximo de 2 processos está ótimo.

As configurações onstart e onconnect especificadas estão apontando para duas funções que nós vamos criar, pois elas serão chamadas internamente pelo Protheus em momentos distintos, para compor o pool de processos AdvPL para atender a requisições de páginas AdvPL ASP. Pra não deixar pra depois, crie um arquivo no seu projeto de testes, chamado por exemplo AspThreads.prw, e dentro dele as seguintes funções:

#include 'protheus.ch'

User Function ASPInit()
conout("ASPINIT - Iniciando Thread Advpl ASP ["+cValToChar(ThreadID())+"]")
SET DATE BRITISH
SET CENTURY ON
Return .T.

USER Function ASPConn()
Local cReturn := ''
Local cAspPage 
Local nTimer
cAspPage := HTTPHEADIN->MAIN
If !empty(cAspPage)
  nTimer := seconds()
  cAspPage := LOWER(cAspPage)
  conout("ASPCONN - Thread Advpl ASP ["+cValToChar(ThreadID())+"] "+;
         "Processando ["+cAspPage+"]")
  do case 
  case cAspPage == 'index'
    // Execura a página INDEX.APH compilada no RPO 
    // A String retornada deve retornar ao Browser
    cReturn := H_INDEX()
  otherwise
    // retorna HTML para informar 
    // a condição de página desconhecida
    cReturn := "<html><body><center><b>"+;
               "Página AdvPL ASP não encontrada."+;
               "</b></body></html>"
  Endcase
  nTimer := seconds() - nTimer
  conout("ASPCONN - Thread Advpl ASP ["+cValToChar(ThreadID())+"] "+;
         "Processamento realizado em "+ alltrim(str(nTimer,8,3))+ "s.")
Endif
Return cReturn

Fazendo a requisição AdvPL ASP

Uma vez tudo configurado corretamente, e os fontes index.aph e o aspthreads.prw compilados no repositório do ambiente configurado, vamos à ultima informação: Como chamar a página AdvPL ASP pelo Browser.

A extensão “.apw” foi reservada para indicar ao servidor HTTP do Protheus, que ele está recebendo uma requisição de processamento de AdvPL ASP. Logo, abra o browse no seu equipamento, e informe a URL http://localhost/index.apw — se tudo deu certo, você deve ver esta mensagem no seu Browser.

Advpl ASP - Ola Mundo

E, no log de console do Protheus Server, você deve ver as seguintes mensagens:

ASPINIT - Iniciando Thread Advpl ASP [1560]
ASPCONN - Thread Advpl ASP [1560] Processando [index]
ASPCONN - Thread Advpl ASP [1560] Processamento realizado em 0.002s.

Resumo para fixação

APH = Extensão de arquivo AdvPL ASP, que ao ser compilado e acrescentado ao projeto, gera no repositório de objetos do ambiente uma função, chamada H_<nomedoarquivo>, para ser usada para compor páginas de HTML dinâmico. O arquivo APH não deve ser colocado dentro da pasta raiz de publicações WEB — como ele é compilado, ele é um arquivo que faz parte de um Projeto AdvPL. Seu conteúdo será gerado mediante requisição de processamento de página dinâmica.

APW = Extensão de LINK para ser usado no Browser, para pedir ao servidor Protheus HTTP uma solicitação de uma página dinâmica. Uma solicitação através desse link será redirecionada a um POOL de threads pré-configurado dentro do Protheus Server, chamando a função configurada no parâmetro ONCONNECT do POOL.

Working Threads do tipo WEBEX = Pool de threads de trabalho, criado para atender a requisições de links de páginas dinâmicas AdvPL ASP (url com terminação .apw) , onde uma ou mais threads AdvPL são colocados em execução, inicializados com a função especificada na configuração ONSTART, que ficam em modo de espera para atender uma requisição. Quando um processo é alocado para atender uma requisição, a função ONCONNECT é chamada, usando o contexto do processo já existente, que permanece alocado (ocupado) até o final do processamento, quando o HTTP Server retorna a string gerada ao Browser, e o processo usado torna-se disponivel novamente para atender outra requisição de extensão APW, que pode vir do mesmo ou de qualquer outro Web Browser.

Inteligência do Pool de Threads

Lembra-se do parâmetro INSTANCES, configurado no Pool de Threads?  Então, no nosso exemplo usamos 1,2. Isto significa que, este pool de processos inicia com somente um processo para atender as requisições de links APW. Se, em um determinado momento, todos os processos estiverem ocupados em atendimento, e chegar uma nova requisição de AdvPL ASP, o Protheus Server vai colocar essa requisição em uma fila com timeout de alguns segundos, e caso o número de processos total do pool ainda não tenha atingido o máximo, ele sobe mais um processo.

Isso garante por exemplo, que somente quando o site começar a receber forte concorrência de requisições, e os processos em execução estiverem todos ocupados, mais processos serão colocados no ar, visando economia de recursos. Isso também permite definir um limite máximo de processos, para evitar que uma avalanche de requisições ou algum processo muito demorado faça com que o Protheus Server suba mais processos do que ele aguentaria dar conta — normalmente por causa de excesso de memória consumida ou mesmo de CPU.

Detalhes adicionais

Quer ver algumas coisas interessantes? Crie uma user function — vide modelo abaixo — e vamos ver o que ela vai fazer.

User Function TstAPH()
Local cRet := ''
cRet := H_IndeX()
conout(cRet)
return

Agora execute ela diretamente pelo SmartClient, e veja o resultado no log de console do Application Server. Deve ser mostrado algo assim:

[INFO ][SERVER] [11/11/2018 23:55:19] Starting Program U_TSTAPH Thread 5516 (siga0,NOTE-JULIOW-SSD)
<html><body>
<p>Olß Mundo AdvPL ASP</p>
<p>Agora sπo 23:55:20</p>
</body></html>


[INFO ][SERVER] [Thread 5516] [11/11/2018 23:55:20] Thread finished (siga0, NOTE-JULIOW-SSD, 2.63 MB.)

Na prática, eu obtive a string da página de retorno, executando meu código pelo SmartClient. Isso somente foi possível pois dentro do arquivo index.aph eu não usei nada específico do ADVPL ASP. A infraestrutura de processo oferecida pelo Protheus Server para a execução de links APW usando Working Threads oferece o uso de alias virtuais especiais para recuperar informações vindas como parâmetro de GET e POST do Browser, além de um controle nativo de variáveis de SESSION (por usuário) e COOKIES do Browser. Estes recursos estão detalhados na TDN, vide links nas referências no final deste post.

O diferencial da documentação do TDN é que as configurações das funções que fazem o ONSTART e o ONCONNECT do Pool de Threads indica que você deve usar as funções de LIB e Framework WEB compiladas no repositório do ERP, para usar alguns pseudo-comandos, como WEB EXTENDED INIT … WEB EXTENDED END e outros recursos de encapsulamento. No caso do nosso exemplo, estamos usando funções específicas e customizadas para atender uma necessidade didática. De qualquer modo, os recursos de ALIAS VIRTUAIS documentados nesta seção são oferecidos pelo Protheus Server, não dependem da LIB.

Conclusão

Com isso, começamos uma jornada no mundo do AdvPL ASP, e abrimos portas para criar muitas coisas legais. A titulo de informação, os Web Services Server do ERP Microsiga foram todos implementados em AdvPL, usando como base o POOL de Working Threads do AdvPL ASP, apenas implementando tratamentos específicos para receber um XML SOAP via POST, e retornar um XML de retorno ao invés de retornar um HTML. Os portais do ERP Microsiga foram implementados em duas camadas, uma sobre o AdvPL ASP e outra sobre Web Services. O portal em si é uma aplicação AdvPL ASP responsável por montar a interface dinâmica em HTML, consumindo um grupo de serviços publicados em um Web Services Server. Desse modo as Working Threads do portal são muito leves, pois não tem conexão persistente com Banco de Dados e não mantém tabelas abertas. Ela apenas consome um Web Service hospedado em outro serviço, e usa os retornos para montar os HTMLs dinâmicos para os usuários interagirem com as funcionalidades.

Agradeço novamente as curtidas, compartilhamentos, comentários, dúvidas e afins, e desejo novamente a todos TERABYTES de sucesso !!!

Referências

 

Anúncios

O Protheus como servidor HTTP – Parte 01

Introdução

Como já foi mencionado em posts anteriores, dentre as capacidades do Protheus Server é a possibilidade de configurá-lo como um servidor WEB / HTTP. Como as próximas funcionalidades do CRUD vão entrar no mundo WEB, vamos ver um be-a-bá do que é um servidor WEB HTTP, e como tornar o Protheus inicialmente um servidor de páginas estáticas, e depois como transformá-lo em um servidor de páginas dinâmicas usando AdvPL ASP.

O que e um servidor WEB?

Cada site da Internet está hospedado em um ou mais servidores, espalhados pelo mundo. Quando executamos um Browser — programa feito para acessar os sites — como por exemplo o Internet Explorer, Firefox, Microsoft Edge, Google Chrome, Mozilla e afins, nós acessamos os sites que nós conhecemos através de um endereço — chamado URL — composto por letras, números e pontos. Por exemplo, http://www.google.com.br

Sem entrar profundamente na resolução de endereços, na prática o programa usado como Internet Browser descobre qual é o IP do servidor onde o site está hospedado, e abre uma conexão TCP com o servidor ou máquina onde está hospedado o site, e através do protocolo HTTP usado sobre a conexão TCP, o Browser pede ao servidor a página inicial do site.

O servidor, por sua vez, identifica a requisição de página recebida, realiza algumas verificações sobre as informações que implicitamente são enviadas pelo Browser, e normalmente retorna ao Browser um conteúdo HTML — chamado de “página”. Esta página contém um texto demarcado por marcadores, que informam ao Browse como ele deve mostrar na tela as informações da página. Uma página HTML de um site pode exibir textos, imagens, vídeos, e inclusive outros conteúdos, desde que o Browser conheça ou saiba como interpretar este conteúdo.

Como funciona por dentro

O computador usado para disponibilizar o site na internet, usa um programa do tipo “Servidor HTTP” — por exemplo o Microsoft IIS (Windows), Apache (Linux), entre outros. Normalmente, independente do programa utilizado, neste computador existe uma pasta no disco, conhecida como “pasta raiz de publicação WEB”, onde você coloca os arquivos HTML do seu site, e dentro dessa pasta você também pode criar outras pastas, para colocar mais arquivos que podem ser acessados pelo Browser de Internet.

Logo, a função básica de um Servidor HTTP é exportar para a internet o diretório (e sub-diretórios ou pastas) criados no servidor. Acho que isso vai ficar mais claro quando a gente configurar o Protheus como servidor HTTP, e fazer um teste no seu computador mesmo.

Configuração de HTTP do Protheus

Como o objetivo inicial é mostrar como a mágica acontece por dentro, vamos começar do exemplo mais simples de configuração, usando o Protheus como um servidor HTTP de conteúdo estático — isto é, ele vai permitir acessar por um Web Browser os arquivos e um diretório do seu computador, que você vai definir. Para isso, vamos acrescentar no arquivo de configuração do Protheus (appserver.ini) as seguintes linhas:

[http]
enable=1
port=80
path=c:\Protheus12LG\Http

A pasta c:\Protheus12\Http neste momento está vazia. Agora, usando o NOTEPAD ou outro editor de textos, crie dentro dessa pasta um arquivo chamado “index.html”, e dentro dele coloque o seguinte conteúdo:

<html>
<body>
Olá Mundo HTTP do Protheus
</body>
</html>

Após salvar o arquivo com o nome indicado, se você clicar duas vezes nele — usando o Windows Explorer por exemplo — seu computador deve abrir o Browser default de Internet, e mostrar o seguinte conteúdo na tela:

Ola Mundo HTTP 1

Porém, repare uma coisa: Na barra de endereços do Browser, é mostrado uma URL que aponta para um caminho LOCAL do seu equipamento. Logo, o Browser não fez conexão TCP nenhuma com o Protheus, ele apenas abriu o arquivo do disco para você ver o conteúdo HTML dele formatado pelo Browser.

Agora, depois de acrescentar as informações no aquivo de configurações do Protheus Server, e subir ele como serviço, desde que não tenha nenhum outro aplicativo usando a porta 80 do seu equipamento, no log de console do Protheus Server você deve ver as seguintes mensagens:

Http server is ready.
Root path is c:\protheus12lg\http\
Listening port 80 (default)

Agora, volte no Browser do seu equipamento, e digite a seguinte URL;  http://localhost/index.html , e veja o que acontece. Se tudo deu certo, você deve ver exatamente o que foi mostrado no Browser anterior, porém agora acessando a sua própria máquina, onde o Protheus Server está fornecendo a interface de conexão para o Browser, e retornando a página solicitada.

Ola Mundo HTTP 2

Experimente agora pegar um arquivo de imagem da sua máquina, pode ser com extensão jpeg, jpg, png, bmp, tanto faz. Copie o arquivo e cole ele dentro da pasta de publicação do seu ambiente. Não use um arquivo que contenha nome composto separado por espaço em branco — ainda não — por exemplo “minhafoto.jpg”.

Agora, vá no Browser, e troque a URL o texto “index.html” para “mihafoto.jpg”. Novamente, se tudo der certo, você deve ver a sua foto no Browser.

Se você errar alguma letra do nome da foto ou do arquivo de indice (html), o Browse deve mostrar no Browse uma tela de erro, onde em algum lugar ele deve mencionar o código 404.

Error 404

Este erro foi retornado pelo Protheus, indicando que o arquivo que eu pedi — chamado naoexiste.html não foi encontrado na pasta de publicação. O erro de arquivo ou página não encontrado do protocolo HTTP é 404.

Acessando esta página de outra máquina

Como até aqui o teste de publicação está sendo feito com o Protheus Server na sua máquina, e o Browser também sendo aberto na sua máquina, a URL “http://localhost/index.html&#8221; funciona. Isso por que “localhost” indica para o Browser que ele deve procurar o servidor de Internet — que no nosso caso é o Protheus Server — na máquina local, isto é, na máquina que o próprio Browser está sendo executado.

Aqui em casa eu acesso a internet usando um Modem Wi-Fi. Quando meu notebook é iniciado, ele conecta no Wi-Fi e recebe um endereço IP, para uma rede interna através  da qual o acesso a Internet é compartilhado entre outros dispositivos, como o notebook da minha esposa, e os nossos aparelhos celulares. Ao usar o comando IPCONFIG do Windows, eu consigo descobrir qual é o IP do meu Notebook dentro da minha rede “interna” — dentro de casa.

Wireless LAN adapter Wi-Fi:

Connection-specific DNS Suffix . :
IPv6 Address. . . . . . . . . . . : 2804:14d:32a0:2a01:3122:114b:ddb7:e5db
Temporary IPv6 Address. . . . . . : 2804:14d:32a0:2a01:d025:52bf:85ca:4a3b
Temporary IPv6 Address. . . . . . : 2804:14d:32a0:2a01:d404:32c:510d:1208
Temporary IPv6 Address. . . . . . : 2804:14d:32a0:2a01:fd1a:5e2:1a67:3f84
Link-local IPv6 Address . . . . . : fe80::3122:114b:ddb7:e5db%5
IPv4 Address. . . . . . . . . . . : 192.168.0.12
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : fe80::2e95:69ff:fe69:218b%5
192.168.0.1

O que interessa para mim é o IPV4 Address, que agora e dentro da minha rede doméstica é “192.168.0.12”. Agora eu vou fazer uma brincadeira, com o meu celular conectado no mesmo Wi-Fi, vou abrir o Chrome dentro do celular, e na barra de endereços, eu vou digitar a URL usada no exemplo acima, porém trocando a palavra “localhost” pelo IP d meu notebook. O endereço fica assim:

http://192.168.0.12/index.html

E, se novamente tudo der certo, eu vejo a mesma mensagem na tela do computador, e no celular !!!

IMG_3628

A imagem acima é um “Print” da tela do meu aparelho celular, acessando a página de exemplo que eu hospedei no Protheus Server do meu notebook. 😀

Conclusão

Esse foi o primeiro post dessa sequência, espero que tenha sido suficiente para pelo menos ter uma “noção básica” de como um servidor de internet funciona. Existem muitos outros controles e configurações no Protheus, desde a parte do HTTP apenas como servidor de arquivos, até a execução de páginas dinâmicas (AdvPL ASP). Não se preocupe, a gente chega juntos lá.

Novamente desejo a todos TERABYTES DE SUCESSO 😀

Referências

 

Protheus como Servidor de FTP

Introdução

Quando eu comentei um pouco sobre as capacidades do Servidor de Aplicação Protheus Server, em um post mais antigo, eu mencionei que ele não apenas servia a conexões do SmartClient para rodar aplicações AdvPL, mas também que ele poderia ser um servidor de HTTP, com páginas estáticas e dinâmicas — usando AdvPL ASP — bem como TELNET e FTP. No post de hoje, vamos explorar o que a gente puder sobre como usar um Protheus Server como servidor de FTP.

Configuração Mínima

Imagine que você quer usar um Protheus Server como um FTP Server, com acesso anônimo — sem criticar usuário e senha — e apenas disponibilizar uma estrutura de pastas para Download. Neste caso, a configuração mínima para este serviço, seria acrescentar no arquivo de configuração do Protheus (appserver.ini) a seção [FTP], com as seguinte chaves:

[ftp]
Enable=1
Port=21
Path=c:\Protheus12LG\EnvLight\ftp
CanAcceptAnonymous=1

Especificamos a porta padrão (21), o acesso anônimo habilitado, e o path raiz do FTP, a partir do qual as conexões terão acesso de Download. Dentro da pasta configurada em “path”, eu coloquei um arquivo chamado leiame.txt, vamos ver este acesso através de um cliente FTP nativo do Windows, usando o comando “ftp” em linha de comando.

C:\Users\siga0>ftp -A localhost
Connected to NOTE-JULIOW-SSD.
220 Connected to FTP server
331 Anonymous access allowed
502 Command not implemented
331 Anonymous access allowed, send email name as PASS
220 Logon successful
230 Welcome to Application Server FTP!
Anonymous login succeeded for siga0@NOTE-JULIOW-SSD
ftp> dir
250 PORT command successful
150 Opening ASCII mode data connection
-r-xr-x--- 1 owner group 39 Nov 04 20:10 leiame.txt
226 Transfer Complete
ftp: 74 bytes received in 0.00Seconds 37.00Kbytes/sec.
ftp> ls
250 PORT command successful
150 Opening ASCII mode data connection
leiame.txt
226 Transfer Complete
ftp: 15 bytes received in 0.00Seconds 15.00Kbytes/sec.
ftp>

Através do parâmetro “-A” na linha de comando, informamos ao cliente FTP que o Login deverá ser anônimo. Caso este parâmetro não seja especificado, você deve entrar manualmente com o usuário “anonymous“. Uma senha deve ser informada, mas não será validada — pode ser qualquer coisa, inclusive “anonymous”.

Após feito o login, executamos os comandos “ls” e “dir” para recuperar a lista de arquivos e pastas disponíveis para download. Vamos então fazer o download do arquivo “leiame.txt”:

ftp> get leiame.txt
250 PORT command successful
150 RETR command started
226 Transfer Complete
ftp: 39 bytes received in 0.00Seconds 39000.00Kbytes/sec.
ftp>

De dentro do FTP Client do Windows, podemos executar um comando do sistema operacional, prefixando ele com o sinal de exclamação. Por exemplo, para verificarmos  o conteúdo do arquivo na pasta local após o Download, vamos executar o comando “type”.

ftp> !type leiame.txt
Exemplo de Configuraτπo Mφnima de FTP
ftp>

No caso, o texto do arquivo justamente é “Exemplo de Configuração Mínima de FTP”. Porém, como a página de código do Prompt de Comando está com o CodePage 437 (CodePage original do IBM-PC, também conhecido por OEM-US, CP437 ou DOS Latin US), a acentuação é mostrada com outros caracteres. Para ver o arquivo da forma correta, ele pode ser aberto pelo NOTEPAD ou qualquer outro editor de textos, OU você deve digitar no Prompt de Comando a instrução abaixo, antes de abrir o cliente FTP:

mode con cp select=1252

Com isso, o seu Prompt de Comando vai usar o CodePage do Windows, CP1252, que também é o CodePage usado pelo Protheus. Para ver a lista de instruções implementadas na camada interna do FTP Server, use o comando remotehelp

ftp> remotehelp
214-The following commands are implemented
USER PASS ACCT QUIT PORT RETR
STOR DELE RNFR PWD CWD CDUP
MKD RMD NOOP TYPE MODE STRU
LIST HELP
214 HELP command successful
ftp>

Caso você tente fazer um upload no FTP nesta conexão, a operação será negada.

ftp> put upload.txt
250 PORT command successful
550 Access is denied
ftp>

Usando outros clientes FTP

Normalmente basta desligar o “Passive Mode” na configuração do programa que você usa como Cliente de FTP (SCP, WINSCP, etc.) que a conexão e operações são realizadas sem maiores problemas.

Implementando mais controles

Na configuração mínima, o FTP está totalmente aberto para download de qualquer arquivo colocado a partir da pasta configurada na chave PATH, para qualquer cliente que conecte usando a identificação “anonymous” — ou seja, sem autenticação alguma. No máximo, usando por exemplo um recurso externo, como um Firewall, você pode permitir por exemplo apenas receber conexões FTP na porta 21 a partir de um ou mais endereços de rede, e apenas isso.

Para atender a necessidade de permitir ou restringir operações por usuário, existe a necessidade de desligar o acesso anônimo, configurar algumas chaves adicionais na seção [FTP], e criar algumas funções AdvPL no repositório para serem acionadas por estas chaves. Vamos direto para o exemplo completo:

[ftp]
Enable=1
Port=21
Path=c:\Protheus12LG\EnvLight\ftp
RPCEnv=envlight
CheckPassword=U_FTPPASS
GetUserPath=U_FTPPATH
CheckUserOper=U_FTPOPER

Primeiramente, removemos o acesso anônimo. Então, criamos uma chave chamada RPCENV, onde colocamos o nome  do environment (ambiente) existente neste Protheus Server, responsável por executar as funções AdvPL que serão colocadas para validar algumas operações do FTP.

Configuração CHECKPASSWORD

Quando um usuário conectar no FTP e informar o usuário e senha, será chamada a função U_FTPPASS(), que receberá como parâmetros o usuário e senha informados pelo cliente de FTP. Se esta função retornar .T., o Protheus Server responde ao cliente de FTP que o login foi aceito, caso contrário responde uma mensagem de erro e nega o acesso. Vejamos o exemplo abaixo:

User Function FTPPass(cUser,cPass)
cUser := lower(cUser)
if ( cUser == "root" )
  if( cPass == "root" )
    Return .T.
  Endif
Endif
Return .F. 

Neste exemplo, permitimos apenas um usuário chamado “root”, com a senha “manager”  a entrar no FTP.

Configuração GETUSERPATH

Imagine que, eu quero fornecer, por exemplo, uma pasta raiz de FTP diferenciada para alguns usuários. Para isso, eu crio uma função AdvPL — no nosso exemplo, USER FUNCTION FTPPATH(), que recebe como parâmetros o usuário e senha informados no login. A função deve retornar um PATH completo no servidor onde está sendo executado o Protheus Server, e esta pasta será o diretório raiz de FTP. Vamos ao exemplo:

User Function FTPPath(cUser,cPass)
cUser := lower(cUser)
If cUser == "siga0984"
  return "C:\Protheus12LG\ftp"
Endif
Return "C:\Protheus12LG\ftp\anonymous"

Neste caso, quando o usuário de FTP for “siga0984“, ele têm acesso à pasta raiz do FTP, quando qualquer outro usuário somente terá acesso a partir da pasta “anonymous”.

Configuração CHECKUSEROPER

Caso você queira permitir UPLOAD de arquivos no FTP, ou outras operações que modifiquem conteúdo, como apagar arquivo, criar ou apagar uma pasta, é necessário implementar uma função AdvPL para ser chamada pelo Protheus Server para autorizar estas operações, usando a configuração CheckUserOper — no nosso exemplo, vamos implementar a função U_FTPOPER(). Ela recebe três parâmetros: O usuário de login no FTP Server, a senha utilizada, e o comando enviado pelo Cliente do FTP.

Apenas alguns comandos são desviados para esta função, por exemplo STOR <arquivo>, DELE <arquivo>, MKD <pasta>,  RMD <pasta>, e dois comandos não implementados para renomear arquivo (RNFR e RNTO).

  • STOR = Upload de arquivo
  • DELE = Apagar arquivo
  • MKD = Criar pasta 
  • RMD = Remover pasta
  • RNFR <arquivo1> e RNTO <arquivo2> — Renomar arquivo1 para arquivo2

Caso a função AdvPL retorne .T., a operação é autorizada. Caso contrário, negada. Vamos ao nosso exemplo:

User Function FTPOPER(cUser,cPass,cOper)
Local cCmd
cUser := lower(cUser)
If cUser == 'root'
  cCmd := left(cOper,4)
  If cCmd $ "STOR,DELE"
    Return .T.
  Endif
Endif
Return .F.

No exemplo acima, permitimos apenas ao usuário “root” a possibilidade de fazer upload ou mesmo de apagar um arquivo remotamente.

Resultados dos Testes

Os testes realizados mostraram que alguns clientes de FTP, por exemplo o WINSCP, usou uma sintaxe para a troca de pasta (comando CWD) que o FTP Server do Protheus não entendeu, mas funcionou adequadamente com o cliente FTP nativo do Windows em linha de comando, e um cliente de FTP do Altap(r) Salamander.

Mesmo com as implementações em AdvPL, o objetivo de ter um servidor nativo de FTP no servidor Protheus é atender a necessidade de integrações entre sistemas, normalmente em ambientes restritos — ou fechados. Ele não oferece logs de utilização nativos, não permite interceptar outros comandos para implementar por exemplo restrição de acesso de usuário para uma pasta ou arquivo, etc.

Devido a questões ligadas a implementação do FTP em múltiplas plataformas, é recomendado usar os nomes de arquivos sem espaços em branco, sem acentuação, e com letras minúsculas, e utilizar sub-pastas se e somente se realmente necessário. Qualquer demanda maior, que exija mais controles, como um FTP publicado na Internet para clientes e parceiros ter acesso a múltiplos arquivos, eu pessoalmente recomendo a utilização de uma aplicação especializada em ser Servidor de FTP, que vai lhe oferecer nativamente muito mais controles do que o Protheus Server como FTP Server.

Conclusão

Para cada tamanho de problema, existe uma solução adequada. O Protheus como servidor de FTP não foi criado para competir com um FTP Server de mercado, mas apenas para ter uma alternativa simples e nativa para integração entre sistemas, onde não são necessários níveis muito avançados de controle. Porém, para o que ele se propõe, ele dá conta do recado.

Em um próximo post, vamos explorar a classe client de FTP do Protheus Server —  chamada TFTPCLIENT() — para conectar e realizar operações de Cliente de FTP conectando-se em um FTP Server configurado também no Protheus.

Agradeço novamente a audiência, e desejo a todos TERABYTES DE SUCESSO !!!

Referências