winemenubuilder: generate XML files using libxml2

Damjan Jovanovic damjan.jov at gmail.com
Sat Nov 7 09:42:33 CST 2009


Changelog:
* generate XML files using libmxl2

Since libxml2 escapes XML special characters (eg. <, >, &) properly,
this should fix #13963.

Damjan Jovanovic
-------------- next part --------------
diff --git a/programs/winemenubuilder/Makefile.in b/programs/winemenubuilder/Makefile.in
index 092405e..9686a5d 100644
--- a/programs/winemenubuilder/Makefile.in
+++ b/programs/winemenubuilder/Makefile.in
@@ -6,7 +6,8 @@ VPATH     = @srcdir@
 MODULE    = winemenubuilder.exe
 APPMODE   = -mwindows
 IMPORTS   = uuid shell32 shlwapi ole32 user32 advapi32 kernel32
-EXTRAINCL = @PNGINCL@
+EXTRAINCL = @PNGINCL@ @XML2INCL@
+EXTRALIBS = @XML2LIBS@
 
 C_SRCS = \
 	winemenubuilder.c
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index fb13878..bc319aa 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -102,6 +102,10 @@
 #include <png.h>
 #endif
 
+#ifdef HAVE_LIBXML2
+#include <libxml/xmlwriter.h>
+#endif
+
 WINE_DEFAULT_DEBUG_CHANNEL(menubuilder);
 
 #define in_desktop_dir(csidl) ((csidl)==CSIDL_DESKTOPDIRECTORY || \
@@ -919,6 +923,7 @@ static BOOL write_directory_entry(const char *directory, const char *location)
 
 static BOOL write_menu_file(const char *unix_link, const char *filename)
 {
+#ifdef HAVE_LIBXML2
     char *tempfilename;
     FILE *tempfile = NULL;
     char *lastEntry;
@@ -926,6 +931,9 @@ static BOOL write_menu_file(const char *unix_link, const char *filename)
     char *menuPath = NULL;
     int i;
     int count = 0;
+    xmlBufferPtr xmlBuffer = NULL;
+    xmlTextWriterPtr xmlWriter = NULL;
+    int rc;
     BOOL ret = FALSE;
 
     WINE_TRACE("(%s)\n", wine_dbgstr_a(filename));
@@ -954,10 +962,19 @@ static BOOL write_menu_file(const char *unix_link, const char *filename)
         return FALSE;
     }
 
-    fprintf(tempfile, "<!DOCTYPE Menu PUBLIC \"-//freedesktop//DTD Menu 1.0//EN\"\n");
-    fprintf(tempfile, "\"http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd\">\n");
-    fprintf(tempfile, "<Menu>\n");
-    fprintf(tempfile, "  <Name>Applications</Name>\n");
+    xmlBuffer = xmlBufferCreate();
+    if (xmlBuffer == NULL)
+        goto end;
+    xmlWriter = xmlNewTextWriterMemory(xmlBuffer, 0);
+    if (xmlWriter == NULL)
+        goto end;
+
+    rc = xmlTextWriterWriteDTD(xmlWriter, BAD_CAST "Menu", BAD_CAST "-//freedesktop//DTD Menu 1.0//EN",
+        BAD_CAST "http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd", NULL);
+    if (rc >= 0)
+        rc = xmlTextWriterStartElement(xmlWriter, BAD_CAST "Menu");
+    if (rc >= 0)
+        rc = xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Name", BAD_CAST "Applications");
 
     name = HeapAlloc(GetProcessHeap(), 0, lstrlenA(filename) + 1);
     if (name == NULL) goto end;
@@ -968,11 +985,26 @@ static BOOL write_menu_file(const char *unix_link, const char *filename)
         if (filename[i] == '/')
         {
             char *dir_file_name;
+            char *wine_name;
+            char *wine_dir;
             struct stat st;
             name[i] = 0;
-            fprintf(tempfile, "  <Menu>\n");
-            fprintf(tempfile, "    <Name>%s%s</Name>\n", count ? "" : "wine-", name);
-            fprintf(tempfile, "    <Directory>%s%s.directory</Directory>\n", count ? "" : "wine-", name);
+            if (rc >= 0)
+                rc = xmlTextWriterStartElement(xmlWriter, BAD_CAST "Menu");
+            wine_name = heap_printf("%s%s", count ? "" : "wine-", name);
+            if (wine_name)
+            {
+                if (rc >= 0)
+                    rc = xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Name", BAD_CAST wine_name);
+                HeapFree(GetProcessHeap(), 0, wine_name);
+            }
+            wine_dir = heap_printf("%s%s.directory", count ? "" : "wine-", name);
+            if (wine_dir)
+            {
+                if (rc >= 0)
+                    rc = xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Directory", BAD_CAST wine_dir);
+                HeapFree(GetProcessHeap(), 0, wine_dir);
+            }
             dir_file_name = heap_printf("%s/desktop-directories/%s%s.directory",
                 xdg_data_dir, count ? "" : "wine-", name);
             if (dir_file_name)
@@ -988,12 +1020,20 @@ static BOOL write_menu_file(const char *unix_link, const char *filename)
     }
     name[i] = 0;
 
-    fprintf(tempfile, "    <Include>\n");
-    fprintf(tempfile, "      <Filename>%s</Filename>\n", name);
-    fprintf(tempfile, "    </Include>\n");
+    if (rc >= 0)
+        rc = xmlTextWriterStartElement(xmlWriter, BAD_CAST "Include");
+    if (rc >= 0)
+        rc = xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Filename", BAD_CAST name);
+    if (rc >= 0)
+        rc = xmlTextWriterEndElement(xmlWriter); /* Include */
+
     for (i = 0; i < count; i++)
