Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sys.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3/*
4 * System abstraction utility routines
5 *
6 * Authors:
7 * Jon A. Cruz <jon@joncruz.org>
8 *
9 * Copyright (C) 2004-2005 Authors
10 *
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
13
14
15#include <fstream>
16#ifdef _WIN32
17#include <fcntl.h>
18#include <io.h>
19#endif
20
21#include <glib.h>
22#include <glib/gstdio.h>
23#include <glibmm/ustring.h>
24
25#include "preferences.h"
26#include "sys.h"
27
28//#define INK_DUMP_FILENAME_CONV 1
29#undef INK_DUMP_FILENAME_CONV
30
31//#define INK_DUMP_FOPEN 1
32#undef INK_DUMP_FOPEN
33
34extern guint update_in_progress;
35
36
37void Inkscape::IO::dump_fopen_call( char const *utf8name, char const *id )
38{
39#ifdef INK_DUMP_FOPEN
40 Glib::ustring str;
41 for ( int i = 0; utf8name[i]; i++ )
42 {
43 if ( utf8name[i] == '\\' )
44 {
45 str += "\\\\";
46 }
47 else if ( (utf8name[i] >= 0x20) && ((0x0ff & utf8name[i]) <= 0x7f) )
48 {
49 str += utf8name[i];
50 }
51 else
52 {
53 gchar tmp[32];
54 g_snprintf( tmp, sizeof(tmp), "\\x%02x", (0x0ff & utf8name[i]) );
55 str += tmp;
56 }
57 }
58 g_message( "fopen call %s for [%s]", id, str.data() );
59#else
60 (void)utf8name;
61 (void)id;
62#endif
63}
64
72FILE *Inkscape::IO::fopen_utf8name( char const *utf8name, char const *mode )
73{
74 FILE* fp = nullptr;
75
76 if (Glib::ustring( utf8name ) == Glib::ustring("-")) {
77 // user requests to use pipes
78
79 Glib::ustring how( mode );
80 if ( how.find("w") != Glib::ustring::npos ) {
81#ifdef _WIN32
82 setmode(fileno(stdout), O_BINARY);
83#endif
84 return stdout;
85 } else {
86 return stdin;
87 }
88 }
89
90 gchar *filename = g_filename_from_utf8( utf8name, -1, nullptr, nullptr, nullptr );
91 if ( filename )
92 {
93 // ensure we open the file in binary mode (not needed in POSIX but doesn't hurt either)
94 Glib::ustring how( mode );
95 if ( how.find("b") == Glib::ustring::npos )
96 {
97 how.append("b");
98 }
99 // when opening a file for writing: create parent directories if they don't exist already
100 if ( how.find("w") != Glib::ustring::npos )
101 {
102 gchar *dirname = g_path_get_dirname(utf8name);
103 if (g_mkdir_with_parents(dirname, 0777)) {
104 g_warning("Could not create directory '%s'", dirname);
105 }
106 g_free(dirname);
107 }
108 fp = g_fopen(filename, how.c_str());
109 g_free(filename);
110 filename = nullptr;
111 }
112 return fp;
113}
114
115
116bool Inkscape::IO::file_test( char const *utf8name, GFileTest test )
117{
118 bool exists = false;
119
120 // in case the file to check is a pipe it doesn't need to exist
121 if (g_strcmp0(utf8name, "-") == 0 && G_FILE_TEST_IS_REGULAR)
122 return true;
123
124 if ( utf8name ) {
125 gchar *filename = nullptr;
126 if (utf8name && !g_utf8_validate(utf8name, -1, nullptr)) {
127 /* FIXME: Trying to guess whether or not a filename is already in utf8 is unreliable.
128 If any callers pass non-utf8 data (e.g. using g_get_home_dir), then change caller to
129 use simple g_file_test. Then add g_return_val_if_fail(g_utf_validate(...), false)
130 to beginning of this function. */
131 filename = g_strdup(utf8name);
132 // Looks like g_get_home_dir isn't safe.
133 //g_warning("invalid UTF-8 detected internally. HUNT IT DOWN AND KILL IT!!!");
134 } else {
135 filename = g_filename_from_utf8 ( utf8name, -1, nullptr, nullptr, nullptr );
136 }
137 if ( filename ) {
138 exists = g_file_test (filename, test);
139 g_free(filename);
140 filename = nullptr;
141 } else {
142 g_warning( "Unable to convert filename in IO:file_test" );
143 }
144 }
145
146 return exists;
147}
148
149bool Inkscape::IO::file_is_writable( char const *utf8name)
150{
151 bool success = true;
152
153 if ( utf8name) {
154 gchar *filename = nullptr;
155 if (utf8name && !g_utf8_validate(utf8name, -1, nullptr)) {
156 /* FIXME: Trying to guess whether or not a filename is already in utf8 is unreliable.
157 If any callers pass non-utf8 data (e.g. using g_get_home_dir), then change caller to
158 use simple g_file_test. Then add g_return_val_if_fail(g_utf_validate(...), false)
159 to beginning of this function. */
160 filename = g_strdup(utf8name);
161 // Looks like g_get_home_dir isn't safe.
162 //g_warning("invalid UTF-8 detected internally. HUNT IT DOWN AND KILL IT!!!");
163 } else {
164 filename = g_filename_from_utf8 ( utf8name, -1, nullptr, nullptr, nullptr );
165 }
166 if ( filename ) {
167 GStatBuf st;
168 if (g_file_test (filename, G_FILE_TEST_EXISTS)){
169 if (g_lstat (filename, &st) == 0) {
170 success = ((st.st_mode & S_IWRITE) != 0);
171 }
172 }
173 g_free(filename);
174 filename = nullptr;
175 } else {
176 g_warning( "Unable to convert filename in IO:file_test" );
177 }
178 }
179
180 return success;
181}
182
183Glib::ustring Inkscape::IO::sanitizeString(char const *str)
184{
185 if (!str) {
186 return {};
187 }
188
189 if (g_utf8_validate(str, -1, nullptr)) {
190 return str;
191 }
192
193 Glib::ustring result;
194
195 for (auto p = str; *p != '\0'; p++) {
196 if (*p == '\\') {
197 result += "\\\\";
198 } else if (*p >= 0) {
199 result += *p;
200 } else {
201 char buf[8];
202 g_snprintf(buf, sizeof(buf), "\\x%02x", unsigned{static_cast<unsigned char>(*p)});
203 result += buf;
204 }
205 }
206
207 return result;
208}
209
210/*
211 * Returns the file extension of a path/filename. Don't use this one unless for display.
212 * Used by src/extension/internal/odf.cpp, src/extension/output.cpp. TODO Remove!
213 */
214Glib::ustring Inkscape::IO::get_file_extension(Glib::ustring const &path)
215{
216 auto loc = path.find_last_of(".");
217 return loc < path.size() ? path.substr(loc) : "";
218}
219
220/*
221 * Returns the file extension of a path/filename. Use this one for filenames.
222 * Used by src/extension/effect.cpp, src/io/file-export-cmd.cpp, etc.
223 */
224std::string Inkscape::IO::get_file_extension(std::string const &path)
225{
226 auto loc = path.find_last_of(".");
227 return loc < path.size() ? path.substr(loc) : "";
228}
229
234{
235 auto ext = Inkscape::IO::get_file_extension(path);
236 if (!ext.empty()) {
237 path.erase(path.size() - ext.size());
238 }
239}
240
241/*
242 Local Variables:
243 mode:c++
244 c-file-style:"stroustrup"
245 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
246 indent-tabs-mode:nil
247 fill-column:99
248 End:
249*/
250// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
int test()
Definition 2junctions.cpp:5
Css & result
Glib::ustring get_file_extension(Glib::ustring const &path)
Definition sys.cpp:214
Glib::ustring sanitizeString(char const *str)
Definition sys.cpp:183
bool file_test(char const *utf8name, GFileTest test)
Definition sys.cpp:116
bool file_is_writable(char const *utf8name)
Definition sys.cpp:149
void remove_file_extension(std::string &path)
Removes a file extension, if found, from the given path.
Definition sys.cpp:233
void dump_fopen_call(char const *utf8name, char const *id)
Definition sys.cpp:37
FILE * fopen_utf8name(char const *utf8name, char const *mode)
Open a file with g_fopen().
Definition sys.cpp:72
int mode
int buf
Singleton class to access the preferences file in a convenient way.
guint update_in_progress