<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>desktop-file.c Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.2.15 --> <center> <a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="modules.html">Modules</a> <a class="qindex" href="annotated.html">Data Structures</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="functions.html">Data Fields</a> <a class="qindex" href="pages.html">Related Pages</a> </center> <hr><h1>desktop-file.c</h1><div class="fragment"><pre>00001 <font class="comment">/* -*- mode: C; c-file-style: "gnu" -*- */</font> 00002 <font class="comment">/* desktop-file.c .desktop file parser</font> 00003 <font class="comment"> *</font> 00004 <font class="comment"> * Copyright (C) 2003 CodeFactory AB</font> 00005 <font class="comment"> * Copyright (C) 2003 Red Hat Inc.</font> 00006 <font class="comment"> *</font> 00007 <font class="comment"> * Licensed under the Academic Free License version 1.2</font> 00008 <font class="comment"> * </font> 00009 <font class="comment"> * This program is free software; you can redistribute it and/or modify</font> 00010 <font class="comment"> * it under the terms of the GNU General Public License as published by</font> 00011 <font class="comment"> * the Free Software Foundation; either version 2 of the License, or</font> 00012 <font class="comment"> * (at your option) any later version.</font> 00013 <font class="comment"> *</font> 00014 <font class="comment"> * This program is distributed in the hope that it will be useful,</font> 00015 <font class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</font> 00016 <font class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</font> 00017 <font class="comment"> * GNU General Public License for more details.</font> 00018 <font class="comment"> * </font> 00019 <font class="comment"> * You should have received a copy of the GNU General Public License</font> 00020 <font class="comment"> * along with this program; if not, write to the Free Software</font> 00021 <font class="comment"> * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</font> 00022 <font class="comment"> *</font> 00023 <font class="comment"> */</font> 00024 <font class="preprocessor">#include <dbus/dbus-sysdeps.h></font> 00025 <font class="preprocessor">#include <dbus/dbus-internals.h></font> 00026 <font class="preprocessor">#include "desktop-file.h"</font> 00027 <font class="preprocessor">#include "utils.h"</font> 00028 00029 <font class="keyword">typedef</font> <font class="keyword">struct</font> 00030 <font class="keyword"></font>{ 00031 <font class="keywordtype">char</font> *key; 00032 <font class="keywordtype">char</font> *value; 00033 } BusDesktopFileLine; 00034 00035 <font class="keyword">typedef</font> <font class="keyword">struct</font> 00036 <font class="keyword"></font>{ 00037 <font class="keywordtype">char</font> *section_name; 00038 00039 <font class="keywordtype">int</font> n_lines; 00040 BusDesktopFileLine *lines; 00041 <font class="keywordtype">int</font> n_allocated_lines; 00042 } BusDesktopFileSection; 00043 00044 <font class="keyword">struct </font>BusDesktopFile 00045 { 00046 <font class="keywordtype">int</font> n_sections; 00047 BusDesktopFileSection *sections; 00048 <font class="keywordtype">int</font> n_allocated_sections; 00049 }; 00050 <a name="l00054"></a><a class="code" href="structBusDesktopFileParser.html">00054</a> <font class="keyword">typedef</font> <font class="keyword">struct</font> 00055 <font class="keyword"></font>{ <a name="l00056"></a><a class="code" href="structBusDesktopFileParser.html#m0">00056</a> <a class="code" href="structDBusString.html">DBusString</a> data; <a name="l00058"></a><a class="code" href="structBusDesktopFileParser.html#m1">00058</a> BusDesktopFile *desktop_file; <a name="l00059"></a><a class="code" href="structBusDesktopFileParser.html#m2">00059</a> <font class="keywordtype">int</font> current_section; <a name="l00061"></a><a class="code" href="structBusDesktopFileParser.html#m3">00061</a> <font class="keywordtype">int</font> pos; <a name="l00062"></a><a class="code" href="structBusDesktopFileParser.html#m4">00062</a> <font class="keywordtype">int</font> len; <a name="l00063"></a><a class="code" href="structBusDesktopFileParser.html#m5">00063</a> <font class="keywordtype">int</font> line_num; 00065 } <a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a>; 00066 00067 <font class="preprocessor">#define VALID_KEY_CHAR 1</font> 00068 <font class="preprocessor"></font><font class="preprocessor">#define VALID_LOCALE_CHAR 2</font> 00069 <font class="preprocessor"></font><font class="keywordtype">unsigned</font> <font class="keywordtype">char</font> valid[256] = { 00070 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00071 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00072 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3 , 0x2 , 0x0 , 00073 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00074 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 00075 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2 , 00076 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 00077 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00078 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00079 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00080 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00081 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00082 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00083 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00084 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00085 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 00086 }; 00087 00088 <font class="keyword">static</font> <font class="keywordtype">void</font> report_error (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser, 00089 <font class="keywordtype">char</font> *message, 00090 <font class="keyword">const</font> <font class="keywordtype">char</font> *error_name, 00091 <a class="code" href="structDBusError.html">DBusError</a> *error); 00092 00093 <font class="keyword">static</font> <font class="keywordtype">void</font> 00094 parser_free (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser) 00095 { 00096 bus_desktop_file_free (parser-><a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a>); 00097 00098 _dbus_string_free (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>); 00099 } 00100 00101 <font class="keyword">static</font> <font class="keywordtype">void</font> 00102 bus_desktop_file_line_free (BusDesktopFileLine *line) 00103 { 00104 dbus_free (line->key); 00105 dbus_free (line->value); 00106 } 00107 00108 <font class="keyword">static</font> <font class="keywordtype">void</font> 00109 bus_desktop_file_section_free (BusDesktopFileSection *section) 00110 { 00111 <font class="keywordtype">int</font> i; 00112 00113 <font class="keywordflow">for</font> (i = 0; i < section->n_lines; i++) 00114 bus_desktop_file_line_free (&section->lines[i]); 00115 00116 dbus_free (section->lines); 00117 dbus_free (section->section_name); 00118 } 00119 00120 <font class="keywordtype">void</font> 00121 bus_desktop_file_free (BusDesktopFile *desktop_file) 00122 { 00123 <font class="keywordtype">int</font> i; 00124 00125 <font class="keywordflow">for</font> (i = 0; i < desktop_file->n_sections; i++) 00126 bus_desktop_file_section_free (&desktop_file->sections[i]); 00127 dbus_free (desktop_file->sections); 00128 00129 dbus_free (desktop_file); 00130 } 00131 00132 <font class="keyword">static</font> dbus_bool_t 00133 grow_lines_in_section (BusDesktopFileSection *section) 00134 { 00135 BusDesktopFileLine *lines; 00136 00137 <font class="keywordtype">int</font> new_n_lines; 00138 00139 <font class="keywordflow">if</font> (section->n_allocated_lines == 0) 00140 new_n_lines = 1; 00141 <font class="keywordflow">else</font> 00142 new_n_lines = section->n_allocated_lines*2; 00143 00144 lines = dbus_realloc (section->lines, 00145 sizeof (BusDesktopFileLine) * new_n_lines); 00146 00147 <font class="keywordflow">if</font> (lines == NULL) 00148 <font class="keywordflow">return</font> FALSE; 00149 00150 section->lines = lines; 00151 section->n_allocated_lines = new_n_lines; 00152 00153 <font class="keywordflow">return</font> TRUE; 00154 } 00155 00156 <font class="keyword">static</font> dbus_bool_t 00157 grow_sections (BusDesktopFile *desktop_file) 00158 { 00159 <font class="keywordtype">int</font> new_n_sections; 00160 BusDesktopFileSection *sections; 00161 00162 <font class="keywordflow">if</font> (desktop_file->n_allocated_sections == 0) 00163 new_n_sections = 1; 00164 <font class="keywordflow">else</font> 00165 new_n_sections = desktop_file->n_allocated_sections*2; 00166 00167 sections = dbus_realloc (desktop_file->sections, 00168 sizeof (BusDesktopFileSection) * new_n_sections); 00169 <font class="keywordflow">if</font> (sections == NULL) 00170 <font class="keywordflow">return</font> FALSE; 00171 00172 desktop_file->sections = sections; 00173 00174 desktop_file->n_allocated_sections = new_n_sections; 00175 00176 <font class="keywordflow">return</font> TRUE; 00177 } 00178 00179 <font class="keyword">static</font> <font class="keywordtype">char</font> * 00180 unescape_string (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser, 00181 <font class="keyword">const</font> <a class="code" href="structDBusString.html">DBusString</a> *str, 00182 <font class="keywordtype">int</font> pos, 00183 <font class="keywordtype">int</font> end_pos, 00184 <a class="code" href="structDBusError.html">DBusError</a> *error) 00185 { 00186 <font class="keywordtype">char</font> *retval, *q; 00187 00188 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00189 00190 <font class="comment">/* len + 1 is enough, because unescaping never makes the</font> 00191 <font class="comment"> * string longer</font> 00192 <font class="comment"> */</font> 00193 retval = dbus_malloc (end_pos - pos + 1); 00194 <font class="keywordflow">if</font> (retval == NULL) 00195 { 00196 BUS_SET_OOM (error); 00197 <font class="keywordflow">return</font> NULL; 00198 } 00199 00200 q = retval; 00201 00202 <font class="keywordflow">while</font> (pos < end_pos) 00203 { 00204 <font class="keywordflow">if</font> (_dbus_string_get_byte (str, pos) == 0) 00205 { 00206 <font class="comment">/* Found an embedded null */</font> 00207 dbus_free (retval); 00208 report_error (parser, <font class="stringliteral">"Text to be unescaped contains embedded nul"</font>, 00209 BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); 00210 <font class="keywordflow">return</font> NULL; 00211 } 00212 00213 <font class="keywordflow">if</font> (_dbus_string_get_byte (str, pos) == <font class="charliteral">'\\'</font>) 00214 { 00215 pos ++; 00216 00217 <font class="keywordflow">if</font> (pos >= end_pos) 00218 { 00219 <font class="comment">/* Escape at end of string */</font> 00220 dbus_free (retval); 00221 report_error (parser, <font class="stringliteral">"Text to be unescaped ended in \\"</font>, 00222 BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); 00223 <font class="keywordflow">return</font> NULL; 00224 } 00225 00226 <font class="keywordflow">switch</font> (_dbus_string_get_byte (str, pos)) 00227 { 00228 <font class="keywordflow">case</font> <font class="charliteral">'s'</font>: 00229 *q++ = <font class="charliteral">' '</font>; 00230 <font class="keywordflow">break</font>; 00231 <font class="keywordflow">case</font> <font class="charliteral">'t'</font>: 00232 *q++ = <font class="charliteral">'\t'</font>; 00233 <font class="keywordflow">break</font>; 00234 <font class="keywordflow">case</font> <font class="charliteral">'n'</font>: 00235 *q++ = <font class="charliteral">'\n'</font>; 00236 <font class="keywordflow">break</font>; 00237 <font class="keywordflow">case</font> <font class="charliteral">'r'</font>: 00238 *q++ = <font class="charliteral">'\r'</font>; 00239 <font class="keywordflow">break</font>; 00240 <font class="keywordflow">case</font> <font class="charliteral">'\\'</font>: 00241 *q++ = <font class="charliteral">'\\'</font>; 00242 <font class="keywordflow">break</font>; 00243 <font class="keywordflow">default</font>: 00244 <font class="comment">/* Invalid escape code */</font> 00245 dbus_free (retval); 00246 report_error (parser, <font class="stringliteral">"Text to be unescaped had invalid escape sequence"</font>, 00247 BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); 00248 <font class="keywordflow">return</font> NULL; 00249 } 00250 pos++; 00251 } 00252 <font class="keywordflow">else</font> 00253 { 00254 *q++ =_dbus_string_get_byte (str, pos); 00255 00256 pos++; 00257 } 00258 } 00259 00260 *q = 0; 00261 00262 <font class="keywordflow">return</font> retval; 00263 } 00264 00265 <font class="keyword">static</font> BusDesktopFileSection* 00266 new_section (BusDesktopFile *desktop_file, 00267 <font class="keyword">const</font> <font class="keywordtype">char</font> *name) 00268 { 00269 <font class="keywordtype">int</font> n; 00270 <font class="keywordtype">char</font> *name_copy; 00271 00272 <font class="keywordflow">if</font> (desktop_file->n_allocated_sections == desktop_file->n_sections) 00273 { 00274 <font class="keywordflow">if</font> (!grow_sections (desktop_file)) 00275 <font class="keywordflow">return</font> NULL; 00276 } 00277 00278 name_copy = _dbus_strdup (name); 00279 <font class="keywordflow">if</font> (name_copy == NULL) 00280 <font class="keywordflow">return</font> NULL; 00281 00282 n = desktop_file->n_sections; 00283 desktop_file->sections[n].section_name = name_copy; 00284 00285 desktop_file->sections[n].n_lines = 0; 00286 desktop_file->sections[n].lines = NULL; 00287 desktop_file->sections[n].n_allocated_lines = 0; 00288 00289 <font class="keywordflow">if</font> (!grow_lines_in_section (&desktop_file->sections[n])) 00290 { 00291 dbus_free (desktop_file->sections[n].section_name); 00292 desktop_file->sections[n].section_name = NULL; 00293 <font class="keywordflow">return</font> NULL; 00294 } 00295 00296 desktop_file->n_sections += 1; 00297 00298 <font class="keywordflow">return</font> &desktop_file->sections[n]; 00299 } 00300 00301 <font class="keyword">static</font> BusDesktopFileSection* 00302 open_section (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser, 00303 <font class="keywordtype">char</font> *name) 00304 { 00305 BusDesktopFileSection *section; 00306 00307 section = new_section (parser-><a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a>, name); 00308 <font class="keywordflow">if</font> (section == NULL) 00309 <font class="keywordflow">return</font> NULL; 00310 00311 parser-><a class="code" href="structBusDesktopFileParser.html#m2">current_section</a> = parser-><a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a>->n_sections - 1; 00312 _dbus_assert (&parser-><a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a>->sections[parser-><a class="code" href="structBusDesktopFileParser.html#m2">current_section</a>] == section); 00313 00314 <font class="keywordflow">return</font> section; 00315 } 00316 00317 <font class="keyword">static</font> BusDesktopFileLine * 00318 new_line (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser) 00319 { 00320 BusDesktopFileSection *section; 00321 BusDesktopFileLine *line; 00322 00323 section = &parser-><a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a>->sections[parser-><a class="code" href="structBusDesktopFileParser.html#m2">current_section</a>]; 00324 00325 <font class="keywordflow">if</font> (section->n_allocated_lines == section->n_lines) 00326 { 00327 <font class="keywordflow">if</font> (!grow_lines_in_section (section)) 00328 <font class="keywordflow">return</font> NULL; 00329 } 00330 00331 line = &section->lines[section->n_lines++]; 00332 00333 memset (line, 0, <font class="keyword">sizeof</font> (BusDesktopFileLine)); 00334 00335 <font class="keywordflow">return</font> line; 00336 } 00337 00338 <font class="keyword">static</font> dbus_bool_t 00339 is_blank_line (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser) 00340 { 00341 <font class="keywordtype">int</font> p; 00342 <font class="keywordtype">char</font> c; 00343 00344 p = parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a>; 00345 00346 c = _dbus_string_get_byte (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, p); 00347 00348 <font class="keywordflow">while</font> (c && c != <font class="charliteral">'\n'</font>) 00349 { 00350 <font class="keywordflow">if</font> (!(c == <font class="charliteral">' '</font> || c == <font class="charliteral">'\t'</font> || c == <font class="charliteral">'\n'</font> || c == <font class="charliteral">'\r'</font> || c == <font class="charliteral">'\f'</font>)) 00351 <font class="keywordflow">return</font> FALSE; 00352 00353 p++; 00354 c = _dbus_string_get_byte (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, p); 00355 } 00356 00357 <font class="keywordflow">return</font> TRUE; 00358 } 00359 00360 <font class="keyword">static</font> <font class="keywordtype">void</font> 00361 parse_comment_or_blank (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser) 00362 { 00363 <font class="keywordtype">int</font> line_end; 00364 00365 <font class="keywordflow">if</font> (!_dbus_string_find (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a>, <font class="stringliteral">"\n"</font>, &line_end)) 00366 line_end = parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>; 00367 00368 <font class="keywordflow">if</font> (line_end == parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>) 00369 parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a> = parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>; 00370 <font class="keywordflow">else</font> 00371 parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a> = line_end + 1; 00372 00373 parser-><a class="code" href="structBusDesktopFileParser.html#m5">line_num</a> += 1; 00374 } 00375 00376 <font class="keyword">static</font> dbus_bool_t 00377 is_valid_section_name (<font class="keyword">const</font> <font class="keywordtype">char</font> *name) 00378 { 00379 <font class="comment">/* 5. Group names may contain all ASCII characters except for control characters and '[' and ']'. */</font> 00380 00381 <font class="keywordflow">while</font> (*name) 00382 { 00383 <font class="keywordflow">if</font> (!((*name >= <font class="charliteral">'A'</font> && *name <= 'Z') || (*name >= <font class="charliteral">'a'</font> || *name <= <font class="charliteral">'z'</font>) || 00384 *name == <font class="charliteral">'\n'</font> || *name == <font class="charliteral">'\t'</font>)) 00385 <font class="keywordflow">return</font> FALSE; 00386 00387 name++; 00388 } 00389 00390 <font class="keywordflow">return</font> TRUE; 00391 } 00392 00393 <font class="keyword">static</font> dbus_bool_t 00394 parse_section_start (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser, <a class="code" href="structDBusError.html">DBusError</a> *error) 00395 { 00396 <font class="keywordtype">int</font> line_end; 00397 <font class="keywordtype">char</font> *section_name; 00398 00399 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00400 00401 <font class="keywordflow">if</font> (!_dbus_string_find (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a>, <font class="stringliteral">"\n"</font>, &line_end)) 00402 line_end = parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>; 00403 00404 <font class="keywordflow">if</font> (line_end - parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a> <= 2 || 00405 _dbus_string_get_byte (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, line_end - 1) != <font class="charliteral">']'</font>) 00406 { 00407 report_error (parser, <font class="stringliteral">"Invalid syntax for section header"</font>, BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); 00408 parser_free (parser); 00409 <font class="keywordflow">return</font> FALSE; 00410 } 00411 00412 section_name = unescape_string (parser, 00413 &parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a> + 1, line_end - 1, 00414 error); 00415 00416 <font class="keywordflow">if</font> (section_name == NULL) 00417 { 00418 parser_free (parser); 00419 <font class="keywordflow">return</font> FALSE; 00420 } 00421 00422 <font class="keywordflow">if</font> (!is_valid_section_name (section_name)) 00423 { 00424 report_error (parser, <font class="stringliteral">"Invalid characters in section name"</font>, BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error); 00425 parser_free (parser); 00426 dbus_free (section_name); 00427 <font class="keywordflow">return</font> FALSE; 00428 } 00429 00430 <font class="keywordflow">if</font> (open_section (parser, section_name) == NULL) 00431 { 00432 dbus_free (section_name); 00433 <font class="keywordflow">return</font> FALSE; 00434 } 00435 00436 <font class="keywordflow">if</font> (line_end == parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>) 00437 parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a> = parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>; 00438 <font class="keywordflow">else</font> 00439 parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a> = line_end + 1; 00440 00441 parser-><a class="code" href="structBusDesktopFileParser.html#m5">line_num</a> += 1; 00442 00443 dbus_free (section_name); 00444 00445 <font class="keywordflow">return</font> TRUE; 00446 } 00447 00448 <font class="keyword">static</font> dbus_bool_t 00449 parse_key_value (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser, <a class="code" href="structDBusError.html">DBusError</a> *error) 00450 { 00451 <font class="keywordtype">int</font> line_end; 00452 <font class="keywordtype">int</font> key_start, key_end; 00453 <font class="keywordtype">int</font> value_start; 00454 <font class="keywordtype">int</font> p; 00455 <font class="keywordtype">char</font> *value, *tmp; 00456 <a class="code" href="structDBusString.html">DBusString</a> key; 00457 BusDesktopFileLine *line; 00458 00459 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00460 00461 <font class="keywordflow">if</font> (!_dbus_string_find (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a>, <font class="stringliteral">"\n"</font>, &line_end)) 00462 line_end = parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>; 00463 00464 p = parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a>; 00465 key_start = p; 00466 <font class="keywordflow">while</font> (p < line_end && 00467 (valid[_dbus_string_get_byte (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, p)] & VALID_KEY_CHAR)) 00468 p++; 00469 key_end = p; 00470 00471 <font class="keywordflow">if</font> (key_start == key_end) 00472 { 00473 report_error (parser, <font class="stringliteral">"Empty key name"</font>, BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); 00474 parser_free (parser); 00475 <font class="keywordflow">return</font> FALSE; 00476 } 00477 00478 <font class="comment">/* We ignore locales for now */</font> 00479 00480 <font class="comment">/* Skip space before '=' */</font> 00481 <font class="keywordflow">while</font> (p < line_end && _dbus_string_get_byte (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, p) == <font class="charliteral">' '</font>) 00482 p++; 00483 00484 <font class="keywordflow">if</font> (p < line_end && _dbus_string_get_byte (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, p) != <font class="charliteral">'='</font>) 00485 { 00486 report_error (parser, <font class="stringliteral">"Invalid characters in key name"</font>, BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error); 00487 parser_free (parser); 00488 <font class="keywordflow">return</font> FALSE; 00489 } 00490 00491 <font class="keywordflow">if</font> (p == line_end) 00492 { 00493 report_error (parser, <font class="stringliteral">"No '=' in key/value pair"</font>, BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); 00494 parser_free (parser); 00495 <font class="keywordflow">return</font> FALSE; 00496 } 00497 00498 <font class="comment">/* Skip the '=' */</font> 00499 p++; 00500 00501 <font class="comment">/* Skip space after '=' */</font> 00502 <font class="keywordflow">while</font> (p < line_end && _dbus_string_get_byte (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, p) == <font class="charliteral">' '</font>) 00503 p++; 00504 00505 value_start = p; 00506 00507 value = unescape_string (parser, &parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, value_start, line_end, error); 00508 <font class="keywordflow">if</font> (value == NULL) 00509 { 00510 parser_free (parser); 00511 <font class="keywordflow">return</font> FALSE; 00512 } 00513 00514 line = new_line (parser); 00515 <font class="keywordflow">if</font> (line == NULL) 00516 { 00517 parser_free (parser); 00518 <font class="keywordflow">return</font> FALSE; 00519 } 00520 00521 <font class="keywordflow">if</font> (!_dbus_string_init (&key)) 00522 { 00523 parser_free (parser); 00524 <font class="keywordflow">return</font> FALSE; 00525 } 00526 00527 <font class="keywordflow">if</font> (!_dbus_string_copy_len (&parser-><a class="code" href="structBusDesktopFileParser.html#m0">data</a>, key_start, key_end - key_start, 00528 &key, 0)) 00529 { 00530 parser_free (parser); 00531 <font class="keywordflow">return</font> FALSE; 00532 } 00533 00534 <font class="keywordflow">if</font> (!_dbus_string_steal_data (&key, &tmp)) 00535 { 00536 parser_free (parser); 00537 <font class="keywordflow">return</font> FALSE; 00538 } 00539 00540 _dbus_string_free (&key); 00541 00542 line->key = tmp; 00543 line->value = value; 00544 00545 <font class="keywordflow">if</font> (line_end == parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>) 00546 parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a> = parser-><a class="code" href="structBusDesktopFileParser.html#m4">len</a>; 00547 <font class="keywordflow">else</font> 00548 parser-><a class="code" href="structBusDesktopFileParser.html#m3">pos</a> = line_end + 1; 00549 00550 parser-><a class="code" href="structBusDesktopFileParser.html#m5">line_num</a> += 1; 00551 00552 <font class="keywordflow">return</font> TRUE; 00553 } 00554 00555 <font class="keyword">static</font> <font class="keywordtype">void</font> 00556 report_error (<a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> *parser, 00557 <font class="keywordtype">char</font> *message, 00558 <font class="keyword">const</font> <font class="keywordtype">char</font> *error_name, 00559 <a class="code" href="structDBusError.html">DBusError</a> *error) 00560 { 00561 <font class="keyword">const</font> <font class="keywordtype">char</font> *section_name = NULL; 00562 00563 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00564 00565 <font class="keywordflow">if</font> (parser-><a class="code" href="structBusDesktopFileParser.html#m2">current_section</a> != -1) 00566 section_name = parser-><a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a>->sections[parser-><a class="code" href="structBusDesktopFileParser.html#m2">current_section</a>].section_name; 00567 00568 <font class="keywordflow">if</font> (section_name) 00569 dbus_set_error (error, error_name, 00570 <font class="stringliteral">"Error in section %s at line %d: %s\n"</font>, section_name, parser-><a class="code" href="structBusDesktopFileParser.html#m5">line_num</a>, message); 00571 <font class="keywordflow">else</font> 00572 dbus_set_error (error, error_name, 00573 <font class="stringliteral">"Error at line %d: %s\n"</font>, parser-><a class="code" href="structBusDesktopFileParser.html#m5">line_num</a>, message); 00574 } 00575 00576 <font class="preprocessor">#if 0</font> 00577 <font class="preprocessor"></font><font class="keyword">static</font> <font class="keywordtype">void</font> 00578 dump_desktop_file (BusDesktopFile *file) 00579 { 00580 <font class="keywordtype">int</font> i; 00581 00582 <font class="keywordflow">for</font> (i = 0; i < file->n_sections; i++) 00583 { 00584 <font class="keywordtype">int</font> j; 00585 00586 printf (<font class="stringliteral">"[%s]\n"</font>, file->sections[i].section_name); 00587 00588 <font class="keywordflow">for</font> (j = 0; j < file->sections[i].n_lines; j++) 00589 { 00590 printf (<font class="stringliteral">"%s=%s\n"</font>, file->sections[i].lines[j].key, 00591 file->sections[i].lines[j].value); 00592 } 00593 } 00594 } 00595 <font class="preprocessor">#endif</font> 00596 <font class="preprocessor"></font> 00597 BusDesktopFile* 00598 bus_desktop_file_load (<a class="code" href="structDBusString.html">DBusString</a> *filename, 00599 <a class="code" href="structDBusError.html">DBusError</a> *error) 00600 { 00601 <a class="code" href="structDBusString.html">DBusString</a> str; 00602 <a class="code" href="structBusDesktopFileParser.html">BusDesktopFileParser</a> parser; 00603 <a class="code" href="structDBusStat.html">DBusStat</a> sb; 00604 00605 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00606 00607 <font class="comment">/* Clearly there's a race here, but it's just to make it unlikely</font> 00608 <font class="comment"> * that we do something silly, we still handle doing it below.</font> 00609 <font class="comment"> */</font> 00610 <font class="keywordflow">if</font> (!_dbus_stat (filename, &sb, error)) 00611 <font class="keywordflow">return</font> NULL; 00612 00613 <font class="keywordflow">if</font> (sb.<a class="code" href="structDBusStat.html#m4">size</a> > _DBUS_ONE_KILOBYTE * 128) 00614 { 00615 dbus_set_error (error, DBUS_ERROR_FAILED, 00616 <font class="stringliteral">"Desktop file size (%ld bytes) is too large"</font>, (<font class="keywordtype">long</font>) sb.<a class="code" href="structDBusStat.html#m4">size</a>); 00617 <font class="keywordflow">return</font> NULL; 00618 } 00619 00620 <font class="keywordflow">if</font> (!_dbus_string_init (&str)) 00621 <font class="keywordflow">return</font> NULL; 00622 00623 <font class="keywordflow">if</font> (!_dbus_file_get_contents (&str, filename, error)) 00624 { 00625 _dbus_string_free (&str); 00626 <font class="keywordflow">return</font> NULL; 00627 } 00628 00629 <font class="keywordflow">if</font> (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str))) 00630 { 00631 _dbus_string_free (&str); 00632 dbus_set_error (error, DBUS_ERROR_FAILED, 00633 <font class="stringliteral">"invalid UTF-8"</font>); 00634 <font class="keywordflow">return</font> NULL; 00635 } 00636 00637 parser.<a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a> = dbus_new0 (BusDesktopFile, 1); 00638 <font class="keywordflow">if</font> (parser.<a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a> == NULL) 00639 { 00640 _dbus_string_free (&str); 00641 BUS_SET_OOM (error); 00642 <font class="keywordflow">return</font> NULL; 00643 } 00644 00645 parser.<a class="code" href="structBusDesktopFileParser.html#m0">data</a> = str; 00646 parser.<a class="code" href="structBusDesktopFileParser.html#m5">line_num</a> = 1; 00647 parser.<a class="code" href="structBusDesktopFileParser.html#m3">pos</a> = 0; 00648 parser.<a class="code" href="structBusDesktopFileParser.html#m4">len</a> = _dbus_string_get_length (&parser.<a class="code" href="structBusDesktopFileParser.html#m0">data</a>); 00649 parser.<a class="code" href="structBusDesktopFileParser.html#m2">current_section</a> = -1; 00650 00651 <font class="keywordflow">while</font> (parser.<a class="code" href="structBusDesktopFileParser.html#m3">pos</a> < parser.<a class="code" href="structBusDesktopFileParser.html#m4">len</a>) 00652 { 00653 <font class="keywordflow">if</font> (_dbus_string_get_byte (&parser.<a class="code" href="structBusDesktopFileParser.html#m0">data</a>, parser.<a class="code" href="structBusDesktopFileParser.html#m3">pos</a>) == <font class="charliteral">'['</font>) 00654 { 00655 <font class="keywordflow">if</font> (!parse_section_start (&parser, error)) 00656 { 00657 _dbus_string_free (&parser.<a class="code" href="structBusDesktopFileParser.html#m0">data</a>); 00658 <font class="keywordflow">return</font> NULL; 00659 } 00660 } 00661 <font class="keywordflow">else</font> <font class="keywordflow">if</font> (is_blank_line (&parser) || 00662 _dbus_string_get_byte (&parser.<a class="code" href="structBusDesktopFileParser.html#m0">data</a>, parser.<a class="code" href="structBusDesktopFileParser.html#m3">pos</a>) == <font class="charliteral">'#'</font>) 00663 parse_comment_or_blank (&parser); 00664 <font class="keywordflow">else</font> 00665 { 00666 <font class="keywordflow">if</font> (!parse_key_value (&parser, error)) 00667 { 00668 _dbus_string_free (&parser.<a class="code" href="structBusDesktopFileParser.html#m0">data</a>); 00669 <font class="keywordflow">return</font> NULL; 00670 } 00671 } 00672 } 00673 00674 _dbus_string_free (&parser.<a class="code" href="structBusDesktopFileParser.html#m0">data</a>); 00675 00676 <font class="keywordflow">return</font> parser.<a class="code" href="structBusDesktopFileParser.html#m1">desktop_file</a>; 00677 } 00678 00679 <font class="keyword">static</font> BusDesktopFileSection * 00680 lookup_section (BusDesktopFile *desktop_file, 00681 <font class="keyword">const</font> <font class="keywordtype">char</font> *section_name) 00682 { 00683 BusDesktopFileSection *section; 00684 <font class="keywordtype">int</font> i; 00685 00686 <font class="keywordflow">if</font> (section_name == NULL) 00687 <font class="keywordflow">return</font> NULL; 00688 00689 <font class="keywordflow">for</font> (i = 0; i < desktop_file->n_sections; i ++) 00690 { 00691 section = &desktop_file->sections[i]; 00692 00693 <font class="keywordflow">if</font> (strcmp (section->section_name, section_name) == 0) 00694 <font class="keywordflow">return</font> section; 00695 } 00696 00697 <font class="keywordflow">return</font> NULL; 00698 } 00699 00700 <font class="keyword">static</font> BusDesktopFileLine * 00701 lookup_line (BusDesktopFile *desktop_file, 00702 BusDesktopFileSection *section, 00703 <font class="keyword">const</font> <font class="keywordtype">char</font> *keyname) 00704 { 00705 BusDesktopFileLine *line; 00706 <font class="keywordtype">int</font> i; 00707 00708 <font class="keywordflow">for</font> (i = 0; i < section->n_lines; i++) 00709 { 00710 line = &section->lines[i]; 00711 00712 <font class="keywordflow">if</font> (strcmp (line->key, keyname) == 0) 00713 <font class="keywordflow">return</font> line; 00714 } 00715 00716 <font class="keywordflow">return</font> NULL; 00717 } 00718 00719 dbus_bool_t 00720 bus_desktop_file_get_raw (BusDesktopFile *desktop_file, 00721 <font class="keyword">const</font> <font class="keywordtype">char</font> *section_name, 00722 <font class="keyword">const</font> <font class="keywordtype">char</font> *keyname, 00723 <font class="keyword">const</font> <font class="keywordtype">char</font> **val) 00724 { 00725 BusDesktopFileSection *section; 00726 BusDesktopFileLine *line; 00727 00728 *val = NULL; 00729 00730 section = lookup_section (desktop_file, section_name); 00731 00732 <font class="keywordflow">if</font> (!section) 00733 <font class="keywordflow">return</font> FALSE; 00734 00735 line = lookup_line (desktop_file, 00736 section, 00737 keyname); 00738 00739 <font class="keywordflow">if</font> (!line) 00740 <font class="keywordflow">return</font> FALSE; 00741 00742 *val = line->value; 00743 00744 <font class="keywordflow">return</font> TRUE; 00745 } 00746 00747 dbus_bool_t 00748 bus_desktop_file_get_string (BusDesktopFile *desktop_file, 00749 <font class="keyword">const</font> <font class="keywordtype">char</font> *section, 00750 <font class="keyword">const</font> <font class="keywordtype">char</font> *keyname, 00751 <font class="keywordtype">char</font> **val) 00752 { 00753 <font class="keyword">const</font> <font class="keywordtype">char</font> *raw; 00754 00755 *val = NULL; 00756 00757 <font class="keywordflow">if</font> (!bus_desktop_file_get_raw (desktop_file, section, keyname, &raw)) 00758 <font class="keywordflow">return</font> FALSE; 00759 00760 *val = _dbus_strdup (raw); 00761 00762 <font class="comment">/* FIXME we don't distinguish "key not found" from "out of memory" here,</font> 00763 <font class="comment"> * which is broken.</font> 00764 <font class="comment"> */</font> 00765 <font class="keywordflow">if</font> (*val == NULL) 00766 <font class="keywordflow">return</font> FALSE; 00767 00768 <font class="keywordflow">return</font> TRUE; 00769 } </pre></div><hr><address align="right"><small>Generated on Mon Sep 29 21:31:02 2003 for D-BUS by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border=0 width=110 height=53></a>1.2.15 </small></address> </body> </html>