Пример #1
0
static void
process_tomboy_xml_content (BijiLazyDeserializer *self)
{
  BijiLazyDeserializerPrivate *priv = self->priv;
  int ret;
  gchar *revamped_html;

  g_string_append (priv->html, "<html xmlns=\"http://www.w3.org/1999/xhtml\"><body>");

  priv->inner = xmlReaderForMemory (priv->content,
                                    strlen(priv->content),
                                    "", "UTF-8", 0);

  ret = xmlTextReaderRead (priv->inner);

  /* Make the GString grow as we read */
  while (ret == 1)
  {
    process_tomboy_node (self);
    ret = xmlTextReaderRead (priv->inner);
  }

  g_string_append (priv->html, "</body></html>");

  /* Now the inner content is known, we can
   * assign note values and let deserialization work on last elements*/
  biji_note_obj_set_raw_text (priv->note, priv->raw_text->str);

  revamped_html = biji_str_replace (priv->html->str, "\n", "<br/>");
  biji_note_obj_set_html (priv->note, revamped_html);
  g_free (revamped_html);
}
char* getElementContent(MemoryStruct *xmlDoc, char *elementName)
{
    xmlTextReaderPtr reader;
    int ret;
    xmlChar *name, *value;

    reader = xmlReaderForMemory(xmlDoc->data, xmlDoc->size, "http://www.example.org/", NULL, 0);
    if (reader != NULL) {
        ret = xmlTextReaderRead(reader);
        while (ret == 1) {
            name = xmlTextReaderName(reader);
            if (strcmp(elementName, (char*) name) == 0 && xmlTextReaderNodeType(reader) == 1) {
                //printf("Name: %s\tType: %d\t", name, xmlTextReaderNodeType(reader));
                ret = xmlTextReaderRead(reader);
                if (ret == 1) {
                    value = xmlTextReaderValue(reader);
                    //printf("Value: %s\n", value);
                    //xmlFree(value);
                    xmlFree(name);
                    xmlFreeTextReader(reader);
                    return (char*) value;
                }
            }
            xmlFree(name);
            ret = xmlTextReaderRead(reader);
        }
        xmlFreeTextReader(reader);
        if (ret != 0) printf("Failed to parse.\n");
    }
    else printf("Unable to read XML from memory.\n");
    return;
}
Пример #3
0
static void
process_bijiben_html_content (BijiLazyDeserializer *self,
                              xmlTextReaderPtr      reader)
{
  BijiLazyDeserializerPrivate *priv = self->priv;
  int ret;
  gchar *sane_html;

  sane_html = (gchar*) xmlTextReaderReadInnerXml (reader);

  priv->inner = xmlReaderForMemory (sane_html,
                                    strlen(sane_html),
                                    "", "UTF-8", 0);

  ret = xmlTextReaderRead (priv->inner);

  /* Make the GString grow as we read */
  while (ret == 1)
  {
    process_bijiben_node (self);
    ret = xmlTextReaderRead (priv->inner);
  }

  biji_note_obj_set_raw_text (priv->note, priv->raw_text->str);
  biji_note_obj_set_html (priv->note, sane_html);

  xmlFree (BAD_CAST sane_html);
}
Пример #4
0
static void
process_bijiben_html_content (BijiLazyDeserializer *self)
{
  BijiLazyDeserializerPrivate *priv = self->priv;
  int ret;
  gchar *sane_text, *sane_html;

  priv->inner = xmlReaderForMemory (priv->content,
                                    strlen(priv->content),
                                    "", "UTF-8", 0);
  
  ret = xmlTextReaderRead (priv->inner);

  /* Make the GString grow as we read */
  while (ret == 1) 
  {
    process_bijiben_node (self);
    ret = xmlTextReaderRead (priv->inner);
  }

  /* Now the inner content is known, we can
   * assign note values and let deserialization work on last elements*/
  sane_html = biji_str_mass_replace (priv->html->str, "&#xA;" , "<br/>",
                                                      "&amp;" , "&"      , NULL);
  sane_text = biji_str_mass_replace (priv->raw_text->str, "&#xA;", "    ",
                                                          "&amp;", "&"   , NULL);

  biji_note_obj_set_raw_text (priv->note, sane_text);
  biji_note_obj_set_html_content (priv->note, sane_html);

  g_free (sane_text);
  g_free (sane_html);
}
Пример #5
0
EPUB3Error EPUB3ParseOPFFromData(EPUB3Ref epub, void * buffer, uint32_t bufferSize)
{
  assert(epub != NULL);
  assert(buffer != NULL);
  assert(bufferSize > 0);

  EPUB3Error error = kEPUB3Success;
  xmlInitParser();
  xmlTextReaderPtr reader = NULL;
  reader = xmlReaderForMemory(buffer, bufferSize, NULL, NULL, XML_PARSE_RECOVER | XML_PARSE_NONET);
  if(reader != NULL) {
    EPUB3XMLParseContext contextStack[PARSE_CONTEXT_STACK_DEPTH];
    EPUB3XMLParseContextPtr currentContext = &contextStack[0];

    int retVal = xmlTextReaderRead(reader);
    currentContext->state = kEPUB3OPFStateRoot;
    currentContext->tagName = xmlTextReaderConstName(reader);
    while(retVal == 1)
    {
      error = EPUB3ParseXMLReaderNodeForOPF(epub, reader, &currentContext);
      retVal = xmlTextReaderRead(reader);
    }
    if(retVal < 0) {
      error = kEPUB3XMLParseError;
    }
  } else {
    error = kEPUB3XMLReadFromBufferError;
  }
  xmlFreeTextReader(reader);
  xmlCleanupParser();
  return error;
}
Пример #6
0
/*
 * call-seq:
 *   from_memory(string, url = nil, encoding = nil, options = 0)
 *
 * Create a new reader that parses +string+
 */
static VALUE from_memory(int argc, VALUE *argv, VALUE klass)
{
  VALUE rb_buffer, rb_url, encoding, rb_options;

  const char * c_url      = NULL;
  const char * c_encoding = NULL;
  int c_options           = 0; 

  rb_scan_args(argc, argv, "13", &rb_buffer, &rb_url, &encoding, &rb_options);

  if (!RTEST(rb_buffer)) rb_raise(rb_eArgError, "string cannot be nil");
  if (RTEST(rb_url)) c_url = StringValuePtr(rb_url);
  if (RTEST(encoding)) c_encoding = StringValuePtr(encoding);
  if (RTEST(rb_options)) c_options = NUM2INT(rb_options);

  xmlTextReaderPtr reader = xmlReaderForMemory(
      StringValuePtr(rb_buffer),
      RSTRING_LEN(rb_buffer),
      c_url,
      c_encoding,
      c_options
  );

  if(reader == NULL) {
    xmlFreeTextReader(reader);
    rb_raise(rb_eRuntimeError, "couldn't create a parser");
  }

  VALUE rb_reader = Data_Wrap_Struct(klass, NULL, dealloc, reader);
  rb_funcall(rb_reader, rb_intern("initialize"), 3, rb_buffer, rb_url, encoding);

  return rb_reader;
}
Пример #7
0
static bool create_xml_reader(write_data_t *write_data) {
    write_data->xml_reader = log_ralloc(write_data->r, xmlReaderForMemory(write_data->response_text->elts, write_data->response_text->nelts * write_data->response_text->elt_size, NULL, NULL, 0) );
    if (write_data->xml_reader == NULL) {
        return false;
    }
    xmlTextReaderSetErrorHandler(write_data->xml_reader, xml_reader_error, write_data);
    return true;
}
Пример #8
0
/**
 * Read the xml document in from a memory location.
 * @param   xml The xml document
 * @param   ptr The source xml input location
 * @param   len The size of the memory buffer
 * @return  @c TRUE if successful, @c FALSE if an error occurs.
 * @ingroup EXML_Read_Group
 */
