[PATCH 3/3] Update header parser for IRPF2014

Thadeu Lima de Souza Cascardo cascardo en cascardo.info
Vie Mar 7 23:46:04 UTC 2014


On Thu, Mar 06, 2014 at 12:58:17PM -0300, Alexandre Oliva wrote:
> Desconsidere este, inclusive porque foi com um pedaço que eu não
> pretendia:
> 
> On Mar  6, 2014, Alexandre Oliva <lxoliva en fsfla.org> wrote:
> 
> > -	if (msg->alen - msg->len < len) {
> > +	if (msg->alen < msg->len + len - 10) {
> 
> 
> Este aqui, ao invés do 3/3 anterior, parece que completa o que faltava
> pro rnetclient funcionar pra declarações de 2014:
> 
> Extend header length and parse new header fields introduced in
> IRPF2014.  Add macros for header sizes, and checks that they match
> what is expected and what we find.  Update the client internal version
> id, and pretend to be running the GNU Interpreter for Java.
> ---

Pode enviar patches separados para:

1) verificação dos valores esperados para os cabeçalhos?
2) atualização do client internal version id?
3) documentação do SO (notando que o cliente distribuído pela Receita
Federal utiliza Linux para o SO)?
4) versão do interpretador Java? (indicando na documentação o que é
usado pelo cliente distribuído pela RF)

Note que a versão que está no repositório sofreu alterações para
suportar o novo cabeçalho e manter o suporte ao de 2013.

Abraços.
Cascardo.

