[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