[evince/wip/chpe/load-fd: 14/15] libdocument: Add function to sniff MIME type from FD




commit f88af66538d51c7c25e89ec9ad5873ebd3c4d988
Author: Christian Persch <chpe src gnome org>
Date:   Tue Jan 11 20:42:24 2022 +0100

    libdocument: Add function to sniff MIME type from FD

 libdocument/ev-file-helpers.c | 74 +++++++++++++++++++++++++++++++++++++++++++
 libdocument/ev-file-helpers.h |  4 +++
 2 files changed, 78 insertions(+)
---
diff --git a/libdocument/ev-file-helpers.c b/libdocument/ev-file-helpers.c
index 436f6a7f5..cf10c3684 100644
--- a/libdocument/ev-file-helpers.c
+++ b/libdocument/ev-file-helpers.c
@@ -503,6 +503,80 @@ ev_file_get_mime_type (const gchar *uri,
        return fast ? get_mime_type_from_uri (uri, error) : get_mime_type_from_data (uri, error);
 }
 
+/**
+ * ev_file_get_mime_type_from_fd:
+ * @fd: an file descriptor (must be seekable)
+ * @error: a #GError location to store an error, or %NULL
+ *
+ * Returns: a newly allocated string with the MIME type of the file referred to
+ *   by @fd, or %NULL on error or if the MIME type could not be determined
+ */
+gchar *
+ev_file_get_mime_type_from_fd (int      fd,
+                               GError **error)
+{
+        guchar buffer[4096];
+        ssize_t r;
+        off_t pos;
+        char *content_type, *mime_type;
+
+        g_return_val_if_fail (fd != -1, NULL);
+
+        pos = lseek (fd, 0, SEEK_CUR);
+        if (pos == (off_t)-1) {
+                int errsv = errno;
+                g_set_error (error, G_IO_ERROR,
+                             g_io_error_from_errno (errsv),
+                             "Failed to get MIME type: %s",
+                             g_strerror (errsv));
+                return NULL;
+        }
+
+        do {
+                r = read (fd, buffer, sizeof (buffer));
+        } while (r == -1 && errno == EINTR);
+
+        if (r == -1) {
+                int errsv = errno;
+                g_set_error (error, G_IO_ERROR,
+                             g_io_error_from_errno (errsv),
+                             "Failed to get MIME type: %s",
+                             g_strerror (errsv));
+
+                (void) lseek (fd, pos, SEEK_SET);
+                return NULL;
+        }
+
+        if (lseek (fd, pos, SEEK_SET) == (off_t)-1) {
+                int errsv = errno;
+                g_set_error (error, G_IO_ERROR,
+                             g_io_error_from_errno (errsv),
+                             "Failed to get MIME type: %s",
+                             g_strerror (errsv));
+                return NULL;
+        }
+
+        content_type = g_content_type_guess (NULL, /* no filename */
+                                             buffer, r,
+                                             NULL);
+        if (content_type == NULL) {
+                g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                                     _("Unknown MIME Type"));
+                return NULL;
+        }
+
+        mime_type = g_content_type_get_mime_type (content_type);
+        g_free (content_type);
+
+        if (mime_type == NULL) {
+                g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                                     _("Unknown MIME Type"));
+                return NULL;
+        }
+
+        return mime_type;
+}
+
 /* Compressed files support */
 
 static const char *compressor_cmds[] = {
diff --git a/libdocument/ev-file-helpers.h b/libdocument/ev-file-helpers.h
index ea7b488b2..22ad81d72 100644
--- a/libdocument/ev-file-helpers.h
+++ b/libdocument/ev-file-helpers.h
@@ -73,6 +73,10 @@ gchar       *ev_file_get_mime_type    (const gchar       *uri,
                                       gboolean           fast,
                                       GError           **error);
 
+EV_PUBLIC
+gchar       *ev_file_get_mime_type_from_fd (int           fd,
+                                            GError      **error);
+
 EV_PUBLIC
 gchar       *ev_file_uncompress       (const gchar       *uri,
                                       EvCompressionType  type,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]