| Últimas 20 atualizações de MARCO ANTONIO SALLES |
|
|
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
|
|
|
|
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 só 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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
| |
|