aboutsummaryrefslogtreecommitdiffstats
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/src/.gitignore1
-rw-r--r--service/src/msgs/welcome2
-rw-r--r--service/src/printdoc.c91
-rw-r--r--service/src/stlfile.c108
-rw-r--r--service/src/stlfile.h5
-rw-r--r--service/src/test.sh11
-rw-r--r--service/src/tests/evil1.stl9
-rw-r--r--service/src/util.c66
-rw-r--r--service/src/util.h8
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 */