filename | src/lxpaths.c |
changeset | 1283:2cbafe321d6f |
prev | 1205:a486ac64f34b |
next | 1286:8376a612a79d |
author | nkeynes |
date | Tue Mar 27 17:39:05 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Treat quotes as entering a double-quoted string (mostly redundant, but we generate them in the path escaping for some reason) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * GUI helper functions that aren't specific to any particular implementation.
5 *
6 * Copyright (c) 2009 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include <ctype.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <glib/gstrfuncs.h>
23 #include <glib/gutils.h>
25 #include "gui.h"
26 #include "config.h"
28 static gchar *gui_paths[CONFIG_KEY_MAX];
30 /**
31 * Test if we need to escape a path to prevent substitution mangling.
32 * @return TRUE if the input value contains any character that doesn't
33 * match [a-zA-Z0-9._@%/] (this will escape slightly more than it needs to,
34 * but is safe)
35 */
36 static gboolean path_needs_escaping( const gchar *value )
37 {
38 const gchar *p = value;
39 while( *p ) {
40 if( !isalnum(*p) && *p != '.' && *p != '_' &&
41 *p != '@' && *p != '%' && *p != '/' ) {
42 return TRUE;
43 }
44 p++;
45 }
46 return FALSE;
47 }
49 gchar *get_escaped_path( const gchar *value )
50 {
51 if( value != NULL && path_needs_escaping(value) ) {
52 /* Escape with "", and backslash the remaining characters:
53 * \ " $ `
54 */
55 char buf[strlen(value)*2+3];
56 const char *s = value;
57 char *p = buf;
58 *p++ = '\"';
59 while( *s ) {
60 if( *s == '\\' || *s == '"' || *s == '$' || *s == '`' ) {
61 *p++ = '\\';
62 }
63 *p++ = *s++;
64 }
65 *p++ = '\"';
66 *p = '\0';
67 return g_strdup(buf);
68 } else {
69 return g_strdup(value);
70 }
71 }
73 gchar *get_expanded_path( const gchar *input )
74 {
75 char result[PATH_MAX];
77 char *d, *e;
78 const char *s;
79 d = result;
80 e = result+sizeof(result)-1;
81 s = input;
82 gboolean inDQstring = FALSE;
84 if( input == NULL )
85 return NULL;
87 while( *s ) {
88 if( d == e ) {
89 return g_strdup(input); /* expansion too long */
90 }
91 char c = *s++;
92 if( c == '$' ) {
93 if( *s == '{' ) {
94 s++;
95 const char *q = s;
96 while( *q != '}' ) {
97 if( ! *q ) {
98 return g_strdup(input); /* unterminated variable */
99 }
100 q++;
101 }
102 char *tmp = g_strndup(s, (q-s));
103 s = q+1;
104 char *value = getenv(tmp);
105 g_free(tmp);
106 if( value != NULL ) {
107 int len = strlen(value);
108 if( d + len > e )
109 return g_strdup(input);
110 strcpy(d, value);
111 d+=len;
112 } /* Else, empty string */
113 } else {
114 const char *q = s;
115 while( isalnum(*q) || *q == '_' ) {
116 q++;
117 }
118 if( q == s ) {
119 *d++ = '$';
120 } else {
121 char *tmp = g_strndup(s,q-s);
122 s = q;
123 char *value = getenv(tmp);
124 g_free(tmp);
125 if( value != NULL ) {
126 int len = strlen(value);
127 if( d + len > e )
128 return g_strdup(input);
129 strcpy(d, value);
130 d += len;
131 }
132 }
133 }
134 } else if( c == '\\' ) {
135 c = *s++;
136 if( c ) {
137 *d++ = c;
138 } else {
139 *d++ = '\\';
140 }
141 } else if( c == '\"' ) {
142 /* Unescaped double-quotes start a DQ string. Although we treat the
143 * string as if it were double-quoted for most purposes anyway, so
144 * this has little effect.
145 */
146 inDQstring = !inDQstring;
147 } else {
148 *d++ = c;
149 }
150 }
151 *d = '\0';
152 if( inDQstring ) {
153 WARN( "Unterminated double-quoted string '%s'", input );
154 }
155 return g_strdup(result);
156 }
157 gchar *get_absolute_path( const gchar *in_path )
158 {
159 char tmp[PATH_MAX];
160 if( in_path == NULL ) {
161 return NULL;
162 }
163 if( in_path[0] == '/' || in_path[0] == 0 ) {
164 return g_strdup(in_path);
165 } else {
166 getcwd(tmp, sizeof(tmp));
167 return g_strdup_printf("%s%c%s", tmp, G_DIR_SEPARATOR, in_path);
168 }
169 }
171 gchar *get_filename_at( const gchar *at, const gchar *filename )
172 {
173 char tmp[PATH_MAX];
174 char *p = strrchr( at, '/' );
175 if( p == NULL ) {
176 /* No path at all, so just return filename */
177 return g_strdup(filename);
178 } else {
179 int off = p-at;
180 return g_strdup_printf("%.*s%c%s", off, at, G_DIR_SEPARATOR, filename );
181 }
182 }
184 const gchar *get_gui_path( int key )
185 {
186 if( gui_paths[key] == NULL ) {
187 gui_paths[key] = lxdream_get_global_config_path_value(key);
188 /* If no path defined, go with the current working directory */
189 if( gui_paths[key] == NULL ) {
190 gui_paths[key] = get_absolute_path(".");
191 }
192 }
193 return gui_paths[key];
194 }
196 void set_gui_path( int key, const gchar *path )
197 {
198 g_free(gui_paths[key]);
199 gui_paths[key] = g_strdup(path);
200 }
202 void reset_gui_paths()
203 {
204 int i;
205 for( i=0; i < CONFIG_KEY_MAX; i++ ) {
206 g_free(gui_paths[i]);
207 gui_paths[i] = NULL;
208 }
209 }
.