[yelp] Initial work on new old new YelpUri API



commit ec875fad52c99c6cebd19fb7a784e97dce716001
Author: Shaun McCance <shaunm gnome org>
Date:   Fri Jun 26 13:42:48 2009 -0500

    Initial work on new old new YelpUri API

 src/Makefile.am |   11 +
 src/test-uri.c  |  165 +++++++++-------
 src/yelp-uri.c  |  580 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/yelp-uri.h  |   78 ++++++++
 4 files changed, 760 insertions(+), 74 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index b8b8dcc..5a47fbf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -108,6 +108,10 @@ endif
 #	test-transform		\
 #	test-resolver
 
+check_PROGRAMS =		\
+	test-document		\
+	test-uri
+
 test_document_SOURCES =					\
 	yelp-debug.c		yelp-debug.h		\
 	yelp-docbook.c		yelp-docbook.h		\
@@ -164,6 +168,13 @@ test_resolver_CFLAGS = $(YELP_CFLAGS) $(AM_CFLAGS) $(YELP_DEFINES)
 test_resolver_LDADD = $(YELP_LIBS)
 test_resolver_LDFLAGS = $(AM_LDFLAGS)
 
+test_uri_SOURCES =					\
+	yelp-uri.c		yelp-uri.h		\
+	test-uri.c
+test_uri_CFLAGS = $(YELP_CFLAGS) $(AM_CFLAGS) $(YELP_DEFINES)
+test_uri_LDADD = $(YELP_LIBS)
+test_uri_LDFLAGS = $(AM_LDFLAGS)
+
 @INTLTOOL_SERVER_RULE@
 
 BUILT_SOURCES = yelp-marshal.h stamp-yelp-marshal.h yelp-marshal.c server-bindings.h \
diff --git a/src/test-uri.c b/src/test-uri.c
index 6d0caeb..4eef76d 100644
--- a/src/test-uri.c
+++ b/src/test-uri.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*
  * Copyright (C) 2002 Mikael Hallendal <micke imendio com>
  *
@@ -21,99 +21,116 @@
  */
 
 #include <config.h>
+#include <stdio.h>
 
-#include <libgnome/gnome-init.h>
-#include <libgnome/gnome-program.h>
-
-#include "yelp-utils.h"
+#include "yelp-uri.h"
 
 static void 
