Cadastre-se Revistas DevMedia Cursos
 

Space de MARCO ANTONIO SALLES
Busca Autor


Últimas 20 atualizações de MARCO ANTONIO SALLES

Artigo - Assinando Validando Arquivos ACBRPAF PAF-ECF parte3


Nesta terceira parte desse pequeno e despretencioso tutorial , vamos dar sequência na Assinatura e a Validação desse mesmo Arquivo(PAF_Produtos.txt )  .Porém utilizando umas funçoes disponibilizadas pela dll da Bematech  , a “sign_bema.dll” que é utilizada em conjunto com a libeay32.dll .  Ressaltando que estamos usando o AcbrPaf para efetuarmos esta assinatura e posteriormente a validação

As duas funçoes são bem simples de serem usadas e tem como Assinatura a definição abaixo :

function genkkey( cChavePublica: AnsiString; cChavePrivada: AnsiString ): integer; stdcall; external ‘sign_bema.dll’;

 function generateEAD( cNomeArquivo: AnsiString; cChavePublica: AnsiString; cChavePrivada: AnsiString; cEAD: AnsiString; iSign: Integer): integer; stdcall; external ‘sign_bema.dll’;

Obs)  > definição para o Delphi 2009 e posteiror… Para delphi anteiror a estas versões utilize apenas strings no lugar do AnsiString

Definido o cabeçãlho da função e tendo as dlls incorparados na Raiz do projeto , vamos passar os devidos parâmetros para podermos então a utilizarmos. A primeira função deve ser usada uma unica vez. Como o seu nome é bem sugestivo ela fornecera para nós as referidas chaves

Execute o metodo abaixo uma unica vez

procedure TFormularioQualquer.btnGerarChaveClick(Sender: TObject);
const
priv_key = ‘priv_key_Bematech.pem’;
pub_key = ‘ pub_key_Bematech.pem’;
var
  cChavePublica, cChavePrivada : AnsiString;
  iRetorno : integer;
  StrArquivo:TStrings;
  strDirPriv,strDirPub:String;
begin
  StrArquivo:=TStringList.Create;
  try
    setlength( cChavePublica, 256 );
    setlength( cChavePrivada, 256 );
    iRetorno := genkkey( (cChavePublica), (cChavePrivada) );
    if ( iRetorno = 0 ) then
      Application.MessageBox( ‘Erro de execução!’, ‘ERRO’, MB_ICONINFORMATION + MB_OK )
    else
      begin
        strDirPriv:=ExtractFilePath(Application.ExeName)+ priv_key;
        StrArquivo.Text:=cChavePrivada;
        StrArquivo.SaveToFile(StrDirPriv);
        StrArquivo.Text:=cChavePublica;
        strDirPub:=ExtractFilePath(Application.ExeName)+ pub_key;
        StrArquivo.SaveToFile(StrDirPub);
      end;
  finally
     FreeAndNil(StrArquivo);
  end;
end;

Apos executarmos este procedimento teremos o Par <Chave Privada e sua correspondente Chave Publica > . Note que se tudo der certo teremos dois Arquivos salvos no diretorio do executável sendo eles conhecidos a seguir :

  • priv_key_Bematech.pem  ?
  • pub_key_Bematech.pem

Todos dois arquivos anteriores são do tipo texto , devem ser guardados a “sete chaves” , mais uma vez reiteramos que são pessoal e intrasnferivel qnd o processo for colocado a nivel de pro

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
19/04/2011 21:45:00





Artigo - CloneCursor como definir os parâmetros Reset KeepSettings ClientDataSet Delphi

O foco principal deste artigo  é como definir os parâmetros Reset KeepSettings do método cloneCursor .  O que esses parâmetros trazem de diferente ao se clonar um clientDataSet ? Ou mesmo ,  o que pode ocasionar uma escolha mal feita ou uma desatenção na hora de definirmos esses parâmetros ? Antes disto vamos a uma breve introdução do método em si

