[PATCH rnetclient] Parse common part of header and accept other years.

Thadeu Lima de Souza Cascardo cascardo en cascardo.info
Lun Mar 7 01:48:18 UTC 2016


This patch allows files from other years to be transmited, but won't be
able to read all the data from the header, and won't be able to do extra
verification.

The only real verifications done is that the header size matches what is
expected for that year and there is a high level of confidence that the
head part of the header is really the same for the years supported by
rnetclient.

No other verification is done for the extra fields present in the file,
and all the extra data is not used any other place in the program
anyway.
---
 decfile.c     | 147 ++++++++++++++++++++++++----------------------------------
 decfile.h     |   8 +---
 rnet_encode.c |  25 ++--------
 3 files changed, 67 insertions(+), 113 deletions(-)

diff --git a/decfile.c b/decfile.c
index be30687..877a333 100644
--- a/decfile.c
+++ b/decfile.c
@@ -74,6 +74,7 @@ static void decfile_release_lines(struct rnet_decfile *decfile)
 }
 
 static char * get_header(struct rnet_decfile *decfile);
+static int parse_header_common(struct pmhash *hash, char **buffer);
 static int parse_header_2013(struct pmhash *hash, char *buffer);
 static int parse_header_2014(struct pmhash *hash, char *buffer);
 static int parse_header_2015(struct pmhash *hash, char *buffer);
@@ -81,9 +82,17 @@ static int decfile_parse_file(struct rnet_decfile *decfile);
 
 static int decfile_parse_header(struct rnet_decfile *decfile)
 {
-	char *buffer = get_header(decfile);
+	char *buffer;
+	int r;
+
+	buffer = get_header(decfile);
 	if (!buffer)
 		return -EINVAL;
+
+	r = parse_header_common(decfile->header, &buffer);
+	if (r)
+		return r;
+
 	switch (strlen(buffer)) {
 	case RNET_HEADER_SIZE_2013:
 		return parse_header_2013(decfile->header, buffer);
@@ -92,8 +101,9 @@ static int decfile_parse_header(struct rnet_decfile *decfile)
 	case RNET_HEADER_SIZE_2015:
 		return parse_header_2015(decfile->header, buffer);
 	default:
-		return -EINVAL;
+		fprintf(stderr, "Unknown file version, but proceeding anyway.\n");
 	}
+	return 0;
 }
 
 static int decfile_parse(struct rnet_decfile *decfile)
@@ -174,14 +184,6 @@ static char * get_header(struct rnet_decfile *decfile)
 	return NULL;
 }
 
