From 8bc2caac55572bc06c4fc6c2f6e2b28104c9f69c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Aug 2009 22:55:25 +0200 Subject: move desktop file parser from bus/ to dbus/ We want to make use of it for reading the ConsoleKit database which will need to be implemented in dbus/dbus-userdb-util.c, so let's move this to dbus/. --- dbus/Makefile.am | 18 +- dbus/dbus-desktop-file.c | 799 +++++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-desktop-file.h | 49 +++ 3 files changed, 858 insertions(+), 8 deletions(-) create mode 100644 dbus/dbus-desktop-file.c create mode 100644 dbus/dbus-desktop-file.h (limited to 'dbus') diff --git a/dbus/Makefile.am b/dbus/Makefile.am index e966a438..bf9e1bb5 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -98,8 +98,8 @@ DBUS_LIB_SOURCES= \ ## dbus-md5.h \ ### source code that goes in the installed client library -### AND is generic utility functionality used by the -### daemon or test programs (all symbols in here should +### AND is generic utility functionality used by the +### daemon or test programs (all symbols in here should ### be underscore-prefixed) DBUS_SHARED_SOURCES= \ dbus-dataslot.c \ @@ -128,8 +128,8 @@ DBUS_SHARED_SOURCES= \ ### source code that is generic utility functionality used ### by the bus daemon or test apps, but is NOT included -### in the D-Bus client library (all symbols in here -### should be underscore-prefixed but don't really need +### in the D-Bus client library (all symbols in here +### should be underscore-prefixed but don't really need ### to be unless they move to DBUS_SHARED_SOURCES later) DBUS_UTIL_SOURCES= \ dbus-auth-util.c \ @@ -151,7 +151,9 @@ DBUS_UTIL_SOURCES= \ dbus-sysdeps-util-unix.c \ dbus-test.c \ dbus-test.h \ - dbus-userdb-util.c + dbus-userdb-util.c \ + dbus-desktop-file.c \ + dbus-desktop-file.h libdbus_1_la_SOURCES= \ $(DBUS_LIB_SOURCES) \ @@ -171,14 +173,14 @@ EXTRA_DIST=dbus-arch-deps.h.in noinst_LTLIBRARIES=libdbus-convenience.la libdbus_1_la_LIBADD= $(DBUS_CLIENT_LIBS) -## don't export symbols that start with "_" (we use this +## don't export symbols that start with "_" (we use this ## convention for internal symbols) libdbus_1_la_LDFLAGS= -export-symbols-regex "^[^_].*" -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -no-undefined @R_DYNAMIC_LDFLAG@ @PIC_LDFLAGS@ libdbus_convenience_la_LDFLAGS=@R_DYNAMIC_LDFLAG@ ## note that TESTS has special meaning (stuff to use in make check) -## so if adding tests not to be run in make check, don't add them to +## so if adding tests not to be run in make check, don't add them to ## TESTS if DBUS_BUILD_TESTS TESTS_ENVIRONMENT=DBUS_TEST_DATA=$(top_builddir)/test/data DBUS_TEST_HOMEDIR=$(top_builddir)/dbus @@ -187,7 +189,7 @@ else TESTS= endif -## we use noinst_PROGRAMS not check_PROGRAMS so that we build +## we use noinst_PROGRAMS not check_PROGRAMS so that we build ## even when not doing "make check" noinst_PROGRAMS=$(TESTS) diff --git a/dbus/dbus-desktop-file.c b/dbus/dbus-desktop-file.c new file mode 100644 index 00000000..45932398 --- /dev/null +++ b/dbus/dbus-desktop-file.c @@ -0,0 +1,799 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* desktop-file.c .desktop file parser + * + * Copyright (C) 2003 CodeFactory AB + * Copyright (C) 2003 Red Hat Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include +#include +#include "dbus-desktop-file.h" + +typedef struct +{ + char *key; + char *value; +} DBusDesktopFileLine; + +typedef struct +{ + char *section_name; + + int n_lines; + DBusDesktopFileLine *lines; + int n_allocated_lines; +} DBusDesktopFileSection; + +struct DBusDesktopFile +{ + int n_sections; + DBusDesktopFileSection *sections; + int n_allocated_sections; +}; + +/** + * Parser for service files. + */ +typedef struct +{ + DBusString data; /**< The data from the file */ + + DBusDesktopFile *desktop_file; /**< The resulting object */ + int current_section; /**< The current section being parsed */ + + int pos; /**< Current position */ + int len; /**< Length */ + int line_num; /**< Current line number */ + +} DBusDesktopFileParser; + +#define VALID_KEY_CHAR 1 +#define VALID_LOCALE_CHAR 2 +static unsigned char valid[256] = { + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3 , 0x2 , 0x0 , + 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , + 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2 , + 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , + 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , + 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , +}; + +static void report_error (DBusDesktopFileParser *parser, + char *message, + const char *error_name, + DBusError *error); + +static void +parser_free (DBusDesktopFileParser *parser) +{ + _dbus_desktop_file_free (parser->desktop_file); + + _dbus_string_free (&parser->data); +} + +static void +bus_desktop_file_line_free (DBusDesktopFileLine *line) +{ + dbus_free (line->key); + dbus_free (line->value); +} + +static void +bus_desktop_file_section_free (DBusDesktopFileSection *section) +{ + int i; + + for (i = 0; i < section->n_lines; i++) + bus_desktop_file_line_free (§ion->lines[i]); + + dbus_free (section->lines); + dbus_free (section->section_name); +} + +void +_dbus_desktop_file_free (DBusDesktopFile *desktop_file) +{ + int i; + + for (i = 0; i < desktop_file->n_sections; i++) + bus_desktop_file_section_free (&desktop_file->sections[i]); + dbus_free (desktop_file->sections); + + dbus_free (desktop_file); +} + +static dbus_bool_t +grow_lines_in_section (DBusDesktopFileSection *section) +{ + DBusDesktopFileLine *lines; + + int new_n_lines; + + if (section->n_allocated_lines == 0) + new_n_lines = 1; + else + new_n_lines = section->n_allocated_lines*2; + + lines = dbus_realloc (section->lines, + sizeof (DBusDesktopFileLine) * new_n_lines); + + if (lines == NULL) + return FALSE; + + section->lines = lines; + section->n_allocated_lines = new_n_lines; + + return TRUE; +} + +static dbus_bool_t +grow_sections (DBusDesktopFile *desktop_file) +{ + int new_n_sections; + DBusDesktopFileSection *sections; + + if (desktop_file->n_allocated_sections == 0) + new_n_sections = 1; + else + new_n_sections = desktop_file->n_allocated_sections*2; + + sections = dbus_realloc (desktop_file->sections, + sizeof (DBusDesktopFileSection) * new_n_sections); + if (sections == NULL) + return FALSE; + + desktop_file->sections = sections; + + desktop_file->n_allocated_sections = new_n_sections; + + return TRUE; +} + +static char * +unescape_string (DBusDesktopFileParser *parser, + const DBusString *str, + int pos, + int end_pos, + DBusError *error) +{ + char *retval, *q; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + /* len + 1 is enough, because unescaping never makes the + * string longer + */ + retval = dbus_malloc (end_pos - pos + 1); + if (retval == NULL) + { + _DBUS_SET_OOM (error); + return NULL; + } + + q = retval; + + while (pos < end_pos) + { + if (_dbus_string_get_byte (str, pos) == 0) + { + /* Found an embedded null */ + dbus_free (retval); + report_error (parser, "Text to be unescaped contains embedded nul", + DBUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); + return NULL; + } + + if (_dbus_string_get_byte (str, pos) == '\\') + { + pos ++; + + if (pos >= end_pos) + { + /* Escape at end of string */ + dbus_free (retval); + report_error (parser, "Text to be unescaped ended in \\", + DBUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); + return NULL; + } + + switch (_dbus_string_get_byte (str, pos)) + { + case 's': + *q++ = ' '; + break; + case 't': + *q++ = '\t'; + break; + case 'n': + *q++ = '\n'; + break; + case 'r': + *q++ = '\r'; + break; + case '\\': + *q++ = '\\'; + break; + default: + /* Invalid escape code */ + dbus_free (retval); + report_error (parser, "Text to be unescaped had invalid escape sequence", + DBUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); + return NULL; + } + pos++; + } + else + { + *q++ =_dbus_string_get_byte (str, pos); + + pos++; + } + } + + *q = 0; + + return retval; +} + +static DBusDesktopFileSection* +new_section (DBusDesktopFile *desktop_file, + const char *name) +{ + int n; + char *name_copy; + + if (desktop_file->n_allocated_sections == desktop_file->n_sections) + { + if (!grow_sections (desktop_file)) + return NULL; + } + + name_copy = _dbus_strdup (name); + if (name_copy == NULL) + return NULL; + + n = desktop_file->n_sections; + desktop_file->sections[n].section_name = name_copy; + + desktop_file->sections[n].n_lines = 0; + desktop_file->sections[n].lines = NULL; + desktop_file->sections[n].n_allocated_lines = 0; + + if (!grow_lines_in_section (&desktop_file->sections[n])) + { + dbus_free (desktop_file->sections[n].section_name); + desktop_file->sections[n].section_name = NULL; + return NULL; + } + + desktop_file->n_sections += 1; + + return &desktop_file->sections[n]; +} + +static DBusDesktopFileSection* +open_section (DBusDesktopFileParser *parser, + char *name) +{ + DBusDesktopFileSection *section; + + section = new_section (parser->desktop_file, name); + if (section == NULL) + return NULL; + + parser->current_section = parser->desktop_file->n_sections - 1; + _dbus_assert (&parser->desktop_file->sections[parser->current_section] == section); + + return section; +} + +static DBusDesktopFileLine * +new_line (DBusDesktopFileParser *parser) +{ + DBusDesktopFileSection *section; + DBusDesktopFileLine *line; + + section = &parser->desktop_file->sections[parser->current_section]; + + if (section->n_allocated_lines == section->n_lines) + { + if (!grow_lines_in_section (section)) + return NULL; + } + + line = §ion->lines[section->n_lines++]; + + _DBUS_ZERO(*line); + + return line; +} + +static dbus_bool_t +is_blank_line (DBusDesktopFileParser *parser) +{ + int p; + char c; + + p = parser->pos; + + c = _dbus_string_get_byte (&parser->data, p); + + while (c && c != '\n') + { + if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f')) + return FALSE; + + p++; + c = _dbus_string_get_byte (&parser->data, p); + } + + return TRUE; +} + +static void +parse_comment_or_blank (DBusDesktopFileParser *parser) +{ + int line_end, eol_len; + + if (!_dbus_string_find_eol (&parser->data, parser->pos, &line_end, &eol_len)) + line_end = parser->len; + + if (line_end == parser->len) + parser->pos = parser->len; + else + parser->pos = line_end + eol_len; + + parser->line_num += 1; +} + +static dbus_bool_t +is_valid_section_name (const char *name) +{ + /* 5. Group names may contain all ASCII characters except for control characters and '[' and ']'. */ + + while (*name) + { + if (!((*name >= 'A' && *name <= 'Z') || (*name >= 'a' || *name <= 'z') || + *name == '\n' || *name == '\t')) + return FALSE; + + name++; + } + + return TRUE; +} + +static dbus_bool_t +parse_section_start (DBusDesktopFileParser *parser, DBusError *error) +{ + int line_end, eol_len; + char *section_name; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (!_dbus_string_find_eol (&parser->data, parser->pos, &line_end, &eol_len)) + line_end = parser->len; + + if (line_end - parser->pos <= 2 || + _dbus_string_get_byte (&parser->data, line_end - 1) != ']') + { + report_error (parser, "Invalid syntax for section header", DBUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); + parser_free (parser); + return FALSE; + } + + section_name = unescape_string (parser, + &parser->data, parser->pos + 1, line_end - 1, + error); + + if (section_name == NULL) + { + parser_free (parser); + return FALSE; + } + + if (!is_valid_section_name (section_name)) + { + report_error (parser, "Invalid characters in section name", DBUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error); + parser_free (parser); + dbus_free (section_name); + return FALSE; + } + + if (open_section (parser, section_name) == NULL) + { + dbus_free (section_name); + parser_free (parser); + _DBUS_SET_OOM (error); + return FALSE; + } + + if (line_end == parser->len) + parser->pos = parser->len; + else + parser->pos = line_end + eol_len; + + parser->line_num += 1; + + dbus_free (section_name); + + return TRUE; +} + +static dbus_bool_t +parse_key_value (DBusDesktopFileParser *parser, DBusError *error) +{ + int line_end, eol_len; + int key_start, key_end; + int value_start; + int p; + char *value, *tmp; + DBusString key; + DBusDesktopFileLine *line; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (!_dbus_string_find_eol (&parser->data, parser->pos, &line_end, &eol_len)) + line_end = parser->len; + + p = parser->pos; + key_start = p; + while (p < line_end && + (valid[_dbus_string_get_byte (&parser->data, p)] & VALID_KEY_CHAR)) + p++; + key_end = p; + + if (key_start == key_end) + { + report_error (parser, "Empty key name", DBUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); + parser_free (parser); + return FALSE; + } + + /* We ignore locales for now */ + if (p < line_end && _dbus_string_get_byte (&parser->data, p) == '[') + { + if (line_end == parser->len) + parser->pos = parser->len; + else + parser->pos = line_end + eol_len; + + parser->line_num += 1; + + return TRUE; + } + + /* Skip space before '=' */ + while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ') + p++; + + if (p < line_end && _dbus_string_get_byte (&parser->data, p) != '=') + { + report_error (parser, "Invalid characters in key name", DBUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error); + parser_free (parser); + return FALSE; + } + + if (p == line_end) + { + report_error (parser, "No '=' in key/value pair", DBUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); + parser_free (parser); + return FALSE; + } + + /* Skip the '=' */ + p++; + + /* Skip space after '=' */ + while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ') + p++; + + value_start = p; + + value = unescape_string (parser, &parser->data, value_start, line_end, error); + if (value == NULL) + { + parser_free (parser); + return FALSE; + } + + line = new_line (parser); + if (line == NULL) + { + dbus_free (value); + parser_free (parser); + _DBUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_init (&key)) + { + dbus_free (value); + parser_free (parser); + _DBUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_copy_len (&parser->data, key_start, key_end - key_start, + &key, 0)) + { + _dbus_string_free (&key); + dbus_free (value); + parser_free (parser); + _DBUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_steal_data (&key, &tmp)) + { + _dbus_string_free (&key); + dbus_free (value); + parser_free (parser); + _DBUS_SET_OOM (error); + return FALSE; + } + + _dbus_string_free (&key); + + line->key = tmp; + line->value = value; + + if (line_end == parser->len) + parser->pos = parser->len; + else + parser->pos = line_end + eol_len; + + parser->line_num += 1; + + return TRUE; +} + +static void +report_error (DBusDesktopFileParser *parser, + char *message, + const char *error_name, + DBusError *error) +{ + const char *section_name = NULL; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (parser->current_section != -1) + section_name = parser->desktop_file->sections[parser->current_section].section_name; + + if (section_name) + dbus_set_error (error, error_name, + "Error in section %s at line %d: %s\n", section_name, parser->line_num, message); + else + dbus_set_error (error, error_name, + "Error at line %d: %s\n", parser->line_num, message); +} + +#if 0 +static void +dump_desktop_file (DBusDesktopFile *file) +{ + int i; + + for (i = 0; i < file->n_sections; i++) + { + int j; + + printf ("[%s]\n", file->sections[i].section_name); + + for (j = 0; j < file->sections[i].n_lines; j++) + { + printf ("%s=%s\n", file->sections[i].lines[j].key, + file->sections[i].lines[j].value); + } + } +} +#endif + +DBusDesktopFile* +_dbus_desktop_file_load (DBusString *filename, + DBusError *error) +{ + DBusString str; + DBusDesktopFileParser parser; + DBusStat sb; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + /* Clearly there's a race here, but it's just to make it unlikely + * that we do something silly, we still handle doing it below. + */ + if (!_dbus_stat (filename, &sb, error)) + return NULL; + + if (sb.size > _DBUS_ONE_KILOBYTE * 128) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Desktop file size (%ld bytes) is too large", (long) sb.size); + return NULL; + } + + if (!_dbus_string_init (&str)) + { + _DBUS_SET_OOM (error); + return NULL; + } + + if (!_dbus_file_get_contents (&str, filename, error)) + { + _dbus_string_free (&str); + return NULL; + } + + if (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str))) + { + _dbus_string_free (&str); + dbus_set_error (error, DBUS_ERROR_FAILED, + "invalid UTF-8"); + return NULL; + } + + parser.desktop_file = dbus_new0 (DBusDesktopFile, 1); + if (parser.desktop_file == NULL) + { + _dbus_string_free (&str); + _DBUS_SET_OOM (error); + return NULL; + } + + parser.data = str; + parser.line_num = 1; + parser.pos = 0; + parser.len = _dbus_string_get_length (&parser.data); + parser.current_section = -1; + + while (parser.pos < parser.len) + { + if (_dbus_string_get_byte (&parser.data, parser.pos) == '[') + { + if (!parse_section_start (&parser, error)) + { + return NULL; + } + } + else if (is_blank_line (&parser) || + _dbus_string_get_byte (&parser.data, parser.pos) == '#') + parse_comment_or_blank (&parser); + else + { + if (!parse_key_value (&parser, error)) + { + return NULL; + } + } + } + + _dbus_string_free (&parser.data); + + return parser.desktop_file; +} + +static DBusDesktopFileSection * +lookup_section (DBusDesktopFile *desktop_file, + const char *section_name) +{ + DBusDesktopFileSection *section; + int i; + + if (section_name == NULL) + return NULL; + + for (i = 0; i < desktop_file->n_sections; i ++) + { + section = &desktop_file->sections[i]; + + if (strcmp (section->section_name, section_name) == 0) + return section; + } + + return NULL; +} + +static DBusDesktopFileLine * +lookup_line (DBusDesktopFile *desktop_file, + DBusDesktopFileSection *section, + const char *keyname) +{ + DBusDesktopFileLine *line; + int i; + + for (i = 0; i < section->n_lines; i++) + { + line = §ion->lines[i]; + + if (strcmp (line->key, keyname) == 0) + return line; + } + + return NULL; +} + +dbus_bool_t +_dbus_desktop_file_get_raw (DBusDesktopFile *desktop_file, + const char *section_name, + const char *keyname, + const char **val) +{ + DBusDesktopFileSection *section; + DBusDesktopFileLine *line; + + *val = NULL; + + section = lookup_section (desktop_file, section_name); + + if (!section) + return FALSE; + + line = lookup_line (desktop_file, + section, + keyname); + + if (!line) + return FALSE; + + *val = line->value; + + return TRUE; +} + +dbus_bool_t +_dbus_desktop_file_get_string (DBusDesktopFile *desktop_file, + const char *section, + const char *keyname, + char **val, + DBusError *error) +{ + const char *raw; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + *val = NULL; + + if (!_dbus_desktop_file_get_raw (desktop_file, section, keyname, &raw)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "No \"%s\" key in .service file\n", keyname); + return FALSE; + } + + *val = _dbus_strdup (raw); + + if (*val == NULL) + { + _DBUS_SET_OOM (error); + return FALSE; + } + + return TRUE; +} diff --git a/dbus/dbus-desktop-file.h b/dbus/dbus-desktop-file.h new file mode 100644 index 00000000..812d82f3 --- /dev/null +++ b/dbus/dbus-desktop-file.h @@ -0,0 +1,49 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* desktop-file.h .desktop file parser + * + * Copyright (C) 2003 CodeFactory AB + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#ifndef BUS_DESKTOP_FILE_H +#define BUS_DESKTOP_FILE_H + +#include +#include + +#define DBUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX "org.freedesktop.DBus.DesktopParseError.InvalidSyntax" +#define DBUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES "org.freedesktop.DBus.DesktopParseError.InvalidEscapes" +#define DBUS_DESKTOP_PARSE_ERROR_INVALID_CHARS "org.freedesktop.DBus.DesktopParseError.InvalidChars" + +typedef struct DBusDesktopFile DBusDesktopFile; + +DBusDesktopFile *_dbus_desktop_file_load (DBusString *filename, + DBusError *error); +void _dbus_desktop_file_free (DBusDesktopFile *file); + +dbus_bool_t _dbus_desktop_file_get_raw (DBusDesktopFile *desktop_file, + const char *section_name, + const char *keyname, + const char **val); +dbus_bool_t _dbus_desktop_file_get_string (DBusDesktopFile *desktop_file, + const char *section, + const char *keyname, + char **val, + DBusError *error); + +#endif /* BUS_DESKTOP_FILE_H */ -- cgit