>  decfile.c      |   40 +++++++++++++++++++++++++++++++++++++++-
>  doc/FORMATO    |    9 ++++-----
>  rnet_encode.c  |   12 +++++++++---
>  rnet_message.h |    4 ++++
>  4 files changed, 56 insertions(+), 9 deletions(-)
> 
> diff --git a/decfile.c b/decfile.c
> index 2220638..b6f9e93 100644
> --- a/decfile.c
> +++ b/decfile.c
> @@ -79,7 +79,7 @@ static int decfile_parse_file(struct rnet_decfile *decfile);
>  static int decfile_parse_header(struct rnet_decfile *decfile)
>  {
>  	char *buffer = get_header(decfile);
> -	if (!buffer || strlen(buffer) != 765)
> +	if (!buffer || strlen(buffer) != IRPF_HEADER_LEN)
>  		return 1;
>  	return parse_header(decfile->header, buffer);
>  }
> @@ -165,6 +165,7 @@ static int parse_header(struct pmhash *hash, char *buffer)
>  	char *p = buffer;
>  	char *key;
>  	char *val;
> +	char *skip_last_start;
>  
>  #define parse(field, sz) \
>  	val = malloc(sz + 1); \
> @@ -191,6 +192,12 @@ static int parse_header(struct pmhash *hash, char *buffer)
>  	parse("nome", 60);
>  	parse("uf", 2);
>  	parse("hash", 10);
> +
> +	if (p - buffer != IRPF_HEADER_SKIP_FIRST) {
> +		fprintf(stderr, "IRPF_HEADER_SKIP_FIRST in rnet_message.h needs to be adjusted to %i\n", p - buffer);
> +		goto out_val;
> +	}
> +
>  	parse("in_cert", 1);
>  	parse("dt_nasc", 8);
>  	parse("in_comp", 1);
> @@ -224,6 +231,8 @@ static int parse_header(struct pmhash *hash, char *buffer)
>  	parse("cpf_rra2", 11);
>  	parse("trib_3rra", 1);
>  	parse("cpf_rra3", 11);
> +	parse("trib_4rra", 1);
> +	parse("cpf_rra4", 11);
>  	parse("vr_doacao", 13);
>  	parse("cnpj1", 14);
>  	parse("cnpj2", 14);
> @@ -258,9 +267,38 @@ static int parse_header(struct pmhash *hash, char *buffer)
>  	parse("vr_totisentos", 13);
>  	parse("vr_totexclusivo", 13);
>  	parse("vr_totpagamentos", 13);
> +	parse("nr_conta", 13);
> +	parse("nr_dv_conta", 2);
> +	parse("in_dv_conta", 1);
> +
> +	skip_last_start = p;
> +
>  	parse("versaotestpgd", 3);
>  	parse("controle", 10);
>  
> +	if (*p++ != '\r') {
> +		fprintf(stderr,
> +			"missing CR at the %ith header character\n",
> +			p - buffer);
> +		goto out_val;
> +	} else if (*p++ != '\n') {
> +		fprintf(stderr,
> +			"missing LF at the %ith header character\n",
> +			p - buffer);
> +		goto out_val;
> +	} else if (*p != 0) {
> +		fprintf(stderr,
> +			"missing NUL at the %ith header character\n",
> +			p - buffer);
> +		goto out_val;
> +	} else if (p - buffer != IRPF_HEADER_LEN) {
> +		fprintf(stderr, "IRPF_HEADER_LEN in rnet_message.h needs to be adjusted to %i,\nor parse_header in decfile.c needs updating\n", p - buffer);
> +		goto out_val;
> +	} else if (p - skip_last_start != IRPF_HEADER_SKIP_LAST) {
> +		fprintf(stderr, "IRPF_HEADER_SKIP_LAST in rnet_message.h needs to be adjusted to %i\n", p - skip_last_start);
> +		goto out_val;
> +	}
> +
>  	return 0;
>  out_add:
>  	free(key);
> diff --git a/doc/FORMATO b/doc/FORMATO
> index ddede18..eeca701 100644
> --- a/doc/FORMATO
> +++ b/doc/FORMATO
> @@ -32,12 +32,11 @@ C: (6 bytes) + deflate(hash)
>  		versao_pgd = 0x00 0x78 (120, mesmo que nr_versao no DEC, segundo arquivo de leiaute)
>  		critica_validador = 0x06 (??)
>  		ip_loc = "127.0.0.1" (endereço IP local)
> -		versao_java = "1.7.0_03-icedtea;OpenJDK Runtime Environment" (versão do Java em ASCII)
> -			será que rola uma versão do GCC?
> +		versao_java = "1.5.0-gij;Free Software rnetclient pretending to be GNU Interpreter for Java" (versão do Java em ASCII)
>  		origem = "JA2R" (melhor repetir!)
> -		so = "Linux"
> -		cliente = "201104" (será a versão do receitanet?)
> -		dados_val = parte do cabeçalho do DEC (desce in_cert até vr_totpagamentos) bytes 112 a 750
> +		so = "GNU"
> +		cliente = "201105" (identificador de versão do receitanet)
> +		dados_val = parte do cabeçalho do DEC (desde in_cert até vr_totpagamentos) bytes IRPF_HEADER_SKIP_FIRST a IRPF_HEADER_LEN - IRPF_HEADER_SKIP_LAST
>  		tam_dados_val = 0x00 0x00 0x00 0x00 (4 bytes)
>  		tam_dados_val_chave = 0x00 0x00 0x00 0x00 (4 bytes)
>  		arquivos_restantes = 0x00 0x00 0x00 0x00 (4 bytes)
> diff --git a/rnet_encode.c b/rnet_encode.c
> index ecb97322..0bd0c33 100644
> --- a/rnet_encode.c
> +++ b/rnet_encode.c
> @@ -53,6 +53,8 @@ int rnet_encode(struct rnet_decfile *decfile, struct rnet_message **msg)
>  	if (!hash)
>  		return -1;
>  	header = rnet_decfile_get_header(decfile);
> +	if (strlen (header) != IRPF_HEADER_LEN)
> +		abort ();
>  
>  	codigo_recnet = rnet_decfile_get_header_field(decfile, "codigo_recnet");
>  	tp_arq = strtoul(codigo_recnet, NULL, 10);
> @@ -86,11 +88,15 @@ int rnet_encode(struct rnet_decfile *decfile, struct rnet_message **msg)
>  	r = rnet_message_add_u16(msg, "versao_pgd", versao_pgd);
>  	r = rnet_message_add_u8(msg, "critica_validador", 0x06);
>  	r = rnet_message_add_ascii(msg, "ip_loc", "127.0.0.1");
> -	r = rnet_message_add_ascii(msg, "versao_java", "1.7.0_03-icedtea;OpenJDK Runtime Environment");
> +	r = rnet_message_add_ascii(msg, "versao_java", "1.5.0-gij;Free Software rnetclient pretending to be GNU Interpreter for Java");
>  	r = rnet_message_add_ascii(msg, "origem", "JA2R");
>  	r = rnet_message_add_ascii(msg, "so", "GNU");
> -	r = rnet_message_add_ascii(msg, "cliente", "201104");
> -	r = rnet_message_add_buffer(msg, "dados_val", header + 111, 750 - 111);
> +	r = rnet_message_add_ascii(msg, "cliente", "201105");
> +	r = rnet_message_add_buffer(msg, "dados_val",
> +				    header + IRPF_HEADER_SKIP_FIRST,
> +				    IRPF_HEADER_LEN
> +				    - IRPF_HEADER_SKIP_FIRST
> +				    - IRPF_HEADER_SKIP_LAST);
>  	r = rnet_message_add_u32(msg, "tam_dados_val", 0);
>  	r = rnet_message_add_u32(msg, "tam_dados_val_chave", 0);
>  	r = rnet_message_add_u32(msg, "arquivos_restantes", 0);
> diff --git a/rnet_message.h b/rnet_message.h
> index 35fe9ed..30ccf6a 100644
> --- a/rnet_message.h
> +++ b/rnet_message.h
> @@ -44,4 +44,8 @@ int rnet_message_add_buffer(struct rnet_message **msg, char *key,
>  int rnet_message_parse(struct rnet_message *msg, char *skey,
>  				char** value, int *vlen);
>  
> +#define IRPF_HEADER_LEN 793
> +#define IRPF_HEADER_SKIP_FIRST 111
> +#define IRPF_HEADER_SKIP_LAST 15
> +
>  #endif
> 
> 
> -- 
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist     Red Hat Brazil Toolchain Engineer


Más información sobre la lista de distribución Softwares-impostos