Merge lp:~widelands-dev/widelands/bug-1588063 into lp:widelands

Proposed by Tino
Status: Merged
Merged at revision: 8051
Proposed branch: lp:~widelands-dev/widelands/bug-1588063
Merge into: lp:widelands
Diff against target: 182 lines (+48/-12)
7 files modified
src/editor/ui_menus/main_menu_save_map.cc (+9/-3)
src/editor/ui_menus/main_menu_save_map_make_directory.cc (+3/-1)
src/io/filesystem/disk_filesystem.cc (+14/-6)
src/io/filesystem/layered_filesystem.cc (+15/-0)
src/io/filesystem/layered_filesystem.h (+2/-0)
src/logic/save_handler.cc (+3/-1)
src/wui/game_main_menu_save_game.cc (+2/-1)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-1588063
Reviewer Review Type Date Requested Status
Tino Approve
GunChleoc Needs Resubmitting
Klaus Halfmann compile, review, test Approve
Review via email: mp+301636@code.launchpad.net

Commit message

Fix automatic creation of the maps/My_Maps folder in Windows. Prevent the user from entering illegal filenames.

Description of the change

Use system dependant file seperator for the My_Maps subdirectory.
Now ensure_directory_exists() does work also on win32.

I don't like the #ifdef __win32 solution, but i was not able to FileSystem::file_separator() because i lack c++ knowledge to concatenate char/char*/char[].

Suggestions welcome.

To post a comment you must log in.
Revision history for this message
GunChleoc (gunchleoc) wrote :

Ah, bl*** file separators, my bad.

I will look into concatenating this properly.

Revision history for this message
Tino (tino79) wrote :

Found another bug in the current state of implementation: https://bugs.launchpad.net/widelands/+bug/1608558

review: Needs Fixing
Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1222. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/148893466.
Appveyor build 1064. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1588063-1064.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1222. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/148893466.
Appveyor build 1064. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1588063-1064.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

The read operation timed out

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1222. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/148893466.
Appveyor build 1064. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1588063-1064.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

<urlopen error timed out>

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1222. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/148893466.
Appveyor build 1064. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1588063-1064.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1229. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/149710458.
Appveyor build 1071. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1588063-1071.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1229. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/149710458.
Appveyor build 1071. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1588063-1071.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

The read operation timed out

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1231. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/149798427.
Appveyor build 1073. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1588063-1073.

Revision history for this message
Klaus Halfmann (klaus-halfmann) wrote :

Testing on OSX:

* removed .widelands folder
* :bug-1588063$ ./widelands --editor
* Created some random map and saved it
* found ./widelands/maps/My_Maps, OK
* Copied some selfmade map into ./widelands/maps
ls -R maps
Crossriver.wmf My_Maps

maps/My_Maps:
Test1608558.wmf

* I can open Crossriver.wmf in the Editor, is merged into the list of Maps.

I now will restore my old .widelands folder an try some evil characters

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1236. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/149854580.
Appveyor build 1078. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1588063-1078.

Revision history for this message
Klaus Halfmann (klaus-halfmann) wrote :

OK, Tested some "evil" charaters. On OSX '`´&$()[]{} are allowed while |/":* are not (incomplete).

Maybe we should filter these as well, to avoid Filenames with bad effects on the Commandline?
OTOH the average user will not not use such characters, will he/she?

Code LGTM, but I can test OSX only, so we need some Windows test, too.

review: Approve (compile, review, test)
Revision history for this message
GunChleoc (gunchleoc) wrote :

I have decided to only filter out the characters that can lead to potential crashes, not the "inconvenient" ones that look confusing on the command line (like e.g. $).

I have tested on Windows and all should be fine now - both bugs fixed.

review: Needs Resubmitting
Revision history for this message
Tino (tino79) wrote :

Nice, thanks Gun.

I can compile fine and do not find those bugs active any longer.

@bunnybot merge

review: Approve
Revision history for this message
GunChleoc (gunchleoc) wrote :

