/* XML function stuff */ #include #include #include #include #include #include #ifndef STANDALONE # include "server.h" #endif #define XUC const xmlChar * char *my_strdup (const char *src) { char *targ = NULL; if (src != NULL) { targ = malloc(strlen(src) + 1); if (targ != NULL) { strcpy(targ, src); } } return targ; } static char *my_strndup (const char *src, size_t n) { char *targ = NULL; if (src != NULL && n > 0) { size_t len = strlen(src); if (len > n) { len = n; } targ = malloc(len + 1); if (targ != NULL) { *targ = '\0'; strncat(targ, src, len); } } return targ; } int validate_uploaded_file (const char *fname) { const char *dtdname = "dtd/gretlfunc.dtd"; xmlValidCtxtPtr cvp; xmlDocPtr doc; xmlDtdPtr dtd; int err = 0; doc = xmlParseFile(fname); if (doc == NULL) { printf("Error: couldn't parse %s", fname); return 1; } dtd = xmlParseDTD(NULL, (const xmlChar *) dtdname); if (dtd == NULL) { puts("Error: couldn't parse DTD"); xmlFreeDoc(doc); return 1; } cvp = xmlNewValidCtxt(); if (cvp == NULL) { puts("Error: couldn't allocate validation context"); xmlFreeDtd(dtd); xmlFreeDoc(doc); return 1; } cvp->userData = (void *) stdout; cvp->error = (xmlValidityErrorFunc) fprintf; cvp->warning = (xmlValidityWarningFunc) fprintf; if (!xmlValidateDtd(cvp, doc, dtd)) { puts("Error: document does not validate against DTD"); err = 1; } else { puts("Document validated successfully against DTD"); } xmlFreeValidCtxt(cvp); xmlFreeDtd(dtd); xmlFreeDoc(doc); return err; } static int xml_open_doc_root (const char *fname, const char *rootname, xmlDocPtr *pdoc, xmlNodePtr *pnode) { xmlDocPtr doc; xmlNodePtr node = NULL; int err = 0; *pdoc = NULL; *pnode = NULL; doc = xmlParseFile(fname); if (doc == NULL) { err = 1; } if (!err) { node = xmlDocGetRootElement(doc); if (node == NULL) { xmlFreeDoc(doc); err = 1; } } if (!err) { if (xmlStrcmp(node->name, (XUC) rootname)) { xmlFreeDoc(doc); err = 1; } } if (!err) { *pdoc = doc; *pnode = node; } return err; } static int xml_node_get_trimmed_string (xmlNodePtr node, xmlDocPtr doc, char **pstr) { char *tmp; char *s; int i, len, ret = 0; tmp = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if (tmp != NULL) { s = tmp; s += strspn(s, " \t\n\r"); len = strlen(s); for (i=len-1; i>=0; i--) { if (s[i] == ' ' || s[i] == '\t' || s[i] == '\r' || s[i] == '\n') { len--; } else { break; } } if (len == strlen(tmp)) { *pstr = tmp; ret = 1; } else if (len > 0) { *pstr = my_strndup(s, len); if (*pstr != NULL) { ret = 1; } free(tmp); } } return ret; } static void normalize_date (char *s) { while (*s) { if (*s == '/' || *s == ':') { *s = '-'; } s++; } } int ok_date (int yr, int mon, int day) { int mdays[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (yr < 2000 || yr > 2050) { return 0; } if (mon < 1 || mon > 12) { return 0; } if (day < 1 || day > mdays[mon - 1]) { return 0; } return 1; } #ifndef STANDALONE static int print_fn_file_info (const char *fname, int version, int html) { xmlDocPtr doc = NULL; xmlNodePtr node = NULL; xmlNodePtr sub; struct stat sbuf; char fullname[128]; char *author = NULL; char *verstr = NULL; char *date = NULL; char *descrip = NULL; int txt_show_verstr = 0; int yr, mon, day; int got, want = 2; int err = 0; sprintf(fullname, "fnfiles/%s", fname); if (stat(fullname, &sbuf) == -1) { return 1; } #if SDEBUG fprintf(fdb, "print_fn_file_info: looking at %s\n", fullname); #endif err = xml_open_doc_root(fullname, "gretl-functions", &doc, &node); if (err) { #if SDEBUG fprintf(fdb, "error reading %s\n", fullname); #endif return err; } got = 0; if (version > 162) { txt_show_verstr = 1; } if (html) { want += 2; } else if (txt_show_verstr) { want++; } node = node->xmlChildrenNode; while (node != NULL) { if (!xmlStrcmp(node->name, (XUC) "gretl-function-package")) { sub = node->xmlChildrenNode; while (sub != NULL) { if (!xmlStrcmp(sub->name, (XUC) "description")) { xml_node_get_trimmed_string(sub, doc, &descrip); got++; } else if (!xmlStrcmp(sub->name, (XUC) "date")) { xml_node_get_trimmed_string(sub, doc, &date); got++; } else if (!xmlStrcmp(sub->name, (XUC) "author")) { if (html) { xml_node_get_trimmed_string(sub, doc, &author); got++; } } else if (!xmlStrcmp(sub->name, (XUC) "version")) { if (html || txt_show_verstr) { xml_node_get_trimmed_string(sub, doc, &verstr); got++; } } if (got == want) break; sub = sub->next; } if (got == want) break; } node = node->next; } if (doc != NULL) { xmlFreeDoc(doc); } if (descrip == NULL) { #if SDEBUG fputs("description missing\n", fdb); #endif err = 1; } else if (date == NULL) { #if SDEBUG fputs("date missing\n", fdb); #endif err = 1; } else { int nf; normalize_date(date); nf = sscanf(date, "%d-%d-%d", &yr, &mon, &day); if (nf != 3 || !ok_date(yr, mon, day)) { #if SDEBUG fprintf(fdb, "date '%s' is bad\n", date); #endif err = 1; } } if (!err) { if (html) { printf(""); printf("%s", fname); printf("