Quando você clona os dados de um ClientDataSet , você cria  não apenas um ponteiro adicional para um armazenamento de memória  compartilhada, mas também uma visão independente dos dados. Quando falo de ponteiros , me refiro a necessidade de deslocarmos todos os dados sem perdermos a localização do ponteiro inicial ou vice versa .Quando  falo de visão independente de dados , falo no sentido de podermos aplicar filtros , índices , ranges nesta nova visão de dados sem afetar a visão dos dados iniciais ou vice-versa .   Apesar de termos uma Visão diferente não se pode  modificar os dados de um sem afetar o conjunto de dados do Outro , pois ele é compartilhado na memória. Toda alteração , inserção , eliminação em um , automaticamente será refletidas para o outro e vice versa .

Vamos a definição do método

procedure CloneCursor(Source :TCustomClientDataSet; Reset: Boolean; KeepSettings: Boolean = False);

Nos exemplos que se seguem iremos sempre referenciar o Objeto Ativo ClientDataSet o qual iremos clonar de CdsFonteDeDados e o Objeto que receberá essa fonte de dados de CloneCds

 
Para usa-la fazemos assim:
    cloneCds:TClientDataSet;
  begin
    cloneCds.CloneCursor(CdsFonteDeDados,Reset ??,KeepSettings ???)
  end;

O primeiro parâmetro é a fonte dos dados que vc quer clonar ou obter . Este argumento tem que ser um ClinteDataSet ativo e que aponte para o armazenamento de memória que vc quer acessar .  Muito intuitivo este argumento e dispensa comentários adicionais

O Segundo parâmetro atua juntamente com o terceiro . Porém se pudéssemos aqui utilizar uma analogia com a genética , diríamos que o segundo parâmetro é o gene dominante . de modo que o terceiro parâmetro  vai influenciar se o segundo parâmetro for recessivo . Então se o Reset:=True (Dominante) , indepedentemente do valor que se atribui para KeepSettings (False ou True) , a característica do Clone já esta traçada e não há como fazer mais nada . Então para efeito de estudo passamos a ter um conjunto de Três situações possíveis que devemos analisar e comentar que são :

  • Reset:= False ; KeepSettings:=False  ****
  • Reset:= False ; KeepSettings:=True
  • Reset:= true ; KeepSettings:=False ou KeepSettings:=True **** Tanto faz

vamos começar com) Reset igual a true .. KeepSettings (False ou True) tanto faz

O Parâmetro Reset como o próprio nome já diz , vai resetar toda e qualquer propriedade que possa já existir (no sentido de que já foi definida) no Clone . Que propriedades seriam estas ?  Por exemplo os valores de IndexName (ou IndexFieldNames), filter, filtered, MasterSource, MasterFields, OnFilterRecord e ProviderName

Leia com muita atenção , po

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
17/02/2011 11:12:00





Artigo - LoadParamsOnConnect LoadParamsFromIniFile params.LoadFromFile quando usar um quando usar outro

Quem é que nunca precisou , nunca utilizou um Arquivo Ini para carregar os parâmetros de uma conexão no DbExpress . Tudo muito bonito e prático , sem ter que recompilar a aplicação , so alterando o database no Arquivo Ini . Mas não se pode falar de parâmetros de conexão do DbExpress sem entender as propriedades LoadParamsOnConnect , DriveName  , connectionName e os métodos Params.LoadFromFile e LoadParamsFromIniFile … Existe uma mágica por trás disso , e na maioria das vezes fazemos sem entender ou não quereremos entender o que esta passando , bem ao estilo : “ ja que deu certo é assim que eu vou fazer “. E vamos simbora para o mundo dos sem “Tempo” . Mas agora é a hora de mudar isto e evitar dores de cabeça no futuro .

 
No delphi  crie novo projeto e adicione ao Form um Componente TButton. todos os exemplo abaixo poderão estar sendo programados no evento Onclick .
Declare na Uses da secção Interface ou implementation os namespaces  DB, SqlExpr,dbxfirebird; Pois esteremos instanciando e configurando um objeto sqlconexao (tSqlConnection) em rumTime e precisaremos dessas unidades .
 
