127 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
This file is part of Telegram Desktop,
 | 
						|
the official desktop application for the Telegram messaging service.
 | 
						|
 | 
						|
For license and copyright information please follow this link:
 | 
						|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
						|
*/
 | 
						|
#include "platform/linux/file_utilities_linux.h"
 | 
						|
 | 
						|
#include "base/platform/base_platform_info.h"
 | 
						|
#include "base/platform/linux/base_linux_xdp_utilities.h"
 | 
						|
#include "base/platform/linux/base_linux_xdg_activation_token.h"
 | 
						|
#include "base/random.h"
 | 
						|
 | 
						|
#include <fcntl.h>
 | 
						|
#include <xdpopenuri/xdpopenuri.hpp>
 | 
						|
#include <xdprequest/xdprequest.hpp>
 | 
						|
 | 
						|
namespace Platform {
 | 
						|
namespace File {
 | 
						|
namespace {
 | 
						|
 | 
						|
using namespace gi::repository;
 | 
						|
using base::Platform::XdgActivationToken;
 | 
						|
 | 
						|
} // namespace
 | 
						|
 | 
						|
bool UnsafeShowOpenWith(const QString &filepath) {
 | 
						|
	auto proxy = XdpOpenURI::OpenURIProxy::new_for_bus_sync(
 | 
						|
		Gio::BusType::SESSION_,
 | 
						|
		Gio::DBusProxyFlags::NONE_,
 | 
						|
		base::Platform::XDP::kService,
 | 
						|
		base::Platform::XDP::kObjectPath,
 | 
						|
		nullptr);
 | 
						|
 | 
						|
	if (!proxy) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	auto interface = XdpOpenURI::OpenURI(proxy);
 | 
						|
	if (interface.get_version() < 3) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	const auto fd = open(
 | 
						|
		QFile::encodeName(filepath).constData(),
 | 
						|
		O_RDONLY);
 | 
						|
 | 
						|
	if (fd == -1) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	const auto fdGuard = gsl::finally([&] { close(fd); });
 | 
						|
 | 
						|
	const auto handleToken = "tdesktop"
 | 
						|
		+ std::to_string(base::RandomValue<uint>());
 | 
						|
 | 
						|
	std::string uniqueName = proxy.get_connection().get_unique_name();
 | 
						|
	uniqueName.erase(0, 1);
 | 
						|
	uniqueName.replace(uniqueName.find('.'), 1, 1, '_');
 | 
						|
 | 
						|
	auto request = XdpRequest::Request(
 | 
						|
		XdpRequest::RequestProxy::new_sync(
 | 
						|
			proxy.get_connection(),
 | 
						|
			Gio::DBusProxyFlags::NONE_,
 | 
						|
			base::Platform::XDP::kService,
 | 
						|
			base::Platform::XDP::kObjectPath
 | 
						|
				+ std::string("/request/")
 | 
						|
				+ uniqueName
 | 
						|
				+ '/'
 | 
						|
				+ handleToken,
 | 
						|
			nullptr,
 | 
						|
			nullptr));
 | 
						|
 | 
						|
	if (!request) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	auto loop = GLib::MainLoop::new_();
 | 
						|
 | 
						|
	const auto signalId = request.signal_response().connect([=](
 | 
						|
			XdpRequest::Request,
 | 
						|
			guint,
 | 
						|
			GLib::Variant) mutable {
 | 
						|
		loop.quit();
 | 
						|
	});
 | 
						|
 | 
						|
	const auto signalGuard = gsl::finally([&] {
 | 
						|
		request.disconnect(signalId);
 | 
						|
	});
 | 
						|
 | 
						|
	auto result = interface.call_open_file_sync(
 | 
						|
		base::Platform::XDP::ParentWindowID(),
 | 
						|
		GLib::Variant::new_handle(0),
 | 
						|
		GLib::Variant::new_array({
 | 
						|
			GLib::Variant::new_dict_entry(
 | 
						|
				GLib::Variant::new_string("handle_token"),
 | 
						|
				GLib::Variant::new_variant(
 | 
						|
					GLib::Variant::new_string(handleToken))),
 | 
						|
			GLib::Variant::new_dict_entry(
 | 
						|
				GLib::Variant::new_string("activation_token"),
 | 
						|
				GLib::Variant::new_variant(
 | 
						|
					GLib::Variant::new_string(
 | 
						|
						XdgActivationToken().toStdString()))),
 | 
						|
			GLib::Variant::new_dict_entry(
 | 
						|
				GLib::Variant::new_string("ask"),
 | 
						|
				GLib::Variant::new_variant(
 | 
						|
					GLib::Variant::new_boolean(true))),
 | 
						|
		}),
 | 
						|
		Gio::UnixFDList::new_from_array((std::array{ fd }).data(), 1),
 | 
						|
		nullptr);
 | 
						|
 | 
						|
	if (!result) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	QWidget window;
 | 
						|
	window.setAttribute(Qt::WA_DontShowOnScreen);
 | 
						|
	window.setWindowModality(Qt::ApplicationModal);
 | 
						|
	window.show();
 | 
						|
	loop.run();
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace File
 | 
						|
} // namespace Platform
 |