int exml_mem_read(EXML *xml, void *s_mem, size_t len)
{
	xmlTextReaderPtr reader;

	CHECK_PARAM_POINTER_RETURN("xml", xml, FALSE);

	reader = xmlReaderForMemory( s_mem, len, "", NULL, XML_PARSE_RECOVER );

	return _exml_read(xml, reader);
}
Пример #9
0
EXPORT EPUB3Error EPUB3CopyRootFilePathFromContainer(EPUB3Ref epub, char ** rootPath)
{
  assert(epub != NULL);

  if(epub->archive == NULL) return kEPUB3ArchiveUnavailableError;

  static const char *containerFilename = "META-INF/container.xml";

  void *buffer = NULL;
  uint32_t bufferSize = 0;
  uint32_t bytesCopied;

  xmlTextReaderPtr reader = NULL;
  EPUB3Bool foundPath = kEPUB3_NO;

  EPUB3Error error = kEPUB3Success;

  error = EPUB3CopyFileIntoBuffer(epub, &buffer, &bufferSize, &bytesCopied, containerFilename);
  if(error == kEPUB3Success) {
    reader = xmlReaderForMemory(buffer, bufferSize, "", NULL, XML_PARSE_RECOVER);
    if(reader != NULL) {
      int retVal;
      while((retVal = xmlTextReaderRead(reader)) == 1)
      {
        const char *rootFileName = "rootfile";
        const xmlChar *name = xmlTextReaderConstLocalName(reader);

        if(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT && xmlStrcmp(name, BAD_CAST rootFileName) == 0) {
          xmlChar *fullPath = xmlTextReaderGetAttribute(reader, BAD_CAST "full-path");
          if(fullPath != NULL) {
            // TODD: validate that the full-path attribute is of the form path-rootless
            //       see http://idpf.org/epub/30/spec/epub30-ocf.html#sec-container-metainf-container.xml
            foundPath = kEPUB3_YES;
            *rootPath = strdup((char *)fullPath);
          } else {
            // The spec requires the full-path attribute
            error = kEPUB3XMLXDocumentInvalidError;
          }
          break;
        }
      }
      if(retVal < 0) {
        error = kEPUB3XMLParseError;
      }
      if(!foundPath) {
        error = kEPUB3XMLXElementNotFoundError;
      }
    } else {
      error = kEPUB3XMLReadFromBufferError;
    }
    EPUB3_FREE_AND_NULL(buffer);
  }
  xmlFreeTextReader(reader);
  return error;
}
Пример #10
0
static xmlTextReaderPtr create_parser_buf(const char *buffer, int buflen, const char *filename) {
	xmlTextReaderPtr reader = NULL;
	if ((reader = xmlReaderForMemory(buffer, buflen, filename, NULL, 0))) {

		xmlTextReaderSetErrorHandler(reader, error_handler, NULL);

		if (xmlTextReaderRead(reader) != 1) {
			xmlFreeTextReader(reader);
			reader = NULL;
		}
	} else {
		tmx_err(E_UNKN, "xml parser: unable to open %s", filename);
	}
	return reader;
}
Пример #11
0
/*DEF*/void *XoReadXmlMem(char *buf,int sz,char *roottype,int flags,int *err)
{
	xmlTextReaderPtr reader	= NULL;
	void		 *obj;

	*err	= 0;
	reader = xmlReaderForMemory(buf,sz,"",NULL,0);
	if (reader == NULL) 
	{
		char	tmperr[256];
		sprintf(tmperr,"XoReadXmlMem():cannot create reader memory\n");
		XOERR(tmperr,0);
	}
	obj	= XoReadXmlReader(reader,roottype,flags,err);
	xmlFreeTextReader(reader);
	return	obj;
}
Пример #12
0
/*DEF*/void *XoReadObixMem(char *buf,int sz,void *unused,int flags,int *err)
{
    xmlTextReaderPtr reader	= NULL;
    void		 *obj;

    flags	= flags | XOML_PARSE_OBIX;
    *err	= 0;
    reader = xmlReaderForMemory(buf,sz,"",NULL,0);
    if (reader == NULL)
    {
        char	tmperr[256];
        sprintf(tmperr,"XoReadObixMem():cannot create reader memory\n");
        XOERR(tmperr,0);
        return	NULL;
    }
    obj	= XoReadXmlReader(reader,NULL,flags,err);
    xmlFreeTextReader(reader);
    return	obj;
}
Пример #13
0
gboolean
xml_reader_load_from_data (XmlReader   *reader,
                           const gchar *data,
                           gssize       length,
                           const gchar *uri,
                           const gchar *encoding)
{
  g_return_val_if_fail (XML_IS_READER (reader), FALSE);

  xml_reader_clear (reader);

  if (length == -1)
    length = strlen (data);

  reader->xml = xmlReaderForMemory (data, length, uri, encoding, 0);
  xmlTextReaderSetErrorHandler (reader->xml, xml_reader_error_cb, reader);

  return (reader->xml != NULL);
}
Пример #14
0
static gboolean
_ag_service_load_from_file (AgService *service)
{
    xmlTextReaderPtr reader;
    gchar *filepath;
    gboolean ret;
    GError *error = NULL;
    gsize len;

    g_return_val_if_fail (service->name != NULL, FALSE);

    DEBUG_REFS ("Loading service %s", service->name);
    filepath = _ag_find_libaccounts_file (service->name,
                                          ".service",
                                          "AG_SERVICES",
                                          SERVICE_FILES_DIR);
    if (G_UNLIKELY (!filepath)) return FALSE;

    g_file_get_contents (filepath, &service->file_data,
                         &len, &error);
    if (G_UNLIKELY (error))
    {
        g_warning ("Error reading %s: %s", filepath, error->message);
        g_error_free (error);
        g_free (filepath);
        return FALSE;
    }

    /* TODO: cache the xmlReader */
    reader = xmlReaderForMemory (service->file_data, len,
                                 filepath, NULL, 0);
    g_free (filepath);
    if (G_UNLIKELY (reader == NULL))
        return FALSE;

    ret = read_service_file (reader, service);

    xmlFreeTextReader (reader);
    return ret;
}
Пример #15
0
/* call-seq:
 *    XML::Reader.string(io) -> XML::Reader
 *    XML::Reader.string(io, :encoding => XML::Encoding::UTF_8,
 *                           :options => XML::Parser::Options::NOENT) -> XML::Parser
 *
 * Creates a new reader by parsing the specified string.
 *
 * You may provide an optional hash table to control how the
 * parsing is performed.  Valid options are:
 *
 *  base_uri - The base url for the parsed document.
 *  encoding - The document encoding, defaults to nil. Valid values
 *             are the encoding constants defined on XML::Encoding.
 *  options - Controls the execution of the parser, defaults to 0.
 *            Valid values are the constants defined on
 *            XML::Parser::Options.  Mutliple options can be combined
 *            by using Bitwise OR (|).
 */
static VALUE rxml_reader_string(int argc, VALUE *argv, VALUE klass)
{
  xmlTextReaderPtr xreader;
  VALUE string;
  VALUE options;
  char *xbaseurl = NULL;
  const char *xencoding = NULL;
  int xoptions = 0;

  rb_scan_args(argc, argv, "11", &string, &options);
  Check_Type(string, T_STRING);

  if (!NIL_P(options))
  {
    VALUE baseurl = Qnil;
    VALUE encoding = Qnil;
    VALUE parserOptions = Qnil;

    Check_Type(options, T_HASH);

    baseurl = rb_hash_aref(options, base_uri_SYMBOL);
    xbaseurl = NIL_P(baseurl) ? NULL : StringValueCStr(baseurl);

    encoding = rb_hash_aref(options, ENCODING_SYMBOL);
    xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding));
      
    parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL);
    xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions);
  }
  
  xreader = xmlReaderForMemory(StringValueCStr(string), RSTRING_LEN(string), 
                               xbaseurl, xencoding, xoptions);

  if (xreader == NULL)
    rxml_raise(&xmlLastError);

  return rxml_reader_wrap(xreader);
}
Пример #16
0
int xml_label_from_mem(const char *buf, int buf_size, struct ltfs_label *label)
{
	int ret;
	xmlTextReaderPtr reader;

	CHECK_ARG_NULL(buf, -LTFS_NULL_ARG);
	CHECK_ARG_NULL(label, -LTFS_NULL_ARG);

	reader = xmlReaderForMemory(buf, buf_size, NULL, NULL, XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
	if (! reader) {
		ltfsmsg(LTFS_ERR, "17009E");
		return -LTFS_LIBXML2_FAILURE;
	}

	ret = _xml_parse_label(reader, label);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "17010E");
		ret = -LTFS_LABEL_INVALID;
	}
	xmlFreeTextReader(reader);

	return ret;
}
Пример #17
0
/**
 * dax_dom_document_new_from_memory:
 *
 * Creates a new #DaxDomDocument. FIXME
 *
 * Return value: the newly created #DaxDomDocument instance
 */
DaxDomDocument *
dax_dom_document_new_from_memory (const gchar  *buffer,
                                  gint          size,
                                  const gchar  *base_iri,
                                  GError      **error)
{
    DaxDomDocument *document;
    ParserContext ctx;

    ctx.reader = xmlReaderForMemory(buffer, size, base_iri, NULL,
                                    XML_PARSE_XINCLUDE);
    if (ctx.reader == NULL)
        return NULL;

    document = dax_document_new ();
    ctx.current_node = DAX_DOM_NODE (document);

    /* Set up the base uri */
    dax_dom_document_set_base_iri (document, base_iri);

    dax_dom_document_parse_and_setup (document, &ctx);

    return document;
}
Пример #18
0
XmlParser& XmlParser::xmlString(const std::string& xmlString) {
    xmlInitParser();
    const char* cstr = xmlString.c_str();
    _reader = xmlReaderForMemory(cstr, (int)strlen(cstr), NULL, NULL, 0);
    return *this;
}
Пример #19
0
 XmlReader::XmlReader(std::string&& xml) :
     buf(std::move(xml)),
     reader(xmlReaderForMemory(buf.c_str(), buf.size(), nullptr, nullptr, 0))
 {
 }