Obs) Aqui eu estarei utilizando o Delphi2010 .Para uma versão anterior do Delphi2010 a diferença esta no Nome do Driver e da respectiva Unidade que o Driver foi definido . Pode-se fazer todos os Teste escolhendo o DiverName Interbase (Nativo do Delphi) e definindo na Uses a Unidade DBXpress no lugar do dbxfirebird
 
 
Vamos começar com a propriedade LoadParamsOnConnect . Esta propriedade esta no Objecto inspector , e tem um impacto importante neste processo. O Padrão desta propriedade é False , mas quando cetada para True , o SqnConnection carrega para a propriedade params o Driver que esta definido na propriedade ConnectionName . Para isto este Driver deve existir no Arquivo dbxconnections.ini . Veja o exemplo abaixo
 

1)Exemplo com a Propriedade LoadParamsOnConnect cetada em True

var
sqlConexao:TSQLConnection;
begin
sqlConexao:=TSQLConnection.Create(nil);
try
sqlconexao.Close;
sqlconexao.ConnectionName:=‘EMPLOYEE_2_1.FDB’;
sqlconexao.DriverName:=’FIREBIRD’;
sqlconexao.LoadParamsOnConnect:=true;
sqlconexao.LoginPrompt:=false;
sqlconexao.Open;
showmessage(sqlconexao.Params.Text); //faça o Exemplo
finally
sqlconexao.free;
end;

ps)no meu caso particular eu tenho um Driver de Nome [EMPLOYEE_2_1.FDB] no Arquivo  dbxconnections.ini

Perceba que o SqlConexao , procurou no Arquivo DBXCONNECTIOS.INI  a definição do driver EMPLOYEE_2_1.FDB  e carregou na propriedade params do SqlConexao . Alterando agora , esta propriedade para False , será nossa a responsabilidade de passar um Arquivo Ini Válido , para isto iremos carregar este Arquivo ini para a propriedadade params do SqlConexao . Para fazer isto temos os métodos Params.LoadFromFile ou LoadParamsFromIniFile . Há uma diferença sutil e significativa entre eles .  No diretório do exe da Applicação defina um Arquivo Ini com as seguintes configuração . Salve este Arquivo com o Nome de Config.ini . Veja

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
14/02/2011 07:48:00





Artigo - Como dividir uma String em um Array utilizando Delphi

Antes de mais nada destaco que este artigo , não é um artigo técnico e tenta mostra os passos que envolvem estas propriedades da TString , tão comumentemente encontrada nos diversos códigos espalados por aí. Vamos começar com uma pergunta clássica:

Qual o Resultado de Showmessage(Lista.DelimitedText) ????
A resposta é feita com uma pergunta : “O que foi Atribuida para Lista.DelimitedText ???”
Pergunta plausivel . Como saber o fim sem conhecer o começo , faz sentido . Mas só isto basta ?

Não !!!. Não é só isto . Para recuperar o DelimitedText temos que definir previamente três parametros:
O Delimiter .. Por padrão é “,” (Virgula)
O QuoteChar .. Por padrão é “ (aspas)
O StrictDelimiter .. Por padrão é False;

Qual a finalidade de cada um na Atribuição de DelimitedText ???

Vamos começar pelo tão mais despercebido mas não  menos importante que é a propriedade StrictDelimiter  . Esta é talves é a mais simples de ser compreendida da três . Qundo definida em False (Valor Padrão)  determina que o caractere de espaço também é interpretado como um delimitador . Então passaremos a ter  dois delimitadores . O Espaço  e mais o que for definido pela propriedade Delimiter

Delimiter …Serve para Separar a String em sequencias de Strings Individuas

Agora ja visto esta duas definiçoes vejamos dois exemplos , logo logo veremos a terceira

Exemplo
LIsta.Delimiter:=’*';
LIsta.StrictDelimiter:=False; //valor Padrão
Lista.DelimitedText:=’Marco * Antonio Salles’

Neste exemplo  definimos Delimiter=’*’ ; StrictDelimiter=False (Padrao) e não definimos o QuoteChar   . Por estar omitido o Delphi assumi o Valor  = “  (Padrão) Vamos delimitar a String ( Marco * Antonio Salles ). Delimitar no sentido de Quebra-la em sequencia de Strings . Delimitando teremos Três Sequencias de Strings ou três cadeias de Strings Listadas abaixo :
> Marco
> Antonio
> Salles

