コード例 #1
0
ファイル: replyparser.c プロジェクト: gnb/Droplet
dpl_status_t
dpl_s3_parse_list_bucket(const dpl_ctx_t *ctx,
                         const char *buf,
                         int len,
                         dpl_vec_t *objects,
                         dpl_vec_t *common_prefixes)
{
  xmlParserCtxtPtr ctxt = NULL;
  xmlDocPtr doc = NULL;
  int ret;
  xmlNode *tmp;
  //ssize_t cc;

  //cc = write(1, buf, len);

  if ((ctxt = xmlNewParserCtxt()) == NULL)
    {
      ret = DPL_FAILURE;
      goto end;
    }

  doc = xmlCtxtReadMemory(ctxt, buf, len, NULL, NULL, 0u);
  if (NULL == doc)
    {
      ret = DPL_FAILURE;
      goto end;
    }

  for (tmp = xmlDocGetRootElement(doc); NULL != tmp; tmp = tmp->next)
    {
      if (tmp->type == XML_ELEMENT_NODE)
        {
          DPRINTF("name: %s\n", tmp->name);

          if (!strcmp((char *) tmp->name, "ListBucketResult"))
            {
              ret = parse_list_bucket_children(tmp->children, objects, common_prefixes);
              if (DPL_SUCCESS != ret)
                return DPL_FAILURE;
            }
        }
      else if (tmp->type == XML_TEXT_NODE)
        {
          DPRINTF("content: %s\n", tmp->content);
        }
    }

  ret = DPL_SUCCESS;

 end:

  if (NULL != doc)
    xmlFreeDoc(doc);

  if (NULL != ctxt)
    xmlFreeParserCtxt(ctxt);

  return ret;
}
コード例 #2
0
ファイル: multipart.c プロジェクト: neverstoplwy/Droplet
static dpl_status_t
_multipart_parse_init(const dpl_ctx_t *ctx,
                      const char *buf, int len,
                      const char **uploadidp)
{
    dpl_status_t          ret = DPL_SUCCESS;
    xmlParserCtxtPtr      ctxt;
    xmlDocPtr             doc;
    xmlNode               *elem;

    ctxt = xmlNewParserCtxt();
    if (ctxt == NULL)
        return DPL_FAILURE;

    doc = xmlCtxtReadMemory(ctxt, buf, len, NULL, NULL, 0u);
    if (doc == NULL) {
        xmlFreeParserCtxt(ctxt);
        return DPL_FAILURE;
    }

    elem = xmlDocGetRootElement(doc);
    while (elem != NULL)
    {
        if (elem->type == XML_ELEMENT_NODE)
        {
            if (!strcmp((char *) elem->name, "InitiateMultipartUploadResult"))
            {
                elem = elem->children;
                ret = DPL_FAILURE;
                while (elem != NULL)
                {
                    if (elem->type == XML_ELEMENT_NODE)
                    {
                        if (!strcmp((char *) elem->name, "UploadId"))
                        {
                            ret = DPL_SUCCESS;
                            *uploadidp = strdup((char *) elem->children->content);
                            if (NULL == *uploadidp)
                                ret = DPL_ENOMEM;
                            break;
                        }
                    }
                    elem = elem->next;
                }
                // Reaching here means that we already browsed
                // the InitiateMultipartUploadResult xml subtree,
                // whether we found UploadId or not.
                break;
            }
        }
        elem = elem->next;
    }

    xmlFreeDoc(doc);
    xmlFreeParserCtxt(ctxt);

    return ret;
}
コード例 #3
0
ファイル: export.cpp プロジェクト: alerque/bibledit
void Editor_Export::load (string html)
{
  // The web editor may insert non-breaking spaces. Convert them to normal ones.
  html = filter_string_str_replace (" ", " ", html);
  
  // The web editor produces <hr> following the HTML specs, but Bibledit needs
  // <hr/> for its XML parser.
  html = filter_string_str_replace ("<hr>", "<hr/>", html);
  
  // The user may add several spaces in sequence. Convert them to single spaces.
  html = filter_string_str_replace ("   ", " ", html);
  html = filter_string_str_replace ("  ", " ", html);
  
  // DOMDocument deals well with imperfect markup, but it may throw warnings to the default error handler.
  // Therefore keep the errors separate.
  xmlGenericErrorFunc handler = (xmlGenericErrorFunc) error_handler;
  initGenericErrorDefaultFunc (&handler);
  
  // To help loadHTML() process utf8 correctly, set the correct meta tag before any other text.
  /*
  string prefix =
  "<!DOCTYPE html>\n"
  "<html>\n"
  "<head>\n"
  "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n"
  "</head>\n"
  "<body>\n";
  string suffix =
  "\n"
  "</body>\n"
  "</html>\n";
  string xml = prefix + html + suffix;
  htmlParserCtxtPtr context = htmlNewParserCtxt();
  document = htmlCtxtReadMemory (context, xml.c_str(), xml.length(), "", "UTF-8", HTML_PARSE_RECOVER);
  htmlFreeParserCtxt (context);
   */

  // On Android, the HTML parser fails. It returns a NULL document.
  // Therefore use the XML parser instead of the HTML one.
  string prefix =
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  "<html>\n"
  "<head>\n"
  "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"></meta>\n"
  "</head>\n"
  "<body>\n";
  string suffix =
  "\n"
  "</body>\n"
  "</html>\n";
  string xml = prefix + html + suffix;
  xmlParserCtxtPtr context = xmlNewParserCtxt();
  document = xmlCtxtReadMemory (context, xml.c_str(), xml.length(), "", "UTF-8", XML_PARSE_RECOVER);
  xmlFreeParserCtxt (context);
}
コード例 #4
0
bool XSLStyleSheet::parseString(const String& string, bool)
{
    // Parse in a single chunk into an xmlDocPtr
    const UChar BOM = 0xFEFF;
    const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
    setLoaderForLibXMLCallbacks(docLoader());
    if (!m_stylesheetDocTaken)
        xmlFreeDoc(m_stylesheetDoc);
    m_stylesheetDocTaken = false;

#if ENABLE(INSPECTOR)
    Console* console = 0;
    if (Frame* frame = ownerDocument()->frame())
        console = frame->domWindow()->console();
    xmlSetStructuredErrorFunc(console, XSLTProcessor::parseErrorFunc);
    xmlSetGenericErrorFunc(console, XSLTProcessor::genericErrorFunc);
#endif

    const char* buffer = reinterpret_cast<const char*>(string.characters());
    int size = string.length() * sizeof(UChar);

    xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(buffer, size);

    if (m_parentStyleSheet) {
        // The XSL transform may leave the newly-transformed document
        // with references to the symbol dictionaries of the style sheet
        // and any of its children. XML document disposal can corrupt memory
        // if a document uses more than one symbol dictionary, so we
        // ensure that all child stylesheets use the same dictionaries as their
        // parents.
        xmlDictFree(ctxt->dict);
        ctxt->dict = m_parentStyleSheet->m_stylesheetDoc->dict;
        xmlDictReference(ctxt->dict);
    }

    m_stylesheetDoc = xmlCtxtReadMemory(ctxt, buffer, size,
                                        href().utf8().data(),
                                        BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",
                                        XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);
    xmlFreeParserCtxt(ctxt);

    loadChildSheets();

    xmlSetStructuredErrorFunc(0, 0);
    xmlSetGenericErrorFunc(0, 0);

    setLoaderForLibXMLCallbacks(0);
    return m_stylesheetDoc;
}
コード例 #5
0
ファイル: libxml2_loader.cpp プロジェクト: mayfourth/mapnik
    void load_string(std::string const& buffer, xml_node &node, std::string const & base_path)
    {
        if (!base_path.empty())
        {
            boost::filesystem::path path(base_path);
            if (!boost::filesystem::exists(path)) {
                throw config_error(std::string("Could not locate base_path '") +
                                   base_path + "': file or directory does not exist");
            }
        }

        xmlDocPtr doc = xmlCtxtReadMemory(ctx_, buffer.data(), buffer.length(), base_path.c_str(), encoding_, options_);

        load(doc, node);
    }
