Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

クリッカブルURLの仕様変更に対するロールバック #1965

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion sakura_core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ LIBS= \
-lwinmm \
-lwindowscodecs \
-lmsimg32 \
-lurlmon \
-mwindows \
-municode \
$(MYLIBS)
Expand Down
40 changes: 33 additions & 7 deletions sakura_core/cmd/CViewCommander_File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,10 +451,28 @@ void CViewCommander::Command_BROWSE( void )
ErrorBeep();
return;
}

std::wstring_view path(GetDocument()->m_cDocFile.GetFilePath());
std::wstring url(strprintf(L"file:///%s", path.data()));
OpenWithBrowser(m_pCommanderView->GetHwnd(), url);
// char szURL[MAX_PATH + 64];
// auto_sprintf( szURL, L"%ls", GetDocument()->m_cDocFile.GetFilePath() );
/* URLを開く */
// ::ShellExecuteEx( NULL, L"open", szURL, NULL, NULL, SW_SHOW );

SHELLEXECUTEINFO info;
info.cbSize =sizeof(info);
info.fMask = 0;
info.hwnd = NULL;
info.lpVerb = NULL;
info.lpFile = GetDocument()->m_cDocFile.GetFilePath();
info.lpParameters = NULL;
info.lpDirectory = NULL;
info.nShow = SW_SHOWNORMAL;
info.hInstApp = 0;
info.lpIDList = NULL;
info.lpClass = NULL;
info.hkeyClass = 0;
info.dwHotKey = 0;
info.hIcon =0;

::ShellExecuteEx(&info);

return;
}
Expand Down Expand Up @@ -523,9 +541,17 @@ void CViewCommander::Command_OPEN_FOLDER_IN_EXPLORER(void)
return;
}

// ドキュメントパスを変数に入れてWindowsエクスプローラーで開く
if (std::filesystem::path docPath = GetDocument()->m_cDocFile.GetFilePath();
!OpenWithExplorer(GetMainWindow(), docPath)) {
// ドキュメントパスを変数に入れる
LPCWSTR pszDocPath = GetDocument()->m_cDocFile.GetFilePath();

// Windows Explorerの引数を作る
CNativeW explorerCommand;
explorerCommand.AppendStringF(L"/select,\"%s\"", pszDocPath);
LPCWSTR pszExplorerCommand = explorerCommand.GetStringPtr();

auto hInstance = ::ShellExecute(GetMainWindow(), L"open", L"explorer.exe", pszExplorerCommand, NULL, SW_SHOWNORMAL);
// If the function succeeds, it returns a value greater than 32.
if (hInstance <= (decltype(hInstance))32) {
ErrorBeep();
return;
}
Expand Down
14 changes: 7 additions & 7 deletions sakura_core/dlg/CDlgAbout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,28 +313,28 @@ BOOL CDlgAbout::OnStnClicked( int wID )
// case IDC_STATIC_URL_ORG: del 2008/7/4 Uchi
// Web Browserの起動
{
std::wstring url;
ApiWrap::DlgItem_GetText(GetHwnd(), wID, url);
OpenWithBrowser(GetHwnd(), url);
WCHAR buf[512];
::GetWindowText( GetItemHwnd( wID ), buf, _countof(buf) );
::ShellExecute( GetHwnd(), NULL, buf, NULL, NULL, SW_SHOWNORMAL );
return TRUE;
}
case IDC_STATIC_URL_CI_BUILD:
{
#if defined(CI_BUILD_URL)
OpenWithBrowser(GetHwnd(), _T(CI_BUILD_URL));
::ShellExecute(GetHwnd(), NULL, _T(CI_BUILD_URL), NULL, NULL, SW_SHOWNORMAL);
#elif defined(GIT_REMOTE_ORIGIN_URL)
OpenWithBrowser(GetHwnd(), _T(GIT_REMOTE_ORIGIN_URL));
::ShellExecute(GetHwnd(), NULL, _T(GIT_REMOTE_ORIGIN_URL), NULL, NULL, SW_SHOWNORMAL);
#endif
return TRUE;
}
case IDC_STATIC_URL_GITHUB_COMMIT:
#if defined(GITHUB_COMMIT_URL)
OpenWithBrowser(GetHwnd(), _T(GITHUB_COMMIT_URL));
::ShellExecute(GetHwnd(), NULL, _T(GITHUB_COMMIT_URL), NULL, NULL, SW_SHOWNORMAL);
#endif
return TRUE;
case IDC_STATIC_URL_GITHUB_PR:
#if defined(GITHUB_PR_HEAD_URL)
OpenWithBrowser(GetHwnd(), _T(GITHUB_PR_HEAD_URL));
::ShellExecute(GetHwnd(), NULL, _T(GITHUB_PR_HEAD_URL), NULL, NULL, SW_SHOWNORMAL);
#endif
return TRUE;
}
Expand Down
4 changes: 2 additions & 2 deletions sakura_core/prop/CPropComPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ INT_PTR CPropPlugin::DispatchEvent( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPAR
break;
}
}
OpenWithExplorer( hwndDlg, sBaseDir );
::ShellExecute( NULL, L"open", sBaseDir.c_str(), NULL, NULL, SW_SHOW );
}
break;
case IDC_PLUGIN_README: // ReadMe表示 // 2011/11/2 Uchi
Expand All @@ -268,7 +268,7 @@ INT_PTR CPropPlugin::DispatchEvent( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPAR
if (sel >= 0){
CPlugin* plugin = CPluginManager::getInstance()->GetPlugin(sel);
if (plugin != NULL){
OpenWithBrowser( hwndDlg, plugin->m_sUrl );
::ShellExecute(NULL, L"Open", plugin->m_sUrl.c_str(), NULL, NULL, SW_SHOW);
}
}
}
Expand Down
222 changes: 35 additions & 187 deletions sakura_core/util/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,11 @@
*/