-static int parse_header_2015(struct pmhash *hash, char *buffer)
-{
-	int r;
-	char *p = buffer;
-	char *key;
-	char *val;
-	char *tail;
-
 #define parse(field, sz) \
 	r = -ENOMEM; \
 	val = malloc(sz + 1); \
@@ -196,12 +198,15 @@ static int parse_header_2015(struct pmhash *hash, char *buffer)
 	if (pmhash_add(&hash, key, val)) \
 		goto out_add;
 
+static int parse_header_common(struct pmhash *hash, char **buffer)
+{
+	int r;
+	char *p = *buffer;
+	char *key;
+	char *val;
+
 	parse("sistema", 8);
 	parse("exerc", 4);
-	if (strcmp(val, "2015")) {
-		r = -EINVAL;
-		goto out_val;
-	}
 	parse("ano", 4);
 	parse("codigo_recnet", 4);
 	parse("in_ret", 1);
@@ -213,8 +218,34 @@ static int parse_header_2015(struct pmhash *hash, char *buffer)
 	parse("uf", 2);
 	parse("hash", 10);
 
-	if (p - buffer != RNET_HEADER_HEAD_2015) {
-		fprintf(stderr, "RNET_HEADER_HEAD_2015 in decfile.h needs to be adjusted to %ti\n", p - buffer);
+	if (p - *buffer != RNET_HEADER_HEAD_COMMON) {
+		fprintf(stderr, "RNET_HEADER_HEAD_COMMON in decfile.h needs to be adjusted to %ti\n", p - *buffer);
+		goto out_val;
+	}
+
+	*buffer = p;
+
+	return 0;
+out_add:
+	free(key);
+out_key:
+	free(val);
+out_val:
+	return r;
+}
+
+static int parse_header_2015(struct pmhash *hash, char *buffer)
+{
+	int r;
+	char *p = buffer;
+	char *key;
+	char *val;
+	char *tail;
+	char *exerc;
+
+	exerc = pmhash_get(hash, "exerc");
+	if (strcmp(exerc, "2015")) {
+		r = -EINVAL;
 		goto out_val;
 	}
 
@@ -331,8 +362,8 @@ static int parse_header_2015(struct pmhash *hash, char *buffer)
 	} else if (p - buffer != RNET_HEADER_SIZE_2015) {
 		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);
 		goto out_val;
-	} else if (p - tail != RNET_HEADER_TAIL_2015) {
-		fprintf(stderr, "RNET_HEADER_TAIL_2015 in decfile.h needs to be adjusted to %ti\n", p - tail);
+	} else if (p - tail != RNET_HEADER_TAIL_COMMON) {
+		fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
 		goto out_val;
 	}
 
@@ -352,42 +383,13 @@ static int parse_header_2014(struct pmhash *hash, char *buffer)
 	char *key;
 	char *val;
 	char *tail;
+	char *exerc;
 
-#define parse(field, sz) \
-	r = -ENOMEM; \
-	val = malloc(sz + 1); \
-	if (!val) \
-		goto out_val; \
-	val[sz] = 0; \
-	memcpy(val, p, sz); \
-	p += sz; \
-	key = strdup(field); \
-	if (!key) \
-		goto out_key; \
-	if (pmhash_add(&hash, key, val)) \
-		goto out_add;
-
-	parse("sistema", 8);
-	parse("exerc", 4);
-	if (strcmp(val, "2014")) {
+	exerc = pmhash_get(hash, "exerc");
+	if (strcmp(exerc, "2014")) {
 		r = -EINVAL;
 		goto out_val;
 	}
-	parse("ano", 4);
-	parse("codigo_recnet", 4);
-	parse("in_ret", 1);
-	parse("cpf", 11);
-	parse("filler", 3);
-	parse("tipo_ni", 1);
-	parse("nr_versao", 3);
-	parse("nome", 60);
-	parse("uf", 2);
-	parse("hash", 10);
-
-	if (p - buffer != RNET_HEADER_HEAD_2014) {
-		fprintf(stderr, "RNET_HEADER_HEAD_2014 in decfile.h needs to be adjusted to %ti\n", p - buffer);
-		goto out_val;
-	}
 
 	parse("in_cert", 1);
 	parse("dt_nasc", 8);
@@ -485,8 +487,8 @@ static int parse_header_2014(struct pmhash *hash, char *buffer)
 	} else if (p - buffer != RNET_HEADER_SIZE_2014) {
 		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);
 		goto out_val;
-	} else if (p - tail != RNET_HEADER_TAIL_2014) {
-		fprintf(stderr, "RNET_HEADER_TAIL_2014 in decfile.h needs to be adjusted to %ti\n", p - tail);
+	} else if (p - tail != RNET_HEADER_TAIL_COMMON) {
+		fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
 		goto out_val;
 	}
 
@@ -506,42 +508,13 @@ static int parse_header_2013(struct pmhash *hash, char *buffer)
 	char *key;
 	char *val;
 	char *tail;
+	char *exerc;
 
-#define parse(field, sz) \
-	r = -ENOMEM; \
-	val = malloc(sz + 1); \
-	if (!val) \
-		goto out_val; \
-	val[sz] = 0; \
-	memcpy(val, p, sz); \
-	p += sz; \
-	key = strdup(field); \
-	if (!key) \
-		goto out_key; \
-	if (pmhash_add(&hash, key, val)) \
-		goto out_add;
-
-	parse("sistema", 8);
-	parse("exerc", 4);
-	if (strcmp(val, "2013")) {
+	exerc = pmhash_get(hash, "exerc");
+	if (strcmp(exerc, "2013")) {
 		r = -EINVAL;
 		goto out_val;
 	}
-	parse("ano", 4);
-	parse("codigo_recnet", 4);
-	parse("in_ret", 1);
-	parse("cpf", 11);
-	parse("filler", 3);
-	parse("tipo_ni", 1);
-	parse("nr_versao", 3);
-	parse("nome", 60);
-	parse("uf", 2);
-	parse("hash", 10);
-
-	if (p - buffer != RNET_HEADER_HEAD_2013) {
-		fprintf(stderr, "RNET_HEADER_HEAD_2013 in decfile.h needs to be adjusted to %ti\n", p - buffer);
-		goto out_val;
-	}
 
 	parse("in_cert", 1);
 	parse("dt_nasc", 8);
@@ -634,8 +607,8 @@ static int parse_header_2013(struct pmhash *hash, char *buffer)
 	} else if (p - buffer != RNET_HEADER_SIZE_2013) {
 		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);
 		goto out_val;