コード例 #6
0
bool XSLStyleSheet::parseString(const String& string)
{
    // Parse in a single chunk into an xmlDocPtr
    const UChar BOM = 0xFEFF;
    const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
    if (!m_stylesheetDocTaken)
        xmlFreeDoc(m_stylesheetDoc);
    m_stylesheetDocTaken = false;

    PageConsoleClient* console = nullptr;
    Frame* frame = ownerDocument()->frame();
    if (frame && frame->page())
        console = &frame->page()->console();

    XMLDocumentParserScope scope(cachedResourceLoader(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console);

    auto upconvertedCharacters = StringView(string).upconvertedCharacters();
    const char* buffer = reinterpret_cast<const char*>(upconvertedCharacters.get());
    int size = string.length() * sizeof(UChar);

    xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(buffer, size);
    if (!ctxt)
        return 0;

    if (m_parentStyleSheet) {
        // The XSL transform may leave the newly-transformed document
        // with references to the symbol dictionaries of the style sheet
        // and any of its children. XML document disposal can corrupt memory
        // if a document uses more than one symbol dictionary, so we
        // ensure that all child stylesheets use the same dictionaries as their
        // parents.
        xmlDictFree(ctxt->dict);
        ctxt->dict = m_parentStyleSheet->m_stylesheetDoc->dict;
        xmlDictReference(ctxt->dict);
    }

    m_stylesheetDoc = xmlCtxtReadMemory(ctxt, buffer, size,
        finalURL().string().utf8().data(),
        BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",
        XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);
    xmlFreeParserCtxt(ctxt);

    loadChildSheets();

    return m_stylesheetDoc;
}
コード例 #7
0
static gboolean
bt_song_io_native_xml_load (gconstpointer const _self,
    const BtSong * const song, GError ** err)
{
  const BtSongIONativeXML *const self = BT_SONG_IO_NATIVE_XML (_self);
  xmlDocPtr song_doc;
  gchar *const file_name;
  guint len;
  gpointer data;
  gboolean result = FALSE;

  xmlParserCtxtPtr const ctxt = xmlNewParserCtxt ();
  if (!ctxt) {
    GST_WARNING ("failed to create parser context");
    g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED,
        "Failed to create parser context.");
    return FALSE;
  }

  g_object_get ((gpointer) self, "file-name", &file_name, "data", &data,
      "data-len", &len, NULL);
  GST_INFO ("native io xml will now load song from \"%s\"",
      file_name ? file_name : "data");

  if (data && len) {
    // parse the file from the memory block
    song_doc = xmlCtxtReadMemory (ctxt, data, len, NULL, NULL, 0L);
  } else {
    // open the file from the file_name argument
    song_doc = xmlCtxtReadFile (ctxt, file_name, NULL, 0L);
  }

  if (song_doc) {
    result = bt_song_io_native_load (song_doc, song, err);
    xmlFreeDoc (song_doc);
  } else {
    bt_song_io_native_load_set_error (ctxt, file_name, err);
  }

  g_free (file_name);
  xmlFreeParserCtxt (ctxt);
  return result;
}
コード例 #8
0
ファイル: xml.cpp プロジェクト: marktsai0316/VirtualMonitor
/**
 * Parse the given buffer and fills the given Document object with its contents.
 * Throws XmlError on parsing errors.
 *
 * The document that is passed in will be reset before being filled if not empty.
 *
 * @param pvBuf in: memory buffer to parse.
 * @param cbSize in: size of the memory buffer.
 * @param strFilename in: name fo file to parse.
 * @param doc out: document to be reset and filled with data according to file contents.
 */