#include "StdAfx.h"
#include "util/shell.h"

#include <cderr.h> // CDERR_FINDRESFAILURE等
#include <comdef.h>
#include <comutil.h>
#include <urlmon.h>
#include <wrl.h>
#include <HtmlHelp.h>
#include <shellapi.h>
#include <ShlObj.h>

#include <regex>

#include "debug/Debug1.h"
#include "util/RegKey.h"
#include <ShellAPI.h>
#include <CdErr.h> // Nov. 3, 2005 genta //CDERR_FINDRESFAILURE等
#include "util/shell.h"
#include "util/string_ex2.h"
#include "util/file.h"
#include "util/os.h"
Expand All @@ -50,8 +40,8 @@
#include "extmodule/CHtmlHelp.h"
#include "config/app_constants.h"
#include "String_define.h"
#include <wrl.h>

#pragma comment(lib, "urlmon.lib")

/* フォルダー選択ダイアログ */
BOOL SelectDir( HWND hWnd, const WCHAR* pszTitle, const WCHAR* pszInitFolder, WCHAR* strFolderName, size_t nMaxCount )
Expand Down Expand Up @@ -224,8 +214,36 @@ static LRESULT CALLBACK PropSheetWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, L

// 選択されたメニューの処理
switch( nId ){
case 100: // 設定フォルダーを開く
OpenWithExplorer(hwnd, GetIniFileName());
case 100: // 設定フォルダを開く
WCHAR szPath[_MAX_PATH];
GetInidir( szPath );

// フォルダの ITEMIDLIST を取得して ShellExecuteEx() で開く
// Note. MSDN の ShellExecute() の解説にある方法でフォルダを開こうとした場合、
// フォルダと同じ場所に <フォルダ名>.exe があるとうまく動かない。
// verbが"open"やNULLではexeのほうが実行され"explore"では失敗する
// (フォルダ名の末尾に'\\'を付加してもWindows 2000では付加しないのと同じ動作になってしまう)
LPSHELLFOLDER pDesktopFolder;
if( SUCCEEDED(::SHGetDesktopFolder(&pDesktopFolder)) ){
LPMALLOC pMalloc;
if( SUCCEEDED(::SHGetMalloc(&pMalloc)) ){
LPITEMIDLIST pIDL;
WCHAR* pszDisplayName = szPath;
if( SUCCEEDED(pDesktopFolder->ParseDisplayName(NULL, NULL, pszDisplayName, NULL, &pIDL, NULL)) ){
SHELLEXECUTEINFO si;
::ZeroMemory( &si, sizeof(si) );
si.cbSize = sizeof(si);
si.fMask = SEE_MASK_IDLIST;
si.lpVerb = L"open";
si.lpIDList = pIDL;
si.nShow = SW_SHOWNORMAL;
::ShellExecuteEx( &si ); // フォルダを開く
pMalloc->Free( (void*)pIDL );
}
pMalloc->Release();
}
pDesktopFolder->Release();
}
break;

case 101: // インポート/エクスポートの起点リセット(起点を設定フォルダーにする)
Expand Down Expand Up @@ -574,7 +592,7 @@ BOOL MyWinHelp(HWND hwndCaller, UINT uCommand, DWORD_PTR dwData)

WCHAR buf[256];
swprintf( buf, _countof(buf), L"https://sakura-editor.github.io/help/HLP%06Iu.html", dwData );
OpenWithBrowser( ::GetActiveWindow(), buf );
ShellExecute( ::GetActiveWindow(), NULL, buf, NULL, NULL, SW_SHOWNORMAL );
}