Пример #20
0
 XmlReader::XmlReader(const std::string& xml) :
     buf(xml),
     reader(xmlReaderForMemory(buf.c_str(), buf.size(), nullptr, nullptr, 0))
 {
 }
static GError *
download_contacts (EBookBackendWebdav *webdav,
                   EFlag *running,
                   EDataBookView *book_view,
                   GCancellable *cancellable)
{
	EBookBackendWebdavPrivate *priv = webdav->priv;
	EBookBackend		  *book_backend;
	SoupMessage               *message;
	guint                      status;
	xmlTextReaderPtr           reader;
	response_element_t        *elements;
	response_element_t        *element;
	response_element_t        *next;
	gint                        count;
	gint                        i;
	gchar                     *new_ctag = NULL;

	g_mutex_lock (&priv->update_lock);

	if (!check_addressbook_changed (webdav, &new_ctag, cancellable)) {
		g_free (new_ctag);
		g_mutex_unlock (&priv->update_lock);
		return EDB_ERROR (SUCCESS);
	}

	book_backend = E_BOOK_BACKEND (webdav);

	if (book_view != NULL) {
		e_data_book_view_notify_progress (book_view, -1,
				_("Loading Addressbook summary..."));
	}

	message = send_propfind (webdav, cancellable);
	status  = message->status_code;

	if (status == 401 || status == 407) {
		g_object_unref (message);
		g_free (new_ctag);
		if (book_view)
			e_data_book_view_notify_progress (book_view, -1, NULL);
		g_mutex_unlock (&priv->update_lock);
		return webdav_handle_auth_request (webdav);
	}
	if (status != 207) {
		GError *error;

		error = e_data_book_create_error_fmt (
			E_DATA_BOOK_STATUS_OTHER_ERROR,
			_("PROPFIND on webdav failed with HTTP status %d (%s)"),
			status,
			message->reason_phrase && *message->reason_phrase ? message->reason_phrase :
			(soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : _("Unknown error")));

		g_object_unref (message);
		g_free (new_ctag);

		if (book_view)
			e_data_book_view_notify_progress (book_view, -1, NULL);

		g_mutex_unlock (&priv->update_lock);

		return error;
	}
	if (message->response_body == NULL) {
		g_warning ("No response body in webdav PROPFIND result");
		g_object_unref (message);
		g_free (new_ctag);

		if (book_view)
			e_data_book_view_notify_progress (book_view, -1, NULL);

		g_mutex_unlock (&priv->update_lock);

		return e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR, _("No response body in webdav PROPFIND result"));
	}

	/* parse response */
	reader = xmlReaderForMemory (
		message->response_body->data,
		message->response_body->length, NULL, NULL,
		XML_PARSE_NOWARNING);

	elements = parse_propfind_response (reader);

	/* count contacts */
	count = 0;
	for (element = elements; element != NULL; element = element->next) {
		++count;
	}

	/* download contacts */
	i = 0;
	for (element = elements; element != NULL; element = element->next, ++i) {
		const gchar  *uri;
		const gchar *etag;
		EContact    *contact;
		gchar *complete_uri;

		/* stop downloading if search was aborted */
		if (running != NULL && !e_flag_is_set (running))
			break;

		if (book_view != NULL) {
			gfloat percent = 100.0 / count * i;
			gchar buf[100];
			snprintf (buf, sizeof (buf), _("Loading Contacts (%d%%)"), (gint) percent);
			e_data_book_view_notify_progress (book_view, -1, buf);
		}

		/* skip collections */
		uri = (const gchar *) element->href;
		if (uri[strlen (uri) - 1] == '/')
			continue;

		/* uri might be relative, construct complete one */
		if (uri[0] == '/') {
			SoupURI *soup_uri = soup_uri_new (priv->uri);
			soup_uri->path    = g_strdup (uri);

			complete_uri = soup_uri_to_string (soup_uri, 0);
			soup_uri_free (soup_uri);
		} else {
			complete_uri = g_strdup (uri);
		}

		etag = (const gchar *) element->etag;

		g_mutex_lock (&priv->cache_lock);
		contact = e_book_backend_cache_get_contact (priv->cache, complete_uri);
		g_mutex_unlock (&priv->cache_lock);

		/* download contact if it is not cached or its ETag changed */
		if (contact == NULL || etag == NULL ||
		    strcmp (e_contact_get_const (contact, E_CONTACT_REV), etag) != 0) {
			contact = download_contact (webdav, complete_uri, cancellable);
			if (contact != NULL) {
				g_mutex_lock (&priv->cache_lock);
				if (e_book_backend_cache_remove_contact (priv->cache, complete_uri))
					e_book_backend_notify_remove (book_backend, complete_uri);
				e_book_backend_cache_add_contact (priv->cache, contact);
				g_mutex_unlock (&priv->cache_lock);
				e_book_backend_notify_update (book_backend, contact);
			}
		}

		g_free (complete_uri);
	}

	/* free element list */
	for (element = elements; element != NULL; element = next) {
		next = element->next;

		xmlFree (element->href);
		xmlFree (element->etag);
		g_free (element);
	}

	xmlFreeTextReader (reader);
	g_object_unref (message);

	if (new_ctag) {
		g_mutex_lock (&priv->cache_lock);
		if (!e_file_cache_replace_object (E_FILE_CACHE (priv->cache), WEBDAV_CTAG_KEY, new_ctag))
			e_file_cache_add_object (E_FILE_CACHE (priv->cache), WEBDAV_CTAG_KEY, new_ctag);
		g_mutex_unlock (&priv->cache_lock);
	}
	g_free (new_ctag);

	if (book_view)
		e_data_book_view_notify_progress (book_view, -1, NULL);

	g_mutex_unlock (&priv->update_lock);

	return EDB_ERROR (SUCCESS);
}
Пример #22
0
int cli_scandmg(cli_ctx *ctx)
{
    struct dmg_koly_block hdr;
    int ret, namelen, ofd;
    size_t maplen, nread;
    off_t pos = 0;
    char *dirname, *tmpfile;
    const char *outdata;
    unsigned int file = 0;
    struct dmg_mish_with_stripes *mish_list = NULL, *mish_list_tail = NULL;
    enum dmgReadState state = DMG_FIND_BASE_PLIST;
    int stateDepth[DMG_MAX_STATE];
#if HAVE_LIBXML2
    xmlTextReaderPtr reader;
#endif

    if (!ctx || !ctx->fmap) {
        cli_errmsg("cli_scandmg: Invalid context\n");
        return CL_ENULLARG;
    }

    maplen = (*ctx->fmap)->real_len;
    pos = maplen - 512;
    if (pos <= 0) {
        cli_dbgmsg("cli_scandmg: Sizing problem for DMG archive.\n");
        return CL_CLEAN;
    }

    /* Grab koly block */
    if (fmap_readn(*ctx->fmap, &hdr, pos, sizeof(hdr)) != sizeof(hdr)) {
        cli_dbgmsg("cli_scandmg: Invalid DMG trailer block\n");
        return CL_EFORMAT;
    }

    /* Check magic */
    hdr.magic = be32_to_host(hdr.magic);
    if (hdr.magic == 0x6b6f6c79) {
        cli_dbgmsg("cli_scandmg: Found koly block @ %ld\n", (long) pos);
    }
    else {
        cli_dbgmsg("cli_scandmg: No koly magic, %8x\n", hdr.magic);
        return CL_EFORMAT;
    }

    hdr.dataForkOffset = be64_to_host(hdr.dataForkOffset);
    hdr.dataForkLength = be64_to_host(hdr.dataForkLength);
    cli_dbgmsg("cli_scandmg: data offset %lu len %d\n", (unsigned long)hdr.dataForkOffset, (int)hdr.dataForkLength);

    hdr.xmlOffset = be64_to_host(hdr.xmlOffset);
    hdr.xmlLength = be64_to_host(hdr.xmlLength);
    if (hdr.xmlLength > (uint64_t)INT_MAX) {
        cli_dbgmsg("cli_scandmg: The embedded XML is way larger than necessary, and probably corrupt or tampered with.\n");
        return CL_EFORMAT;
    }
    if ((hdr.xmlOffset > (uint64_t)maplen) || (hdr.xmlLength > (uint64_t)maplen)
            || (hdr.xmlOffset + hdr.xmlLength) > (uint64_t)maplen) {
        cli_dbgmsg("cli_scandmg: XML out of range for this file\n");
        return CL_EFORMAT;
    }
    cli_dbgmsg("cli_scandmg: XML offset %lu len %d\n", (unsigned long)hdr.xmlOffset, (int)hdr.xmlLength);
    if (hdr.xmlLength == 0) {
        cli_dbgmsg("cli_scandmg: Embedded XML length is zero.\n");
        return CL_EFORMAT;
    }

    /* Create temp folder for contents */
    if (!(dirname = cli_gentemp(ctx->engine->tmpdir))) {
        return CL_ETMPDIR;
    }
    if (mkdir(dirname, 0700)) {
        cli_errmsg("cli_scandmg: Cannot create temporary directory %s\n", dirname);
        free(dirname);
        return CL_ETMPDIR;
    }
    cli_dbgmsg("cli_scandmg: Extracting into %s\n", dirname);

    /* Dump XML to tempfile, if needed */
    if (ctx->engine->keeptmp) {
        int xret;
        xret = dmg_extract_xml(ctx, dirname, &hdr);

        if (xret != CL_SUCCESS) {
            /* Printed err detail inside dmg_extract_xml */
            free(dirname);
            return xret;
        }
    }

    /* scan XML with cli_map_scandesc */
    ret = cli_map_scandesc(*ctx->fmap, (off_t)hdr.xmlOffset, (size_t)hdr.xmlLength, ctx);
    if (ret != CL_CLEAN) {
        cli_dbgmsg("cli_scandmg: retcode from scanning TOC xml: %s\n", cl_strerror(ret));
        if (!ctx->engine->keeptmp)
            cli_rmdirs(dirname);
        free(dirname);
        return ret;
    }

    /* page data from map */
    outdata = fmap_need_off_once_len(*ctx->fmap, hdr.xmlOffset, hdr.xmlLength, &nread);
    if (!outdata || (nread != hdr.xmlLength)) {
        cli_errmsg("cli_scandmg: Failed getting XML from map, len %d\n", (int)hdr.xmlLength);
        if (!ctx->engine->keeptmp)
            cli_rmdirs(dirname);
        free(dirname);
        return CL_EMAP;
    }

    /* time to walk the tree */
    /* plist -> dict -> (key:resource_fork) dict -> (key:blkx) array -> dict */
    /* each of those bottom level dict should have 4 parts */
    /* [ Attributes, Data, ID, Name ], where Data is Base64 mish block */

    /* This is the block where we require libxml2 */
#if HAVE_LIBXML2

    /* XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_COMPACT */
#define DMG_XML_PARSE_OPTS (1 << 1 | 1 << 11 | 1 << 16)

    reader = xmlReaderForMemory(outdata, (int)hdr.xmlLength, "toc.xml", NULL, DMG_XML_PARSE_OPTS);
    if (!reader) {
        cli_dbgmsg("cli_scandmg: Failed parsing XML!\n");
        if (!ctx->engine->keeptmp)
            cli_rmdirs(dirname);
        free(dirname);
        return CL_EFORMAT;
    }

    stateDepth[DMG_FIND_BASE_PLIST] = -1;

    // May need to check for (xmlTextReaderIsEmptyElement(reader) == 0)

    /* Break loop if have return code or reader can't read any more */
    while ((ret == CL_CLEAN) && (xmlTextReaderRead(reader) == 1)) {
        xmlReaderTypes nodeType;
        nodeType = xmlTextReaderNodeType(reader);

        if (nodeType == XML_READER_TYPE_ELEMENT) {
            // New element, do name check
            xmlChar *nodeName;
            int depth;

            depth = xmlTextReaderDepth(reader);
            if (depth < 0) {
                break;
            }
            if ((depth > 50) && SCAN_ALGO) {
                // Possible heuristic, should limit runaway
                cli_dbgmsg("cli_scandmg: Excessive nesting in DMG TOC.\n");
                break;
            }
            nodeName = xmlTextReaderLocalName(reader);
            if (!nodeName)
                continue;
            dmg_parsemsg("read: name %s depth %d\n", nodeName, depth);

            if ((state == DMG_FIND_DATA_MISH)
                    && (depth == stateDepth[state-1])) {
                xmlChar * textValue;
                struct dmg_mish_with_stripes *mish_set;
                /* Reset state early, for continue cases */
                stateDepth[DMG_FIND_KEY_DATA] = -1;
                state--;
                if (xmlStrcmp(nodeName, "data") != 0) {
                    cli_dbgmsg("cli_scandmg: Not blkx data element\n");
                    xmlFree(nodeName);
                    continue;
                }
                dmg_parsemsg("read: Found blkx data element\n");
                /* Pull out data content from text */
                if (xmlTextReaderIsEmptyElement(reader)) {
                    cli_dbgmsg("cli_scandmg: blkx data element is empty\n");
                    xmlFree(nodeName);
                    continue;
                }
                if (xmlTextReaderRead(reader) != 1) {
                    xmlFree(nodeName);
                    break;
                }
                if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_TEXT) {
                    cli_dbgmsg("cli_scandmg: Next node not text\n");
                    xmlFree(nodeName);
                    continue;
                }
                textValue = xmlTextReaderValue(reader);
                if (textValue == NULL) {
                    xmlFree(nodeName);
                    continue;
                }
                /* Have encoded mish block */
                mish_set = cli_malloc(sizeof(struct dmg_mish_with_stripes));
                if (mish_set == NULL) {
                    ret = CL_EMEM;
                    xmlFree(textValue);
                    xmlFree(nodeName);
                    break;
                }
                ret = dmg_decode_mish(ctx, &file, textValue, mish_set);
                xmlFree(textValue);
                if (ret == CL_EFORMAT) {
                    /* Didn't decode, or not a mish block */
                    ret = CL_CLEAN;
                    xmlFree(nodeName);
                    continue;
                }
                else if (ret != CL_CLEAN) {
                    xmlFree(nodeName);
                    continue;
                }
                /* Add mish block to list */
                if (mish_list_tail != NULL) {
                    mish_list_tail->next = mish_set;
                    mish_list_tail = mish_set;
                }
                else {
                    mish_list = mish_set;
                    mish_list_tail = mish_set;
                }
                mish_list_tail->next = NULL;
            }
            if ((state == DMG_FIND_KEY_DATA)
                    && (depth > stateDepth[state-1])
                    && (xmlStrcmp(nodeName, "key") == 0)) {
                xmlChar * textValue;
                dmg_parsemsg("read: Found key - checking for Data\n");
                if (xmlTextReaderRead(reader) != 1) {
                    xmlFree(nodeName);
                    break;
                }
                if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_TEXT) {
                    cli_dbgmsg("cli_scandmg: Key node no text\n");
                    xmlFree(nodeName);
                    continue;
                }
                textValue = xmlTextReaderValue(reader);
                if (textValue == NULL) {
                    cli_dbgmsg("cli_scandmg: no value from xmlTextReaderValue\n");
                    xmlFree(nodeName);
                    continue;
                }
                if (xmlStrcmp(textValue, "Data") == 0) {
                    dmg_parsemsg("read: Matched data\n");
                    stateDepth[DMG_FIND_KEY_DATA] = depth;
                    state++;
                }
                else {
                    dmg_parsemsg("read: text value is %s\n", textValue);
                }
                xmlFree(textValue);
            }
            if ((state == DMG_FIND_BLKX_CONTAINER)
                    && (depth == stateDepth[state-1])) {
                if (xmlStrcmp(nodeName, "array") == 0) {
                    dmg_parsemsg("read: Found array blkx\n");
                    stateDepth[DMG_FIND_BLKX_CONTAINER] = depth;
                    state++;
                }
                else if (xmlStrcmp(nodeName, "dict") == 0) {
                    dmg_parsemsg("read: Found dict blkx\n");
                    stateDepth[DMG_FIND_BLKX_CONTAINER] = depth;
                    state++;
                }
                else {
                    cli_dbgmsg("cli_scandmg: Bad blkx, not container\n");
                    stateDepth[DMG_FIND_KEY_BLKX] = -1;
                    state--;
                }
            }
            if ((state == DMG_FIND_KEY_BLKX)
                    && (depth == stateDepth[state-1] + 1)
                    && (xmlStrcmp(nodeName, "key") == 0)) {
                xmlChar * textValue;
                dmg_parsemsg("read: Found key - checking for blkx\n");
                if (xmlTextReaderRead(reader) != 1) {
                    xmlFree(nodeName);
                    break;
                }
                if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_TEXT) {
                    cli_dbgmsg("cli_scandmg: Key node no text\n");
                    xmlFree(nodeName);
                    continue;
                }
                textValue = xmlTextReaderValue(reader);
                if (textValue == NULL) {
                    cli_dbgmsg("cli_scandmg: no value from xmlTextReaderValue\n");
                    xmlFree(nodeName);
                    continue;
                }
                if (xmlStrcmp(textValue, "blkx") == 0) {
                    cli_dbgmsg("cli_scandmg: Matched blkx\n");
                    stateDepth[DMG_FIND_KEY_BLKX] = depth;
                    state++;
                }
                else {
                    cli_dbgmsg("cli_scandmg: wanted blkx, text value is %s\n", textValue);
                }
                xmlFree(textValue);
            }
            if ((state == DMG_FIND_DICT_RESOURCE_FORK)
                    && (depth == stateDepth[state-1])) {
                if (xmlStrcmp(nodeName, "dict") == 0) {
                    dmg_parsemsg("read: Found resource-fork dict\n");
                    stateDepth[DMG_FIND_DICT_RESOURCE_FORK] = depth;
                    state++;
                }
                else {
                    dmg_parsemsg("read: Not resource-fork dict\n");
                    stateDepth[DMG_FIND_KEY_RESOURCE_FORK] = -1;
                    state--;
                }
            }
            if ((state == DMG_FIND_KEY_RESOURCE_FORK)
                    && (depth == stateDepth[state-1] + 1)
                    && (xmlStrcmp(nodeName, "key") == 0)) {
                dmg_parsemsg("read: Found resource-fork key\n");
                stateDepth[DMG_FIND_KEY_RESOURCE_FORK] = depth;
                state++;
            }
            if ((state == DMG_FIND_BASE_DICT)
                    && (depth == stateDepth[state-1] + 1)
                    && (xmlStrcmp(nodeName, "dict") == 0)) {
                dmg_parsemsg("read: Found dict start\n");
                stateDepth[DMG_FIND_BASE_DICT] = depth;
                state++;
            }
            if ((state == DMG_FIND_BASE_PLIST) && (xmlStrcmp(nodeName, "plist") == 0)) {
                dmg_parsemsg("read: Found plist start\n");
                stateDepth[DMG_FIND_BASE_PLIST] = depth;
                state++;
            }
            xmlFree(nodeName);
        }
        else if ((nodeType == XML_READER_TYPE_END_ELEMENT) && (state > DMG_FIND_BASE_PLIST)) {
            int significantEnd = 0;
            int depth = xmlTextReaderDepth(reader);
            if (depth < 0) {
                break;
            }
            else if (depth < stateDepth[state-1]) {
                significantEnd = 1;
            }
            else if ((depth == stateDepth[state-1])
                     && (state-1 == DMG_FIND_BLKX_CONTAINER)) {
                /* Special case, ending blkx container */
                significantEnd = 1;
            }
            if (significantEnd) {
                dmg_parsemsg("read: significant end tag, state %d\n", state);
                stateDepth[state-1] = -1;
                state--;
                if ((state-1 == DMG_FIND_KEY_RESOURCE_FORK)
                        || (state-1 == DMG_FIND_KEY_BLKX)) {
                    /* Keys end their own tag (validly) and the next state depends on the following tag */
                    // cli_dbgmsg("read: significant end tag ending prior key state\n");
                    stateDepth[state-1] = -1;
                    state--;
                }
            }
            else {
                dmg_parsemsg("read: not significant end tag, state %d depth %d prior depth %d\n", state, depth, stateDepth[state-1]);
            }
        }
    }

    xmlFreeTextReader(reader);
    xmlCleanupParser();