%s

", author? author : "unknown"); printf("

%s

", verstr? verstr : "unknown"); printf("

%s

", date); printf("

%s

", descrip); puts(""); } else { printf("%8d Foo %s %02d 00:00:00 %d %15s\n", (int) sbuf.st_size, month_name(mon), day, yr, fname); printf("# %s\n", descrip); if (txt_show_verstr) { printf("# %s\n", verstr); } } } free(author); free(verstr); free(descrip); free(date); return err; } void emit_function_info (char **fnames, int nfiles, int version, int html) { int i; LIBXML_TEST_VERSION; xmlKeepBlanksDefault(0); for (i=0; i 4 && !strcmp(fname + len - 4, ".gfn")) { ; } else { strcat(fname, ".gfn"); } } int stream_function_file (char *fname) { struct stat fbuf; char buf[BUFSIZE]; size_t bgot; FILE *fp; maybe_add_gfn_ext(fname); if (chdir("fnfiles")) { return 1; } if (stat(fname, &fbuf)) { content_line(TEXT); printf("Couldn't access %s on server\n", fname); return 1; } fp = fopen(fname, "rb"); if (fp == NULL) { content_line(TEXT); printf("Couldn't access %s on server\n", fname); return 1; } content_line(XML); printf("Content-Length: %lu\n\n", fbuf.st_size); while (1) { if ((bgot = fread(buf, 1, BUFSIZE, fp)) > 0) { fwrite(buf, 1, bgot, stdout); } else { break; } } fclose(fp); return 0; } #else int main (int argc, char **argv) { int err; if (argc != 2) { fprintf(stderr, "Give the name of one gfn file to test\n"); return 1; } err = validate_uploaded_file(argv[1]); fprintf(stderr, "Got err = %d\n", err); return 0; } #endif