void XmlMemParser::read(const void* pvBuf, size_t cbSize,
                        const RTCString &strFilename,
                        Document &doc)
{
    GlobalLock lock;
//     global.setExternalEntityLoader(ExternalEntityLoader);

    const char *pcszFilename = strFilename.c_str();

    doc.m->reset();
    if (!(doc.m->plibDocument = xmlCtxtReadMemory(m_ctxt,
                                (const char*)pvBuf,
                                (int)cbSize,
                                pcszFilename,
                                NULL,       // encoding = auto
                                XML_PARSE_NOBLANKS | XML_PARSE_NONET)))
        throw XmlError(xmlCtxtGetLastError(m_ctxt));

    doc.refreshInternals();
}
コード例 #9
0
ファイル: multipart.c プロジェクト: neverstoplwy/Droplet
static dpl_status_t
_multipart_parse_complete(const dpl_ctx_t *ctx,
                          const char *buf, int len)
{
    dpl_status_t          ret = DPL_SUCCESS;
    xmlParserCtxtPtr      ctxt;
    xmlDocPtr             doc;
    xmlNode               *elem;

    if (len == 0)
        return DPL_SUCCESS;

    ctxt = xmlNewParserCtxt();
    if (ctxt == NULL)
        return DPL_FAILURE;

    doc = xmlCtxtReadMemory(ctxt, buf, len, NULL, NULL, 0u);
    if (doc == NULL) {
        xmlFreeParserCtxt(ctxt);
        return DPL_FAILURE;
    }

    elem = xmlDocGetRootElement(doc);
    while (elem != NULL)
    {
        if (elem->type == XML_ELEMENT_NODE)
        {
            if (!strcmp((char *)(elem->name), "Error"))
            {
                ret = DPL_FAILURE;
                break ;
            }
        }
        elem = elem->next;
    }

    xmlFreeDoc(doc);
    xmlFreeParserCtxt(ctxt);

    return ret;
}
コード例 #10
0
bool XSLStyleSheet::parseString(const String& source)
{
    // Parse in a single chunk into an xmlDocPtr
    if (!m_stylesheetDocTaken)
        xmlFreeDoc(m_stylesheetDoc);
    m_stylesheetDocTaken = false;

    PageConsole* console = 0;
    Frame* frame = ownerDocument()->frame();
    if (frame && frame->host())
        console = &frame->host()->console();

    XMLDocumentParserScope scope(fetcher(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console);
    XMLParserInput input(source);

    xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(input.data(), input.size());
    if (!ctxt)
        return 0;

    if (m_parentStyleSheet) {
        // The XSL transform may leave the newly-transformed document
        // with references to the symbol dictionaries of the style sheet
        // and any of its children. XML document disposal can corrupt memory
        // if a document uses more than one symbol dictionary, so we
        // ensure that all child stylesheets use the same dictionaries as their
        // parents.
        xmlDictFree(ctxt->dict);
        ctxt->dict = m_parentStyleSheet->m_stylesheetDoc->dict;
        xmlDictReference(ctxt->dict);
    }

    m_stylesheetDoc = xmlCtxtReadMemory(ctxt, input.data(), input.size(),
        finalURL().string().utf8().data(), input.encoding(),
        XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);

    xmlFreeParserCtxt(ctxt);
    loadChildSheets();
    return m_stylesheetDoc;
}
コード例 #11
0
ファイル: xcal.c プロジェクト: kolab-groupware/cyrus-imapd
/*
 * Construct an iCalendar component from an xCal string.
 */
icalcomponent *xcal_string_as_icalcomponent(const char *str)
{
    xmlParserCtxtPtr ctxt;
    xmlDocPtr doc = NULL;
    xmlNodePtr root;
    icalcomponent *ical = NULL;

    if (!str) return NULL;

    /* Parse the XML request */
    ctxt = xmlNewParserCtxt();
    if (ctxt) {
        doc = xmlCtxtReadMemory(ctxt, str, strlen(str), NULL, NULL,
                                XML_PARSE_NOWARNING);
        xmlFreeParserCtxt(ctxt);
    }
    if (!doc) {
        syslog(LOG_WARNING, "XML parse error");
        return NULL;
    }

    /* Get root element */
    if (!(root = xmlDocGetRootElement(doc)) ||
            xmlStrcmp(root->name, BAD_CAST "icalendar") ||
            xmlStrcmp(root->ns->href, BAD_CAST XML_NS_ICALENDAR)) {
        syslog(LOG_WARNING,
               "XML root element is not %s:icalendar", XML_NS_ICALENDAR);
        goto done;
    }

    ical = xml_element_to_icalcomponent(xmlFirstElementChild(root));

done:
    xmlFreeDoc(doc);

    return ical;
}
コード例 #12
0
ファイル: Vpz.cpp プロジェクト: SJasson/vle
void Vpz::validateMemory(const std::string& buffer)
{
    xmlParserCtxtPtr ctxt;
    xmlDocPtr doc;

    ctxt = xmlNewParserCtxt();
    if (ctxt == NULL) {
        throw utils::SaxParserError(_("Failed to allocate parser context\n"));
    }

    doc = xmlCtxtReadMemory(ctxt, buffer.c_str(), buffer.size(), NULL, NULL,
                            XML_PARSE_DTDVALID);
    if (not doc) {
        xmlFreeParserCtxt(ctxt);
        throw utils::SaxParserError(_("Failed to parse memory '%1%'"));
    }

    if (ctxt->valid == 0) {
        xmlFreeDoc(doc);
        xmlFreeParserCtxt(ctxt);
        throw utils::SaxParserError(_("Failed to validate memory"));
    }
    xmlFreeParserCtxt(ctxt);
}
コード例 #13
0
ファイル: libmetrics.c プロジェクト: vhostmd/vhostmd
/*
 * dump metrics received from xenstore to the dest file 
 */
int dump_xenstore_metrics(const char *dest_file)
{
    char *buf = NULL, *path = NULL, *metrics = NULL;
    struct xs_handle *xsh = NULL;
    unsigned int len;
    int ret = 0;
	xmlParserCtxtPtr pctxt = NULL;
	xmlDocPtr doc = NULL;
    int domid;
    FILE *fp;

    if (dest_file) {
        fp = fopen(dest_file, "w");
        if (fp == NULL) {
            libmsg("Error, unable to dump metrics from xenstore: %s\n", strerror(errno));
            return -1;
        }
    }
    else {
        fp = stdout;
    }

    if ((domid = get_dom_id()) == -1) {
        libmsg("Unable to derive domID.\n" );
        ret = -1;
        goto out;
    }

    xsh = xs_domain_open();
    if (xsh == NULL) {
        libmsg("xs_domain_open() error. errno: %d.\n", errno);
        ret = -1;
        goto out;
    }

    path = xs_get_domain_path(xsh, domid);
    if (path == NULL) {
        libmsg("xs_get_domain_path() error. domid %d.\n", 0);
        ret = -1;
        goto out;
    }
    asprintf(&buf, "%s/metrics", path);
    metrics = xs_read(xsh, XBT_NULL, buf, &len);
    if (metrics == NULL) {
        libmsg("xs_read(): uuid get error. %s.\n", buf);
        ret = -1;
        goto out;
    }

    pctxt = xmlNewParserCtxt();
    if (!pctxt || !pctxt->sax) {
      libmsg("%s(): failed to create parser \n", __func__);
      ret = -1;
      goto out;
    }

    doc = xmlCtxtReadMemory(pctxt, metrics,
                            strlen(metrics), "mdisk.xml", NULL,
                            XML_PARSE_NOENT | XML_PARSE_NONET |
                            XML_PARSE_NOWARNING);
    if (!doc) {
      libmsg("%s(): libxml failed to xenstore metrics attribute\n", __func__);
      ret = -1;
      goto out;
    }
    xmlDocFormatDump(fp, doc, 1);

out:
    if (fp && fp != stdout)
        fclose(fp);
    if (doc)
      xmlFreeDoc(doc);
    if (pctxt)
      xmlFreeParserCtxt(pctxt);
    free(path);
    free(buf);
    free(metrics);
    return ret;
}
コード例 #14
0
ファイル: libmetrics.c プロジェクト: vhostmd/vhostmd
/*
 * Read metrics disk and populate mdisk
 *  Location of metrics disk is derived by looking at all block
 *  devices and then reading until a valid metrics disk signature
 *  is found.
 */
static int read_mdisk(metric_disk *mdisk)
{
   mdisk_header md_header;
   uint32_t busy;
   uint32_t sig;
   int fd;
   char *path;

   DIR* dir;
   struct dirent* entry;

   dir = opendir(SYS_BLOCK);
   if (dir == NULL)
      goto error;

   while((entry = readdir(dir))) {
retry:
#ifndef DEBUG_FROM_DOM0
      if (strcmp(entry->d_name, ".") == 0 ||
            strcmp(entry->d_name, "..") == 0)
         continue;

      asprintf(&path, "/dev/%s", entry->d_name);
#else
      path = strdup("/dev/shm/vhostmd0");
#endif
      /* Open with O_DIRECT to avoid kernel keeping old copies around
       * in the cache.
       */
      fd = open (path, O_RDONLY|O_DIRECT);
      if (fd == -1) {
         free (path);
         continue;
      }
      if (odirect_read (fd, &md_header, 0, sizeof md_header) == -1) {
         free (path);
	 close (fd);
         continue;
      }

      if ((sig = ntohl(md_header.sig)) == MDISK_SIGNATURE) {
         busy = ntohl(md_header.busy);
         if (busy) {
	     close(fd);
             free(path);
             sleep(1);
             goto retry;
         }
         mdisk->sum = ntohl(md_header.sum);
         mdisk->length = ntohl(md_header.length);
         mdisk->buffer = malloc(mdisk->length);
         mdisk->disk_name = strdup(path);
	 /* XXX check return value */
         odirect_read (fd, mdisk->buffer, sizeof md_header, mdisk->length);
	 free(path);

         /* Verify data still valid */
         if (odirect_read (fd, &md_header, 0, sizeof md_header) == -1) {
	     mdisk_content_free();
             close (fd);
             sleep(1);
             goto retry;
         }
         busy = ntohl(md_header.busy);
         if (busy || mdisk->sum != ntohl(md_header.sum)) {
             mdisk_content_free();
             close (fd);
             sleep(1);
             goto retry;
         }
         close (fd);
	 break;
      }
      close (fd);
   }

   if (mdisk->buffer == NULL)
      goto error;

   /* Set up a parser context */
   mdisk->pctxt = xmlNewParserCtxt();
   if (!mdisk->pctxt || !mdisk->pctxt->sax) {
      goto error;
   }

   mdisk->doc = xmlCtxtReadMemory(mdisk->pctxt, mdisk->buffer, 
           mdisk->length, "mdisk.xml", NULL, 
           XML_PARSE_NOENT | XML_PARSE_NONET |
           XML_PARSE_NOWARNING);
   if (!mdisk->doc) {
      libmsg("%s(): libxml failed to parse mdisk.xml buffer\n", __func__);
      goto error;
   }

   closedir(dir);

   return 0;
error:
   if (dir)
       closedir(dir);

   libmsg("%s(): Unable to read metrics disk\n", __func__);

   return -1;
}
コード例 #15
0
ファイル: message2.c プロジェクト: clokep/libgadu
static void test_text_to_html(const char *input, const unsigned char *attr,
	size_t attr_len, const char *output, gg_encoding_t encoding)
{
	char *result;
	size_t len;
#ifdef HAVE_LIBXML2
	char *tmp;
	xmlParserCtxtPtr ctxt;
	xmlDocPtr doc;
#endif

	len = gg_message_text_to_html(NULL, input, encoding, attr, attr_len);

	result = malloc(len + 1);

	if (result == NULL) {
		perror("malloc");
		exit(1);
	}

	gg_message_text_to_html(result, input, encoding, attr, attr_len);

	printf("text: \"%s\"", input);
	if (attr != NULL) {
		size_t i;

		printf(" + attr:");
		for (i = 0; i < attr_len; i++)
			printf(" %02x", (unsigned char) attr[i]);
	}
	printf("\n");
	printf("output: \"%s\"\n", result);

	if (strcmp(result, output) != 0) {
		printf("expected: \"%s\"\n", output);
		free(result);
		exit(1);
	}

#ifdef HAVE_LIBXML2
	/* Doklej <html></html>, żeby mieć tag dokumentu. */

	if (encoding == GG_ENCODING_CP1250) {
		tmp = realloc(result, strlen(result) +
			strlen("<?xml version=\"1.0\" "
			"encoding=\"windows-1250\"?><html></html>") + 1);
	} else {
		tmp = realloc(result, strlen(result) + strlen("<html></html>") + 1);
	}

	if (tmp == NULL) {
		perror("realloc");
		free(result);
		exit(1);
	}

	result = tmp;

	if (encoding == GG_ENCODING_CP1250) {
		const char *xmls = "<?xml version=\"1.0\" encoding=\"windows-1250\"?><html>";
		memmove(result + strlen(xmls), result, strlen(result) + 1);
		memcpy(result, xmls, strlen(xmls));
	} else {
		memmove(result + strlen("<html>"), result, strlen(result) + 1);
		memcpy(result, "<html>", strlen("<html>"));
	}
	strcat(result, "</html>");

	/* Zamień <br> na <x/>, żeby parser się nie wywalił. */

	while ((tmp = strstr(result, "<br>")) != NULL)
		memcpy(tmp, "<x/>", 4);

	/* Zamień <img ...> na <xx .../>, żeby parser się nie wywalił. */

	while ((tmp = strstr(result, "<img ")) != NULL) {
		memcpy(tmp + 1, "xx", 2);
		memmove(tmp + 3, tmp + 4, 25);
		tmp[27] = '/';
	}

	/* Parsuj! */

	ctxt = xmlNewParserCtxt();

	if (ctxt == NULL) {
		perror("xmlNewParserCtxt");
		exit(1);
	}

	doc = xmlCtxtReadMemory(ctxt, result, strlen(result), "", NULL, 0);

	if (doc == NULL) {
		printf("expected not well-formed XML\n");
		free(result);
		xmlFreeParserCtxt(ctxt);
		exit(1);
	}

	xmlFreeDoc(doc);

	xmlFreeParserCtxt(ctxt);
#endif

	printf("correct\n\n");
	free(result);
}