#include #include #include #include #include #include #include #include #include #include "s1kd_tools.h" #include "stylesheets.h" #define PROG_NAME "s1kd-neutralize" #define VERSION "1.11.0" #define ERR_PREFIX PROG_NAME ": ERROR: " #define INF_PREFIX PROG_NAME ": INFO: " #define E_BAD_LIST ERR_PREFIX "Could not read list: %s\n" #define I_NEUTRALIZE INF_PREFIX "Adding neutral metadata to %s...\n" static enum verbosity { QUIET, NORMAL, VERBOSE } verbosity = NORMAL; static void neutralizeFile(const char *fname, const char *outfile, bool overwrite, bool namesp) { xmlDocPtr doc, res, styledoc, orig; xsltStylesheetPtr style; xmlNodePtr oldroot; if (verbosity >= VERBOSE) { fprintf(stderr, I_NEUTRALIZE, fname); } orig = read_xml_doc(fname); doc = xmlCopyDoc(orig, 1); styledoc = read_xml_mem((const char *) stylesheets_xlink_xsl, stylesheets_xlink_xsl_len); style = xsltParseStylesheetDoc(styledoc); res = xsltApplyStylesheet(style, doc, NULL); xmlFreeDoc(doc); xsltFreeStylesheet(style); doc = res; styledoc = read_xml_mem((const char *) stylesheets_rdf_xsl, stylesheets_rdf_xsl_len); style = xsltParseStylesheetDoc(styledoc); res = xsltApplyStylesheet(style, doc, NULL); xmlFreeDoc(doc); xsltFreeStylesheet(style); if (namesp) { doc = res; styledoc = read_xml_mem((const char *) stylesheets_namespace_xsl, stylesheets_namespace_xsl_len); style = xsltParseStylesheetDoc(styledoc); res = xsltApplyStylesheet(style, doc, NULL); xmlFreeDoc(doc); xsltFreeStylesheet(style); } oldroot = xmlDocGetRootElement(orig); xmlUnlinkNode(oldroot); xmlFreeNode(oldroot); xmlDocSetRootElement(orig, xmlCopyNode(xmlDocGetRootElement(res), 1)); if (overwrite) { save_xml_doc(orig, fname); } else { save_xml_doc(orig, outfile); } xmlFreeDoc(res); xmlFreeDoc(orig); } static void neutralizeList(const char *path, const char *outfile, bool overwrite, bool namesp) { FILE *f; char line[PATH_MAX]; if (path) { if (!(f = fopen(path, "r"))) { if (verbosity >= NORMAL) { fprintf(stderr, E_BAD_LIST, path); } return; } } else { f = stdin; } while (fgets(line, PATH_MAX, f)) { strtok(line, "\t\r\n"); neutralizeFile(line, outfile, overwrite, namesp); } if (path) { fclose(f); } } static void deneutralizeFile(const char *fname, const char *outfile, bool overwrite) { xmlDocPtr doc, res, styledoc, orig; xsltStylesheetPtr style; xmlNodePtr oldroot; if (verbosity >= VERBOSE) { fprintf(stderr, I_NEUTRALIZE, fname); } orig = read_xml_doc(fname); doc = xmlCopyDoc(orig, 1); styledoc = read_xml_mem((const char *) stylesheets_delete_xsl, stylesheets_delete_xsl_len); style = xsltParseStylesheetDoc(styledoc); res = xsltApplyStylesheet(style, doc, NULL); xmlFreeDoc(doc); xsltFreeStylesheet(style); oldroot = xmlDocGetRootElement(orig); xmlUnlinkNode(oldroot); xmlFreeNode(oldroot); xmlDocSetRootElement(orig, xmlCopyNode(xmlDocGetRootElement(res), 1)); if (overwrite) { save_xml_doc(orig, fname); } else { save_xml_doc(orig, outfile); } xmlFreeDoc(res); xmlFreeDoc(orig); } static void deneutralizeList(const char *path, const char *outfile, bool overwrite) { FILE *f; char line[PATH_MAX]; if (path) { if (!(f = fopen(path, "r"))) { if (verbosity >= NORMAL) { fprintf(stderr, E_BAD_LIST, path); } return; } } else { f = stdin; } while (fgets(line, PATH_MAX, f)) { strtok(line, "\t\r\n"); deneutralizeFile(line, outfile, overwrite); } if (path) { fclose(f); } } static void show_help(void) { puts("Usage: " PROG_NAME " [-o ] [-Dflnqvh?] [...]"); puts(""); puts("Options:"); puts(" -D, --delete Remove neutral metadata."); puts(" -f, --overwrite Overwrite CSDB objects automatically."); puts(" -h, -?, --help Show usage message."); puts(" -l, --list Treat input as list of CSDB objects."); puts(" -n, --namespace Include IETP namespaces on elements."); puts(" -o, --out Output to instead of stdout."); puts(" -q, --quiet Quiet mode."); puts(" -v, --verbose Verbose output."); puts(" --version Show version information."); LIBXML2_PARSE_LONGOPT_HELP } static void show_version(void) { printf("%s (s1kd-tools) %s\n", PROG_NAME, VERSION); printf("Using libxml %s and libxslt %s\n", xmlParserVersion, xsltEngineVersion); } int main(int argc, char **argv) { int i; char *outfile = strdup("-"); bool overwrite = false; bool islist = false; bool namesp = false; bool delete = false; const char *sopts = "Dflno:qvh?"; struct option lopts[] = { {"version" , no_argument , 0, 0}, {"help" , no_argument , 0, 'h'}, {"delete" , no_argument , 0, 'D'}, {"overwrite", no_argument , 0, 'f'}, {"list" , no_argument , 0, 'l'}, {"namespace", no_argument , 0, 'n'}, {"out" , required_argument, 0, 'o'}, {"quiet" , no_argument , 0, 'q'}, {"verbose" , no_argument , 0, 'v'}, LIBXML2_PARSE_LONGOPT_DEFS {0, 0, 0, 0} }; int loptind = 0; while ((i = getopt_long(argc, argv, sopts, lopts, &loptind)) != -1) { switch (i) { case 0: if (strcmp(lopts[loptind].name, "version") == 0) { show_version(); return 0; } LIBXML2_PARSE_LONGOPT_HANDLE(lopts, loptind, optarg) break; case 'D': delete = true; break; case 'f': overwrite = true; break; case 'l': islist = true; break; case 'n': namesp = true; break; case 'o': free(outfile); outfile = strdup(optarg); break; case 'q': --verbosity; break; case 'v': ++verbosity; break; case 'h': case '?': show_help(); exit(0); } } if (delete) { if (optind < argc) { for (i = optind; i < argc; ++i) { if (islist) { deneutralizeList(argv[i], outfile, overwrite); } else { deneutralizeFile(argv[i], outfile, overwrite); } } } else if (islist) { deneutralizeList(NULL, outfile, overwrite); } else { deneutralizeFile("-", outfile, false); } } else { if (optind < argc) { for (i = optind; i < argc; ++i) { if (islist) { neutralizeList(argv[i], outfile, overwrite, namesp); } else { neutralizeFile(argv[i], outfile, overwrite, namesp); } } } else if (islist) { neutralizeList(NULL, outfile, overwrite, namesp); } else { neutralizeFile("-", outfile, false, namesp); } } free(outfile); xsltCleanupGlobals(); xmlCleanupParser(); return 0; }