return TRUE;
Expand Down Expand Up @@ -628,173 +646,3 @@ BOOL MySelectFont( LOGFONT* plf, INT* piPointSize, HWND hwndDlgOwner, bool Fixed

return TRUE;
}

//! Windows エクスプローラーで開く
bool OpenWithExplorer(HWND hWnd, const std::filesystem::path& path)
{
if (path.empty()) {
return false;
}

std::filesystem::path explorerPath;
std::wstring_view verb = L"explore";
std::wstring_view file = path.c_str();
std::wstring params;
const wchar_t* lpParameters = nullptr;

// ファイル名(最後の'\'に続く部分)がドット('.')でない場合、
// Windowsエクスプローラーのコマンドを指定してファイルを選択させる。
// ※ドットは「フォルダー自身」を表す特殊なファイル名。
if (path.filename() != L".") {
std::wstring buf(_MAX_PATH, wchar_t());
size_t requiredSize;
_wgetenv_s(&requiredSize, buf.data(), buf.capacity(), L"windir");
verb = L"open";
explorerPath = buf.data();
explorerPath /= L"explorer.exe";
file = explorerPath.c_str();
params = strprintf(L"/select,\"%s\"", path.c_str());
lpParameters = params.c_str();
}

// If the function succeeds, it returns a value greater than 32.
if (auto hInstance = ::ShellExecuteW(hWnd, verb.data(), file.data(), lpParameters, nullptr, SW_SHOWNORMAL);
hInstance <= (decltype(hInstance))32) {
return false;
}

return true;
}

/*!
* 指定したプロトコルに関連付けされたProgIDを取得する
*/
std::wstring GetProgIdForProtocol(std::wstring_view protocol)
{
constexpr const auto& defaultProgId = L"MSEdgeHTM";

// HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice
if (const auto keyPath(strprintf(LR"(SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\%s\UserChoice)", protocol.data()));
CRegKey::ExistsKey(HKEY_CURRENT_USER, keyPath.data()))
{
CRegKey regKey;
if (const auto errorCode = regKey.Open(HKEY_CURRENT_USER, keyPath.data(), KEY_READ);
errorCode != 0)
{
return defaultProgId;
}

std::wstring buf(1024, wchar_t());
if (const auto errorCode = regKey.GetValue(L"ProgId", buf.data(), static_cast<uint32_t>(buf.capacity()), nullptr);
errorCode != 0)
{
return defaultProgId;
}

buf.resize(::wcsnlen(buf.data(), 1024));

return buf;
}

return defaultProgId;
}

