Skip to content

Commit

Permalink
Disallow certain non-filename characters in Export Text (#13693)
Browse files Browse the repository at this point in the history
Added control in code for not allowed characters in the filename when saving a
tab.

Closes #13664
  • Loading branch information
Eschivo authored Aug 11, 2022
1 parent a43d502 commit 8721573
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/cascadia/TerminalApp/TabManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "TerminalPage.h"
#include "Utils.h"
#include "../../types/inc/utils.hpp"
#include "../../inc/til/string.h"

#include <LibraryResources.h>

Expand Down Expand Up @@ -433,7 +434,9 @@ namespace winrt::TerminalApp::implementation
THROW_IF_FAILED(dialog->SetDefaultExtension(L"txt"));

// Default to using the tab title as the file name
THROW_IF_FAILED(dialog->SetFileName((control.Title() + L".txt").c_str()));
std::wstring filename{ control.Title() };
filename = til::clean_filename(filename);
THROW_IF_FAILED(dialog->SetFileName((filename + L".txt").c_str()));
});
}
else
Expand Down
23 changes: 23 additions & 0 deletions src/inc/til/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
} };

std::erase_if(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);
});
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
Expand Down

0 comments on commit 8721573

Please sign in to comment.