#else

    cli_dbgmsg("cli_scandmg: libxml2 support is compiled out. It is required for full DMG support.\n");

#endif

    /* Loop over mish array */
    file = 0;
    while ((ret == CL_CLEAN) && (mish_list != NULL)) {
        /* Handle & scan mish block */
        ret = dmg_handle_mish(ctx, file++, dirname, hdr.xmlOffset, mish_list);
        free(mish_list->mish);
        mish_list_tail = mish_list;
        mish_list = mish_list->next;
        free(mish_list_tail);
    }

    /* Cleanup */
    /* If error occurred, need to free mish items and mish blocks */
    while (mish_list != NULL) {
        free(mish_list->mish);
        mish_list_tail = mish_list;
        mish_list = mish_list->next;
        free(mish_list_tail);
    }
    if (!ctx->engine->keeptmp)
        cli_rmdirs(dirname);
    free(dirname);
    return ret;
}
Пример #23
0
int cli_scanxdp(cli_ctx *ctx)
{
#if HAVE_LIBXML2
    xmlTextReaderPtr reader = NULL;
    fmap_t *map = *(ctx->fmap);
    const char *buf;
    const xmlChar *name, *value;
    char *decoded;
    size_t decodedlen;
    int rc = CL_SUCCESS;
    char *dumpname;
    size_t i;
    
    buf = (const char *)fmap_need_off_once(map, map->offset, map->len);
    if (!(buf))
        return CL_EREAD;

    if (ctx->engine->keeptmp) {
        dumpname = dump_xdp(ctx, buf, map->len);
        if (dumpname)
            free(dumpname);
    }

    /*
     * Since a PDF file can contain embedded XDP documents,
     * it's possible that the filetyping code matched an embedded XDP document.
     * If that's the case, then xmlReaderForMemory will throw an error. For now,
     * silently ignore the error and return CL_SUCCESS so the filetyping code can
     * continue on.
     */
    reader = xmlReaderForMemory(buf, (int)(map->len), "noname.xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS);
    if (!(reader))
        return CL_SUCCESS;

    while (xmlTextReaderRead(reader) == 1) {
        name = xmlTextReaderConstLocalName(reader);
        if (!(name))
            continue;

        if (!strcmp((const char *)name, "chunk") && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
            value = xmlTextReaderReadInnerXml(reader);
            if (value) {
                decoded = cl_base64_decode((char *)value, strlen((const char *)value), NULL, &decodedlen, 0);
                if (decoded) {
                    unsigned int shouldscan=0;

                    if (decodedlen > 5) {
                        for (i=0; i < MIN(MAGIC_BUFFER_SIZE, decodedlen-5); i++) {
                            if (decoded[i] != '%')
                                continue;

                            if (decoded[i+1] == 'P' || decoded[i+1] == 'p') {
                                if (decoded[i+2] == 'D' || decoded[i+2] == 'd') {
                                    if (decoded[i+3] == 'F' || decoded[i+3] == 'f') {
                                        if (decoded[i+4] == '-') {
                                            shouldscan=1;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (!shouldscan) {
                        free(decoded);
                        xmlFree((void *)value);
                        break;
                    }

                    rc = cli_mem_scandesc(decoded, decodedlen, ctx);
                    free(decoded);
                    if (rc != CL_SUCCESS || rc == CL_BREAK) {
                        xmlFree((void *)value);
                        break;
                    }
                }

                xmlFree((void *)value);
            }
        }
    }

    xmlFreeTextReader(reader);

    return rc;
#else
    return CL_SUCCESS;
#endif
}
Пример #24
0
	/** Handles deserialization from both myanimelist and search results.
	 * Search results are      <anime><entry></entry><entry></entry></anime>
	 * myanimelist results are <entry><anime></anime><anime></anime></entry>
	 */
	std::list<std::shared_ptr<Anime> > AnimeSerializer::deserialize(const std::string& xml) const {
		std::list<std::shared_ptr<Anime> > res;
		std::unique_ptr<char[]> cstr(new char[xml.size()]);
		std::memcpy(cstr.get(), xml.c_str(), xml.size());
		std::unique_ptr<xmlTextReader, xmlTextReaderDeleter> reader(xmlReaderForMemory(
			         cstr.get(), xml.size(), "", "UTF-8", XML_PARSE_RECOVER | XML_PARSE_NOENT ));

		if (!reader) {
			std::cerr << "Error: Couldn't create XML reader" << std::endl;
            std::cerr << "XML follows: " << xml << std::endl;
			return res;
		}

		Anime anime;
		int ret                = 1;
		FIELDS field           = FIELDNONE;
		FIELDS prev_field      = FIELDNONE;
		bool entry_after_anime = false;
		bool seen_anime        = false;
		bool seen_entry        = false;

		for( ret = xmlTextReaderRead(reader.get()); ret == 1;
		     ret = xmlTextReaderRead(reader.get()) ) {
			const std::string name  = xmlchar_to_str(xmlTextReaderConstName (reader.get()));
			std::string value = xmlchar_to_str(xmlTextReaderConstValue(reader.get()));
            m_text_util->parse_html_entities(value);

			if (name.size() > 0) {
				auto field_iter = field_map.find(name);
				if (field_iter != field_map.end()) {
					prev_field = field;
					field = field_iter->second;
				} else {
					std::cerr << "Unexpected field " << name << std::endl;
				}

				switch (xmlTextReaderNodeType(reader.get())) {
				case XML_READER_TYPE_ELEMENT:
					entry_after_anime |= (field == ENTRY) && seen_anime && !seen_entry;
					seen_entry        |= field == ENTRY;
					seen_anime        |= field == ANIME;
					break;
				case XML_READER_TYPE_END_ELEMENT:
					if ( ( entry_after_anime && field == ENTRY) ||
					     (!entry_after_anime && field == ANIME)) {
						res.push_back(std::make_shared<Anime>(anime));
						anime = Anime();
					}
					field = FIELDNONE;
					break;
				case XML_READER_TYPE_TEXT:
					if( field != FIELDTEXT ) {
						std::cerr << "There's a problem!" << std::endl;
					}
					if (value.size() > 0) {
						auto member_iter = member_map.find(prev_field);
						if ( member_iter != member_map.end() ) {
							member_iter->second(anime, std::move(value));
						}
					} else {
						std::cerr << "Error: Unexpected " << name << " = " 
						          << value << std::endl;
					}
					break;
				case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
					break;
				default:
					std::cerr << "Warning: Unexpected node type "
					          << xmlTextReaderNodeType(reader.get())
					          << " : " << name << "=" << value << std::endl;
					break;
				}
			}
		}
		
		if ( ret != 0 ) {
			std::cerr << "Error: Failed to parse! ret = " << ret << std::endl;
            std::cerr << "The xml is:\n" << xml << std::endl;
		}

		return res;
	}
BusConfigParser*
bus_config_load (const DBusString      *file,
                 dbus_bool_t            is_toplevel,
                 const BusConfigParser *parent,
                 DBusError             *error)

{
  xmlTextReader *reader;
  BusConfigParser *parser;
  DBusString dirname, data;
  DBusError tmp_error;
  int ret;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
  parser = NULL;
  reader = NULL;

  if (!_dbus_string_init (&dirname))
    {
      _DBUS_SET_OOM (error);
      return NULL;
    }

  if (!_dbus_string_init (&data))
    {
      _DBUS_SET_OOM (error);
      _dbus_string_free (&dirname);
      return NULL;
    }

  if (is_toplevel)
    {
      /* xmlMemSetup only fails if one of the functions is NULL */
    /*
      xmlMemSetup (dbus_free,
                   dbus_malloc,
                   dbus_realloc,
                   _dbus_strdup);
     */              
      xmlInitParser ();
      xmlSetGenericErrorFunc (NULL, xml_shut_up);
    }

  if (!_dbus_string_get_dirname (file, &dirname))
    {
      _DBUS_SET_OOM (error);
      goto failed;
    }
  
  parser = bus_config_parser_new (&dirname, is_toplevel, parent);
  if (parser == NULL)
    {
      _DBUS_SET_OOM (error);
      goto failed;
    }
  
  if (!_dbus_file_get_contents (&data, file, error))
    goto failed;

  reader = xmlReaderForMemory (_dbus_string_get_const_data (&data), 
                               _dbus_string_get_length (&data),
			       NULL, NULL, 0);
  if (reader == NULL)
    {
      _DBUS_SET_OOM (error);
      goto failed;
    }

  xmlTextReaderSetParserProp (reader, XML_PARSER_SUBST_ENTITIES, 1);

  dbus_error_init (&tmp_error);
  xmlTextReaderSetStructuredErrorHandler (reader, xml_text_reader_error, &tmp_error);

  while ((ret = xmlTextReaderRead (reader)) == 1)
    {
      int type;
      
      if (dbus_error_is_set (&tmp_error))
        goto reader_out;

      type = xmlTextReaderNodeType (reader);
      if (type == -1)
        {
          _DBUS_MAYBE_SET_OOM (&tmp_error);
          goto reader_out;
        }

      switch ((xmlReaderTypes) type) {
      case XML_READER_TYPE_ELEMENT:
	xml_text_start_element (parser, reader, &tmp_error);
	break;

      case XML_READER_TYPE_TEXT:
      case XML_READER_TYPE_CDATA:
	{
	  DBusString content;
	  const char *value;
#ifdef __SYMBIAN32__
	  value = (const char *) xmlTextReaderConstValue (reader);
#else
	  value = xmlTextReaderConstValue (reader);
#endif
	  if (value != NULL)
	    {
	      _dbus_string_init_const (&content, value);
	      bus_config_parser_content (parser, &content, &tmp_error);
	    }
          else
            _DBUS_MAYBE_SET_OOM (&tmp_error);
	  break;
	}

      case XML_READER_TYPE_DOCUMENT_TYPE:
	{
	  const char *name;
#ifdef __SYMBIAN32__
	  name = (const char *) xmlTextReaderConstName (reader);
#else
	  name = xmlTextReaderConstName (reader);
#endif
	  if (name != NULL)
	    bus_config_parser_check_doctype (parser, name, &tmp_error);
          else
            _DBUS_MAYBE_SET_OOM (&tmp_error);
	  break;
	}

      case XML_READER_TYPE_END_ELEMENT:
	{
	  const char *name;
#ifdef __SYMBIAN32__
	  name = (const char *) xmlTextReaderConstName (reader);
#else
	  name = xmlTextReaderConstName (reader);
#endif
	  if (name != NULL)
	    bus_config_parser_end_element (parser, name, &tmp_error);
          else
            _DBUS_MAYBE_SET_OOM (&tmp_error);
	  break;
	}

      case XML_READER_TYPE_DOCUMENT:
      case XML_READER_TYPE_DOCUMENT_FRAGMENT:
      case XML_READER_TYPE_PROCESSING_INSTRUCTION:
      case XML_READER_TYPE_COMMENT:
      case XML_READER_TYPE_ENTITY:
      case XML_READER_TYPE_NOTATION:
      case XML_READER_TYPE_WHITESPACE:
      case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
      case XML_READER_TYPE_END_ENTITY:
      case XML_READER_TYPE_XML_DECLARATION:
	/* nothing to do, just read on */
	break;

      case XML_READER_TYPE_NONE:
      case XML_READER_TYPE_ATTRIBUTE:
      case XML_READER_TYPE_ENTITY_REFERENCE:
	_dbus_assert_not_reached ("unexpected nodes in XML");
      }

      if (dbus_error_is_set (&tmp_error))
        goto reader_out;
    }

  if (ret == -1)
    _DBUS_MAYBE_SET_OOM (&tmp_error);

 reader_out:
  xmlFreeTextReader (reader);
  reader = NULL;
  if (dbus_error_is_set (&tmp_error))
    {
      dbus_move_error (&tmp_error, error);
      goto failed;
    }
  
  if (!bus_config_parser_finished (parser, error))
    goto failed;
  _dbus_string_free (&dirname);
  _dbus_string_free (&data);
  if (is_toplevel)
    xmlCleanupParser();
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  return parser;
  
 failed:
  _DBUS_ASSERT_ERROR_IS_SET (error);
  _dbus_string_free (&dirname);
  _dbus_string_free (&data);
  if (is_toplevel)
    xmlCleanupParser();
  if (parser)
    bus_config_parser_unref (parser);
  _dbus_assert (reader == NULL); /* must go to reader_out first */
  return NULL;
}
Пример #26
0
int cli_scanxar(cli_ctx *ctx)
{
    int rc = CL_SUCCESS;
    unsigned int cksum_fails = 0;
    unsigned int extract_errors = 0;
#if HAVE_LIBXML2
    int fd = -1;
    struct xar_header hdr;
    fmap_t *map = *ctx->fmap;
    long length, offset, size, at;
    int encoding;
    z_stream strm;
    char *toc, *tmpname;
    xmlTextReaderPtr reader = NULL;
    int a_hash, e_hash;
    unsigned char *a_cksum = NULL, *e_cksum = NULL;

    memset(&strm, 0x00, sizeof(z_stream));

    /* retrieve xar header */
    if (fmap_readn(*ctx->fmap, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) {
        cli_dbgmsg("cli_scanxar: Invalid header, too short.\n");
        return CL_EFORMAT;
    }
    hdr.magic = be32_to_host(hdr.magic);

    if (hdr.magic == XAR_HEADER_MAGIC) {
        cli_dbgmsg("cli_scanxar: Matched magic\n");
    }
    else {
        cli_dbgmsg("cli_scanxar: Invalid magic\n");
        return CL_EFORMAT;
    }
    hdr.size = be16_to_host(hdr.size);
    hdr.version = be16_to_host(hdr.version);
    hdr.toc_length_compressed = be64_to_host(hdr.toc_length_compressed);
    hdr.toc_length_decompressed = be64_to_host(hdr.toc_length_decompressed);
    hdr.chksum_alg = be32_to_host(hdr.chksum_alg);

    /* cli_dbgmsg("hdr.magic %x\n", hdr.magic); */
    /* cli_dbgmsg("hdr.size %i\n", hdr.size); */
    /* cli_dbgmsg("hdr.version %i\n", hdr.version); */
    /* cli_dbgmsg("hdr.toc_length_compressed %lu\n", hdr.toc_length_compressed); */
    /* cli_dbgmsg("hdr.toc_length_decompressed %lu\n", hdr.toc_length_decompressed); */
    /* cli_dbgmsg("hdr.chksum_alg %i\n", hdr.chksum_alg); */

    /* Uncompress TOC */
    strm.next_in = (unsigned char *)fmap_need_off_once(*ctx->fmap, hdr.size, hdr.toc_length_compressed);
    if (strm.next_in == NULL) {
        cli_dbgmsg("cli_scanxar: fmap_need_off_once fails on TOC.\n");
        return CL_EREAD;
    }
    strm.avail_in = hdr.toc_length_compressed;
    toc = cli_malloc(hdr.toc_length_decompressed+1);
    if (toc == NULL) {
        cli_dbgmsg("cli_scanxar: cli_malloc fails on TOC decompress buffer.\n");
        return CL_EMEM;
    }
    toc[hdr.toc_length_decompressed] = '\0';
    strm.avail_out = hdr.toc_length_decompressed;
    strm.next_out = (unsigned char *)toc;
    rc = inflateInit(&strm);
    if (rc != Z_OK) {
        cli_dbgmsg("cli_scanxar:inflateInit error %i \n", rc);
        rc = CL_EFORMAT;
        goto exit_toc;
    }
    rc = inflate(&strm, Z_SYNC_FLUSH);
    if (rc != Z_OK && rc != Z_STREAM_END) {
        cli_dbgmsg("cli_scanxar:inflate error %i \n", rc);
        rc = CL_EFORMAT;
        goto exit_toc;
    }
    rc = inflateEnd(&strm);
    if (rc != Z_OK) {
        cli_dbgmsg("cli_scanxar:inflateEnd error %i \n", rc);
        rc = CL_EFORMAT;
        goto exit_toc;
    }

    /* cli_dbgmsg("cli_scanxar: TOC xml:\n%s\n", toc); */
    /* printf("cli_scanxar: TOC xml:\n%s\n", toc); */
    /* cli_dbgmsg("cli_scanxar: TOC end:\n"); */
    /* printf("cli_scanxar: TOC end:\n"); */

    /* scan the xml */
    cli_dbgmsg("cli_scanxar: scanning xar TOC xml in memory.\n");
    rc = cli_mem_scandesc(toc, hdr.toc_length_decompressed, ctx);
    if (rc != CL_SUCCESS) {
        if (rc != CL_VIRUS || !SCAN_ALL)
            goto exit_toc;
    }

    /* make a file to leave if --leave-temps in effect */
    if(ctx->engine->keeptmp) {
        if ((rc = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
            cli_dbgmsg("cli_scanxar: Can't create temporary file for TOC.\n");
            goto exit_toc;
        }
        if (cli_writen(fd, toc, hdr.toc_length_decompressed) < 0) {
            cli_dbgmsg("cli_scanxar: cli_writen error writing TOC.\n");
            rc = CL_EWRITE;
            xar_cleanup_temp_file(ctx, fd, tmpname);
            goto exit_toc;
        }
        rc = xar_cleanup_temp_file(ctx, fd, tmpname);
        if (rc != CL_SUCCESS)
            goto exit_toc;
    }

    reader = xmlReaderForMemory(toc, hdr.toc_length_decompressed, "noname.xml", NULL, 0);
    if (reader == NULL) {
        cli_dbgmsg("cli_scanxar: xmlReaderForMemory error for TOC\n");
        goto exit_toc;
    }

    rc = xar_scan_subdocuments(reader, ctx);
    if (rc != CL_SUCCESS) {
        cli_dbgmsg("xar_scan_subdocuments returns %i.\n", rc);
        goto exit_reader;
    }

    /* Walk the TOC XML and extract files */
    fd = -1;
    tmpname = NULL;
    while (CL_SUCCESS == (rc = xar_get_toc_data_values(reader, &length, &offset, &size, &encoding,
                               &a_cksum, &a_hash, &e_cksum, &e_hash))) {
        int do_extract_cksum = 1;
        unsigned char * blockp;
        void *a_sc, *e_sc;
        void *a_mc, *e_mc;
        void *a_hash_ctx, *e_hash_ctx;
        char result[SHA1_HASH_SIZE];
        char * expected;

        /* clean up temp file from previous loop iteration */
        if (fd > -1 && tmpname) {
            rc = xar_cleanup_temp_file(ctx, fd, tmpname);
            if (rc != CL_SUCCESS)
                goto exit_reader;
        }

        at = offset + hdr.toc_length_compressed + hdr.size;

        if ((rc = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
            cli_dbgmsg("cli_scanxar: Can't generate temporary file.\n");
            goto exit_reader;
        }

        cli_dbgmsg("cli_scanxar: decompress into temp file:\n%s, size %li,\n"
                   "from xar heap offset %li length %li\n",
                   tmpname, size, offset, length);


        a_hash_ctx = xar_hash_init(a_hash, &a_sc, &a_mc);
        e_hash_ctx = xar_hash_init(e_hash, &e_sc, &e_mc);

        switch (encoding) {
        case CL_TYPE_GZ:
            /* inflate gzip directly because file segments do not contain magic */
            memset(&strm, 0, sizeof(strm));
            if ((rc = inflateInit(&strm)) != Z_OK) {
                cli_dbgmsg("cli_scanxar: InflateInit failed: %d\n", rc);
                rc = CL_EFORMAT;
                extract_errors++;
                break;
            }

            while ((size_t)at < map->len && (unsigned long)at < offset+hdr.toc_length_compressed+hdr.size+length) {
                unsigned long avail_in;
                void * next_in;
                unsigned int bytes = MIN(map->len - at, map->pgsz);
                bytes = MIN(length, bytes);
                if(!(strm.next_in = next_in = (void*)fmap_need_off_once(map, at, bytes))) {
                    cli_dbgmsg("cli_scanxar: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at);
                    inflateEnd(&strm);
                    rc = CL_EREAD;
                    goto exit_tmpfile;
                }
                at += bytes;
                strm.avail_in = avail_in = bytes;
                do {
                    int inf, outsize = 0;
                    unsigned char buff[FILEBUFF];
                    strm.avail_out = sizeof(buff);
                    strm.next_out = buff;
                    inf = inflate(&strm, Z_SYNC_FLUSH);
                    if (inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
                        cli_dbgmsg("cli_scanxar: inflate error %i %s.\n", inf, strm.msg?strm.msg:"");
                        rc = CL_EFORMAT;
                        extract_errors++;
                        break;
                    }

                    bytes = sizeof(buff) - strm.avail_out;

                    xar_hash_update(e_hash_ctx, buff, bytes, e_hash);

                    if (cli_writen(fd, buff, bytes) < 0) {
                        cli_dbgmsg("cli_scanxar: cli_writen error file %s.\n", tmpname);
                        inflateEnd(&strm);
                        rc = CL_EWRITE;
                        goto exit_tmpfile;
                    }
                    outsize += sizeof(buff) - strm.avail_out;
                    if (cli_checklimits("cli_scanxar", ctx, outsize, 0, 0) != CL_CLEAN) {
                        break;
                    }
                    if (inf == Z_STREAM_END) {
                        break;
                    }
                } while (strm.avail_out == 0);

                if (rc != CL_SUCCESS)
                    break;

                avail_in -= strm.avail_in;
                xar_hash_update(a_hash_ctx, next_in, avail_in, a_hash);
            }

            inflateEnd(&strm);
            break;
        case CL_TYPE_7Z:
#define CLI_LZMA_OBUF_SIZE 1024*1024
#define CLI_LZMA_HDR_SIZE LZMA_PROPS_SIZE+8
#define CLI_LZMA_IBUF_SIZE CLI_LZMA_OBUF_SIZE>>2 /* estimated compression ratio 25% */
        {
            struct CLI_LZMA lz;
            unsigned long in_remaining = length;
            unsigned long out_size = 0;
            unsigned char * buff = __lzma_wrap_alloc(NULL, CLI_LZMA_OBUF_SIZE);
            int lret;

            memset(&lz, 0, sizeof(lz));
            if (buff == NULL) {
                cli_dbgmsg("cli_scanxar: memory request for lzma decompression buffer fails.\n");
                rc = CL_EMEM;
                goto exit_tmpfile;

            }

            blockp = (void*)fmap_need_off_once(map, at, CLI_LZMA_HDR_SIZE);
            if (blockp == NULL) {
                char errbuff[128];
                cli_strerror(errno, errbuff, sizeof(errbuff));
                cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
                           length, at, errbuff);
                rc = CL_EREAD;
                __lzma_wrap_free(NULL, buff);
                goto exit_tmpfile;
            }

            lz.next_in = blockp;
            lz.avail_in = CLI_LZMA_HDR_SIZE;

            xar_hash_update(a_hash_ctx, blockp, CLI_LZMA_HDR_SIZE, a_hash);

            lret = cli_LzmaInit(&lz, 0);
            if (lret != LZMA_RESULT_OK) {
                cli_dbgmsg("cli_scanxar: cli_LzmaInit() fails: %i.\n", lret);
                rc = CL_EFORMAT;
                __lzma_wrap_free(NULL, buff);
                extract_errors++;
                break;
            }

            at += CLI_LZMA_HDR_SIZE;
            in_remaining -= CLI_LZMA_HDR_SIZE;
            while ((size_t)at < map->len && (unsigned long)at < offset+hdr.toc_length_compressed+hdr.size+length) {
                SizeT avail_in;
                SizeT avail_out;
                void * next_in;
                unsigned long in_consumed;

                lz.next_out = buff;
                lz.avail_out = CLI_LZMA_OBUF_SIZE;
                lz.avail_in = avail_in = MIN(CLI_LZMA_IBUF_SIZE, in_remaining);
                lz.next_in = next_in = (void*)fmap_need_off_once(map, at, lz.avail_in);
                if (lz.next_in == NULL) {
                    char errbuff[128];
                    cli_strerror(errno, errbuff, sizeof(errbuff));
                    cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno: %s.\n",
                               length, at, errbuff);
                    rc = CL_EREAD;
                    __lzma_wrap_free(NULL, buff);
                    cli_LzmaShutdown(&lz);
                    goto exit_tmpfile;
                }

                lret = cli_LzmaDecode(&lz);
                if (lret != LZMA_RESULT_OK && lret != LZMA_STREAM_END) {
                    cli_dbgmsg("cli_scanxar: cli_LzmaDecode() fails: %i.\n", lret);
                    rc = CL_EFORMAT;
                    extract_errors++;
                    break;
                }

                in_consumed = avail_in - lz.avail_in;
                in_remaining -= in_consumed;
                at += in_consumed;
                avail_out = CLI_LZMA_OBUF_SIZE - lz.avail_out;

                if (avail_out == 0)
                    cli_dbgmsg("cli_scanxar: cli_LzmaDecode() produces no output for "
                               "avail_in %lu, avail_out %lu.\n", avail_in, avail_out);

                xar_hash_update(a_hash_ctx, next_in, in_consumed, a_hash);
                xar_hash_update(e_hash_ctx, buff, avail_out, e_hash);

                /* Write a decompressed block. */
                /* cli_dbgmsg("Writing %li bytes to LZMA decompress temp file, " */
                /*            "consumed %li of %li available compressed bytes.\n", */
                /*            avail_out, in_consumed, avail_in); */

                if (cli_writen(fd, buff, avail_out) < 0) {
                    cli_dbgmsg("cli_scanxar: cli_writen error writing lzma temp file for %li bytes.\n",
                               avail_out);
                    __lzma_wrap_free(NULL, buff);
                    cli_LzmaShutdown(&lz);
                    rc = CL_EWRITE;
                    goto exit_tmpfile;
                }

                /* Check file size limitation. */
                out_size += avail_out;
                if (cli_checklimits("cli_scanxar", ctx, out_size, 0, 0) != CL_CLEAN) {
                    break;
                }

                if (lret == LZMA_STREAM_END)
                    break;
            }

            cli_LzmaShutdown(&lz);
            __lzma_wrap_free(NULL, buff);
        }
        break;
        case CL_TYPE_ANY:
        default:
        case CL_TYPE_BZ:
        case CL_TYPE_XZ:
            /* for uncompressed, bzip2, xz, and unknown, just pull the file, cli_magic_scandesc does the rest */
            do_extract_cksum = 0;
            {
                unsigned long write_len;

                if (ctx->engine->maxfilesize)
                    write_len = MIN((size_t)(ctx->engine->maxfilesize), (size_t)length);
                else
                    write_len = length;

                if (!(blockp = (void*)fmap_need_off_once(map, at, length))) {
                    char errbuff[128];
                    cli_strerror(errno, errbuff, sizeof(errbuff));
                    cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
                               length, at, errbuff);
                    rc = CL_EREAD;
                    goto exit_tmpfile;
                }

                xar_hash_update(a_hash_ctx, blockp, length, a_hash);

                if (cli_writen(fd, blockp, write_len) < 0) {
                    cli_dbgmsg("cli_scanxar: cli_writen error %li bytes @ %li.\n", length, at);
                    rc = CL_EWRITE;
                    goto exit_tmpfile;
                }
                /*break;*/
            }
        }

        if (rc == CL_SUCCESS) {
            xar_hash_final(a_hash_ctx, result, a_hash);
            if (a_cksum != NULL) {
                expected = cli_hex2str((char *)a_cksum);
                if (xar_hash_check(a_hash, result, expected) != 0) {
                    cli_dbgmsg("cli_scanxar: archived-checksum missing or mismatch.\n");
                    cksum_fails++;
                } else {
                    cli_dbgmsg("cli_scanxar: archived-checksum matched.\n");
                }
                free(expected);
            }
            if (e_cksum != NULL) {
                if (do_extract_cksum) {
                    xar_hash_final(e_hash_ctx, result, e_hash);
                    expected = cli_hex2str((char *)e_cksum);
                    if (xar_hash_check(e_hash, result, expected) != 0) {
                        cli_dbgmsg("cli_scanxar: extracted-checksum missing or mismatch.\n");
                        cksum_fails++;
                    } else {
                        cli_dbgmsg("cli_scanxar: extracted-checksum matched.\n");
                    }
                    free(expected);
                }
            }

            rc = cli_magic_scandesc(fd, ctx);
            if (rc != CL_SUCCESS) {
                if (rc == CL_VIRUS) {
                    cli_dbgmsg("cli_scanxar: Infected with %s\n", cli_get_last_virus(ctx));
                    if (!SCAN_ALL)
                        goto exit_tmpfile;
                } else if (rc != CL_BREAK) {
                    cli_dbgmsg("cli_scanxar: cli_magic_scandesc error %i\n", rc);
                    goto exit_tmpfile;
                }
            }
        }

        if (a_cksum != NULL) {
            xmlFree(a_cksum);
            a_cksum = NULL;
        }
        if (e_cksum != NULL) {
            xmlFree(e_cksum);
            e_cksum = NULL;
        }
    }

exit_tmpfile:
    xar_cleanup_temp_file(ctx, fd, tmpname);

exit_reader:
    if (a_cksum != NULL)
        xmlFree(a_cksum);
    if (e_cksum != NULL)
        xmlFree(e_cksum);
    xmlTextReaderClose(reader);
    xmlFreeTextReader(reader);

exit_toc:
    free(toc);
    if (rc == CL_BREAK)
        rc = CL_SUCCESS;
#else
    cli_dbgmsg("cli_scanxar: can't scan xar files, need libxml2.\n");
#endif
    if (cksum_fails + extract_errors != 0) {
        cli_warnmsg("cli_scanxar: %u checksum errors and %u extraction errors, use --debug for more info.\n",
                    cksum_fails, extract_errors);
    }

    return rc;
}
	CInterfaceDefinition *CInterfaceDefinitionLoader::load( const unsigned char &buffer, unsigned int buffer_size )
	{
		assert( !m_interface_definition && !m_reader && m_element_path.empty() );

		m_interface_definition = new CInterfaceDefinition;

		xmlInitParser();

		m_reader = xmlReaderForMemory( (char *) &buffer, buffer_size, NULL, NULL, 0 );
		if( !m_reader )
		{
			INTEGRA_TRACE_ERROR << "unable to read file";
			cleanup();
			return NULL;
		}

		int depth = -1;
		bool handled_element_content = false;
		char *inner_xml = NULL; 

		while( xmlTextReaderRead( m_reader ) )
		{
			switch( xmlTextReaderNodeType( m_reader ) )
			{
				case XML_READER_TYPE_TEXT:
					{
						char *element_value = ( char * ) xmlTextReaderValue( m_reader );
						if( handle_element_value( element_value ) != CError::SUCCESS )
						{
							xmlFree( element_value );
							cleanup();
							return NULL;
						}
						xmlFree( element_value );
						handled_element_content = true;

						store_map_entries();
					}
					break;

				case XML_READER_TYPE_ELEMENT:
					{
						const char *element_name = ( const char * ) xmlTextReaderConstName( m_reader );
						int new_depth = xmlTextReaderDepth( m_reader );

						while( depth >= new_depth )
						{
							pop_element_name();
							depth--;
						}

						if( depth < new_depth )
						{
							push_element_name( element_name );
							depth++;
						}

						assert( depth == new_depth );

						if( handle_element() != CError::SUCCESS )
						{
							cleanup();
							return NULL;
						}

						if( xmlTextReaderHasAttributes( m_reader ) )
						{
							if( handle_element_attributes() != CError::SUCCESS )
							{
								cleanup();
								return NULL;
							}
						}

						if( xmlTextReaderIsEmptyElement( m_reader ) )
						{
							handle_element_value( "" );
							handled_element_content = true;
						}
						else
						{
							handled_element_content = false;
							inner_xml = ( char * ) xmlTextReaderReadInnerXml( m_reader );
						}
					}

					break;

				case XML_READER_TYPE_END_ELEMENT:
					if( !handled_element_content && inner_xml )
					{
						handle_element_value( inner_xml );
					}
					if( inner_xml )
					{
						xmlFree( inner_xml );
						inner_xml = NULL;
					}
					handled_element_content = true;
					break;

				default:
					break;
			}
		}

		CError CError = do_sanity_check();
		if( CError != CError::SUCCESS )
		{
			INTEGRA_TRACE_ERROR << "sanity check failed";
			cleanup();
			return NULL;
		}

		m_interface_definition->propagate_defaults();

		INTEGRA_TRACE_VERBOSE << "Loaded ok: " << m_interface_definition->get_interface_info().get_name();
		CInterfaceDefinition *loaded_interface = m_interface_definition;
		m_interface_definition = NULL;
		cleanup();

		return loaded_interface;
	}