-         fprintf(tempfile, "  </Menu>\n");
-    fprintf(tempfile, "</Menu>\n");
+    {
+        if (rc >= 0)
+            rc = xmlTextWriterEndElement(xmlWriter); /* Menu */
+    }
+    if (rc >= 0)
+        rc = xmlTextWriterEndElement(xmlWriter); /* Menu */
 
     menuPath = heap_printf("%s/%s", xdg_config_dir, name);
     if (menuPath == NULL) goto end;
@@ -1001,8 +1041,14 @@ static BOOL write_menu_file(const char *unix_link, const char *filename)
     ret = TRUE;
 
 end:
+    if (xmlWriter)
+        xmlFreeTextWriter(xmlWriter);
+    if (ret && tempfile)
+        fprintf(tempfile, "%s", (const char *) xmlBuffer->content);
     if (tempfile)
         fclose(tempfile);
+    if (xmlBuffer)
+        xmlBufferFree(xmlBuffer);
     if (ret)
         ret = (rename(tempfilename, menuPath) == 0);
     if (!ret && tempfilename)
@@ -1020,6 +1066,10 @@ end:
     HeapFree(GetProcessHeap(), 0, name);
     HeapFree(GetProcessHeap(), 0, menuPath);
     return ret;
+#else
+    WINE_ERR("cannot generate menu file %s, libxml2 was not present at compile time\n", wine_dbgstr_a(filename));
+    return FALSE;
+#endif
 }
 
 static BOOL write_menu_entry(const char *unix_link, const char *link, const char *path, const char *args,
@@ -1791,28 +1841,55 @@ static BOOL cleanup_associations(void)
 static BOOL write_freedesktop_mime_type_entry(const char *packages_dir, const char *dot_extension,
                                               const char *mime_type, const char *comment)
 {
+#ifdef HAVE_LIBXML2
     BOOL ret = FALSE;
     char *filename;
 
     WINE_TRACE("writing MIME type %s, extension=%s, comment=%s\n", wine_dbgstr_a(mime_type),
                wine_dbgstr_a(dot_extension), wine_dbgstr_a(comment));
 
-    filename = heap_printf("%s/x-wine-extension-%s.xml", packages_dir, &dot_extension[1]);
+    filename = heap_printf("file://%s/x-wine-extension-%s.xml", packages_dir, &dot_extension[1]);
     if (filename)
     {
-        FILE *packageFile = fopen(filename, "w");
-        if (packageFile)
+        xmlTextWriterPtr writer;
+        int rc;
+        writer = xmlNewTextWriterFilename(filename, 0);
+        if (writer)
         {
-            fprintf(packageFile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-            fprintf(packageFile, "<mime-info xmlns=\"http://www.freedesktop.org/standards/shared-mime-info\">\n");
-            fprintf(packageFile, "  <mime-type type=\"%s\">\n", mime_type);
-            fprintf(packageFile, "    <glob pattern=\"*%s\"/>\n", dot_extension);
-            if (comment)
-                fprintf(packageFile, "    <comment>%s</comment>\n", comment);
-            fprintf(packageFile, "  </mime-type>\n");
-            fprintf(packageFile, "</mime-info>\n");
-            ret = TRUE;
-            fclose(packageFile);
+            rc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
+            if (rc >= 0)
+                rc = xmlTextWriterStartElement(writer, BAD_CAST "mime-info");
+            if (rc >= 0)
+                rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "xmlns",
+                    BAD_CAST "http://www.freedesktop.org/standards/shared-mime-info");
+            if (rc >= 0)
+                rc = xmlTextWriterStartElement(writer, BAD_CAST "mime-type");
+            if (rc >= 0)
+                rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST mime_type);
+            if (rc >= 0)
+                rc = xmlTextWriterStartElement(writer, BAD_CAST "glob");
+            if (rc >= 0)
+            {
+                char *star_dot_extension = heap_printf("*%s", dot_extension);
+                if (star_dot_extension)
+                {
+                    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "pattern", BAD_CAST star_dot_extension);
+                    HeapFree(GetProcessHeap(), 0, star_dot_extension);
+                }
+                else
+                    rc = -1;
+            }
+            if (rc >= 0)
+                rc = xmlTextWriterEndElement(writer); /* glob */
+            if (rc >= 0 && comment)
+                rc = xmlTextWriterWriteElement(writer, BAD_CAST "comment", BAD_CAST comment);
+            if (rc >= 0)
+                rc = xmlTextWriterEndElement(writer); /* mime-type */
+            if (rc >= 0)
+                rc = xmlTextWriterEndElement(writer); /* mime-info */
+
+            ret = (rc >= 0);
+            xmlFreeTextWriter(writer);
         }
         else
             WINE_ERR("error writing file %s\n", filename);
@@ -1821,6 +1898,11 @@ static BOOL write_freedesktop_mime_type_entry(const char *packages_dir, const ch
     else
         WINE_ERR("out of memory\n");
     return ret;
+#else
+    WINE_ERR("cannot generate MIME type entry for extension %s, libxml2 was not present at compile time\n",
+        wine_dbgstr_a(dot_extension));
+    return FALSE;
+#endif
 }
 
 static BOOL is_extension_blacklisted(LPCWSTR extension)


More information about the wine-patches mailing list