-print_doc_info (YelpDocInfo *doc)
+print_uri (YelpUri *uri)
 {
-    gchar *type, *uri, *file;
-    gboolean hasfile = FALSE;
-    gint i, max, tmp;
+    gchar *type, *tmp, **tmpv;
 
-    switch (yelp_doc_info_get_type(doc)) {
-    case YELP_DOC_TYPE_ERROR:
-	type = "YELP_DOC_TYPE_ERROR";
-	break;
-    case YELP_DOC_TYPE_DOCBOOK_XML:
-	type = "YELP_DOC_TYPE_DOCBOOK_XML";
-	break;
-    case YELP_DOC_TYPE_DOCBOOK_SGML:
-	type = "YELP_DOC_TYPE_DOCBOOK_SGML";
-	break;
-    case YELP_DOC_TYPE_HTML:
-	type = "YELP_DOC_TYPE_HTML";
-	break;
-    case YELP_DOC_TYPE_XHTML:
-	type = "YELP_DOC_TYPE_XHTML";
-	break;
-    case YELP_DOC_TYPE_MAN:
-	type = "YELP_DOC_TYPE_MAN";
-	break;
-    case YELP_DOC_TYPE_INFO:
-	type = "YELP_DOC_TYPE_INFO";
-	break;
-    case YELP_DOC_TYPE_TOC:
-	type = "YELP_DOC_TYPE_DOC";
-	break;
-    case YELP_DOC_TYPE_EXTERNAL:
-	type = "YELP_DOC_TYPE_EXTERNAL";
-	break;
+    switch (yelp_uri_get_document_type (uri)) {
+    case YELP_URI_DOCUMENT_TYPE_DOCBOOK:
+        type = "DOCBOOK";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_MALLARD:
+        type = "MALLARD";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_MAN:
+        type = "MAN";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_INFO:
+        type = "INFO";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_TEXT:
+        type = "TEXT";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_HTML:
+        type = "HTML";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_XHTML:
+        type = "XHTML";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_TOC:
+        type = "TOC";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_SEARCH:
+        type = "SEARCH";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_NOT_FOUND:
+        type = "NOT FOUND";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_EXTERNAL:
+        type = "EXTERNAL";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_ERROR:
+        type = "ERROR";
+        break;
+    case YELP_URI_DOCUMENT_TYPE_UNKNOWN:
+        type = "UNKNOWN";
+        break;
     }
 
-    printf ("Address:  %i\n", (guint) doc);
-    printf ("Type:     %s\n", type);
+    printf ("TYPE:  %s\n", type);
+
+    tmp = yelp_uri_get_base_uri (uri);
+    if (tmp) {
+        printf ("URI:   %s\n", tmp);
+        g_free (tmp);
+    }
 
-    max = 0;
-    tmp = YELP_URI_TYPE_ANY;
-    while ((tmp = tmp >> 1))
-	max++;
+    tmpv = yelp_uri_get_search_path (uri);
+    if (tmpv) {
+        int i;
+        for (i = 0; tmpv[i]; i++) {
+            if (i == 0)
+                printf ("PATH:  %s\n", tmpv[i]);
+            else
+                printf ("       %s\n", tmpv[i]);
+        }
+        g_strfreev (tmpv);
+    }
 
-    for (i = 0; i <= max; i++) {
-	uri = yelp_doc_info_get_uri (doc, NULL, 1 << i);
-	if (uri) {
-	    printf ("URI:      %s\n", uri);
-	    if ((1 << i) == YELP_URI_TYPE_FILE)
-		hasfile = TRUE;
-	    g_free (uri);
-	}
+    tmp = yelp_uri_get_page_id (uri);
+    if (tmp) {
+        printf ("PAGE:  %s\n", tmp);
+        g_free (tmp);
     }
 
-    if (hasfile) {
-	file = yelp_doc_info_get_filename (doc);
-	printf ("Filename: %s\n", file);
-	g_free (file);
+    tmp = yelp_uri_get_frag_id (uri);
+    if (tmp) {
+        printf ("FRAG:  %s\n", tmp);
+        g_free (tmp);
     }
 }
 
 int
 main (int argc, char **argv)
 {
-    GnomeProgram *program;
-    YelpDocInfo  *doc;
-    gint i;
-	
+    YelpUri *parent = NULL;
+    YelpUri *uri = NULL;
+
+    g_type_init ();
+    g_log_set_always_fatal (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
+        
     if (argc < 2) {
-	g_print ("Usage: test-uri uri\n");
-	return 1;
+        g_print ("Usage: test-uri uri\n");
+        return 1;
     }
 
-    program = gnome_program_init (PACKAGE, VERSION,
-				  LIBGNOME_MODULE, argc, argv,
-				  GNOME_PROGRAM_STANDARD_PROPERTIES,
-				  NULL);
-
-    for (i = 1; i < argc; i++) {
-	if (i != 1)
-	    printf ("\n");
-	doc = yelp_doc_info_get (argv[i], FALSE);
-	if (doc)
-	    print_doc_info (doc);
-	else
-	    printf ("Failed to load URI: %s\n", argv[i]);
+    if (argc > 2) {
+        parent = yelp_uri_resolve (argv[1]);
+        uri = yelp_uri_resolve_relative (parent, argv[2]);
+    } else {
+        uri = yelp_uri_resolve (argv[1]);
+    }
+    if (uri) {
+        print_uri (uri);
+        g_object_unref (uri);
+    }
+    if (parent) {
+        g_object_unref (parent);
     }
 
     return 0;
diff --git a/src/yelp-uri.c b/src/yelp-uri.c
new file mode 100644
index 0000000..1c402f7
--- /dev/null
+++ b/src/yelp-uri.c
@@ -0,0 +1,580 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Shaun McCance  <shaunm gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance  <shaunm gnome org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "yelp-uri.h"
+#include "yelp-debug.h"
+
+#define YELP_URI_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_URI, YelpUriPriv))
+
+struct _YelpUriPriv {
+    YelpUriDocumentType   doctype;
+    GFile                *gfile;
+    gchar               **search_path;
+    gchar                *page_id;
+    gchar                *frag_id;
+};
+
+static void           uri_class_init        (YelpUriClass   *klass);
+static void           uri_init              (YelpUri        *uri);
+static void           uri_dispose           (GObject        *object);
+
+static void           resolve_file_uri      (YelpUri        *ret,
+                                             gchar          *arg);
+static void           resolve_file_path     (YelpUri        *ret,
+                                             YelpUri        *base,
+                                             gchar          *arg);
+static void           resolve_ghelp_uri     (YelpUri        *ret,
+                                             gchar          *arg);
+static void           resolve_man_uri       (YelpUri        *ret,
+                                             gchar          *arg);
+static void           resolve_info_uri      (YelpUri        *ret,
+                                             gchar          *arg);
+static void           resolve_page_and_frag (YelpUri        *ret,
+                                             gchar          *arg);
+static void           resolve_common        (YelpUri        *ret);
+static gboolean       is_man_path           (gchar          *uri,
+                                             gchar          *encoding);
+
+static GObjectClass *parent_class;
+
+
+/******************************************************************************/
+
+static const gchar *mancats[] = {
+    "0p",
+    "1", "1p", "1g", "1t", "1x", "1ssl", "1m",
+    "2",
+    "3", "3o", "3t", "3p", "3blt", "3nas", "3form", "3menu", "3tiff", "3ssl", "3readline",
+    "3ncurses", "3curses", "3f", "3pm", "3perl", "3qt", "3x", "3X11",
+    "4", "4x",
+    "5", "5snmp", "5x", "5ssl",
+    "6", "6x",
+    "7", "7gcc", "7x", "7ssl",
+    "8", "8l", "9", "0p",
+    NULL
+};
+
+/******************************************************************************/
+
+GType
+yelp_uri_get_type (void)
+{
+    static GType type = 0;
+    if (!type) {
+        static const GTypeInfo info = {
+            sizeof (YelpUriClass),
+            NULL, NULL,
+            (GClassInitFunc) uri_class_init,
+            NULL, NULL,
+            sizeof (YelpUri),
+            0,
+            (GInstanceInitFunc) uri_init,
+        };
+        type = g_type_register_static (G_TYPE_OBJECT,
+                                       "YelpUri", 
+                                       &info, 0);
+    }
+    return type;
+}
+
+static void
+uri_class_init (YelpUriClass *klass)
+{
+    GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+    parent_class = g_type_class_peek_parent (klass);
+    object_class->dispose      = uri_dispose;
+    g_type_class_add_private (klass, sizeof (YelpUriPriv));
+}
+
+static void
+uri_init (YelpUri *uri)
+{
+    uri->priv = YELP_URI_GET_PRIVATE (uri);
+}
+
+static void
+uri_dispose (GObject *object)
+{
+    YelpUri *uri = YELP_URI (object);
+
+    if (uri->priv->gfile)
+        g_object_unref (uri->priv->gfile);
+    g_strfreev (uri->priv->search_path);
+    g_free (uri->priv->page_id);
+    g_free (uri->priv->frag_id);
+
+    parent_class->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpUri *
+yelp_uri_resolve (gchar *arg)
+{
+    return yelp_uri_resolve_relative (NULL, arg);
+}
+
+YelpUri *
+yelp_uri_resolve_relative (YelpUri *base, gchar *arg)
+{
+    YelpUri *ret;
+
+    ret = (YelpUri *) g_object_new (YELP_TYPE_URI, NULL);
+    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_UNKNOWN;
+
+    if (g_str_has_prefix (arg, "ghelp:") || g_str_has_prefix (arg, "gnome-help:")) {
+        resolve_ghelp_uri (ret, arg);
+    }
+    else if (g_str_has_prefix (arg, "file:")) {
+        resolve_file_uri (ret, arg);
+    }
+    else if (g_str_has_prefix (arg, "man:")) {
+        resolve_man_uri (ret, arg);
+    }
+    else if (g_str_has_prefix (arg, "info:")) {
+        resolve_info_uri (ret, arg);
+    }
+    else if (strchr (arg, ':')) {
+        ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_EXTERNAL;
+        ret->priv->gfile = g_file_new_for_uri (arg);
+        TRUE;
+    }
+    else {
+        resolve_file_path (ret, base, arg);
+    }
+
+    return ret;
+}
+
+YelpUriDocumentType
+yelp_uri_get_document_type (YelpUri *uri)
+{
+    return uri->priv->doctype;
+}
+
+gchar *
+yelp_uri_get_base_uri (YelpUri *uri)
+{
+    return uri->priv->gfile ? g_file_get_uri (uri->priv->gfile) : NULL;
+}
+
+gchar **
+yelp_uri_get_search_path (YelpUri *uri)
+{
+    return g_strdupv (uri->priv->search_path);
+}
+
+gchar *
+yelp_uri_get_page_id (YelpUri *uri)
+{
+    return g_strdup (uri->priv->page_id);
+}
+
+gchar *
+yelp_uri_get_frag_id (YelpUri *uri)
+{
+    return g_strdup (uri->priv->frag_id);
+}
+
+/******************************************************************************/
+
+static void
+resolve_file_uri (YelpUri *ret, gchar *arg)
+{
+    gchar *uri;
+    gchar *hash;
+
+    hash = strchr (arg, '#');
+    if (hash)
+        uri = g_strndup (arg, hash - arg);
+    else
+        uri = arg;
+
+    ret->priv->gfile = g_file_new_for_uri (uri);
+
+    if (hash) {
+        resolve_page_and_frag (ret, hash + 1);
+        g_free (uri);
+    }
+
+    resolve_common (ret);
+}
+
+static void
+resolve_file_path (YelpUri *ret, YelpUri *base, gchar *arg)
+{
+    gchar *path;
+    gchar *hash;
+
+    hash = strchr (arg, '#');
+    if (hash)
+        path = g_strndup (arg, hash - arg);
+    else
+        path = arg;
+
+    if (arg[0] == '/') {
+        ret->priv->gfile = g_file_new_for_path (path);
+    }
+    else if (base && base->priv->gfile) {
+        ret->priv->gfile = g_file_resolve_relative_path (base->priv->gfile, path);
+    }
+    else {
+        gchar *cur;
+        GFile *curfile;
+        cur = g_get_current_dir ();
+        curfile = g_file_new_for_path (cur);
+        ret->priv->gfile = g_file_resolve_relative_path (curfile, path);
+        g_object_unref (curfile);
+        g_free (cur);
+    }
+
+    if (hash) {
+        resolve_page_and_frag (ret, hash + 1);
+        g_free (path);
+    }
+
+    resolve_common (ret);
+}
+
+static void
+resolve_ghelp_uri (YelpUri *ret, gchar *arg)
+{
+    /* ghelp:/path/to/file
+     * ghelp:document
+     */
+    gchar *colon;
+
+    colon = strchr (arg, ':');
+    if (!colon) {
+        ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_ERROR;
+        return;
+    }
+
+    colon++;
+    if (*colon == '/') {
+        gchar *newuri;
+        newuri = g_strdup_printf ("file:%s", colon);
+        resolve_file_uri (ret, newuri);
+        g_free (newuri);
+        return;
+    }
+
+}
+
+static void
+resolve_man_uri (YelpUri *ret, gchar *arg)
+{
+    /* man:/path/to/file
+     * man:name(section)
+     * man:name.section
+     * man:name
+     */
+    static gchar **manpath = NULL;
+    const gchar * const * langs = g_get_language_names ();
+    gchar *newarg = NULL;
+    gchar *section = NULL;
+    gchar *name = NULL;
+    gchar *fullpath = NULL;
+    /* not to be freed */
+    gchar *colon, *hash;
+    gchar *lbrace = NULL;
+    gchar *rbrace = NULL;
+    gint i, j, k;
+
+    if (g_str_has_prefix (arg, "man:/")) {
+        gchar *newuri;
+        ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_MAN;
+        newuri = g_strdup_printf ("file:%s", arg + 4);
+        resolve_file_uri (ret, newuri);
+        g_free (newuri);
+        return;
+    }
+
+    if (!manpath) {
+        /* Initialize manpath only once */
+        const gchar *env = g_getenv ("MANPATH");
+        if (!env || env[0] == '\0')
+            env = "/usr/share/man:/usr/man:/usr/local/share/man:/usr/local/man";
+        manpath = g_strsplit (env, ":", 0);
+    }
+
+    colon = strchr (arg, ':');
+    if (colon)
+        colon++;
+    else
+        colon = arg;
+
+    hash = strchr (colon, '#');
+    if (hash)
+        newarg = g_strndup (colon, hash - colon);
+    else
+        newarg = g_strdup (colon);
+
+    lbrace = strrchr (newarg, '(');
+    if (lbrace) {
+        rbrace = strrchr (lbrace, ')');
+        if (rbrace) {
+            section = g_strndup (lbrace + 1, rbrace - lbrace - 1);
+            name = g_strndup (newarg, lbrace - newarg);
+        } else {
+            section = NULL;
+            name = strdup (newarg);
+        }
+    } else {
+        lbrace = strrchr (newarg, '.');
+        if (lbrace) {
+            section = strdup (lbrace + 1);
+            name = g_strndup (newarg, lbrace - newarg);
+        } else {
+            section = NULL;
+            name = strdup (newarg);
+        }
+    }
+
+    for (i = 0; langs[i]; i++) {
+        for (j = 0; manpath[j]; j++) {
+            gchar *langdir;
+            if (g_str_equal (langs[i], "C"))
+                langdir = g_strdup (manpath[j]);
+            else
+                langdir = g_strconcat (manpath[j], "/", langs[i], NULL);
+            if (!g_file_test (langdir, G_FILE_TEST_IS_DIR)) {
+                g_free (langdir);
+                continue;
+            }
+
+            for (k = 0; section ? k == 0 : mancats[k] != NULL; k++) {
+                gchar *sectiondir;
+                if (section)
+                    sectiondir = g_strconcat ("man", section, NULL);
+                else
+                    sectiondir = g_strconcat ("man", mancats[k], NULL);
+
+                fullpath = g_strconcat (langdir, "/", sectiondir,
+                                        "/", name, ".", sectiondir + 3,
+                                        NULL);
+                if (g_file_test (fullpath, G_FILE_TEST_IS_REGULAR))
+                    goto gotit;
+                g_free (fullpath);
+
+                fullpath = g_strconcat (langdir, "/", sectiondir,
+                                        "/", name, ".", sectiondir + 3, ".gz",
+                                        NULL);
+                if (g_file_test (fullpath, G_FILE_TEST_IS_REGULAR))
+                    goto gotit;
+                g_free (fullpath);
+
+                fullpath = g_strconcat (langdir, "/", sectiondir,
+                                        "/", name, ".", sectiondir + 3, ".bz2",
+                                        NULL);
+                if (g_file_test (fullpath, G_FILE_TEST_IS_REGULAR))
+                    goto gotit;
+                g_free (fullpath);
+
+                fullpath = g_strconcat (langdir, "/", sectiondir,
+                                        "/", name, ".", sectiondir + 3, ".lzma",
+                                        NULL);
+                if (g_file_test (fullpath, G_FILE_TEST_IS_REGULAR))
+                    goto gotit;
+                g_free (fullpath);
+
+                fullpath = NULL;
+            gotit:
+                g_free (sectiondir);
+                if (fullpath)
+                    break;
+            }
+            g_free (langdir);
+            if (fullpath)
+                break;
+        }
+        if (fullpath)
+            break;
+    }
+
+    if (fullpath) {
+        ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_MAN;
+        ret->priv->gfile = g_file_new_for_path (fullpath);
+        resolve_common (ret);
+        g_free (fullpath);
+    } else {
+        ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_NOT_FOUND;
+    }
+
+    if (hash)
+        resolve_page_and_frag (ret, hash + 1);
+
+    g_free (newarg);
+}
+
+static void
+resolve_info_uri (YelpUri *ret, gchar *arg)
+{
+    /* FIXME */
+}
+
+static void
+resolve_page_and_frag (YelpUri *ret, gchar *arg)
+{
+    gchar *hash;
+
+    if (!arg || arg[0] == '\0')
+        return;
+
+    hash = strchr (arg, '#');
+    if (hash) {
+        ret->priv->page_id = g_strndup (arg, hash - arg);
+        ret->priv->frag_id = g_strdup (hash + 1);
+    } else {
+        ret->priv->page_id = g_strdup (arg);
+        ret->priv->frag_id = g_strdup (arg);
+    }
+    return;
+}
+
+static void
+resolve_common (YelpUri *ret)
+{
+    GFileInfo *info;
+    GError *error = NULL;
+
+    info = g_file_query_info (ret->priv->gfile,
+                              G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+                              G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
+                              G_FILE_QUERY_INFO_NONE,
+                              NULL, &error);
+    if (error) {
+        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+            ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_NOT_FOUND;
+        else
+            ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_ERROR;
+        g_error_free (error);
+        return;
+    }
+
+    if (ret->priv->search_path == NULL) {
+        if (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) ==
+            G_FILE_TYPE_DIRECTORY) {
+            ret->priv->search_path = g_new0 (gchar *, 2);
+            ret->priv->search_path[0] = g_file_get_path (ret->priv->gfile);
+        } else {
+            GFile *parent = g_file_get_parent (ret->priv->gfile);
+            ret->priv->search_path = g_new0 (gchar *, 2);
+            ret->priv->search_path[0] = g_file_get_path (parent);
+            g_object_unref (parent);
+        }
+    }
+
+    if (ret->priv->doctype == YELP_URI_DOCUMENT_TYPE_UNKNOWN) {
+        if (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) ==
+            G_FILE_TYPE_DIRECTORY) {
+            ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_MALLARD;
+        }
+        else {
+            gchar *basename;
+            const gchar *mime_type = g_file_info_get_attribute_string (info,
+                                                                       G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
+            basename = g_file_get_basename (ret->priv->gfile);
+            if (g_str_equal (mime_type, "text/xml") ||
+                g_str_equal (mime_type, "application/docbook+xml") ||
+                g_str_equal (mime_type, "application/xml")) {
+                ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_DOCBOOK;
+            }
+            else if (g_str_equal (mime_type, "text/html")) {
+                ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_HTML;
+            }
+            else if (g_str_equal (mime_type, "application/xhtml+xml")) {
+                ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_XHTML;
+            }
+            else if (g_str_equal (mime_type, "application/x-gzip")) {
+                if (g_str_has_suffix (basename, ".info.gz"))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_INFO;
+                else if (is_man_path (basename, "gz"))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_MAN;
+            }
+            else if (g_str_equal (mime_type, "application/x-bzip")) {
+                if (g_str_has_suffix (basename, ".info.bz2"))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_INFO;
+                else if (is_man_path (basename, "bz2"))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_MAN;
+            }
+            else if (g_str_equal (mime_type, "application/x-lzma")) {
+                if (g_str_has_suffix (basename, ".info.lzma"))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_INFO;
+                else if (is_man_path (basename, "lzma"))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_MAN;
+            }
+            else if (g_str_equal (mime_type, "application/octet-stream")) {
+                if (g_str_has_suffix (basename, ".info"))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_INFO;
+                else if (is_man_path (basename, NULL))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_MAN;
+            }
+            else if (g_str_equal (mime_type, "text/plain")) {
+                if (g_str_has_suffix (basename, ".info"))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_INFO;
+                else if (is_man_path (basename, NULL))
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_MAN;
+                else
+                    ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_TEXT;
+            }
+            else {
+                ret->priv->doctype = YELP_URI_DOCUMENT_TYPE_EXTERNAL;
+            }
+        }
+    }
+}
+
+static gboolean
+is_man_path (gchar *path, gchar *encoding)
+{
+    gchar **iter = (gchar **) mancats;
+
+    if (encoding && *encoding) {
+        while (iter && *iter) {
+            gchar *ending = g_strdup_printf ("%s.%s", *iter, encoding);
+            if (g_str_has_suffix (path, ending)) {
+                g_free (ending);
+                return TRUE;
+            }
+            g_free (ending);
+            iter++;
+        }
+    } else {
+        while (iter && *iter) {
+            if (g_str_has_suffix (path, *iter)) {
+                return TRUE;
+            }
+            iter++;
+        }
+    }
+    return FALSE;
+}
diff --git a/src/yelp-uri.h b/src/yelp-uri.h
new file mode 100644
index 0000000..9562f50
--- /dev/null
+++ b/src/yelp-uri.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Shaun McCance  <shaunm gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance  <shaunm gnome org>
+ */
+
+#ifndef __YELP_URI_H__
+#define __YELP_URI_H__
+
+#include <glib-object.h>
+
+#define YELP_TYPE_URI         (yelp_uri_get_type ())
+#define YELP_URI(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_URI, YelpUri))
+#define YELP_URI_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_URI, YelpUriClass))
+#define YELP_IS_URI(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_URI))
+#define YELP_IS_URI_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_URI))
+#define YELP_URI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_URI, YelpUriClass))
+
+typedef struct _YelpUri      YelpUri;
+typedef struct _YelpUriClass YelpUriClass;
+typedef struct _YelpUriPriv  YelpUriPriv;
+
+typedef enum {
+    YELP_URI_DOCUMENT_TYPE_UNKNOWN = 0,
+    YELP_URI_DOCUMENT_TYPE_DOCBOOK,
+    YELP_URI_DOCUMENT_TYPE_MALLARD,
+    YELP_URI_DOCUMENT_TYPE_MAN,
+    YELP_URI_DOCUMENT_TYPE_INFO,
+    YELP_URI_DOCUMENT_TYPE_TEXT,
+    YELP_URI_DOCUMENT_TYPE_HTML,
+    YELP_URI_DOCUMENT_TYPE_XHTML,
+    YELP_URI_DOCUMENT_TYPE_TOC,
+    YELP_URI_DOCUMENT_TYPE_SEARCH,
+    YELP_URI_DOCUMENT_TYPE_NOT_FOUND,
+    YELP_URI_DOCUMENT_TYPE_EXTERNAL,
+    YELP_URI_DOCUMENT_TYPE_ERROR
+} YelpUriDocumentType;
+
+struct _YelpUri {
+    GObject      parent;
+    YelpUriPriv *priv;
+};
+
+struct _YelpUriClass {
+    GObjectClass    parent_class;
+};
+
+
+GType             yelp_uri_get_type     (void);
+
+YelpUri *         yelp_uri_resolve           (gchar     *arg);
+YelpUri *         yelp_uri_resolve_relative  (YelpUri   *base,
+                                              gchar     *arg);
+
+YelpUriDocumentType  yelp_uri_get_document_type  (YelpUri   *uri);
+gchar *              yelp_uri_get_base_uri       (YelpUri   *uri);
+gchar **             yelp_uri_get_search_path    (YelpUri   *uri);
+gchar *              yelp_uri_get_page_id        (YelpUri   *uri);
+gchar *              yelp_uri_get_frag_id        (YelpUri   *uri);
+
+
+#endif /* __YELP_URI_H__ */



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