1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Shaun McCance <shaunm@gnome.org>
32 #include "yelp-settings.h"
34 static void yelp_uri_dispose (GObject
*object
);
35 static void yelp_uri_finalize (GObject
*object
);
37 static void resolve_start (YelpUri
*uri
);
38 static void resolve_sync (YelpUri
*uri
);
39 static void resolve_async (YelpUri
*uri
);
40 static gboolean
resolve_final (YelpUri
*uri
);
42 static void resolve_file_uri (YelpUri
*uri
);
43 static void resolve_file_path (YelpUri
*uri
);
44 static void resolve_data_dirs (YelpUri
*uri
,
49 static void resolve_ghelp_uri (YelpUri
*uri
);
50 static void resolve_help_uri (YelpUri
*uri
);
51 static void resolve_help_list_uri (YelpUri
*uri
);
52 static void resolve_man_uri (YelpUri
*uri
);
53 static void resolve_info_uri (YelpUri
*uri
);
54 static void resolve_xref_uri (YelpUri
*uri
);
55 static void resolve_page_and_frag (YelpUri
*uri
,
57 static void resolve_gfile (YelpUri
*uri
,
61 static gboolean
is_man_path (const gchar
*uri
,
62 const gchar
*encoding
);
64 G_DEFINE_TYPE (YelpUri
, yelp_uri
, G_TYPE_OBJECT
)
65 #define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_URI, YelpUriPrivate))
67 typedef struct _YelpUriPrivate YelpUriPrivate
;
68 struct _YelpUriPrivate
{
71 YelpUriDocumentType doctype
;
72 YelpUriDocumentType tmptype
;
93 static guint uri_signals
[LAST_SIGNAL
] = {0,};
95 /******************************************************************************/
97 static const gchar
*mancats
[] = {
99 "1", "1p", "1g", "1t", "1x", "1ssl", "1m",
101 "3", "3o", "3t", "3p", "3blt", "3nas", "3form", "3menu", "3tiff", "3ssl", "3readline",
102 "3ncurses", "3curses", "3f", "3pm", "3perl", "3qt", "3x", "3X11",
104 "5", "5snmp", "5x", "5ssl",
106 "7", "7gcc", "7x", "7ssl",
107 "8", "8l", "9", "0p",
111 static const gchar
*infosuffix
[] = {
113 ".info.gz", ".info.bz2", ".info.lzma",
114 ".gz", ".bz2", ".lzma",
118 static const gchar default_info_path
[] =
119 "/usr/info:/usr/share/info:/usr/local/info:/usr/local/share/info";
121 /******************************************************************************/
124 yelp_uri_class_init (YelpUriClass
*klass
)
126 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
128 object_class
->dispose
= yelp_uri_dispose
;
129 object_class
->finalize
= yelp_uri_finalize
;
131 uri_signals
[RESOLVED
] =
132 g_signal_new ("resolved",
133 G_OBJECT_CLASS_TYPE (klass
),
136 g_cclosure_marshal_VOID__VOID
,
139 g_type_class_add_private (klass
, sizeof (YelpUriPrivate
));
143 yelp_uri_init (YelpUri
*uri
)
145 YelpUriPrivate
*priv
= GET_PRIV (uri
);
147 priv
->query
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, g_free
);
153 yelp_uri_dispose (GObject
*object
)
155 YelpUriPrivate
*priv
= GET_PRIV (object
);
158 g_object_unref (priv
->gfile
);
162 if (priv
->res_base
) {
163 g_object_unref (priv
->res_base
);
164 priv
->res_base
= NULL
;
168 g_hash_table_destroy (priv
->query
);
172 G_OBJECT_CLASS (yelp_uri_parent_class
)->dispose (object
);
176 yelp_uri_finalize (GObject
*object
)
178 YelpUriPrivate
*priv
= GET_PRIV (object
);
180 g_free (priv
->docuri
);
181 g_free (priv
->fulluri
);
182 g_strfreev (priv
->search_path
);
183 g_free (priv
->page_id
);
184 g_free (priv
->frag_id
);
185 g_free (priv
->res_arg
);
187 G_OBJECT_CLASS (yelp_uri_parent_class
)->finalize (object
);
190 /******************************************************************************/
193 yelp_uri_new (const gchar
*arg
)
195 return yelp_uri_new_relative (NULL
, arg
);
199 yelp_uri_new_relative (YelpUri
*base
, const gchar
*arg
)
202 YelpUriPrivate
*priv
;
204 uri
= (YelpUri
*) g_object_new (YELP_TYPE_URI
, NULL
);
206 priv
= GET_PRIV (uri
);
207 priv
->doctype
= YELP_URI_DOCUMENT_TYPE_UNRESOLVED
;
209 priv
->res_base
= g_object_ref (base
);
210 priv
->res_arg
= g_strdup (arg
);
216 yelp_uri_new_search (YelpUri
*base
,
220 YelpUriPrivate
*priv
;
223 uri
= (YelpUri
*) g_object_new (YELP_TYPE_URI
, NULL
);
225 priv
= GET_PRIV (uri
);
226 priv
->doctype
= YELP_URI_DOCUMENT_TYPE_UNRESOLVED
;
228 priv
->res_base
= g_object_ref (base
);
229 tmp
= g_uri_escape_string (text
, NULL
, FALSE
);
230 priv
->res_arg
= g_strconcat("xref:search=", tmp
, NULL
);
236 /******************************************************************************/
239 yelp_uri_resolve (YelpUri
*uri
)
241 YelpUriPrivate
*priv
= GET_PRIV (uri
);
243 if (priv
->res_base
&& !yelp_uri_is_resolved (priv
->res_base
)) {
244 g_signal_connect_swapped (priv
->res_base
, "resolved",
245 G_CALLBACK (resolve_start
),
247 yelp_uri_resolve (priv
->res_base
);
255 yelp_uri_resolve_sync (YelpUri
*uri
)
257 YelpUriPrivate
*priv
= GET_PRIV (uri
);
259 if (priv
->doctype
!= YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
263 yelp_uri_resolve_sync (priv
->res_base
);
270 /* We want code to be able to do something like this:
272 * if (yelp_uri_get_document_type (uri) != YELP_URI_DOCUMENT_TYPE_UNRESOLVED) {
273 * g_signal_connect (uri, "resolve", callback, data);
274 * yelp_uri_resolve (uri);
277 * Resolving happens in a separate thread, though, so if that thread can change
278 * the document type, we have a race condition. So here's the rules we play by:
280 * 1) None of the getters except the document type getter can return real data
281 * while the URI is unresolved. They all do a resolved check first, and
282 * return NULL if the URI is not resolved.
284 * 2) The threaded resolver functions can modify anything but the document
285 * type. They are the only things that are allowed to modify that data.
287 * 3) The resolver thread is not allowed to modify the document type. When
288 * it's done, it queues an async function to set the document type and
289 * emit "resolved" in the main thread.
291 * 4) Once a URI is resolved, it is immutable.
294 resolve_start (YelpUri
*uri
)
296 YelpUriPrivate
*priv
= GET_PRIV (uri
);
298 if (priv
->resolver
== NULL
) {
300 priv
->resolver
= g_thread_new ("uri-resolve",
301 (GThreadFunc
)(GCallback
) resolve_async
,
307 resolve_sync (YelpUri
*uri
)
309 YelpUriPrivate
*priv
= GET_PRIV (uri
);
311 if (g_str_has_prefix (priv
->res_arg
, "ghelp:")
312 || g_str_has_prefix (priv
->res_arg
, "gnome-help:")) {
313 resolve_ghelp_uri (uri
);
315 else if (g_str_has_prefix (priv
->res_arg
, "help:")) {
316 resolve_help_uri (uri
);
318 else if (g_str_has_prefix (priv
->res_arg
, "help-list:")) {
319 resolve_help_list_uri (uri
);
321 else if (g_str_has_prefix (priv
->res_arg
, "file:")) {
322 resolve_file_uri (uri
);
324 else if (g_str_has_prefix (priv
->res_arg
, "man:")) {
325 resolve_man_uri (uri
);
327 else if (g_str_has_prefix (priv
->res_arg
, "info:")) {
328 resolve_info_uri (uri
);
330 else if (g_str_has_prefix (priv
->res_arg
, "xref:")) {
331 YelpUriPrivate
*base_priv
;
332 if (priv
->res_base
== NULL
) {
333 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_ERROR
;
336 base_priv
= GET_PRIV (priv
->res_base
);
337 switch (base_priv
->doctype
) {
338 case YELP_URI_DOCUMENT_TYPE_UNRESOLVED
:
340 case YELP_URI_DOCUMENT_TYPE_DOCBOOK
:
341 case YELP_URI_DOCUMENT_TYPE_MALLARD
:
342 case YELP_URI_DOCUMENT_TYPE_INFO
:
343 resolve_xref_uri (uri
);
345 case YELP_URI_DOCUMENT_TYPE_MAN
: {
346 gchar
*tmp
= g_strconcat ("man:", priv
->res_arg
+ 5, NULL
);
347 g_free (priv
->res_arg
);
349 resolve_man_uri (uri
);
352 case YELP_URI_DOCUMENT_TYPE_TEXT
:
353 case YELP_URI_DOCUMENT_TYPE_HTML
:
354 case YELP_URI_DOCUMENT_TYPE_XHTML
:
355 resolve_file_path (uri
);
357 case YELP_URI_DOCUMENT_TYPE_HELP_LIST
:
358 /* FIXME: what do we do? */
360 case YELP_URI_DOCUMENT_TYPE_NOT_FOUND
:
361 case YELP_URI_DOCUMENT_TYPE_EXTERNAL
:
362 case YELP_URI_DOCUMENT_TYPE_ERROR
:
365 g_assert_not_reached ();
369 else if (strchr (priv
->res_arg
, ':')) {
370 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_EXTERNAL
;
373 resolve_file_path (uri
);
376 /* We _always_ want to have a non-null fulluri, so check for it
377 * having been set here and, if we can't think of something
378 * better, set it to res_arg. */
379 if (!priv
->fulluri
) {
380 priv
->fulluri
= g_strdup (priv
->res_arg
);
385 resolve_async (YelpUri
*uri
)
388 g_idle_add ((GSourceFunc
) resolve_final
, uri
);
392 resolve_final (YelpUri
*uri
)
394 YelpUriPrivate
*priv
= GET_PRIV (uri
);
396 priv
->resolver
= NULL
;
398 if (priv
->tmptype
!= YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
399 priv
->doctype
= priv
->tmptype
;
401 priv
->doctype
= YELP_URI_DOCUMENT_TYPE_ERROR
;
403 if (priv
->res_base
) {
404 g_object_unref (priv
->res_base
);
405 priv
->res_base
= NULL
;
409 g_free (priv
->res_arg
);
410 priv
->res_arg
= NULL
;
413 g_signal_emit (uri
, uri_signals
[RESOLVED
], 0);
414 g_object_unref (uri
);
418 /******************************************************************************/
421 yelp_uri_is_resolved (YelpUri
*uri
)
423 YelpUriPrivate
*priv
= GET_PRIV (uri
);
424 return priv
->doctype
!= YELP_URI_DOCUMENT_TYPE_UNRESOLVED
;
428 yelp_uri_get_document_type (YelpUri
*uri
)
430 YelpUriPrivate
*priv
= GET_PRIV (uri
);
431 return priv
->doctype
;
435 yelp_uri_get_document_uri (YelpUri
*uri
)
437 YelpUriPrivate
*priv
= GET_PRIV (uri
);
438 if (priv
->doctype
== YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
441 /* There's some client code where it makes sense to want a
442 * document uri, whether or not it conforms to a scheme we really
443 * understand. For example, we might want to look up whether the
444 * given page is currently being visited. */
445 if ((!priv
->docuri
) && priv
->fulluri
) {
446 return g_strdup (priv
->fulluri
);
449 return g_strdup (priv
->docuri
);
453 yelp_uri_get_canonical_uri (YelpUri
*uri
)
455 YelpUriPrivate
*priv
= GET_PRIV (uri
);
456 if (priv
->doctype
== YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
458 return g_strdup (priv
->fulluri
);
462 yelp_uri_get_file (YelpUri
*uri
)
464 YelpUriPrivate
*priv
= GET_PRIV (uri
);
465 if (priv
->doctype
== YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
467 return priv
->gfile
? g_object_ref (priv
->gfile
) : NULL
;
471 yelp_uri_get_search_path (YelpUri
*uri
)
473 YelpUriPrivate
*priv
= GET_PRIV (uri
);
474 if (priv
->doctype
== YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
476 return g_strdupv (priv
->search_path
);
480 yelp_uri_get_page_id (YelpUri
*uri
)
482 YelpUriPrivate
*priv
= GET_PRIV (uri
);
483 if (priv
->doctype
== YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
485 return g_strdup (priv
->page_id
);
489 yelp_uri_get_frag_id (YelpUri
*uri
)
491 YelpUriPrivate
*priv
= GET_PRIV (uri
);
492 if (priv
->doctype
== YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
494 return g_strdup (priv
->frag_id
);
498 yelp_uri_get_query (YelpUri
*uri
,
501 YelpUriPrivate
*priv
= GET_PRIV (uri
);
502 const gchar
*ret
= g_hash_table_lookup (priv
->query
, key
);
504 return g_strdup (ret
);
509 /******************************************************************************/
512 yelp_uri_locate_file_uri (YelpUri
*uri
,
513 const gchar
*filename
)
515 YelpUriPrivate
*priv
= GET_PRIV (uri
);
518 gchar
*returi
= NULL
;
521 if (g_path_is_absolute (filename
)) {
522 if (g_file_test (filename
, G_FILE_TEST_EXISTS
))
523 return g_filename_to_uri (filename
, NULL
, NULL
);
527 for (i
= 0; priv
->search_path
[i
] != NULL
; i
++) {
528 fullpath
= g_strconcat (priv
->search_path
[i
],
532 if (g_file_test (fullpath
, G_FILE_TEST_EXISTS
)) {
533 gfile
= g_file_new_for_path (fullpath
);
534 returi
= g_file_get_uri (gfile
);
535 g_object_unref (gfile
);
544 /******************************************************************************/
547 resolve_file_uri (YelpUri
*uri
)
549 YelpUriPrivate
*priv
= GET_PRIV (uri
);
551 const gchar
*hash
= strchr (priv
->res_arg
, '#');
554 uristr
= g_strndup (priv
->res_arg
, hash
- priv
->res_arg
);
558 uristr
= priv
->res_arg
;
560 priv
->gfile
= g_file_new_for_uri (uristr
);
562 resolve_gfile (uri
, NULL
, hash
);
566 resolve_file_path (YelpUri
*uri
)
568 YelpUriPrivate
*base_priv
= NULL
;
569 YelpUriPrivate
*priv
= GET_PRIV (uri
);
573 /* Treat xref: URIs like relative file paths */
574 if (g_str_has_prefix (priv
->res_arg
, "xref:")) {
575 gchar
*tmp
= g_strdup (priv
->res_arg
+ 5);
576 g_free (priv
->res_arg
);
581 base_priv
= GET_PRIV (priv
->res_base
);
583 hash
= strchr (priv
->res_arg
, '#');
585 path
= g_strndup (priv
->res_arg
, hash
- priv
->res_arg
);
589 path
= priv
->res_arg
;
591 if (priv
->res_arg
[0] == '/') {
592 priv
->gfile
= g_file_new_for_path (path
);
594 else if (base_priv
&& base_priv
->gfile
) {
596 info
= g_file_query_info (base_priv
->gfile
,
597 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
598 G_FILE_QUERY_INFO_NONE
,
600 if (g_file_info_get_file_type (info
) == G_FILE_TYPE_REGULAR
) {
601 GFile
*parent
= g_file_get_parent (base_priv
->gfile
);
602 priv
->gfile
= g_file_resolve_relative_path (parent
, path
);
603 g_object_unref (parent
);
606 priv
->gfile
= g_file_resolve_relative_path (base_priv
->gfile
, path
);
609 g_object_unref (info
);
614 cur
= g_get_current_dir ();
615 curfile
= g_file_new_for_path (cur
);
616 priv
->gfile
= g_file_resolve_relative_path (curfile
, path
);
617 g_object_unref (curfile
);
621 resolve_gfile (uri
, NULL
, hash
);
625 resolve_data_dirs (YelpUri
*ret
,
631 const gchar
* const *sdatadirs
= g_get_system_data_dirs ();
632 const gchar
* const *langs
= g_get_language_names ();
633 /* The strings are still owned by GLib; we just own the array. */
635 YelpUriPrivate
*priv
= GET_PRIV (ret
);
636 gchar
*filename
= NULL
;
637 gchar
**searchpath
= NULL
;
638 gint searchi
, searchmax
;
639 gint datadir_i
, lang_i
;
641 datadirs
= g_new0 (gchar
*, g_strv_length ((gchar
**) sdatadirs
) + 2);
642 datadirs
[0] = (gchar
*) g_get_user_data_dir ();
643 for (datadir_i
= 0; sdatadirs
[datadir_i
]; datadir_i
++)
644 datadirs
[datadir_i
+ 1] = (gchar
*) sdatadirs
[datadir_i
];
648 searchpath
= g_new0 (gchar
*, 10);
650 for (datadir_i
= 0; datadirs
[datadir_i
]; datadir_i
++) {
651 for (lang_i
= 0; langs
[lang_i
]; lang_i
++) {
652 gchar
*helpdir
= g_build_filename (datadirs
[datadir_i
],
654 langfirst
? langs
[lang_i
] : docid
,
655 langfirst
? docid
: langs
[lang_i
],
657 if (!g_file_test (helpdir
, G_FILE_TEST_IS_DIR
)) {
662 if (searchi
+ 1 >= searchmax
) {
664 searchpath
= g_renew (gchar
*, searchpath
, searchmax
);
666 searchpath
[searchi
] = helpdir
;
667 searchpath
[++searchi
] = NULL
;
669 if (priv
->tmptype
!= YELP_URI_DOCUMENT_TYPE_UNRESOLVED
)
670 /* We've already found it. We're just adding to the search path now. */
673 filename
= g_strdup_printf ("%s/index.page", helpdir
);
674 if (g_file_test (filename
, G_FILE_TEST_IS_REGULAR
)) {
675 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MALLARD
;
677 filename
= g_strdup (helpdir
);
683 filename
= g_strdup_printf ("%s/index.docbook", helpdir
);
684 if (g_file_test (filename
, G_FILE_TEST_IS_REGULAR
)) {
685 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_DOCBOOK
;
691 filename
= g_strdup_printf ("%s/%s.xml", helpdir
, pageid
);
692 if (g_file_test (filename
, G_FILE_TEST_IS_REGULAR
)) {
693 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_DOCBOOK
;
699 filename
= g_strdup_printf ("%s/%s.html", helpdir
, pageid
);
700 if (g_file_test (filename
, G_FILE_TEST_IS_REGULAR
)) {
701 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_HTML
;
706 filename
= g_strdup_printf ("%s/%s.xhtml", helpdir
, pageid
);
707 if (g_file_test (filename
, G_FILE_TEST_IS_REGULAR
)) {
708 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_XHTML
;
712 } /* end for langs */
713 } /* end for datadirs */
716 if (priv
->tmptype
== YELP_URI_DOCUMENT_TYPE_UNRESOLVED
) {
717 g_strfreev (searchpath
);
718 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_NOT_FOUND
;
721 priv
->gfile
= g_file_new_for_path (filename
);
722 priv
->search_path
= searchpath
;
727 build_ghelp_fulluri (YelpUri
*uri
)
729 YelpUriPrivate
*priv
= GET_PRIV (uri
);
731 g_assert (priv
->tmptype
!= YELP_URI_DOCUMENT_TYPE_UNRESOLVED
);
732 g_assert (priv
->docuri
!= NULL
);
733 priv
->fulluri
= g_strconcat (priv
->docuri
,
734 priv
->tmptype
== YELP_URI_DOCUMENT_TYPE_MALLARD
? "/" : "",
735 priv
->page_id
? "?" : "",
736 priv
->page_id
? priv
->page_id
: "",
737 priv
->frag_id
? "#" : "",
738 priv
->frag_id
? priv
->frag_id
: "",
743 resolve_ghelp_uri (YelpUri
*uri
)
745 /* ghelp:/path/to/file
746 * ghelp:document[/file][?page][#frag]
748 YelpUriPrivate
*priv
= GET_PRIV (uri
);
749 gchar
*document
, *slash
, *query
, *hash
;
750 gchar
*colon
, *c
; /* do not free */
752 colon
= strchr (priv
->res_arg
, ':');
754 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_ERROR
;
758 slash
= query
= hash
= NULL
;
759 for (c
= colon
; *c
!= '\0'; c
++) {
760 if (*c
== '#' && hash
== NULL
)
762 else if (*c
== '?' && query
== NULL
&& hash
== NULL
)
764 else if (*c
== '/' && slash
== NULL
&& query
== NULL
&& hash
== NULL
)
768 if (slash
|| query
|| hash
)
769 document
= g_strndup (colon
+ 1,
770 (slash
? slash
: (query
? query
: hash
)) - colon
- 1);
772 document
= g_strdup (colon
+ 1);
774 if (slash
&& (query
|| hash
))
775 slash
= g_strndup (slash
+ 1,
776 (query
? query
: hash
) - slash
- 1);
778 slash
= g_strdup (slash
+ 1);
781 query
= g_strndup (query
+ 1,
784 query
= g_strdup (query
+ 1);
787 hash
= g_strdup (hash
+ 1);
789 if (*(colon
+ 1) == '/') {
792 path
= g_build_filename ("/", slash
, NULL
);
793 if (g_file_test (path
, G_FILE_TEST_EXISTS
)) {
794 priv
->gfile
= g_file_new_for_path (path
);
795 resolve_gfile (uri
, query
, hash
);
797 gchar
*dirname
= g_path_get_dirname (path
);
798 gchar
*basename
= g_path_get_basename (path
);
800 priv
->gfile
= g_file_new_for_path (dirname
);
802 resolve_gfile (uri
, basename
, hash
);
814 resolve_data_dirs (uri
, "gnome/help", document
, slash
? slash
: document
, FALSE
);
817 priv
->page_id
= query
;
818 priv
->frag_id
= hash
;
821 priv
->page_id
= query
;
822 if (priv
->tmptype
!= YELP_URI_DOCUMENT_TYPE_MALLARD
)
823 priv
->frag_id
= g_strdup (query
);
826 priv
->page_id
= hash
;
827 priv
->frag_id
= g_strdup (hash
);
830 if (priv
->frag_id
&& g_str_has_prefix (priv
->frag_id
, "search=")) {
831 g_free (priv
->frag_id
);
832 priv
->frag_id
= NULL
;
835 priv
->docuri
= g_strconcat ("ghelp:", document
,
839 build_ghelp_fulluri (uri
);
847 resolve_help_uri (YelpUri
*uri
)
849 /* help:document[/page][?query][#frag]
851 YelpUriPrivate
*priv
= GET_PRIV (uri
);
852 gchar
*document
, *slash
, *query
, *hash
;
853 gchar
*colon
, *c
; /* do not free */
855 colon
= strchr (priv
->res_arg
, ':');
857 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_ERROR
;
861 slash
= query
= hash
= NULL
;
862 for (c
= colon
; *c
!= '\0'; c
++) {
863 if (*c
== '#' && hash
== NULL
)
865 else if (*c
== '?' && query
== NULL
&& hash
== NULL
)
867 else if (*c
== '/' && slash
== NULL
&& query
== NULL
&& hash
== NULL
)
871 if (slash
|| query
|| hash
)
872 document
= g_strndup (colon
+ 1,
873 (slash
? slash
: (query
? query
: hash
)) - colon
- 1);
875 document
= g_strdup (colon
+ 1);
877 if (slash
&& (query
|| hash
))
878 slash
= g_strndup (slash
+ 1,
879 (query
? query
: hash
) - slash
- 1);
881 slash
= g_strdup (slash
+ 1);
884 query
= g_strndup (query
+ 1,
887 query
= g_strdup (query
+ 1);
890 gchar
**keyvals
= g_strsplit (query
, "&", 0);
893 for (i
= 0; keyvals
[i
]; i
++) {
895 val
= strchr (keyvals
[i
], '=');
898 key
= g_uri_unescape_segment (keyvals
[i
], val
, NULL
);
899 val
= g_uri_unescape_string (val
+ 1, NULL
);
901 g_hash_table_insert (priv
->query
, key
, val
);
904 g_strfreev (keyvals
);
908 hash
= g_strdup (hash
+ 1);
910 priv
->page_id
= (slash
? slash
: g_strdup ("index"));
911 resolve_data_dirs (uri
, "help", document
, priv
->page_id
, TRUE
);
914 priv
->frag_id
= hash
;
915 if (priv
->frag_id
&& g_str_has_prefix (priv
->frag_id
, "search=")) {
916 g_free (priv
->frag_id
);
917 priv
->frag_id
= NULL
;
920 priv
->docuri
= g_strconcat ("help:", document
, NULL
);
922 priv
->fulluri
= g_strconcat (priv
->docuri
,
923 priv
->page_id
? "/" : "",
924 priv
->page_id
? priv
->page_id
: "",
927 priv
->frag_id
? "#" : "",
928 priv
->frag_id
? priv
->frag_id
: "",
937 resolve_help_list_uri (YelpUri
*uri
)
939 YelpUriPrivate
*priv
= GET_PRIV (uri
);
940 priv
->docuri
= g_strdup ("help-list:");
941 priv
->fulluri
= g_strdup (priv
->res_arg
);
942 priv
->page_id
= g_strdup ("index");
943 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_HELP_LIST
;
947 Resolve a manual file's path using 'man -w'. section may be NULL,
948 otherwise should be the section of the manual (ie should have dealt
949 with empty strings before calling this!) Returns NULL if the file
953 find_man_path (gchar
* name
, gchar
* section
)
955 const gchar
* argv
[] = { "man", "-w", NULL
, NULL
, NULL
};
957 gchar
*ystdout
= NULL
;
960 GError
*error
= NULL
;
962 /* Syntax for man is "man -w <section> <name>", possibly omitting
971 /* g_strdupv() should accept a "const gchar **". */
972 my_argv
= g_strdupv ((gchar
**) argv
);
974 if (!g_spawn_sync (NULL
, my_argv
, NULL
,
975 G_SPAWN_SEARCH_PATH
| G_SPAWN_STDERR_TO_DEV_NULL
,
977 &ystdout
, NULL
, &status
, &error
)) {
978 g_warning ("Couldn't find path for %s(%s). Error: %s",
979 name
, section
, error
->message
);
980 g_error_free (error
);
983 g_strfreev (my_argv
);
986 lines
= g_strsplit (ystdout
, "\n", 2);
988 ystdout
= g_strdup (lines
[0]);
999 build_man_uris (YelpUri
*uri
, const char *name
, const char *section
)
1001 YelpUriPrivate
*priv
= GET_PRIV (uri
);
1003 g_assert (priv
->tmptype
== YELP_URI_DOCUMENT_TYPE_MAN
);
1004 priv
->docuri
= g_strdup ("man:");
1005 priv
->fulluri
= g_strconcat ("man:", name
,
1007 section
? section
: "",
1009 priv
->page_id
= g_strconcat (name
,
1011 section
? section
: "",
1016 resolve_man_uri (YelpUri
*uri
)
1018 YelpUriPrivate
*priv
= GET_PRIV (uri
);
1019 /* man:/path/to/file
1025 /* Search via regular expressions for name, name(section) and
1026 * name.section (assuming that name doesn't contain forward
1027 * slashes or other nasties)
1029 * If these don't match, assume that we were given a filename
1030 * (absolute iff it starts with a /).
1032 static GRegex
* man_not_path
= NULL
;
1033 GError
*error
= NULL
;
1034 GMatchInfo
*match_info
= NULL
;
1035 gchar
*name
, *section
, *hash
;
1038 if (!man_not_path
) {
1039 /* Match group 1 should contain the name; then one of groups 3
1040 * and 4 will contain the section if there was one. Group 6
1041 * will contain any hash fragment. */
1042 man_not_path
= g_regex_new ("man:((?:[^ /.()#]|\\.(?=[^0-9]))+)"
1043 "(\\(([0-9A-Za-z]+)\\)|\\.([0-9A-Za-z]+)|)"
1046 if (!man_not_path
) {
1047 g_error ("Error with regex in man uri: %s\n",
1052 if (!g_regex_match (man_not_path
, priv
->res_arg
,
1054 /* The regexp didn't match, so treat as a file name. */
1056 static const char *man_suffixes
[] = { "gz", "bz2", "lzma", NULL
};
1058 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MAN
;
1059 priv
->gfile
= g_file_new_for_path (priv
->res_arg
+ 4);
1060 name
= g_file_get_basename (priv
->gfile
);
1061 for (i
= 0; i
< G_N_ELEMENTS (man_suffixes
); i
++) {
1062 if (is_man_path (name
, man_suffixes
[i
])) {
1063 if (man_suffixes
[i
])
1064 name
[strlen (name
) - strlen (man_suffixes
[i
]) - 1] = '\0';
1068 build_man_uris (uri
, name
, NULL
);
1071 /* The regexp matched, so we've got a name/section pair that
1072 * needs resolving. */
1073 name
= g_match_info_fetch (match_info
, 1);
1074 section
= g_match_info_fetch (match_info
, 3);
1075 hash
= g_match_info_fetch (match_info
, 6);
1077 g_error ("Error matching strings in man uri '%s'",
1080 if ((!section
) || (section
[0] == '\0')) {
1081 section
= g_match_info_fetch (match_info
, 4);
1083 if (section
&& section
[0] == '\0') section
= NULL
;
1085 path
= find_man_path (name
, section
);
1088 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_NOT_FOUND
;
1091 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MAN
;
1092 priv
->gfile
= g_file_new_for_path (path
);
1093 build_man_uris (uri
, name
, section
);
1095 if (hash
&& hash
[0] != '\0')
1096 resolve_page_and_frag (uri
, hash
+ 1);
1099 g_match_info_free (match_info
);
1104 build_info_uris (YelpUri
*uri
, const char *name
, const char *section
)
1106 YelpUriPrivate
*priv
= GET_PRIV (uri
);
1108 g_assert (priv
->tmptype
== YELP_URI_DOCUMENT_TYPE_INFO
);
1109 priv
->docuri
= g_strconcat ("info:", name
, NULL
);
1110 priv
->fulluri
= g_strconcat (priv
->docuri
,
1112 section
? section
: "",
1114 priv
->page_id
= g_strdup (section
);
1115 priv
->frag_id
= g_strdup (section
);
1119 resolve_info_uri (YelpUri
*uri
)
1121 YelpUriPrivate
*priv
= GET_PRIV (uri
);
1122 /* info:/path/to/file
1128 static gchar
**infopath
= NULL
;
1131 gchar
*fullpath
= NULL
;
1134 gint infopath_i
, suffix_i
;
1136 if (g_str_has_prefix (priv
->res_arg
, "info:/")) {
1139 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_INFO
;
1141 hash
= strchr (priv
->res_arg
+ 5, '#');
1145 path
= g_strndup (priv
->res_arg
+ 5, hash
- (priv
->res_arg
+ 5));
1146 priv
->gfile
= g_file_new_for_path (path
);
1148 sect
= g_strdup (hash
+ 1);
1151 priv
->gfile
= g_file_new_for_path (priv
->res_arg
+ 5);
1153 name
= g_file_get_basename (priv
->gfile
);
1154 for (suffix_i
= 0; infosuffix
[suffix_i
]; suffix_i
++) {
1155 if (g_str_has_suffix (name
, infosuffix
[suffix_i
])) {
1156 name
[strlen (name
) - strlen (infosuffix
[suffix_i
])] = '\0';
1161 build_info_uris (uri
, name
, sect
);
1168 /* Initialize infopath only once */
1170 /* Use the same logic as the info program. If INFOPATH is not
1171 specified, use the default. If it is specified, just use it
1172 unless it ends with a colon, in which case we add the
1173 default as a suffix.
1175 const gchar
*env
= g_getenv ("INFOPATH");
1177 if (!env
|| env
[0] == '\0')
1178 paths
= g_strdup (default_info_path
);
1179 else if (env
[strlen (env
)-1] == ':')
1180 paths
= g_strconcat (env
, default_info_path
, NULL
);
1182 paths
= g_strdup (env
);
1184 infopath
= g_strsplit (paths
, ":", 0);
1189 colon
= strchr (priv
->res_arg
, ':');
1193 colon
= (gchar
*) priv
->res_arg
;
1195 if (colon
[0] == '(') {
1196 const gchar
*rbrace
= strchr (colon
, ')');
1198 name
= g_strndup (colon
+ 1, rbrace
- colon
- 1);
1199 sect
= g_strdup (rbrace
+ 1);
1203 const gchar
*hash
= strchr (colon
, '#');
1205 name
= g_strndup (colon
, hash
- colon
);
1206 sect
= g_strdup (hash
+ 1);
1209 name
= g_strdup (colon
);
1214 for (infopath_i
= 0; infopath
[infopath_i
]; infopath_i
++) {
1215 if (!g_file_test (infopath
[infopath_i
], G_FILE_TEST_IS_DIR
))
1217 for (suffix_i
= 0; infosuffix
[suffix_i
]; suffix_i
++) {
1218 fullpath
= g_strconcat (infopath
[infopath_i
], "/",
1219 name
, infosuffix
[suffix_i
], NULL
);
1220 if (g_file_test (fullpath
, G_FILE_TEST_IS_REGULAR
))
1225 if (fullpath
!= NULL
)
1230 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_INFO
;
1231 priv
->gfile
= g_file_new_for_path (fullpath
);
1232 build_info_uris (uri
, name
, sect
);
1234 gchar
*res_arg
= priv
->res_arg
;
1235 priv
->res_arg
= g_strconcat ("man:", name
, NULL
);
1236 resolve_man_uri (uri
);
1237 if (priv
->tmptype
== YELP_URI_DOCUMENT_TYPE_MAN
) {
1238 g_free (priv
->res_arg
);
1239 priv
->res_arg
= res_arg
;
1243 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_NOT_FOUND
;
1252 resolve_xref_uri (YelpUri
*uri
)
1254 YelpUriPrivate
*priv
= GET_PRIV (uri
);
1255 const gchar
*arg
= priv
->res_arg
+ 5;
1256 YelpUriPrivate
*base_priv
= GET_PRIV (priv
->res_base
);
1258 priv
->tmptype
= base_priv
->doctype
;
1259 priv
->gfile
= g_object_ref (base_priv
->gfile
);
1260 priv
->search_path
= g_strdupv (base_priv
->search_path
);
1261 priv
->docuri
= g_strdup (base_priv
->docuri
);
1263 if (arg
[0] == '#') {
1264 priv
->page_id
= g_strdup (base_priv
->page_id
);
1265 priv
->frag_id
= g_strdup (arg
+ 1);
1268 gchar
*hash
= strchr (arg
, '#');
1270 priv
->page_id
= g_strndup (arg
, hash
- arg
);
1271 priv
->frag_id
= g_strdup (hash
+ 1);
1274 priv
->page_id
= g_strdup (arg
);
1275 priv
->frag_id
= NULL
;
1278 if (priv
->page_id
&& priv
->page_id
[0] == '\0') {
1279 g_free (priv
->page_id
);
1280 if (g_str_has_prefix (priv
->docuri
, "help:"))
1281 priv
->page_id
= g_strdup ("index");
1283 priv
->page_id
= NULL
;
1286 if (priv
->page_id
&&
1287 g_str_has_prefix (priv
->docuri
, "info:")) {
1289 Special characters get url-encoded when they get clicked on
1290 as links. Info files, at least, don't want that so decode
1293 gchar
* tmp
= priv
->page_id
;
1294 priv
->page_id
= g_uri_unescape_string (tmp
, NULL
);
1298 if (g_str_has_prefix (priv
->docuri
, "ghelp:"))
1299 build_ghelp_fulluri (uri
);
1300 else if (g_str_has_prefix (priv
->docuri
, "help:"))
1301 priv
->fulluri
= g_strconcat (priv
->docuri
,
1302 priv
->page_id
? "/" : "",
1303 priv
->page_id
? priv
->page_id
: "",
1304 priv
->frag_id
? "#" : "",
1305 priv
->frag_id
? priv
->frag_id
: "",
1307 else if (g_str_has_prefix (priv
->docuri
, "file:") ||
1308 g_str_has_prefix (priv
->docuri
, "info:") )
1309 priv
->fulluri
= g_strconcat (priv
->docuri
,
1310 (priv
->page_id
|| priv
->frag_id
) ? "#" : "",
1311 priv
->page_id
? priv
->page_id
: "",
1312 priv
->frag_id
? "#" : "",
1316 /* FIXME: other URI schemes */
1317 priv
->fulluri
= g_strconcat (priv
->docuri
,
1318 priv
->page_id
? "#" : "",
1324 resolve_page_and_frag (YelpUri
*uri
, const gchar
*arg
)
1326 YelpUriPrivate
*priv
= GET_PRIV (uri
);
1329 if (!arg
|| arg
[0] == '\0')
1332 hash
= strchr (arg
, '#');
1334 priv
->page_id
= g_strndup (arg
, hash
- arg
);
1335 priv
->frag_id
= g_strdup (hash
+ 1);
1337 priv
->page_id
= g_strdup (arg
);
1338 priv
->frag_id
= g_strdup (arg
);
1344 resolve_gfile (YelpUri
*uri
, const gchar
*query
, const gchar
*hash
)
1346 YelpUriPrivate
*priv
= GET_PRIV (uri
);
1348 GError
*error
= NULL
;
1350 info
= g_file_query_info (priv
->gfile
,
1351 G_FILE_ATTRIBUTE_STANDARD_TYPE
","
1352 G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE
,
1353 G_FILE_QUERY_INFO_NONE
,
1356 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
)) {
1357 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_NOT_FOUND
;
1360 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_ERROR
;
1361 g_error_free (error
);
1365 if (priv
->search_path
== NULL
) {
1366 if (g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_STANDARD_TYPE
) ==
1367 G_FILE_TYPE_DIRECTORY
) {
1368 priv
->search_path
= g_new0 (gchar
*, 2);
1369 priv
->search_path
[0] = g_file_get_path (priv
->gfile
);
1371 GFile
*parent
= g_file_get_parent (priv
->gfile
);
1372 priv
->search_path
= g_new0 (gchar
*, 2);
1373 priv
->search_path
[0] = g_file_get_path (parent
);
1374 g_object_unref (parent
);
1378 if (priv
->tmptype
== YELP_URI_DOCUMENT_TYPE_UNRESOLVED
) {
1379 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_EXTERNAL
;
1381 if (g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_STANDARD_TYPE
) ==
1382 G_FILE_TYPE_DIRECTORY
) {
1383 GFile
*child
= g_file_get_child (priv
->gfile
, "index.page");
1384 if (g_file_query_exists (child
, NULL
)) {
1387 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MALLARD
;
1388 if (priv
->page_id
== NULL
)
1389 priv
->page_id
= g_strdup (query
);
1390 if (priv
->frag_id
== NULL
)
1391 priv
->frag_id
= g_strdup (hash
);
1393 path
= g_file_get_path (priv
->gfile
);
1394 priv
->docuri
= g_strconcat ("ghelp:", path
, NULL
);
1395 build_ghelp_fulluri (uri
);
1398 else if (yelp_settings_get_editor_mode (yelp_settings_get_default ())) {
1399 g_object_unref (child
);
1400 child
= g_file_get_child (priv
->gfile
, "index.page.stub");
1401 if (g_file_query_exists (child
, NULL
)) {
1402 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MALLARD
;
1403 if (priv
->page_id
== NULL
)
1404 priv
->page_id
= g_strdup (query
);
1405 if (priv
->frag_id
== NULL
)
1406 priv
->frag_id
= g_strdup (hash
);
1409 g_object_unref (child
);
1413 const gchar
*mime_type
= g_file_info_get_attribute_string (info
,
1414 G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE
);
1415 basename
= g_file_get_basename (priv
->gfile
);
1416 if (g_str_has_suffix (basename
, ".page")) {
1420 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MALLARD
;
1422 priv
->gfile
= g_file_get_parent (old
);
1423 if (priv
->page_id
== NULL
) {
1424 /* File names aren't really page IDs, so we stick an illegal character
1425 on the beginning so it can't possibly be confused with a real page
1426 ID. Then we let YelpMallardDocument map file names to pages IDs.
1428 gchar
*tmp
= g_file_get_basename (old
);
1429 priv
->page_id
= g_strconcat (G_DIR_SEPARATOR_S
, tmp
, NULL
);
1433 if (priv
->frag_id
== NULL
)
1434 priv
->frag_id
= g_strdup (hash
);
1435 path
= g_file_get_path (priv
->gfile
);
1436 priv
->docuri
= g_strconcat ("ghelp:", path
, NULL
);
1437 build_ghelp_fulluri (uri
);
1439 g_object_unref (old
);
1441 else if (g_str_equal (mime_type
, "text/xml") ||
1442 g_str_equal (mime_type
, "application/docbook+xml") ||
1443 g_str_equal (mime_type
, "application/xml") ||
1444 g_str_has_suffix (basename
, ".docbook")) {
1447 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_DOCBOOK
;
1449 if (priv
->page_id
== NULL
)
1450 priv
->page_id
= g_strdup (query
);
1451 if (priv
->frag_id
== NULL
)
1452 priv
->frag_id
= g_strdup (hash
);
1454 path
= g_file_get_path (priv
->gfile
);
1455 priv
->docuri
= g_strconcat ("ghelp:", path
, NULL
);
1456 build_ghelp_fulluri (uri
);
1459 else if (g_str_equal (mime_type
, "text/html") ||
1460 g_str_equal (mime_type
, "application/xhtml+xml")) {
1461 GFile
*parent
= g_file_get_parent (priv
->gfile
);
1462 priv
->docuri
= g_file_get_uri (parent
);
1463 g_object_unref (parent
);
1464 priv
->tmptype
= mime_type
[0] == 't' ? YELP_URI_DOCUMENT_TYPE_HTML
: YELP_URI_DOCUMENT_TYPE_XHTML
;
1465 if (priv
->page_id
== NULL
)
1466 priv
->page_id
= g_strdup (basename
);
1467 if (priv
->frag_id
== NULL
)
1468 priv
->frag_id
= g_strdup (hash
);
1469 if (priv
->fulluri
== NULL
) {
1471 fulluri
= g_file_get_uri (priv
->gfile
);
1472 priv
->fulluri
= g_strconcat (fulluri
,
1473 priv
->frag_id
? "#" : NULL
,
1479 else if (g_str_equal (mime_type
, "application/x-gzip") ||
1480 g_str_equal (mime_type
, "application/gzip")) {
1481 if (g_str_has_suffix (basename
, ".info.gz")) {
1482 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_INFO
;
1483 basename
[strlen (basename
) - strlen (".info.gz")] = '\0';
1484 build_info_uris (uri
, basename
, hash
);
1486 else if (is_man_path (basename
, "gz")) {
1487 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MAN
;
1488 basename
[strlen (basename
) - strlen ("gz") - 1] = '\0';
1489 build_man_uris (uri
, basename
, NULL
);
1492 else if (g_str_equal (mime_type
, "application/x-bzip")) {
1493 if (g_str_has_suffix (basename
, ".info.bz2")) {
1494 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_INFO
;
1495 basename
[strlen (basename
) - strlen (".info.bz2")] = '\0';
1496 build_info_uris (uri
, basename
, hash
);
1498 else if (is_man_path (basename
, "bz2")) {
1499 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MAN
;
1500 basename
[strlen (basename
) - strlen ("bz2") - 1] = '\0';
1501 build_man_uris (uri
, basename
, NULL
);
1504 else if (g_str_equal (mime_type
, "application/x-lzma")) {
1505 if (g_str_has_suffix (basename
, ".info.lzma")) {
1506 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_INFO
;
1507 basename
[strlen (basename
) - strlen (".info.lzma")] = '\0';
1508 build_info_uris (uri
, basename
, hash
);
1510 else if (is_man_path (basename
, "lzma")) {
1511 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MAN
;
1512 basename
[strlen (basename
) - strlen ("lzma") - 1] = '\0';
1513 build_man_uris (uri
, basename
, NULL
);
1516 else if (g_str_equal (mime_type
, "application/octet-stream")) {
1517 if (g_str_has_suffix (basename
, ".info")) {
1518 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_INFO
;
1519 basename
[strlen (basename
) - strlen (".info")] = '\0';
1520 build_info_uris (uri
, basename
, hash
);
1522 else if (is_man_path (basename
, NULL
)) {
1523 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MAN
;
1524 build_man_uris (uri
, basename
, NULL
);
1527 else if (g_str_equal (mime_type
, "text/plain")) {
1528 if (g_str_has_suffix (basename
, ".info")) {
1529 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_INFO
;
1530 basename
[strlen (basename
) - strlen (".info")] = '\0';
1531 build_info_uris (uri
, basename
, hash
);
1533 else if (is_man_path (basename
, NULL
)) {
1534 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_MAN
;
1535 build_man_uris (uri
, basename
, NULL
);
1537 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_TEXT
;
1538 if (priv
->frag_id
== NULL
)
1539 priv
->frag_id
= g_strdup (hash
);
1541 else if (g_str_equal (mime_type
, "text/x-readme")) {
1542 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_TEXT
;
1545 priv
->tmptype
= YELP_URI_DOCUMENT_TYPE_EXTERNAL
;
1551 if (priv
->docuri
== NULL
)
1552 priv
->docuri
= g_file_get_uri (priv
->gfile
);
1554 if (priv
->fulluri
== NULL
)
1555 priv
->fulluri
= g_strconcat (priv
->docuri
,
1556 (priv
->page_id
|| priv
->frag_id
) ? "#" : NULL
,
1557 priv
->page_id
? priv
->page_id
: "",
1558 priv
->frag_id
? "#" : NULL
,
1559 priv
->frag_id
? priv
->frag_id
: NULL
,
1562 g_object_unref (info
);
1566 is_man_path (const gchar
*path
, const gchar
*encoding
)
1568 gchar
**iter
= (gchar
**) mancats
;
1570 if (encoding
&& *encoding
) {
1571 while (iter
&& *iter
) {
1572 gchar
*ending
= g_strdup_printf ("%s.%s", *iter
, encoding
);
1573 if (g_str_has_suffix (path
, ending
)) {
1581 while (iter
&& *iter
) {
1582 if (g_str_has_suffix (path
, *iter
)) {