/* This file is part of Eclat. Copyright (C) 2012-2018 Sergey Poznyakoff. Eclat is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Eclat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eclat. If not, see . */ #include "eclat.h" extern FILE *xml_dump_file; static void dumpxml(void *ptr, size_t realsize) { static int open_failed = 0; if (open_failed) return; if (!xml_dump_file) { xml_dump_file = fopen(XML_DUMP_FILE_NAME, "w"); if (!xml_dump_file) { err("cannot open dump file %s: %s", XML_DUMP_FILE_NAME, strerror(errno)); open_failed = 1; return; } } fwrite(ptr, realsize, 1, xml_dump_file); } static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *data) { size_t realsize = size * nmemb; XML_Parser parser = data; enum XML_Status status; int line = XML_GetCurrentLineNumber(parser); int column = XML_GetCurrentColumnNumber(parser); if (debug_level(ECLAT_DEBCAT_MAIN) >= 10 || debug_level(ECLAT_DEBCAT_DUMP)) dumpxml(ptr, realsize); status = XML_Parse(parser, ptr, realsize, 0); if (status == XML_STATUS_ERROR) { enum XML_Error error = XML_GetErrorCode(parser); line = XML_GetCurrentLineNumber(parser); column = XML_GetCurrentColumnNumber(parser); /* FIXME: better diagnostics. */ die(EX_SOFTWARE, "XML parse error at %d:%d: %s", line, column, XML_ErrorString(error)); } return realsize; } static int eclat_io_setup(struct eclat_io *io, int errfatal) { io->curl = curl_easy_init(); if (!io->curl) { if (errfatal) die(EX_UNAVAILABLE, "curl_easy_init failed"); else { err("curl_easy_init failed"); return 1; } } eclat_set_curl_trace(io->curl, debug_level(ECLAT_DEBCAT_CURL)); /* Create XML parser */ io->parser = XML_ParserCreate("UTF-8"); if (!io->parser) { if (errfatal) die(EX_SOFTWARE, "cannot create XML parser"); else { err("cannot create XML parser"); return 1; } } XML_SetElementHandler(io->parser, eclat_partial_tree_start_handler, eclat_partial_tree_end_handler); XML_SetCharacterDataHandler(io->parser, eclat_partial_tree_data_handler); io->part = eclat_partial_tree_create(); XML_SetUserData(io->parser, io->part); curl_easy_setopt(io->curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(io->curl, CURLOPT_WRITEDATA, io->parser); if (use_ssl) { curl_easy_setopt(io->curl, CURLOPT_SSL_VERIFYPEER, (long) ssl_verify_peer); if (ssl_verify_peer) { if (ssl_ca_file) curl_easy_setopt(io->curl, CURLOPT_CAINFO, ssl_ca_file); if (ssl_ca_path) curl_easy_setopt(io->curl, CURLOPT_CAPATH, ssl_ca_path); } } return 0; } void eclat_io_free(struct eclat_io *io) { if (!io) return; eclat_io_shutdown(io); if (io->part) eclat_partial_tree_destroy(io->part); if (io->parser) XML_ParserFree(io->parser); free(io); } struct eclat_io * eclat_io_init(int onerr) { struct eclat_io *io; io = grecs_zalloc(sizeof(*io)); if (eclat_io_setup(io, onerr)) { eclat_io_free(io); return NULL; } return io; } void eclat_io_shutdown(struct eclat_io *io) { if (io->curl) { curl_easy_cleanup(io->curl); io->curl = NULL; } } struct grecs_node * eclat_io_finish(struct eclat_io *io) { struct grecs_node *p; eclat_io_shutdown(io); XML_Parse(io->parser, "", 0, 1); p = eclat_partial_tree_finish(io->part); io->part = NULL; return p; }