From d92133c025a3caea41a53c5f1989ac7d8f29d2f6 Mon Sep 17 00:00:00 2001 From: Toni Gundogdu Date: Thu, 17 Oct 2013 21:02:08 +0300 Subject: [PATCH] linput: Rewrite input parsing completely * FIX (memory leak): Release the GIOChannel created for the stdin by decrementing the reference count of the GIOChannel * Do not unescape input URLs - This was previously done because quvi-dump shamelessly escaped the URLs completely (incl. the "reserved chars") and g_uri_parse_scheme, which linput calls (to determine the action it should take with the input URL), couldn't parse the escaped URI schemes otherwise - Any normal applications leave the "reserved chars" unescaped, e.g. the web browsers * linput_new now returns an integer, indicating the success - Program now exits if input parsing failed (e.g. invalid URI) * Follow file URIs - Making it possible to pass "file://" URIs to the program Signed-off-by: Toni Gundogdu --- src/input/linput.c | 192 ++++++++++++++++++++++++++++++----------------------- src/input/linput.h | 4 +- 2 files changed, 111 insertions(+), 85 deletions(-) diff --git a/src/input/linput.c b/src/input/linput.c index d7bf3a7..15eeeac 100644 --- a/src/input/linput.c +++ b/src/input/linput.c @@ -21,75 +21,44 @@ #include "config.h" #include +#include #include #include -#include "lutil.h" #include "linput.h" +#include "lutil.h" -static gchar *_read_stdin(linput_t linput) +static gchar *_read_stdin() { - gchar *s, *r, *p; GIOChannel *c; - gsize n, sn; + gchar *r, *s; + gsize n; c = g_io_channel_unix_new(STDIN_FILENO); - s = NULL; - r = NULL; + r = s = NULL; n = 0; while (g_io_channel_read_line(c, &s, NULL, NULL, NULL) != G_IO_STATUS_EOF) { - sn = strlen(s); - p = g_realloc(r, n+sn+1); + gchar *p; + gsize l; + + l = strlen(s); + p = g_realloc(r, n+l+1); + if (p != NULL) { r = p; - memcpy(&(r[n]), s, sn); - n += sn; + memcpy(&r[n], s, l); + n += l; r[n] = '\0'; } g_free(s); - s = NULL; } + g_io_channel_unref(c); return (r); } -static gboolean _has_uri_scheme(const gchar *s, gchar **dst) -{ - gchar *p, *t; - gboolean r; - - t = g_uri_unescape_string(s, NULL); - p = g_uri_parse_scheme(t); - r = (p != NULL) ? TRUE:FALSE; - g_free(p); - - if (dst != NULL && r == TRUE) - *dst = t; - else - g_free(t); - - return (r); -} - -static void _extract_urls(const gchar *b, linput_t l) -{ - gchar **r, *u; - gint i; - - r = g_uri_list_extract_uris(b); - i = 0; - - while (r[i] != NULL) - { - if (_has_uri_scheme(r[i], &u) == TRUE) - l->url.input = lutil_slist_prepend_if_unique(l->url.input, u); - ++i; - } - g_strfreev(r); -} - static gchar *_read_file(const gchar *fpath) { GError *e; @@ -102,72 +71,129 @@ static gchar *_read_file(const gchar *fpath) { if (e != NULL) { - g_printerr(_("error: %s: while reading file: %s\n"), - fpath, e->message); + g_printerr(_("error: while reading file: %s\n"), e->message); g_error_free(e); - e = NULL; } } return (r); } -static void _no_rargs(linput_t linput) +static gint _extract_uris(linput_t, const gchar*); + +static gint _read_from_uri(linput_t p, const gchar *u) { - gchar *b = _read_stdin(linput); - if (b != NULL) + GError *e; + gchar *f; + gint r; + + r = EXIT_FAILURE; + e = NULL; + f = g_filename_from_uri(u, NULL, &e); + + if (f !=NULL) + { + gchar *c = _read_file(f); + if (c !=NULL) + { + r = _extract_uris(p, c); + r = EXIT_SUCCESS; + g_free(c); + } + g_free(f); + } + else { - _extract_urls(b, linput); - g_free(b); + g_printerr(_("error: while converting to URI: %s\n"), e->message); + g_error_free(e); } + return (r); } -static void _have_rargs(linput_t linput, const gchar **rargs) +static gint _determine_input(linput_t p, const gboolean try_read_as_file, + const gchar *invalid_msg, const gchar *s) { - static const gchar *_E = - N_("error: ignoring input value `%s': not an URL or a file\n"); + gchar *c; + gint r; - gchar *p, *u; - gint i; + c = g_uri_parse_scheme(s); + r = EXIT_SUCCESS; - i = 0; - while (rargs[i] != NULL) + if ((c ==NULL || strlen(c) ==0) && try_read_as_file ==TRUE) { - p = (gchar*) rargs[i++]; - g_strstrip(p); - - /* If file. */ - if (g_file_test(p, G_FILE_TEST_IS_REGULAR) == TRUE) - { - gchar *b = _read_file(p); - if (b != NULL) - { - _extract_urls(b, linput); - g_free(b); - } - } - /* If URI. */ - else if (_has_uri_scheme(p, &u) == TRUE) + gchar *b = _read_file(s); + if (b != NULL) { - linput->url.input = - lutil_slist_prepend_if_unique(linput->url.input, u); + r = _extract_uris(p, b); + g_free(b); } - /* Unable to determine. */ else - g_printerr(g_dgettext(GETTEXT_PACKAGE, _E), p); + r = EXIT_FAILURE; + } + else if (g_strcmp0(c, "http") ==0 || g_strcmp0(c, "https") ==0) + p->url.input = lutil_slist_prepend_if_unique(p->url.input, s); + else if (g_strcmp0(c, "file") ==0) + r = _read_from_uri(p, s); + else + { + g_printerr(g_dgettext(GETTEXT_PACKAGE, invalid_msg), s); + r = EXIT_FAILURE; } + g_free(c); + return (r); } -void linput_new(linput_t linput, const gchar **rargs) +static gint _extract_uris(linput_t p, const gchar *s) { + static const gchar *E = N_("error: %s: an invalid URI\n"); + + gchar **u; + gint i, r; + + u = g_uri_list_extract_uris(s); + + for (i=0, r=EXIT_SUCCESS; u[i] !=NULL && r==EXIT_SUCCESS; ++i) + r = _determine_input(p, FALSE, E, u[i]); + + g_strfreev(u); + return (r); +} + +static gint _parse_without_rargs(linput_t p) +{ + gchar *c; + gint r; + c = _read_stdin(); + r = _extract_uris(p, c); + g_free(c); + return (r); +} + +static gint _parse_with_rargs(linput_t p, const gchar **rargs) +{ + static const gchar *E = + N_("error: %s: neither a valid URI or a local file\n"); + + gint i, r; + for (i=0, r=EXIT_SUCCESS; rargs[i] !=NULL && r ==EXIT_SUCCESS; ++i) + r = _determine_input(p, TRUE, E, rargs[i]); + + return (r); +} + +gint linput_new(linput_t linput, const gchar **rargs) +{ + gint r; + g_assert(linput != NULL); g_assert(linput->url.input == NULL); if (rargs == NULL || g_strv_length((gchar**) rargs) == 0) - _no_rargs(linput); + r = _parse_without_rargs(linput); else - _have_rargs(linput, rargs); + r = _parse_with_rargs(linput, rargs); linput->url.input = g_slist_reverse(linput->url.input); + return (r); } void linput_free(linput_t linput) diff --git a/src/input/linput.h b/src/input/linput.h index 2f05270..c50a163 100644 --- a/src/input/linput.h +++ b/src/input/linput.h @@ -1,5 +1,5 @@ /* quvi - * Copyright (C) 2012 Toni Gundogdu + * Copyright (C) 2012,2013 Toni Gundogdu * * This file is part of quvi . * @@ -31,7 +31,7 @@ struct linput_s typedef struct linput_s *linput_t; -void linput_new(linput_t, const gchar**); +gint linput_new(linput_t, const gchar**); void linput_free(linput_t); #endif /* linput_h */ -- 2.11.4.GIT