Perceba que Salles e Antonio  foram divididos pq o espaço tb contou como se fosse um Delimiter ja que propriedade StrictDelimiter esta definida como False

obs)Para visualizar isto basta fazer um Showmessage(Lista.text) ou percorrer a lista com o comando for …

Agora Vamos fazer o mesmo Exemplo com a mesma String ( Marco * Antonio Salles ) porém definindo a propriedade  StrictDelimiter=True .
Delimitando teremos duas sequencias de Strings Listadas abaixo que são
> Marco
> Antonio Salles
perceba que o espaço agora não conta mais e so temos um Delimeter que neste caso é o * (Asterisco)

Da mesma forma podemos Visalizar utilizando Showmessage(Lista.text) ou percorrer a lista com o comando for

Então o que o delimitexText faz é gerar uma sequencia de String ou cadeia de Strings  a partir de uma String , seguindo é claro alguns critérios …
Nosso próximo passo passa será o Processo Inverso . Será Definir a String a partir de uma sequencia de String ou cadeia de Strings. Muitas das vezes temos necessidade de fazer este tipo de processo. Mas isto o Delphi ja Faz para Nos sem precisarmos digitar
quase nada . É apenas entender o processo inverso que envolve alguamas armadilhas , vamos a algumas delas ..  Imagine a Lista
 Lista.add(‘Marco ‘);
 Lista.add(‘Antonio Salles’);

Se vc prestar atenção , vai perceber que ja fizemos isto no processo Inverso .. Isto

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
08/02/2011 23:46:00





Artigo - Assinando Validando Arquivos ACBRPAF PAF-ECF parte2

Após a introduçao , visto na parte1 desse tutorial , temos o objetivo de montar o Arquivo xml que por padrão ficará na pasta SHouse onde o aplicativo eECFc.exe distribuido gratuitamente pelos orgões competentes , poderá validar ou não seus arquivos

Este arquivo Xml tem um padrão pré-definido e não pode fugir desta definição. A primeira coisa é fazer o download do aplicativo eECFc.exe

Após o download e a descompactação teremos alem do arquivo eECFc.exe propriamente dito uma pasta denominada SHouse. Onde ao clicarmos nela veremos dois arquivos padrão xml que são

  • Software House Ltda – TESTE
  • Software House SA – TESTE

Esses dois Arquivos tem a finalidade única de mostrar a formatação dos arquivos Xml que devem ser  gerados . Vejamos a sua estrutura interna para posterior comentários:

<?xml version=”1.0″?>

<empresa_desenvolvedora>

 <nome>Software House Ltda – TESTE</nome>

 <chave>
  <modulo></modulo>
  <expoente_publico></expoente_publico>
 </chave>

</empresa_desenvolvedora>

Algo que deve ser observado e que passa despercebido é que o valor atribuido a tag <nome>   </nome> deve ser obrigatoriamente o nome do Arquivo Xml . Neste caso o arquivo é o Software House Ltda – TESTE portanto o valor da tag <nome> tem que ser o mesmo Software House Ltda – TESTE

Copie esta estrutura , no editor de sua preferencia pode ser o notepad e Salve as o arquivo atribuindo o nome de sua preferência e alterando o valor devido na sua tag <name> , salvando-o conforme ja fora dito na mesma pasta Shouse . Pasta padrão utilizada pelo aplicativo Validador eECFc.exe . Não esqueça da extensão .XML

voltando agora na razão desta segunda parte do tutorial vamos utilizar o arquivo modulus.txt criado na secção anterior para então atribuir valores corretos a tag <modulo

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
02/02/2011 22:41:00





Artigo - Filtrando Tabela Master pela Detalhe

Em algumas situações de um projeto ( Delphi no ambiente Win32 ) , trabalhando com o NestedDataSet ( Estrutura Mestre Detalhe DbExpress ClientDataSet ) , deparamos com uma situação que parece simples e que deveria ser simples , mas esta longe disso . Fazer um filtro na Tabela Mestre com alguma condição da Tabela Detalhe . Lembrando que na Tabela Mestre não tem os campo da Tabela Detalhe . A Saída simples,  seria usar JOIN ou mesmo un IN entre essas tabelas . Mas ai vc para e pergunta : “Um SQL vai consumir recurso de Rede , e esses dados estão aqui , bem pertinho de mim ",  ” Por outro lado , o Servidor pode esta em outro lugar bem distante neste mundão ….Ou mesmo vc esta trabalhando desconectadamente num LapTop e ortanto sem conexão com o Servidor . Portanto não seria pedir nada de mais , que esse filtro pudesse ser feito localmente . Mas como fazer ? , o que o Delphi tem a nos fornecer de maneira RAD para completarmos nais esta tarefa ????
 