-	} else if (p - tail != RNET_HEADER_TAIL_2013) {
-		fprintf(stderr, "RNET_HEADER_TAIL_2013 in decfile.h needs to be adjusted to %ti\n", p - tail);
+	} else if (p - tail != RNET_HEADER_TAIL_COMMON) {
+		fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
 		goto out_val;
 	}
 
@@ -648,6 +621,8 @@ out_val:
 	return r;
 }
 
+#undef parse
+
 char *rnet_decfile_get_header_field(struct rnet_decfile *decfile, char *field)
 {
 	return pmhash_get(decfile->header, field);
diff --git a/decfile.h b/decfile.h
index 2181ecb..ca2eb70 100644
--- a/decfile.h
+++ b/decfile.h
@@ -22,15 +22,11 @@
 
 #include "rnet_message.h"
 
+#define RNET_HEADER_HEAD_COMMON 111
+#define RNET_HEADER_TAIL_COMMON  15
 #define RNET_HEADER_SIZE_2013 765
-#define RNET_HEADER_HEAD_2013 111
-#define RNET_HEADER_TAIL_2013  15
 #define RNET_HEADER_SIZE_2014 793
-#define RNET_HEADER_HEAD_2014 111
-#define RNET_HEADER_TAIL_2014  15
 #define RNET_HEADER_SIZE_2015 871
-#define RNET_HEADER_HEAD_2015 111
-#define RNET_HEADER_TAIL_2015  15
 
 struct rnet_decfile;
 struct rnet_decfile * rnet_decfile_open(char *filename);
diff --git a/rnet_encode.c b/rnet_encode.c
index b653199..f7fea6c 100644
--- a/rnet_encode.c
+++ b/rnet_encode.c
@@ -56,6 +56,10 @@ int rnet_encode(struct rnet_decfile *decfile, struct rnet_message **msg)
 	if (!hash)
 		goto out;
 	header = rnet_decfile_get_header(decfile);
+	header_head = RNET_HEADER_HEAD_COMMON;
+	header_tail = RNET_HEADER_TAIL_COMMON;
+	/* This was already checked at parse time. */
+	header_size = strlen(header);
 
 	codigo_recnet = rnet_decfile_get_header_field(decfile, "codigo_recnet");
 	tp_arq = strtoul(codigo_recnet, NULL, 10);
@@ -67,27 +71,6 @@ int rnet_encode(struct rnet_decfile *decfile, struct rnet_message **msg)
 	versao_pgd = strtoul(rnet_decfile_get_header_field(decfile, "nr_versao"), NULL, 10);
 	ret = strtoul(rnet_decfile_get_header_field(decfile, "in_ret"), NULL, 10);
 
-	if (!strcmp(exerc, "2015")) {
-		header_size = RNET_HEADER_SIZE_2015;
-		header_head = RNET_HEADER_HEAD_2015;
-		header_tail = RNET_HEADER_TAIL_2015;
-	} else if (!strcmp(exerc, "2014")) {
-		header_size = RNET_HEADER_SIZE_2014;
-		header_head = RNET_HEADER_HEAD_2014;
-		header_tail = RNET_HEADER_TAIL_2014;
-	} else if (!strcmp(exerc, "2013")) {
-		header_size = RNET_HEADER_SIZE_2013;
-		header_head = RNET_HEADER_HEAD_2013;
-		header_tail = RNET_HEADER_TAIL_2013;
-	} else {
-		r = -EINVAL;
-		goto out2;
-	}
-
-	/* This was already checked at parse time.  */
-	if (strlen (header) != header_size)
-		abort ();
-
 	(*msg)->buffer[0] = 0x40;
 	(*msg)->len = 1;
 	r = rnet_message_add_u32(msg, "a_comp", 0);
-- 
2.7.0



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