/*!
* 指定したProgIDに関連付けされたコマンドラインを取得する
*/
std::wstring GetCommandAssociatedWithProgID(std::wstring_view progId)
{
constexpr const auto& notAssociated = L"";

// HKEY_CLASSES_ROOT\MSEdgeHTM\shell\open\command
if (const auto keyPath(strprintf(LR"(%s\shell\open\command)", progId.data()));
CRegKey::ExistsKey(HKEY_CLASSES_ROOT, keyPath.data()))
{
CRegKey regKey;
if (const auto errorCode = regKey.Open(HKEY_CLASSES_ROOT, keyPath.data(), KEY_READ);
errorCode != 0)
{
return notAssociated;
}

std::wstring buf(1024, wchar_t());
if (const auto errorCode = regKey.GetValue(nullptr, buf.data(), static_cast<uint32_t>(buf.capacity()), nullptr);
errorCode != 0)
{
return notAssociated;
}

buf.resize(::wcsnlen(buf.data(), 1024));

return buf;
}

return notAssociated;
}

//! ブラウザで開く
bool OpenWithBrowser(HWND hWnd, std::wstring_view url)
{
if (url.empty()) {
return false;
}

using namespace Microsoft::WRL;
ComPtr<IUri> pUri;
DWORD dwFlags = Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_IE_SETTINGS;
if (const auto hr = ::CreateUri(url.data(), dwFlags, 0, &pUri);
FAILED(hr)) {
_com_error ex(hr);
auto desc = ex.Description();
TRACE("%s", (const wchar_t*)desc);
return false;
}

_bstr_t bstrSchemeName;
if (const auto hr = pUri->GetSchemeName(&bstrSchemeName.GetBSTR());
FAILED(hr)) {
_com_error ex(hr);
auto desc = ex.Description();
TRACE("%s", (const wchar_t*)desc);
return false;
}

std::filesystem::path browserPath;
std::wstring_view verb = L"open";
std::wstring_view file = url.data();
std::wstring params;
const wchar_t* lpParameters = nullptr;

// fileプロトコル対策
if (bstrSchemeName == _bstr_t(L"file")) {
// 実行可能ファイルはダウンロードになるので失敗させる
if (const std::filesystem::path urlPath(url.data());
::_wcsicmp(urlPath.extension().c_str(), L".exe") == 0) {
return false;
}

// HTTPプロトコルに関連付けられたコマンドラインを取得し、パターンマッチでパラメータを組み立てる
// => "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --single-argument %1
std::wsmatch matched;
std::wregex re(LR"(^("[^"]+"|[^ ]+)\s+(.+))");
if (auto browserCommandline = GetCommandAssociatedWithProgID(GetProgIdForProtocol(L"http"));
std::regex_search(browserCommandline, matched, re)) {
// $1 ブラウザのパス
std::wstring buf = matched[1];
buf.erase(std::remove(buf.begin(), buf.end(), L'\"'), buf.cend());
browserPath = buf.data();
file = browserPath.c_str();
// $2 パラメータ
params = std::regex_replace(matched[2].str(), std::wregex(L"%1"), url.data());
lpParameters = params.c_str();
}
}

// If the function succeeds, it returns a value greater than 32.
if (auto hInstance = ::ShellExecuteW(hWnd, verb.data(), file.data(), lpParameters, nullptr, SW_SHOWNORMAL);
hInstance <= (decltype(hInstance))32) {
return false;
}

return true;
}
10 changes: 0 additions & 10 deletions sakura_core/util/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@

#include <Windows.h>

#include <filesystem>
#include <string_view>

BOOL MyWinHelp(HWND hwndCaller, UINT uCommand, DWORD_PTR dwData); /* WinHelp のかわりに HtmlHelp を呼び出す */ // 2006.07.22 ryoji

/* Shell Interface系(?) */
Expand All @@ -59,11 +56,4 @@ INT_PTR MyPropertySheet( LPPROPSHEETHEADER lppsph ); // 独自拡張プロパテ

//!フォント選択ダイアログ
BOOL MySelectFont( LOGFONT* plf, INT* piPointSize, HWND hwndDlgOwner, bool ); // 2009.10.01 ryoji ポイントサイズ(1/10ポイント単位)引数追加

//! Windows エクスプローラーで開く
bool OpenWithExplorer(HWND hWnd, const std::filesystem::path& path);

//! ブラウザで開く
bool OpenWithBrowser(HWND hWnd, std::wstring_view url);

#endif /* SAKURA_SHELL_0A8B6454_B007_46E5_9606_8D2FD7993B91_H_ */
Loading
Loading