Confesso que nas andanças por este forums , sites ,relacionamentos afins , não encontrei nada nativo do Delphi. Nenhum Recurso atê a versão 2010 … Sabemos que um Filtro no clientDataSet que pudesse resolver o problema tem mais ou menos a estrutura abaixo
 
ClientDataSet.Filtered:=false;
ClientDataSet.Filter:=’CAMPO OperadorLogico Condicao’;
ClientDataSet1.Filtered:=True;
 
E Esta estrutura nos ajuda em muitos casos  , concatenando condiçoes , usando o operador LIKE enfim numa série de condições que nos deixam quase cem por cento de satisfação . Afinal trata do ClientDataset um dos melhores componentes ja criados se não o MELHOR!!! .  Mas o nosso “PROBLEMA” , é que esta Condicao esta na Tabela DETALHE e pode nen existir na Tabela MESTRE  . Alem disso vale ressaltar que um filtro na TAbela DETALHE , não resolve o nosso Problema , porque funciona na Tabela DETALHE , mas os registros na Tabela Mestre Não são filtrados . Estamos diante de uma situação e esta delongas , são para vcs entenderem o tamanho do problema .
 
Mas pera ai , num relacionamento Utilizando o NestedDataSet , tem um campo que  se refere a Tabela Detalhes. Nele temos tudo que precisamos .. Todos os Campos , todos os Dados da Tabela DETALHE… Que dizer que existe um campo na Tabela MESTRE do Tipo TDataSetField  … ( Assim como temos os Tipo TIntegerField , TStringField etc … temos tb o TDataSetField ) . Então vamos usar este campo na Estrutura anterior .. É uma Idéia , seria uma Idéia , funcionaria se subessemos , ou nos fosse fornecido algum operador Lógico para comparmos esses Tipos . Comparar com que ,  e ainda  , como Comparar ??? São perguntas que , para eu  falta resposta , e se alguem tiver que a coloque no Blog .Facilitaria muitas as coisas …
 
Como bom Brasileiro eu não desisto nunca e tive que partir para outros artificios e resolvi o probrema utilizando a propriedade DATA do ClientDataSet juntamente com o evento FilterRecord do ClientDataSet MESTRE
 
Veremos a segui …
 
