Disallow certain non-filename characters in Export Text (#13693)

Added control in code for not allowed characters in the filename when saving a
tab.

Closes #13664

(cherry picked from commit 8721573957)
Service-Card-Id: 85487287
Service-Version: 1.15
This commit is contained in:
EliaSchiavon
2022-08-11 22:57:08 +02:00
committed by Dustin Howett
parent 377cc05fb7
commit d1c7ee2c17
3 changed files with 30 additions and 0 deletions

View File

@@ -12,6 +12,7 @@
#include "TerminalPage.h"
#include "Utils.h"
#include "../../types/inc/utils.hpp"
#include "../../inc/til/string.h"
#include <LibraryResources.h>
@@ -392,6 +393,7 @@ namespace winrt::TerminalApp::implementation
THROW_IF_FAILED(dialog->SetDefaultExtension(L"txt"));
// Default to using the tab title as the file name
filename = til::clean_filename(filename);
THROW_IF_FAILED(dialog->SetFileName((filename + L".txt").c_str()));
});
}

View File

@@ -30,6 +30,29 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return visualize_control_codes(std::wstring{ str });
}
_TIL_INLINEPREFIX std::wstring clean_filename(std::wstring str) noexcept
{
static constexpr std::array<bool, 128> filter{ {
// clang-format off
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
0 /* SP */, 0 /* ! */, 1 /* " */, 0 /* # */, 0 /* $ */, 0 /* % */, 0 /* & */, 0 /* ' */, 0 /* ( */, 0 /* ) */, 1 /* * */, 0 /* + */, 0 /* , */, 0 /* - */, 0 /* . */, 1 /* / */,
0 /* 0 */, 0 /* 1 */, 0 /* 2 */, 0 /* 3 */, 0 /* 4 */, 0 /* 5 */, 0 /* 6 */, 0 /* 7 */, 0 /* 8 */, 0 /* 9 */, 1 /* : */, 0 /* ; */, 1 /* < */, 0 /* = */, 1 /* > */, 1 /* ? */,
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */, 0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */, 0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */, 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */, 0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */, 0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */, 1 /* \ */, 0 /* ] */, 0 /* ^ */, 0 /* _ */,
0 /* ` */, 0 /* a */, 0 /* b */, 0 /* c */, 0 /* d */, 0 /* e */, 0 /* f */, 0 /* g */, 0 /* h */, 0 /* i */, 0 /* j */, 0 /* k */, 0 /* l */, 0 /* m */, 0 /* n */, 0 /* o */,
0 /* p */, 0 /* q */, 0 /* r */, 0 /* s */, 0 /* t */, 0 /* u */, 0 /* v */, 0 /* w */, 0 /* x */, 0 /* y */, 0 /* z */, 0 /* { */, 1 /* | */, 0 /* } */, 0 /* ~ */, 0 /* DEL */,
// clang-format on
} };
str.erase(std::remove_if(std::begin(str), std::end(str), [](auto ch) {
// This lookup is branchless: It always checks the filter, but throws
// away the result if ch >= 128. This is faster than using `&&` (branchy).
return til::at(filter, ch & 127) & (ch < 128);
}), str.end());
return str;
}
// std::string_view::starts_with support for C++17.
template<typename T, typename Traits>
constexpr bool starts_with(const std::basic_string_view<T, Traits>& str, const std::basic_string_view<T, Traits>& prefix) noexcept

View File

@@ -169,4 +169,9 @@ class StringTests
VERIFY_ARE_EQUAL("", s);
}
}
TEST_METHOD(CleanPathAndFilename)
{
VERIFY_ARE_EQUAL(LR"(CUsersGeddyMusicAnalog Man)", til::clean_filename(LR"(C:\Users\Geddy\Music\"Analog Man")"));
}
};