*happy* Thanks for testing, everyone!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc 2016-08-04 15:49:05 +0000
+++ src/editor/ui_menus/main_menu_save_map.cc 2016-08-04 19:19:13 +0000
@@ -155,8 +155,10 @@
155 MainMenuSaveMapMakeDirectory md(this, _("unnamed"));155 MainMenuSaveMapMakeDirectory md(this, _("unnamed"));
156 if (md.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kOk) {156 if (md.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kOk) {
157 g_fs->ensure_directory_exists(curdir_);157 g_fs->ensure_directory_exists(curdir_);
158 // create directory158 // Create directory.
159 std::string fullname = curdir_ + g_fs->file_separator() + md.get_dirname();159 std::string fullname = curdir_ + g_fs->file_separator() + md.get_dirname();
160 // Trim it for preceding/trailing whitespaces in user input
161 boost::trim(fullname);
160 g_fs->make_directory(fullname);162 g_fs->make_directory(fullname);
161 fill_table();163 fill_table();
162 }164 }
@@ -215,7 +217,8 @@
215 * The editbox was changed. Enable ok button217 * The editbox was changed. Enable ok button
216 */218 */
217void MainMenuSaveMap::edit_box_changed() {219void MainMenuSaveMap::edit_box_changed() {
218 ok_.set_enabled(!editbox_->text().empty());220 // Prevent the user from creating nonsense file names, like e.g. ".." or "...".
221 ok_.set_enabled(LayeredFileSystem::is_legal_filename(editbox_->text()));
219}222}
220223
221void MainMenuSaveMap::set_current_directory(const std::string& filename) {224void MainMenuSaveMap::set_current_directory(const std::string& filename) {
@@ -237,11 +240,14 @@
237 // Make sure that the current directory exists and is writeable.240 // Make sure that the current directory exists and is writeable.
238 g_fs->ensure_directory_exists(curdir_);241 g_fs->ensure_directory_exists(curdir_);
239242
243 // Trim it for preceding/trailing whitespaces in user input
244 boost::trim(filename);
245
240 // OK, first check if the extension matches (ignoring case).246 // OK, first check if the extension matches (ignoring case).
241 if (!boost::iends_with(filename, WLMF_SUFFIX))247 if (!boost::iends_with(filename, WLMF_SUFFIX))
242 filename += WLMF_SUFFIX;248 filename += WLMF_SUFFIX;
243249
244 // append directory name250 // Append directory name.
245 const std::string complete_filename = curdir_ + g_fs->file_separator() + filename;251 const std::string complete_filename = curdir_ + g_fs->file_separator() + filename;
246252
247 // Check if file exists. If so, show a warning.253 // Check if file exists. If so, show a warning.
248254
=== modified file 'src/editor/ui_menus/main_menu_save_map_make_directory.cc'
--- src/editor/ui_menus/main_menu_save_map_make_directory.cc 2016-08-04 15:49:05 +0000
+++ src/editor/ui_menus/main_menu_save_map_make_directory.cc 2016-08-04 19:19:13 +0000
@@ -22,6 +22,7 @@
22#include "base/i18n.h"22#include "base/i18n.h"
23#include "graphic/font_handler1.h"23#include "graphic/font_handler1.h"
24#include "graphic/graphic.h"24#include "graphic/graphic.h"
25#include "io/filesystem/layered_filesystem.h"
2526
26MainMenuSaveMapMakeDirectory::MainMenuSaveMapMakeDirectory(UI::Panel* const parent,27MainMenuSaveMapMakeDirectory::MainMenuSaveMapMakeDirectory(UI::Panel* const parent,
27 char const* dirname)28 char const* dirname)
@@ -91,6 +92,7 @@
91 */92 */
92void MainMenuSaveMapMakeDirectory::edit_changed() {93void MainMenuSaveMapMakeDirectory::edit_changed() {
93 const std::string& text = edit_.text();94 const std::string& text = edit_.text();
94 ok_button_.set_enabled(!text.empty());95 // Prevent the user from creating nonsense directory names, like e.g. ".." or "...".
96 ok_button_.set_enabled(LayeredFileSystem::is_legal_filename(text));
95 dirname_ = text;97 dirname_ = text;
96}98}
9799
=== modified file 'src/io/filesystem/disk_filesystem.cc'
--- src/io/filesystem/disk_filesystem.cc 2016-08-04 15:49:05 +0000
+++ src/io/filesystem/disk_filesystem.cc 2016-08-04 19:19:13 +0000
@@ -297,17 +297,25 @@
297 * if the dir can't be created or if a file with this name exists297 * if the dir can't be created or if a file with this name exists
298 */298 */
299void RealFSImpl::ensure_directory_exists(const std::string& dirname) {299void RealFSImpl::ensure_directory_exists(const std::string& dirname) {
300 std::string clean_dirname = dirname;
301#ifdef _WIN32
302 // Make sure we always use "/" for splitting the directory, because
303 // directory names might be hardcoded in C++ or come from the file system.
304 // Calling canonicalize_name will take care of this working for all file systems.
305 boost::replace_all(clean_dirname, "\\", "/");
306#endif
307
300 try {308 try {
301 std::string::size_type it = 0;309 std::string::size_type it = 0;
302 while (it < dirname.size()) {310 while (it < clean_dirname.size()) {
303 it = dirname.find(file_separator(), it);311 it = clean_dirname.find('/', it);
304312
305 FileSystemPath fspath(canonicalize_name(dirname.substr(0, it)));313 FileSystemPath fspath(canonicalize_name(clean_dirname.substr(0, it)));
306 if (fspath.exists_ && !fspath.is_directory_)314 if (fspath.exists_ && !fspath.is_directory_)
307 throw wexception("'%s' in directory '%s' exists and is not a directory",315 throw wexception("'%s' in directory '%s' exists and is not a directory",
308 dirname.substr(0, it).c_str(), directory_.c_str());316 clean_dirname.substr(0, it).c_str(), directory_.c_str());
309 if (!fspath.exists_)317 if (!fspath.exists_)
310 make_directory(dirname.substr(0, it));318 make_directory(clean_dirname.substr(0, it));
311319
312 if (it == std::string::npos)320 if (it == std::string::npos)
313 break;321 break;
@@ -315,7 +323,7 @@
315 }323 }
316 } catch (const std::exception& e) {324 } catch (const std::exception& e) {
317 throw wexception("RealFSImpl::ensure_directory_exists(%s) in directory '%s': %s",325 throw wexception("RealFSImpl::ensure_directory_exists(%s) in directory '%s': %s",
318 dirname.c_str(), directory_.c_str(), e.what());326 clean_dirname.c_str(), directory_.c_str(), e.what());
319 }327 }
320}328}
321329
322330
=== modified file 'src/io/filesystem/layered_filesystem.cc'
--- src/io/filesystem/layered_filesystem.cc 2016-08-04 15:49:05 +0000
+++ src/io/filesystem/layered_filesystem.cc 2016-08-04 19:19:13 +0000
@@ -22,6 +22,9 @@
22#include <cstdio>22#include <cstdio>
23#include <memory>23#include <memory>
2424
25#include <boost/algorithm/string/predicate.hpp>
26#include <boost/regex.hpp>
27
25#include "base/log.h"28#include "base/log.h"
26#include "base/wexception.h"29#include "base/wexception.h"
27#include "io/fileread.h"30#include "io/fileread.h"
@@ -38,6 +41,18 @@
38LayeredFileSystem::~LayeredFileSystem() {41LayeredFileSystem::~LayeredFileSystem() {
39}42}
4043
44bool LayeredFileSystem::is_legal_filename(const std::string& filename) {
45 // No potential file separators or other potentially illegal characters
46 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
47 // http://www.linfo.org/file_name.html
48 // https://support.apple.com/en-us/HT202808
49 // We can't just regex for word & digit characters here because of non-Latin scripts.
50 boost::regex re(".*[<>:\"|?*/\\\\].*");
51 return !filename.empty() && !boost::starts_with(filename, ".") &&
52 !boost::starts_with(filename, " ") && !boost::starts_with(filename, "-") &&
53 !boost::regex_match(filename, re);
54}
55
41/**56/**
42 * Just assume that at least one of our child FSs is writable57 * Just assume that at least one of our child FSs is writable
43 */58 */
4459
=== modified file 'src/io/filesystem/layered_filesystem.h'
--- src/io/filesystem/layered_filesystem.h 2016-08-04 15:49:05 +0000
+++ src/io/filesystem/layered_filesystem.h 2016-08-04 19:19:13 +0000
@@ -60,6 +60,8 @@
6060
61 std::set<std::string> list_directory(const std::string& path) override;61 std::set<std::string> list_directory(const std::string& path) override;
6262
63 /// Returns true if the filename is legal in all operating systems
64 static bool is_legal_filename(const std::string& filename);
63 bool is_writable() const override;65 bool is_writable() const override;
64 bool file_exists(const std::string& path) override;66 bool file_exists(const std::string& path) override;
65 bool is_directory(const std::string& path) override;67 bool is_directory(const std::string& path) override;
6668
=== modified file 'src/logic/save_handler.cc'
--- src/logic/save_handler.cc 2016-08-04 15:49:05 +0000
+++ src/logic/save_handler.cc 2016-08-04 19:19:13 +0000
@@ -174,8 +174,10 @@
174 */174 */
175std::string SaveHandler::create_file_name(const std::string& dir,175std::string SaveHandler::create_file_name(const std::string& dir,
176 const std::string& filename) const {176 const std::string& filename) const {
177 // Append directory name177 // Append directory name.
178 std::string complete_filename = dir + g_fs->file_separator() + filename;178 std::string complete_filename = dir + g_fs->file_separator() + filename;
179 // Trim it for preceding/trailing whitespaces in user input
180 boost::trim(complete_filename);
179181
180 // Now check if the extension matches (ignoring case)182 // Now check if the extension matches (ignoring case)
181 if (!boost::iends_with(filename, WLGF_SUFFIX)) {183 if (!boost::iends_with(filename, WLGF_SUFFIX)) {
182184
=== modified file 'src/wui/game_main_menu_save_game.cc'
--- src/wui/game_main_menu_save_game.cc 2016-08-04 15:49:05 +0000
+++ src/wui/game_main_menu_save_game.cc 2016-08-04 19:19:13 +0000
@@ -207,7 +207,8 @@
207 * The editbox was changed. Enable ok button207 * The editbox was changed. Enable ok button
208 */208 */
209void GameMainMenuSaveGame::edit_box_changed() {209void GameMainMenuSaveGame::edit_box_changed() {
210 button_ok_->set_enabled(editbox_.text().size());210 // Prevent the user from creating nonsense directory names, like e.g. ".." or "...".
211 button_ok_->set_enabled(LayeredFileSystem::is_legal_filename(editbox_.text()));
211}212}
212213
213static void dosave(InteractiveGameBase& igbase, const std::string& complete_filename) {214static void dosave(InteractiveGameBase& igbase, const std::string& complete_filename) {

Subscribers

People subscribed via source and target branches

to status/vote changes: