Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2015-07-14 19:42:22 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2015-07-14 19:57:38 +0300
commitd7b9202567199cb769305d4037eefbba71dda3f9 (patch)
tree6bd69218d728e9e85762d8e3183a8431010ea349
parentd0c5eac4b7e5dc3173ee354f6f0afdd0d1e078dc (diff)
BLI_path_utils: fix/enhance BLI_filename_make_safe(), add BLI_path_make_safe().
BLI_filename_make_safe had several issues: * Would replace all dots ('.'), not a great idea since it would break extensions. * Was not checking for 'control' ASCII chars (though unlikely, better to be safe here). * Win32 only: was not checking for forbidden names (con, aux, ltp0, com0, etc.). New BLI_path_make_safe() simply checks each path's item with BLI_filename_make_safe().
-rw-r--r--source/blender/blenlib/BLI_path_util.h3
-rw-r--r--source/blender/blenlib/intern/path_util.c122
2 files changed, 120 insertions, 5 deletions
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 63b5207f941..a344c9d2bc1 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -112,7 +112,8 @@ void BLI_cleanup_dir(const char *relabase, char *dir) ATTR_NONNULL(2);
/* doesn't touch trailing slash */
void BLI_cleanup_path(const char *relabase, char *path) ATTR_NONNULL(2);
-void BLI_filename_make_safe(char *fname) ATTR_NONNULL(1);
+bool BLI_filename_make_safe(char *fname) ATTR_NONNULL(1);
+bool BLI_path_make_safe(char *path) ATTR_NONNULL(1);
/* go back one directory */
bool BLI_parent_dir(char *path) ATTR_NONNULL();
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index c1f6cc4b49a..3a73d4cc0c7 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -56,15 +56,25 @@
# include <windows.h>
# include <shlobj.h>
# include "BLI_winstuff.h"
-# include "MEM_guardedalloc.h"
# include "BLI_alloca.h"
#else
# include "unistd.h"
#endif /* WIN32 */
+#include "MEM_guardedalloc.h"
+
/* local */
#define UNIQUE_NAME_MAX 128
+/* Declarations */
+
+#ifdef WIN32
+
+/* return true if the path is absolute ie starts with a drive specifier (eg A:\) or is a UNC path */
+static bool BLI_path_is_abs(const char *name);
+
+#endif /* WIN32 */
+
/* implementation */
/**
@@ -435,17 +445,121 @@ void BLI_cleanup_file(const char *relabase, char *path)
/**
* Make given name safe to be used in paths.
*
+ * \return true if \a fname was changed, false otherwise.
+ *
* For now, simply replaces reserved chars (as listed in
* http://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words )
* by underscores ('_').
+ *
+ * \note Space case ' ' is a bit of an edge case here - in theory it is allowed, but again can be an issue
+ * in some cases, so we simply replace it by an underscore too (good practice anyway).
+ *
+ * \note On Windows, it also ensures there is no '.' (dot char) at the end of the file, this can lead to issues...
+ *
+ * \note On Windows, it also checks for forbidden names
+ * (see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx ).
*/
-void BLI_filename_make_safe(char *fname)
+bool BLI_filename_make_safe(char *fname)
{
- const char *invalid = "/\\?%*:|\"<>. ";
+ const char *invalid = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "/\\?%*:|\"<> ";
+ char *fn;
+ bool changed = false;
+
+ if (*fname == '\0') {
+ return changed;
+ }
- for (; *fname && (fname = strpbrk(fname, invalid)); fname++) {
+ for (fn = fname; *fn && (fn = strpbrk(fn, invalid)); fn++) {
+ *fn = '_';
+ changed = true;
+ }
+
+ /* Forbid only dots. */
+ for (fn = fname; *fn == '.'; fn++);
+ if (*fn == '\0') {
*fname = '_';
+ changed = true;
}
+
+#ifdef WIN32
+ {
+ const size_t len = strlen(fname);
+ const char *invalid_names[] = {
+ "con", "prn", "aux", "null",
+ "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
+ "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
+ NULL
+ };
+ char *lower_fname = BLI_strdup(fname);
+ const char **iname;
+
+ /* Forbid trailing dot (trailing space has already been replaced above). */
+ if (fname[len - 1] == '.') {
+ fname[len - 1] = '_';
+ changed = true;
+ }
+
+ /* Check for forbidden names - not we have to check all combination of upper and lower cases, hence the usage
+ * of lower_fname (more efficient than using BLI_strcasestr repeatedly). */
+ BLI_str_tolower_ascii(lower_fname, len);
+ for (iname = invalid_names; *iname; iname++) {
+ if (strstr(lower_fname, *iname) == lower_fname) {
+ const size_t iname_len = strlen(*iname);
+ /* Only invalid if the whole name is made of the invalid chunk, or it has an (assumed extension) dot
+ * just after. This means it will also catch 'valid' names like 'aux.foo.bar', but should be
+ * good enough for us! */
+ if ((iname_len == len) || (lower_fname[iname_len] == '.')) {
+ *fname = '_';
+ changed = true;
+ break;
+ }
+ }
+ }
+
+ MEM_freeN(lower_fname);
+ }
+#endif
+
+ return changed;
+}
+
+/**
+ * Make given path OS-safe.
+ *
+ * \return true if \a path was changed, false otherwise.
+ */
+bool BLI_path_make_safe(char *path)
+{
+ /* Simply apply BLI_filename_make_safe() over each component of the path.
+ * Luckily enough, same 'sfae' rules applies to filenames and dirnames. */
+ char *curr_slash, *curr_path = path;
+ bool changed = false;
+ bool skip_first = false;
+
+#ifdef WIN32
+ if (BLI_path_is_abs(path)) {
+ /* Do not make safe 'C:' in 'C:\foo\bar'... */
+ skip_first = true;
+ }
+#endif
+
+ for (curr_slash = (char *)BLI_first_slash(curr_path); curr_slash; curr_slash = (char *)BLI_first_slash(curr_path)) {
+ const char backup = *curr_slash;
+ *curr_slash = '\0';
+ if (!skip_first && (*curr_path != '\0') && BLI_filename_make_safe(curr_path)) {
+ changed = true;
+ }
+ skip_first = false;
+ curr_path = curr_slash + 1;
+ *curr_slash = backup;
+ }
+ if (BLI_filename_make_safe(curr_path)) {
+ changed = true;
+ }
+
+ return changed;
}
/**