diff options
| -rw-r--r-- | service/src/.gitignore | 1 | ||||
| -rw-r--r-- | service/src/msgs/welcome | 2 | ||||
| -rw-r--r-- | service/src/printdoc.c | 91 | ||||
| -rw-r--r-- | service/src/stlfile.c | 108 | ||||
| -rw-r--r-- | service/src/stlfile.h | 5 | ||||
| -rw-r--r-- | service/src/test.sh | 11 | ||||
| -rw-r--r-- | service/src/tests/evil1.stl | 9 | ||||
| -rw-r--r-- | service/src/util.c | 66 | ||||
| -rw-r--r-- | service/src/util.h | 8 |
9 files changed, 220 insertions, 81 deletions
diff --git a/service/src/.gitignore b/service/src/.gitignore index e97b31a..a765305 100644 --- a/service/src/.gitignore +++ b/service/src/.gitignore @@ -1,3 +1,4 @@ printdoc +scans *.o vgcore.* diff --git a/service/src/msgs/welcome b/service/src/msgs/welcome index c470659..b4eb256 100644 --- a/service/src/msgs/welcome +++ b/service/src/msgs/welcome @@ -1,2 +1,2 @@ Welcome to PrintDoc! -Upload an stl file and we'll analyze it! +Submit a stl file and we'll analyze it! diff --git a/service/src/printdoc.c b/service/src/printdoc.c index d7a4131..951f40b 100644 --- a/service/src/printdoc.c +++ b/service/src/printdoc.c @@ -3,6 +3,9 @@ #include <stdarg.h> #include <unistd.h> #include <dirent.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <time.h> #include "stlfile.h" #include "util.h" @@ -12,9 +15,6 @@ struct command { void (*func)(char *); }; -const char* ask(const char *fmtstr, ...); -void dump(const char *filepath); - void search_cmd(char *arg); void submit_cmd(char *arg); void list_cmd(char *arg); @@ -30,39 +30,6 @@ struct command commands[] = { struct parseinfo lastrun; const char *resultdir; -const char* -ask(const char *fmtstr, ...) -{ - static char linebuf[256]; - va_list ap; - int fail; - - va_start(ap, fmtstr); - vprintf(fmtstr, ap); - va_end(ap); - - fail = !fgets(linebuf, sizeof(linebuf), stdin); - - if (!fail) linebuf[strlen(linebuf) - 1] = '\0'; - - return fail ? "" : linebuf; -} - -void -dump(const char *filename) -{ - char buf[256]; - FILE *f; - int nb; - - if (!(f = fopen(filename, "r"))) return; - - while ((nb = fread(buf, 1, sizeof(buf), f))) - printf("%.*s\n", nb, buf); - - fclose(f); -} - void search_cmd(char *arg) { @@ -82,14 +49,14 @@ search_cmd(char *arg) i = 0; while ((de = readdir(d))) { - if (de->d_type != DT_DIR && !strncmp(hash, de->d_name, strlen(hash))) { + if (de->d_type != DT_DIR && !strpfcmp(hash, de->d_name)) { printf("%i : %s\n", i, de->d_name); i++; } } if (i == 0) { - fprintf(stderr, "Sorry, couldnt find any matching scan result!\n"); + fprintf(stderr, "Sorry, couldnt find a matching scan result!\n"); goto cleanup; } else { which = strtoul(ask("Which of these results?\n"), &end, 10); @@ -100,7 +67,7 @@ search_cmd(char *arg) } while ((de = readdir(d))) { - if (de->d_type != DT_DIR && !strncmp(hash, de->d_name, strlen(hash))) { + if (de->d_type != DT_DIR && !strpfcmp(hash, de->d_name)) { if (i == which) { resultfile = aprintf("scans/%s/info", strdup(de->d_name)); break; @@ -117,6 +84,44 @@ cleanup: closedir(d); } +int +save_submission(char *stldata, int stlsize) +{ + DIR *d; + FILE *f; + char *dirpath = NULL, *infopath = NULL, *modelpath = NULL; + + dirpath = aprintf("%s/%s-%i", resultdir, lastrun.hash, time(NULL)); + if (mkdir(dirpath, S_IRWXU | S_IRWXG | S_IRWXO)) goto fail; + + modelpath = aprintf("%s/%s", dirpath, "model"); + if (!(f = fopen(modelpath, "w+"))) goto fail; + if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail; + fclose(f); + + infopath = aprintf("%s/%s", dirpath, "info"); + if (!(f = fopen(infopath, "w+"))) goto fail; + if (save_info(&lastrun, f) != OK) goto fail; + fclose(f); + + free(dirpath); + free(modelpath); + free(infopath); + + return OK; + +fail: + remove(infopath); + remove(modelpath); + remove(dirpath); + + free(dirpath); + free(modelpath); + free(infopath); + + return FAIL; +} + void submit_cmd(char *arg) { @@ -139,10 +144,10 @@ submit_cmd(char *arg) lastrun.valid = parse_file(&lastrun, contents, len); if (lastrun.valid) { - print_info(&lastrun); - save_info(&lastrun, resultdir); - printf("Your file was saved with ID %s!\n", lastrun.hash); - printf("You may retrieve your results via the 'search' function\n"); + if (save_submission(contents, len) != OK) + fprintf(stderr, "Failed to save your submission!\n"); + else + printf(">> Your file was saved with ID %s!\n", lastrun.hash); } free(contents); diff --git a/service/src/stlfile.c b/service/src/stlfile.c index 6a59dd1..4f6d0e1 100644 --- a/service/src/stlfile.c +++ b/service/src/stlfile.c @@ -68,16 +68,16 @@ skip_set(char *p, const char *set) } char* -consume_arg(char **start) +consume_arg(char **start, char **end) { char *p, *tmp; p = skip_set(*start, wsset); for (; !strchr(wsset, *p); p++); if (!*p) return NULL; - *p = '\0'; tmp = *start; *start = p + 1; + *end = p; return tmp; } @@ -107,7 +107,7 @@ consume_keyword(char **start) int parse_file_ascii(struct parseinfo *info, char *buf, size_t len) { - char *bp, *arg, *prev, *tmp; + char *bp, *arg, *prev, *tmp, *end; struct stack states; float farg; int i, kw; @@ -117,6 +117,8 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) info->type = TYPE_ASCII; info->loopcount = 0; + memset(info->header, 0, 80); + for (i = 0; i < 3; i++) { info->bbmin[i] = INFINITY; info->bbmax[i] = -INFINITY; @@ -130,8 +132,8 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) if (stack_ind(&states, KW_SOLID_BEGIN) != -1) PARSE_FAIL("Multiple nested solids!\n"); tmp = bp; - if (!consume_keyword(&bp) && (arg = consume_arg(&bp))) { - strncpy(info->extra, arg, sizeof(info->extra)); + if (!consume_keyword(&bp) && (arg = consume_arg(&bp, &end))) { + info->modelname = strndup(arg, end - arg); } else { bp = tmp; } @@ -140,9 +142,9 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) if ((kw = stack_pop(&states)) != STATE_SOLID) PARSE_FAIL("Improper nesting, parent: %s\n", kwmap[kw].str); tmp = bp; - if (*info->extra && !consume_keyword(&bp) - && (arg = consume_arg(&bp))) { - if (strncmp(info->extra, arg, sizeof(info->extra))) + if (info->modelname && !consume_keyword(&bp) + && (arg = consume_arg(&bp, &end))) { + if (strncmp(info->modelname, arg, end - arg)) PARSE_FAIL("Solid end/begin names do not match!\n"); } else { bp = tmp; @@ -163,10 +165,10 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) if (stack_ind(&states, KW_LOOP_BEGIN) != -1) PARSE_FAIL("Multiple nested facets!\n"); for (i = 0; i < 3; i++) { - if (!(arg = consume_arg(&bp))) + if (!(arg = consume_arg(&bp, &end))) PARSE_FAIL("Facet with less than 3 args!\n"); farg = strtof(arg, &tmp); - if (*tmp) + if (!strchr(wsset, *tmp)) PARSE_FAIL("Facet with invalid arg '%s'!\n", arg); } break; @@ -176,10 +178,10 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) break; case KW_VERTEX: for (i = 0; i < 3; i++) { - if (!(arg = consume_arg(&bp))) + if (!(arg = consume_arg(&bp, &end))) PARSE_FAIL("Vertex with less than 3 args!\n"); farg = strtof(arg, &tmp); - if (*tmp) + if (!strchr(wsset, *tmp)) PARSE_FAIL("Vertex with invalid arg '%s'!\n", arg); info->bbmin[i] = MIN(info->bbmin[i], farg); info->bbmax[i] = MAX(info->bbmax[i], farg); @@ -215,7 +217,7 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) if (len < 84) PARSE_FAIL("Truncated data! (header missing)\n"); - memcpy(info->extra, buf, 80); + memcpy(info->header, buf, 80); bp = buf + 80; info->loopcount = le32toh(*(uint32_t*)bp); @@ -249,33 +251,79 @@ int parse_file(struct parseinfo *info, char *buf, size_t len) { int status; + const char *tmp; char *bp; if (info->valid) free_info(info); - /* check bin vs ascii */ for (bp = buf; strchr(wsset, *bp); bp++); + /* check bin vs ascii with first keyword */ status = !strncmp("solid ", bp, 6) ? parse_file_ascii(info, buf, len) : parse_file_bin(info, buf, len); if (status == FAIL) return FAIL; - /* create model hash */ - strncpy(info->hash, mhash(info->extra, sizeof(info->extra)), MHASHLEN); + if (!info->modelname) { + tmp = ask("Please enter your model name:\n"); + if (strlen(tmp) < 4) { + fprintf(stderr, "Model name is too short!\n"); + return FAIL; + } + info->modelname = checkp(strdup(tmp)); + } + + info->hash = checkp(strdup(mhash(info->modelname, -1))); return OK; } int -save_info(struct parseinfo *info, const char *resultdir) +save_info(struct parseinfo *info, FILE *f) { - /* <HASH>: - * - info : binary file info - * - model : original stl file - */ + size_t nwrote = 0; + int i; - return FAIL; + nwrote += fwrite(&info->type, sizeof(int), 1, f); + nwrote += fwrite(&info->loopcount, sizeof(int), 1, f); + + for (i = 0; i < 3; i++) { + nwrote += fwrite(&info->bbmin[i], sizeof(float), 1, f); + nwrote += fwrite(&info->bbmax[i], sizeof(float), 1, f); + } + + nwrote += fwrite(info->header, 80, 1, f); + + if (nwrote != 9) return FAIL; + + fputstr(f, info->modelname); + fputstr(f, info->hash); + + return OK; +} + +int +load_info(struct parseinfo *info, FILE *f) +{ + size_t nread = 0; + int i; + + nread += fread(&info->type, sizeof(int), 1, f); + nread += fread(&info->loopcount, sizeof(int), 1, f); + + for (i = 0; i < 3; i++) { + nread += fwrite(&info->bbmin[i], sizeof(float), 1, f); + nread += fwrite(&info->bbmax[i], sizeof(float), 1, f); + } + + nread += fread(info->header, 80, 1, f); + + if (nread != 9) return FAIL; + + freadstr(f, &info->modelname); + freadstr(f, &info->hash); + + return OK; } void @@ -285,16 +333,16 @@ print_info(struct parseinfo *info) #define FILTERCHAR(c) ((c) >= 32 ? (c) : ' ') - if (info->type == TYPE_ASCII) { - printf("Modelname: %s\n", info->extra); - } else { - printf("Model Header:\n"); + printf("Name: %s\n", info->modelname); + + if (info->type == TYPE_BIN) { + printf("Header:\n"); for (i = 0; i < 80; i += k) { for (k = 0; k < MIN(80 - i, 20); k++) - printf(" %02x", (uint8_t) info->extra[i+k]); + printf(" %02x", (uint8_t) info->header[i+k]); printf(" | "); for (k = 0; k < MIN(80 - i, 20); k++) - printf("%c", FILTERCHAR(info->extra[i+k])); + printf("%c", FILTERCHAR(info->header[i+k])); printf("\n"); } } @@ -310,7 +358,7 @@ print_info(struct parseinfo *info) void free_info(struct parseinfo *info) { - NULLFREE(info->stlpath); - NULLFREE(info->infopath); + NULLFREE(info->hash); + NULLFREE(info->modelname); info->valid = 0; } diff --git a/service/src/stlfile.h b/service/src/stlfile.h index e31a8c9..8a52ea9 100644 --- a/service/src/stlfile.h +++ b/service/src/stlfile.h @@ -38,15 +38,14 @@ struct stack { }; struct parseinfo { - char extra[80], hash[MHASHLEN+1]; + char header[80], *hash, *modelname; unsigned int loopcount; float bbmin[3], bbmax[3]; int type, valid; - char *infopath, *stlpath; }; int parse_file(struct parseinfo *info, char *buf, size_t len); -int save_info(struct parseinfo *info, const char *resultdir); +int save_info(struct parseinfo *info, FILE *f); void print_info(struct parseinfo *info); void free_info(struct parseinfo *info); diff --git a/service/src/test.sh b/service/src/test.sh index 4627d81..9a905b7 100644 --- a/service/src/test.sh +++ b/service/src/test.sh @@ -24,6 +24,8 @@ checkleaks() { fi } +export RESULTDIR="scans" + announce "Trying ASCII STL" ( echo "submit" @@ -36,5 +38,14 @@ announce "Trying BIN STL" echo "submit" cat tests/sample-binary.stl | wc -c cat tests/sample-binary.stl + echo "testname" +) | checkleaks + + +announce "Testing Proof-Of-Concept" +( + echo "submit" + cat tests/evil1.stl | wc -c + cat tests/evil1.stl ) | checkleaks diff --git a/service/src/tests/evil1.stl b/service/src/tests/evil1.stl new file mode 100644 index 0000000..2aac44a --- /dev/null +++ b/service/src/tests/evil1.stl @@ -0,0 +1,9 @@ +solid test˙ + facet normal 0 0 1.0 + outer loop + vertex 1 0 0 + vertex 1 1 0 + vertex 0 1 0 + endloop + endfacet +endsolid
\ No newline at end of file diff --git a/service/src/util.c b/service/src/util.c index 946bc19..7d3317b 100644 --- a/service/src/util.c +++ b/service/src/util.c @@ -29,14 +29,14 @@ aprintf(const char *fmtstr, ...) va_copy(cpy, ap); va_start(cpy, fmtstr); - nb = vsnprintf(NULL, 0, fmtstr, ap); + nb = vsnprintf(NULL, 0, fmtstr, cpy); va_end(cpy); - if (nb <= 0) die("encountered invalid fmtstr!\n"); + if (nb <= 0) die("Invalid fmtstr!\n"); + str = checkp(malloc(nb+1)); - str = checkp(malloc(nb)); va_start(ap, fmtstr); - nb = vsnprintf(str, nb, fmtstr, ap); + nb = vsnprintf(str, nb+1, fmtstr, ap); va_end(ap); return str; @@ -71,4 +71,62 @@ mhash(const char *filename, int len) return buf; } +void +freadstr(FILE *f, char **dst) +{ + size_t start, len; + char c; + + start = ftell(f); + while ((c = fgetc(f)) != EOF && c) len++; + + *dst = calloc(len + 1, 1); + fread(*dst, len, 1, f); +} + +void +fputstr(FILE *f, char *s) +{ + fprintf(f, "%s", s); + fputc(0, f); +} + +const char* +ask(const char *fmtstr, ...) +{ + static char linebuf[256]; + va_list ap; + int fail; + + va_start(ap, fmtstr); + vprintf(fmtstr, ap); + va_end(ap); + + fail = !fgets(linebuf, sizeof(linebuf), stdin); + + if (!fail) linebuf[strlen(linebuf) - 1] = '\0'; + + return fail ? "" : linebuf; +} + +void +dump(const char *filename) +{ + char buf[256]; + FILE *f; + int nb; + + if (!(f = fopen(filename, "r"))) return; + + while ((nb = fread(buf, 1, sizeof(buf), f))) + printf("%.*s\n", nb, buf); + + fclose(f); +} + +int +strpfcmp(const char *prefix, const char *str) +{ + return strncmp(prefix, str, strlen(prefix)); +} diff --git a/service/src/util.h b/service/src/util.h index 303d9c9..d012f25 100644 --- a/service/src/util.h +++ b/service/src/util.h @@ -19,6 +19,14 @@ enum { FAIL = 0, OK = 1 }; void* checkp(void *p); void* die(const char *fmtstr, ...); char* aprintf(const char *fmtstr, ...); + const char* mhash(const char *filename, int len); +void freadstr(FILE *f, char **dst); +void fputstr(FILE *f, char *s); + +const char* ask(const char *fmtstr, ...); +void dump(const char *filepath); +int strpfcmp(const char *prefix, const char *str); + #endif /* UTIL_H */ |