No campo Private do Formulário declare um Objeto do Tipo TClientDataSet , que chamaremos aqui de cdsAUX . Este Objeto sera responsável por receber em memória os Dados da Tabela DETALHE (TELE
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
29/01/2011 14:49:00





Artigo - Assinando Validando Arquivos ACBRPAF PAF-ECF parte1

Antes tarde do que nunca . Comecei esta semana , ja que sobrou um tempo , tentar entender um pouco sobre o processo de validaçao e assinatura usando o componente AcbrPaf da biblioteca ACBR . Confesso que  não foi muito fácil , mas enfim consegui obter bons resultados e gostaria de compartilhar .

Antes de tudo meu ambiente de Trabalho .

  • Delphi21010
  • AcbrPaf Versao 0.05
  • libeay32.dll Versão 0.9.8.6
  • sign_bema.dll
  • openssl.exe 

Todas essas dll e mais o aplicativo.exe estão no Diretorio do executavel que foi compilado pelo Delphi

Vou começar o meu exemplo utilizando uma caracteristica do componente que é de gerar o EAD no Arquivo automaticamente.  De forma que não é necessário nenhuma codificação e o processo ja terá uma assinatura. Para isto a propriedade CBrPAF1.AssinarArquivo tem que ser true. Por padrão esta propriedade ja é true e vc não precisa se preocupar . Ressalto que nesta primeira parte do processo de geração de chaves é utilizando o OPENSSL.exe , padrão do AcbrPaf

Ao executar a linha de comando ACBrPAF1.SaveFileTXT_P(‘PAF_Produtos.txt’); será gerado um Arquivo txt no caminho especificado pela propridade path do componente . Neste arquivo se vc observar ja tem uma assinatura EADA709CF02D0631993AE6B43AE0EBC78FE1CF112D1D944F73782892BF75D5ADDC151E 0D9020C3234D22F0178B2E563311F6FFBEFAA5BFF791DC2C2016A634A447B0015B004B0 258027F90296D9830A9E9F550EAFA1288AA129510F9A3B26ACE37E9F3165CDA4494768B 8CF09F865E8C2578318DE90F04085E5534D0B7E303B98BE

 Esta assinatura foi gerada por uma chave particular definida na uses unit ACBrEAD; e  aqui eu subscrevo

  { Chave padrão… por motivos de segurança, GERE A SUA PROPRIA CHAVE e
     informe-a em: “OnGetKeyRSA” }

   cRFDRSAKey = ‘—–BEGIN RSA PRIVATE KEY—–’ + sLineBreak +
 ’MIICXQIBAAKBgQCtpPqcoOX4rwgdoKi6zJwPX9PA2iX2KxgvyxjE+daI5ZmYxcg0′+sLineBreak+                ‘NScjX59nXRaLmtltVRfsRc1n4+mLSXiWMh3jIbw+TWn+GXKQhS2GitpLVhO3A6Ns’+sLineBreak+                ‘vO1+RuP77s+uGYhqVvbD0Pziq+I2r4oktsjTbpnC7Mof3BjJdIUFsTHKYwIDAQAB’+sLineBreak+
‘AoGAXXqwU7umsi8ADnsb+pwF85zh8TM/NnvSpIAQkJHzNXVtL7ph4gEvVbK3rLyH’+sLineBreak +
 ’U5aEMICbxV16i9A9PPfLjAfk4CuPpZlTibgfBRIG3MXirum0tjcyzbPyiDrk0qwM’+sLineBreak+
 ’e83MyRkrnGlss6cRT3mZk67txEamqTVmDwz/Sfo1fVlCQAkCQQDW3N/EKyT+8tPW’+sLineBreak+
 ’1EuPXafRONMel4xB1RiBmHYJP1bo/sDebLpocL6oiVlUX/k/zPRo1wMvlXJxPyiz’+sLineBreak+
 ’mnf37cZ9AkEAzuPcDvGxwawr7EPGmPQ0f7aWv87tS/rt9L3nKiz8HfrT6WT0R1Bh’+sLineBreak+
 ’I7lLGq4VFWE29I6hQ2lPNGX9IGFjiflKXwJBALgsO+J62QtwOgU7lEkfjmnYu57N’+sLineBreak+
‘aHxFnOv5M7RZhrXRKKF/sYk0mzj8AoZAffYiSJ5VL3XqNF6+NLU/AvaR6kECQQCV’+sLineBreak+
‘nY6sd/kWmA4DhFgAkMnOehq2h0xwH/0pepPLmlCQ1a2eIVXOpMA692rq1m2E0pLN’+sLineBreak+ ‘dMAGYgfXWtIdMpCrXM59AkB5npcELeGBv1K8B41fmrlA6rEq4aqmfwAFRKcQTj8a’+sLineBreak+ ‘n09FVtccLVPJ42AM1/QXK6a8DGCtB9R+j5j3UO/iL0+3′+ sLineBreak +
 ’—–END RSA PRIVATE KEY—–’ ;

O  grande passo é vc gerar uma chave publica e juntamente coma chave privada para então gerar o Arquivo modulus.txt e dele extrair a sequência

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
28/01/2011 15:26:00





 

Um pouco de merchandising http://marcosalles.wordpress.com/ Se Deus não existe então Vale Tudo
Arquivo de atualizações
 2011

Estatísticas do Autor:
Número de posts: 7
Características dos posts deste autor:
Conteúdo:
Utilidade:
6 0
 
DevMedia Group - Tel: (21) 3382-5038 - www.devmedia.com.br
Todos os Direitos Reservados a DevMedia Group