Skip to content

Commit

Permalink
Merge pull request #1449 from berryzplus/feature/add_check_invalid_fi…
Browse files Browse the repository at this point in the history
…lename_chars

ファイルパスに「ファイルに使えない文字」を含めた場合の処理を改善する
  • Loading branch information
berryzplus authored Nov 1, 2020
2 parents e54a074 + 85f29b9 commit 8acb720
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 15 deletions.
23 changes: 8 additions & 15 deletions sakura_core/_main/CCommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,21 +315,14 @@ void CCommandLine::ParseCommandLine( LPCWSTR pszCmdLineSrc, bool bResponse )
if (wcsncmp_literal(szPath, L"file:///")==0) {
wcscpy(szPath, &(szPath[8]));
}
int len = wcslen(szPath);
for (int i = 0; i < len ; ) {
if ( !TCODE::IsValidFilenameChar(szPath[i]) ){
WCHAR msg_str[_MAX_PATH + 1];
swprintf(
msg_str, _countof(msg_str),
LS(STR_CMDLINE_PARSECMD1),
szPath
);
MessageBox( NULL, msg_str, L"FileNameError", MB_OK);
szPath[0] = L'\0';
break;
}
int nChars = t_max(1, int(CNativeW::GetCharNext( szPath, len, szPath + i ) - (szPath + i)));
i += nChars;

if ( IsInvalidFilenameChars( szPath ) ){
std::wstring msg;
// "%ls\r\n上記のファイル名は不正です。ファイル名に \\ / : * ? "" < > | の文字は使えません。 "
strprintf( msg, LS(STR_CMDLINE_PARSECMD1), szPath );
const WCHAR* msg_str = msg.c_str();
MessageBox( NULL, msg_str, L"FileNameError", MB_OK);
szPath[0] = L'\0';
}

if (szPath[0] != L'\0') {
Expand Down
20 changes: 20 additions & 0 deletions sakura_core/util/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ bool fexist(LPCWSTR pszPath)
return _waccess(pszPath,0)!=-1;
}


/*!
* パスがファイル名に使えない文字を含んでいるかチェックする
* @param[in] strPath チェック対象のパス
* @retval true パスはファイル名に使えない文字を含んでいる
* retuval false パスはファイル名に使えない文字を含んでいない
*/
bool IsInvalidFilenameChars( const std::wstring_view& strPath )
{
// ファイル名に使えない文字
constexpr const wchar_t invalidFilenameChars[] = L":*?\"<>|";

// 文字列中の最後のパス区切り位置を検出してファイル名を抽出する
const auto lastPathSep = strPath.find_last_of( L"\\/" );
const auto strFilename = lastPathSep == std::wstring_view::npos ? strPath : strPath.substr( lastPathSep + 1 );

// ファイル名に使えない文字が含まれる場合、trueを返す
return ::wcscspn( strFilename.data(), invalidFilenameChars ) < strFilename.length();
}

/*! ファイル名の切り出し
指定文字列からファイル名と認識される文字列を取り出し、
Expand Down
4 changes: 4 additions & 0 deletions sakura_core/util/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@
#define SAKURA_FILE_FE33056B_6B48_4668_AE95_923EC960A607_H_
#pragma once

#include <string>

bool fexist(LPCWSTR pszPath); //!< ファイルまたはディレクトリが存在すればtrue

bool IsFilePath( const wchar_t* pLine, size_t* pnBgn, size_t* pnPathLen, bool bFileOnly = true );
bool IsFileExists(const WCHAR* path, bool bFileOnly = false);
bool IsDirectory(LPCWSTR pszPath); // 2009.08.20 ryoji

bool IsInvalidFilenameChars( const std::wstring_view& strPath );

// Apr. 30, 2003 genta
// ディレクトリの深さを調べる
int CalcDirectoryDepth(const WCHAR* path);
Expand Down
28 changes: 28 additions & 0 deletions tests/unittests/test-ccommandline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -842,3 +842,31 @@ TEST(CCommandLine, EndOfOptionMark)
cCommandLine.ParseCommandLine(L"-- -GROUP=2", false);
EXPECT_EQ(-1, cCommandLine.GetGroupId());
}

/*!
* @brief ファイルパスに「ファイルに使えない文字」を含めた場合の仕様
* @remark 無視される
*/
TEST(CCommandLine, ParseFileNameIncludesInvalidFilenameChars)
{
// ファイル名に使えない文字 = "\\/:*?\"<>|"
// このうち、\\と/はパス区切りのため実質対象外になる。
const std::wstring_view badNames[] = {
L"localhost:8080",
L"test*.txt",
L"test?.txt",
L"test\".txt",
L"test<.txt",
L"test>.txt",
L"test|.txt",
};

// ファイル名に使えない文字を含んでいたら、ファイル名としては認識されない。
CCommandLineWrapper cCommandLine;
for (const auto& badName : badNames) {
cCommandLine.ParseCommandLine( badName.data(), false );
EXPECT_STREQ(L"", cCommandLine.GetOpenFile());
EXPECT_EQ(NULL, cCommandLine.GetFileName(0));
EXPECT_EQ(0, cCommandLine.GetFileNum());
}
}
59 changes: 59 additions & 0 deletions tests/unittests/test-file.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*! @file */
/*
Copyright (C) 2018-2020 Sakura Editor Organization
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but is
not required.
2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <gtest/gtest.h>

#ifndef NOMINMAX
#define NOMINMAX
#endif /* #ifndef NOMINMAX */

#include <tchar.h>
#include <Windows.h>
#include <Shlwapi.h>

#include "util/file.h"

/*!
* @brief パスがファイル名に使えない文字を含んでいるかチェックする
*/
TEST( file, IsInvalidFilenameChars )
{
// ファイル名に使えない文字 = "\\/:*?\"<>|"
// このうち、\\と/はパス区切りのため実質対象外になる。
EXPECT_FALSE(IsInvalidFilenameChars(L"test.txt"));
EXPECT_FALSE(IsInvalidFilenameChars(L".\\test.txt"));
EXPECT_FALSE(IsInvalidFilenameChars(L"./test.txt"));
EXPECT_FALSE(IsInvalidFilenameChars(L"C:\\test.txt"));
EXPECT_FALSE(IsInvalidFilenameChars(L"C:/test.txt"));
EXPECT_FALSE(IsInvalidFilenameChars(L"C:\\"));
EXPECT_FALSE(IsInvalidFilenameChars(L"C:/"));

EXPECT_TRUE(IsInvalidFilenameChars(L"localhost:8080"));
EXPECT_TRUE(IsInvalidFilenameChars(L"test*.txt"));
EXPECT_TRUE(IsInvalidFilenameChars(L"test?.txt"));
EXPECT_TRUE(IsInvalidFilenameChars(L"test\".txt"));
EXPECT_TRUE(IsInvalidFilenameChars(L"test<.txt"));
EXPECT_TRUE(IsInvalidFilenameChars(L"test>.txt"));
EXPECT_TRUE(IsInvalidFilenameChars(L"test|.txt"));
}
1 change: 1 addition & 0 deletions tests/unittests/tests1.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
<ClCompile Include="test-cnative.cpp" />
<ClCompile Include="test-cprofile.cpp" />
<ClCompile Include="test-editinfo.cpp" />
<ClCompile Include="test-file.cpp" />
<ClCompile Include="test-grepinfo.cpp" />
<ClCompile Include="test-int2dec.cpp" />
<ClCompile Include="test-is_mailaddress.cpp" />
Expand Down
3 changes: 3 additions & 0 deletions tests/unittests/tests1.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@
<ClCompile Include="test-string_ex.cpp">
<Filter>Test Files</Filter>
</ClCompile>
<ClCompile Include="test-file.cpp">
<Filter>Test Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="StartEditorProcessForTest.h">
Expand Down

0 comments on commit 8acb720

Please sign in to comment.