2 * Copyright (C) 2012-2014 Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
3 * Copyright (C) 2014 Alexandre Oliva <lxoliva@fsfla.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "rnet_message.h"
32 #define MAX(a,b) (a >= b) ? a : b
40 struct pmhash *header;
41 struct rnet_message *message;
45 * line should be an allocated buffer given to append_line
46 * this means, free(line) will be called when decfile is released
48 static int append_line(struct rnet_decfile *decfile, char *line)
52 decfile->lines_len += 1;
53 len = sizeof(*decfile->lines) * decfile->lines_len;
54 old_lines = decfile->lines;
55 decfile->lines = realloc(decfile->lines, len);
56 if (!decfile->lines) {
57 decfile->lines = old_lines;
60 decfile->lines[decfile->lines_len - 1] = line;
63 decfile->lines_len -= 1;
67 static void decfile_release_lines(struct rnet_decfile *decfile)
70 for (i = 0; i < decfile->lines_len; i++)
71 free(decfile->lines[i]);
73 decfile->lines = NULL;
76 static char * get_header(struct rnet_decfile *decfile);
77 static int parse_header_common(struct pmhash *hash, char **buffer);
78 static int parse_header_2013(struct pmhash *hash, char *buffer);
79 static int parse_header_2014(struct pmhash *hash, char *buffer);
80 static int parse_header_2015(struct pmhash *hash, char *buffer);
81 static int decfile_parse_file(struct rnet_decfile *decfile);
83 static int decfile_parse_header(struct rnet_decfile *decfile)
89 p = buffer = get_header(decfile);
93 r = parse_header_common(decfile->header, &p);
97 switch (strlen(buffer)) {
98 case RNET_HEADER_SIZE_2013:
99 return parse_header_2013(decfile->header, p);
100 case RNET_HEADER_SIZE_2014:
101 return parse_header_2014(decfile->header, p);
102 case RNET_HEADER_SIZE_2015:
103 return parse_header_2015(decfile->header, p);
105 fprintf(stderr, "Unknown file version, but proceeding anyway.\n");
110 static int decfile_parse(struct rnet_decfile *decfile)
115 while ((r = getline(&buffer, &len, decfile->file)) > 0) {
116 r = append_line(decfile, buffer);
124 if (!(r = decfile_parse_header(decfile)) && !(r = decfile_parse_file(decfile)))
127 decfile_release_lines(decfile);
131 struct rnet_decfile * rnet_decfile_open(char *filename)
133 struct rnet_decfile *decfile;
135 decfile = malloc(sizeof(*decfile));
138 decfile->header = pmhash_new();
139 if (!decfile->header)
141 decfile->message = rnet_message_new();
142 if (!decfile->message)
144 decfile->filename = strdup(filename);
145 if (!decfile->filename)
147 decfile->file = fopen(filename, "r");
150 decfile->lines_len = 0;
151 decfile->lines = NULL;
152 if ((r = decfile_parse(decfile)))
156 fclose(decfile->file);
158 free(decfile->filename);
160 rnet_message_del(decfile->message);
162 pmhash_del(decfile->header);
169 void rnet_decfile_close(struct rnet_decfile *decfile)
171 decfile_release_lines(decfile);
172 fclose(decfile->file);
173 free(decfile->filename);
177 static char * get_header(struct rnet_decfile *decfile)
180 for (i = 0; i < decfile->lines_len; i++) {
181 if (!strncmp(decfile->lines[i], "IRPF", 4)) {
182 return decfile->lines[i];
188 #define parse(field, sz) \
190 val = malloc(sz + 1); \
194 memcpy(val, p, sz); \
196 key = strdup(field); \
199 if (pmhash_add(&hash, key, val)) \
202 static int parse_header_common(struct pmhash *hash, char **buffer)
212 parse("codigo_recnet", 4);
217 parse("nr_versao", 3);
222 if (p - *buffer != RNET_HEADER_HEAD_COMMON) {
223 fprintf(stderr, "RNET_HEADER_HEAD_COMMON in decfile.h needs to be adjusted to %ti\n", p - *buffer);
238 static int parse_header_2015(struct pmhash *hash, char *buffer)
247 exerc = pmhash_get(hash, "exerc");
248 if (strcmp(exerc, "2015")) {
257 parse("in_gerada", 1);
258 parse("nr_recibo_anterior", 10);
261 parse("versao_so", 7);
263 parse("nr_recibo", 10);
264 parse("municipio", 4);
265 parse("conjuge", 11);
267 parse("impdevido", 13);
268 parse("nr_recibo", 10);
278 parse("data_julgado", 8);
279 parse("imppagar", 13);
280 parse("tribfonte", 1);
282 parse("trib_rra", 1);
283 parse("cpf_rra2", 11);
284 parse("trib_3rra", 1);
285 parse("cpf_rra3", 11);
286 parse("trib_4rra", 1);
287 parse("cpf_rra4", 11);
288 parse("vr_doacao", 13);
293 parse("cpf_dep1", 11);
294 parse("dnas_dep1", 8);
295 parse("cpf_dep2", 11);
296 parse("dnas_dep2", 8);
297 parse("cpf_dep3", 11);
298 parse("dnas_dep3", 8);
299 parse("cpf_dep4", 11);
300 parse("dnas_dep4", 8);
301 parse("cpf_dep5", 11);
302 parse("dnas_dep5", 8);
303 parse("cpf_dep6", 11);
304 parse("dnas_dep6", 8);
305 parse("cnpj_med1", 14);
306 parse("cnpj_med2", 14);
307 parse("cpf_alim", 11);
308 parse("cpf_invent", 11);
309 parse("municipio", 40);
310 parse("contribuinte", 60);
313 parse("data_nao_residente", 8);
314 parse("cpf_procurador", 11);
315 parse("obrigatoriedade", 3);
316 parse("rendtrib", 13);
317 parse("cnpj_prev", 14);
318 parse("cnpj_prev2", 14);
319 parse("vr_totisentos", 13);
320 parse("vr_totexclusivo", 13);
321 parse("vr_totpagamentos", 13);
322 parse("nr_conta", 13);
323 parse("nr_dv_conta", 2);
324 parse("in_dv_conta", 1);
326 parse("codnaturezaocup", 2);
327 parse("cpfdomestic@", 11);
328 parse("nitdomestic@", 11);
329 parse("cpfdomestic@2", 11);
330 parse("nitdomestic@2", 11);
331 parse("cpfdomestic@3", 11);
332 parse("nitdomestic@3", 11);
333 parse("deciniciada", 1);
336 parse("utilonline", 1);
337 parse("utilrascunho", 1);
338 parse("utilprepreenchida", 1);
339 parse("utilfontes", 1);
340 parse("utilplanosaude", 1);
341 parse("utilrecuperar", 1);
342 parse("dectransmitida", 1);
345 parse("versaotestpgd", 3);
346 parse("controle", 10);
350 "missing CR at the %tith header character\n",
353 } else if (*p++ != '\n') {
355 "missing LF at the %tith header character\n",
358 } else if (*p != 0) {
360 "missing NUL at the %tith header character\n",
363 } else if (p - buffer != RNET_HEADER_SIZE_2015) {
364 fprintf(stderr, "RNET_HEADER_SIZE_2015 in decfile.h needs to be adjusted to %ti,\nor parse_header in decfile.c needs updating\n", p - buffer);
366 } else if (p - tail != RNET_HEADER_TAIL_COMMON) {
367 fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
380 static int parse_header_2014(struct pmhash *hash, char *buffer)
389 exerc = pmhash_get(hash, "exerc");
390 if (strcmp(exerc, "2014")) {
399 parse("in_gerada", 1);
400 parse("nr_recibo_anterior", 10);
403 parse("versao_so", 7);
405 parse("nr_recibo", 10);
406 parse("municipio", 4);
407 parse("conjuge", 11);
409 parse("impdevido", 13);
410 parse("nr_recibo", 10);
420 parse("data_julgado", 8);
421 parse("imppagar", 13);
422 parse("tribfonte", 1);
424 parse("trib_rra", 1);
425 parse("cpf_rra2", 11);
426 parse("trib_3rra", 1);
427 parse("cpf_rra3", 11);
428 parse("trib_4rra", 1);
429 parse("cpf_rra4", 11);
430 parse("vr_doacao", 13);
435 parse("cpf_dep1", 11);
436 parse("dnas_dep1", 8);
437 parse("cpf_dep2", 11);
438 parse("dnas_dep2", 8);
439 parse("cpf_dep3", 11);
440 parse("dnas_dep3", 8);
441 parse("cpf_dep4", 11);
442 parse("dnas_dep4", 8);
443 parse("cpf_dep5", 11);
444 parse("dnas_dep5", 8);
445 parse("cpf_dep6", 11);
446 parse("dnas_dep6", 8);
447 parse("cnpj_med1", 14);
448 parse("cnpj_med2", 14);
449 parse("cpf_alim", 11);
450 parse("cpf_invent", 11);
451 parse("municipio", 40);
452 parse("contribuinte", 60);
453 parse("cpf_empregada", 11);
454 parse("hashcode", 12);
455 parse("data_nao_residente", 8);
456 parse("cpf_procurador", 11);
457 parse("obrigatoriedade", 3);
458 parse("rendtrib", 13);
459 parse("cnpj_prev", 14);
460 parse("cnpj_prev2", 14);
461 parse("vr_totisentos", 13);
462 parse("vr_totexclusivo", 13);
463 parse("vr_totpagamentos", 13);
464 parse("nr_conta", 13);
465 parse("nr_dv_conta", 2);
466 parse("in_dv_conta", 1);
470 parse("versaotestpgd", 3);
471 parse("controle", 10);
475 "missing CR at the %tith header character\n",
478 } else if (*p++ != '\n') {
480 "missing LF at the %tith header character\n",
483 } else if (*p != 0) {
485 "missing NUL at the %tith header character\n",
488 } else if (p - buffer != RNET_HEADER_SIZE_2014) {
489 fprintf(stderr, "RNET_HEADER_SIZE_2014 in decfile.h needs to be adjusted to %ti,\nor parse_header in decfile.c needs updating\n", p - buffer);
491 } else if (p - tail != RNET_HEADER_TAIL_COMMON) {
492 fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
505 static int parse_header_2013(struct pmhash *hash, char *buffer)
514 exerc = pmhash_get(hash, "exerc");
515 if (strcmp(exerc, "2013")) {
524 parse("in_gerada", 1);
525 parse("nr_recibo_anterior", 10);
528 parse("versao_so", 7);
530 parse("nr_recibo", 10);
531 parse("municipio", 4);
532 parse("conjuge", 11);
534 parse("impdevido", 13);
535 parse("nr_recibo", 10);
545 parse("data_julgado", 8);
546 parse("imppagar", 13);
547 parse("tribfonte", 1);
549 parse("trib_rra", 1);
550 parse("cpf_rra2", 11);
551 parse("trib_3rra", 1);
552 parse("cpf_rra3", 11);
553 parse("vr_doacao", 13);
558 parse("cpf_dep1", 11);
559 parse("dnas_dep1", 8);
560 parse("cpf_dep2", 11);
561 parse("dnas_dep2", 8);
562 parse("cpf_dep3", 11);
563 parse("dnas_dep3", 8);
564 parse("cpf_dep4", 11);
565 parse("dnas_dep4", 8);
566 parse("cpf_dep5", 11);
567 parse("dnas_dep5", 8);
568 parse("cpf_dep6", 11);
569 parse("dnas_dep6", 8);
570 parse("cnpj_med1", 14);
571 parse("cnpj_med2", 14);
572 parse("cpf_alim", 11);
573 parse("cpf_invent", 11);
574 parse("municipio", 40);
575 parse("contribuinte", 60);
576 parse("cpf_empregada", 11);
577 parse("hashcode", 12);
578 parse("data_nao_residente", 8);
579 parse("cpf_procurador", 11);
580 parse("obrigatoriedade", 3);
581 parse("rendtrib", 13);
582 parse("cnpj_prev", 14);
583 parse("cnpj_prev2", 14);
584 parse("vr_totisentos", 13);
585 parse("vr_totexclusivo", 13);
586 parse("vr_totpagamentos", 13);
590 parse("versaotestpgd", 3);
591 parse("controle", 10);
595 "missing CR at the %tith header character\n",
598 } else if (*p++ != '\n') {
600 "missing LF at the %tith header character\n",
603 } else if (*p != 0) {
605 "missing NUL at the %tith header character\n",
608 } else if (p - buffer != RNET_HEADER_SIZE_2013) {
609 fprintf(stderr, "RNET_HEADER_SIZE_2013 in decfile.h needs to be adjusted to %ti,\nor parse_header in decfile.c needs updating\n", p - buffer);
611 } else if (p - tail != RNET_HEADER_TAIL_COMMON) {
612 fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
627 char *rnet_decfile_get_header_field(struct rnet_decfile *decfile, char *field)
629 return pmhash_get(decfile->header, field);
632 /* returns true if register is declaration and not a receipt */
633 static int decfile_reg_is_dec(char *line)
635 if (line[0] >= '0' && line[0] <= '9' &&
636 line[1] >= '0' && line[1] <= '9')
638 if (!strncmp(line, "IRPF ", 8))
640 if (!strncmp(line, "T9", 2))
645 /* strip a register from its control number and append it to message */
646 static int append_stripped_reg_ctrl(struct rnet_message **message, char *line)
649 struct rnet_message *msg = *message;
651 if (!decfile_reg_is_dec(line))
656 growth = msg->len + len - 10 - msg->alen;
658 if (rnet_message_expand(message, growth))
662 memcpy(&msg->buffer[msg->len], line, len - 12);
663 msg->buffer[msg->len + len - 12] = '\r';
664 msg->buffer[msg->len + len - 11] = '\n';
665 msg->len += len - 10;
669 static int decfile_parse_file(struct rnet_decfile *decfile)
673 for (i = 0; i < decfile->lines_len; i++) {
674 r = append_stripped_reg_ctrl(&decfile->message,
682 struct rnet_message * rnet_decfile_get_file(struct rnet_decfile *decfile)
684 return decfile->message;
687 char * rnet_decfile_get_file_hash(struct rnet_decfile *decfile)
691 if (gcry_md_test_algo(GCRY_MD_MD5))
693 len = gcry_md_get_algo_dlen(GCRY_MD_MD5);
697 gcry_md_hash_buffer(GCRY_MD_MD5, hash, decfile->message->buffer,
698 decfile->message->len);
702 char * rnet_decfile_get_header(struct rnet_decfile *decfile)
704 return get_header(decfile);