try fix clipboard, flutter version

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2023-06-18 20:23:54 +08:00
parent 22b0b54527
commit ccd2cbd760
14 changed files with 136 additions and 166 deletions

View File

@ -191,8 +191,6 @@ extern "C"
typedef UINT (*pcCliprdrServerFileContentsResponse)( typedef UINT (*pcCliprdrServerFileContentsResponse)(
CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse); CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse);
typedef BOOL (*pcCheckEnabled)(UINT32 connID);
// TODO: hide more members of clipboard context // TODO: hide more members of clipboard context
struct _cliprdr_client_context struct _cliprdr_client_context
{ {
@ -200,7 +198,6 @@ extern "C"
BOOL enableFiles; BOOL enableFiles;
BOOL enableOthers; BOOL enableOthers;
pcCheckEnabled CheckEnabled;
pcCliprdrServerCapabilities ServerCapabilities; pcCliprdrServerCapabilities ServerCapabilities;
pcCliprdrClientCapabilities ClientCapabilities; pcCliprdrClientCapabilities ClientCapabilities;
pcCliprdrMonitorReady MonitorReady; pcCliprdrMonitorReady MonitorReady;

View File

@ -444,9 +444,6 @@ pub type pcCliprdrServerFileContentsResponse = ::std::option::Option<
fileContentsResponse: *const CLIPRDR_FILE_CONTENTS_RESPONSE, fileContentsResponse: *const CLIPRDR_FILE_CONTENTS_RESPONSE,
) -> UINT, ) -> UINT,
>; >;
pub type pcCheckEnabled = ::std::option::Option<
unsafe extern "C" fn(connID: UINT32) -> BOOL,
>;
// TODO: hide more members of clipboard context // TODO: hide more members of clipboard context
#[repr(C)] #[repr(C)]
@ -455,7 +452,6 @@ pub struct _cliprdr_client_context {
pub custom: *mut ::std::os::raw::c_void, pub custom: *mut ::std::os::raw::c_void,
pub enableFiles: BOOL, pub enableFiles: BOOL,
pub enableOthers: BOOL, pub enableOthers: BOOL,
pub CheckEnabled: pcCheckEnabled,
pub ServerCapabilities: pcCliprdrServerCapabilities, pub ServerCapabilities: pcCliprdrServerCapabilities,
pub ClientCapabilities: pcCliprdrClientCapabilities, pub ClientCapabilities: pcCliprdrClientCapabilities,
pub MonitorReady: pcCliprdrMonitorReady, pub MonitorReady: pcCliprdrMonitorReady,
@ -504,7 +500,6 @@ impl CliprdrClientContext {
pub fn create( pub fn create(
enable_files: bool, enable_files: bool,
enable_others: bool, enable_others: bool,
check_enabled: pcCheckEnabled,
client_format_list: pcCliprdrClientFormatList, client_format_list: pcCliprdrClientFormatList,
client_format_list_response: pcCliprdrClientFormatListResponse, client_format_list_response: pcCliprdrClientFormatListResponse,
client_format_data_request: pcCliprdrClientFormatDataRequest, client_format_data_request: pcCliprdrClientFormatDataRequest,
@ -516,7 +511,6 @@ impl CliprdrClientContext {
custom: 0 as *mut _, custom: 0 as *mut _,
enableFiles: if enable_files { TRUE } else { FALSE }, enableFiles: if enable_files { TRUE } else { FALSE },
enableOthers: if enable_others { TRUE } else { FALSE }, enableOthers: if enable_others { TRUE } else { FALSE },
CheckEnabled: check_enabled,
ServerCapabilities: None, ServerCapabilities: None,
ClientCapabilities: None, ClientCapabilities: None,
MonitorReady: None, MonitorReady: None,

View File

@ -1,28 +1,36 @@
use crate::cliprdr::*; use crate::cliprdr::*;
use hbb_common::log; use hbb_common::log;
use std::sync::Mutex; use std::sync::{Arc, Mutex};
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref CONTEXT_SEND: ContextSend = ContextSend{addr: Mutex::new(0)}; static ref CONTEXT_SEND: Arc<Mutex<ContextSend>> = Arc::new(Mutex::new(ContextSend::new()));
} }
pub struct ContextSend { pub struct ContextSend {
addr: Mutex<u64>, server_enabled: bool,
addr: u64,
} }
impl ContextSend { impl ContextSend {
pub fn is_enabled() -> bool { fn new() -> Self {
*CONTEXT_SEND.addr.lock().unwrap() != 0 Self {
server_enabled: false,
addr: 0,
}
} }
pub fn enable(enabled: bool) { pub fn is_server_enabled() -> bool {
let mut lock = CONTEXT_SEND.addr.lock().unwrap(); CONTEXT_SEND.lock().unwrap().server_enabled
}
pub fn enable(enabled: bool, is_server_side: bool, is_server_process: bool) {
let mut lock = CONTEXT_SEND.lock().unwrap();
if enabled { if enabled {
if *lock == 0 { if lock.addr == 0 {
match crate::create_cliprdr_context(true, false, crate::ProcessSide::ClientSide) { match crate::create_cliprdr_context(true, false) {
Ok(context) => { Ok(context) => {
log::info!("clipboard context for file transfer created."); log::info!("clipboard context for file transfer created.");
*lock = Box::into_raw(context) as _; lock.addr = Box::into_raw(context) as _;
} }
Err(err) => { Err(err) => {
log::error!( log::error!(
@ -32,25 +40,29 @@ impl ContextSend {
} }
} }
} }
if is_server_side {
lock.server_enabled = true;
}
} else { } else {
if *lock != 0 { if lock.addr != 0 {
if is_server_process {
unsafe { unsafe {
let _ = Box::from_raw(*lock as *mut CliprdrClientContext); let _ = Box::from_raw(lock.addr as *mut CliprdrClientContext);
} }
log::info!("clipboard context for file transfer destroyed."); log::info!("clipboard context for file transfer destroyed.");
*lock = 0; lock.addr = 0;
}
lock.server_enabled = false;
} }
} }
} }
pub fn proc<F: FnOnce(&mut Box<CliprdrClientContext>) -> u32>(f: F) -> u32 { pub fn proc<F: FnOnce(&mut Box<CliprdrClientContext>) -> u32>(f: F) -> u32 {
let mut lock = CONTEXT_SEND.addr.lock().unwrap(); let lock = CONTEXT_SEND.lock().unwrap();
if *lock != 0 { if lock.addr != 0 {
unsafe { unsafe {
let mut context = Box::from_raw(*lock as *mut CliprdrClientContext); let mut context = Box::from_raw(lock.addr as *mut CliprdrClientContext);
let res = f(&mut context); f(&mut context)
*lock = Box::into_raw(context) as _;
res
} }
} else { } else {
0 0

View File

@ -10,7 +10,6 @@ use hbb_common::{
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::{ use std::{
boxed::Box, boxed::Box,
collections::HashMap,
ffi::{CStr, CString}, ffi::{CStr, CString},
sync::{Arc, Mutex, RwLock}, sync::{Arc, Mutex, RwLock},
}; };
@ -53,11 +52,6 @@ pub enum ClipboardFile {
}, },
} }
#[derive(Default)]
struct ConnEnabled {
conn_enabled: HashMap<i32, bool>,
}
struct MsgChannel { struct MsgChannel {
session_uuid: SessionID, session_uuid: SessionID,
conn_id: i32, conn_id: i32,
@ -65,17 +59,20 @@ struct MsgChannel {
receiver: Arc<TokioMutex<UnboundedReceiver<ClipboardFile>>>, receiver: Arc<TokioMutex<UnboundedReceiver<ClipboardFile>>>,
} }
#[derive(PartialEq)]
pub enum ProcessSide {
UnknownSide,
ClientSide,
ServerSide,
}
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref VEC_MSG_CHANNEL: RwLock<Vec<MsgChannel>> = Default::default(); static ref VEC_MSG_CHANNEL: RwLock<Vec<MsgChannel>> = Default::default();
static ref CLIP_CONN_ENABLED: Mutex<ConnEnabled> = Mutex::new(ConnEnabled::default()); static ref CLIENT_CONN_ID_COUNTER: Mutex<i32> = Mutex::new(0);
static ref PROCESS_SIDE: RwLock<ProcessSide> = RwLock::new(ProcessSide::UnknownSide); }
impl ClipboardFile {
pub fn is_stopping_allowed(&self) -> bool {
match self {
ClipboardFile::MonitorReady
| ClipboardFile::FormatList { .. }
| ClipboardFile::FormatDataRequest { .. } => true,
_ => false,
}
}
} }
pub fn get_client_conn_id(session_uuid: &SessionID) -> Option<i32> { pub fn get_client_conn_id(session_uuid: &SessionID) -> Option<i32> {
@ -87,6 +84,12 @@ pub fn get_client_conn_id(session_uuid: &SessionID) -> Option<i32> {
.map(|x| x.conn_id) .map(|x| x.conn_id)
} }
fn get_conn_id() -> i32 {
let mut lock = CLIENT_CONN_ID_COUNTER.lock().unwrap();
*lock += 1;
*lock
}
pub fn get_rx_cliprdr_client( pub fn get_rx_cliprdr_client(
session_uuid: &SessionID, session_uuid: &SessionID,
) -> (i32, Arc<TokioMutex<UnboundedReceiver<ClipboardFile>>>) { ) -> (i32, Arc<TokioMutex<UnboundedReceiver<ClipboardFile>>>) {
@ -100,7 +103,7 @@ pub fn get_rx_cliprdr_client(
let (sender, receiver) = unbounded_channel(); let (sender, receiver) = unbounded_channel();
let receiver = Arc::new(TokioMutex::new(receiver)); let receiver = Arc::new(TokioMutex::new(receiver));
let receiver2 = receiver.clone(); let receiver2 = receiver.clone();
let conn_id = lock.len() as i32 + 1; let conn_id = get_conn_id();
let msg_channel = MsgChannel { let msg_channel = MsgChannel {
session_uuid: session_uuid.to_owned(), session_uuid: session_uuid.to_owned(),
conn_id, conn_id,
@ -146,13 +149,6 @@ fn send_data(conn_id: i32, data: ClipboardFile) {
} }
} }
pub fn set_conn_enabled(conn_id: i32, enabled: bool) {
let mut lock = CLIP_CONN_ENABLED.lock().unwrap();
if conn_id != 0 {
let _ = lock.conn_enabled.insert(conn_id, enabled);
}
}
pub fn empty_clipboard(context: &mut Box<CliprdrClientContext>, conn_id: i32) -> bool { pub fn empty_clipboard(context: &mut Box<CliprdrClientContext>, conn_id: i32) -> bool {
unsafe { TRUE == cliprdr::empty_cliprdr(&mut (**context), conn_id as u32) } unsafe { TRUE == cliprdr::empty_cliprdr(&mut (**context), conn_id as u32) }
} }
@ -430,14 +426,10 @@ pub fn server_file_contents_response(
pub fn create_cliprdr_context( pub fn create_cliprdr_context(
enable_files: bool, enable_files: bool,
enable_others: bool, enable_others: bool,
process_side: ProcessSide,
) -> ResultType<Box<CliprdrClientContext>> { ) -> ResultType<Box<CliprdrClientContext>> {
*PROCESS_SIDE.write().unwrap() = process_side;
Ok(CliprdrClientContext::create( Ok(CliprdrClientContext::create(
enable_files, enable_files,
enable_others, enable_others,
Some(check_enabled),
Some(client_format_list), Some(client_format_list),
Some(client_format_list_response), Some(client_format_list_response),
Some(client_format_data_request), Some(client_format_data_request),
@ -447,24 +439,6 @@ pub fn create_cliprdr_context(
)?) )?)
} }
extern "C" fn check_enabled(conn_id: UINT32) -> BOOL {
if *PROCESS_SIDE.read().unwrap() == ProcessSide::ClientSide {
return TRUE;
}
let lock = CLIP_CONN_ENABLED.lock().unwrap();
let mut connd_enabled = false;
if conn_id != 0 {
if let Some(true) = lock.conn_enabled.get(&(conn_id as i32)) {
connd_enabled = true;
}
} else {
connd_enabled = true;
}
return if connd_enabled { TRUE } else { FALSE };
}
extern "C" fn client_format_list( extern "C" fn client_format_list(
_context: *mut CliprdrClientContext, _context: *mut CliprdrClientContext,
clip_format_list: *const CLIPRDR_FORMAT_LIST, clip_format_list: *const CLIPRDR_FORMAT_LIST,

View File

@ -681,10 +681,6 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
} }
clipboard = (wfClipboard *)instance->m_pData; clipboard = (wfClipboard *)instance->m_pData;
if (!clipboard->context->CheckEnabled(instance->m_connID))
{
return E_INVALIDARG;
}
if (!clipboard) if (!clipboard)
return E_INVALIDARG; return E_INVALIDARG;
@ -1469,16 +1465,9 @@ static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UIN
{ {
DWORD waitRes = WaitForSingleObject(clipboard->response_data_event, 50); DWORD waitRes = WaitForSingleObject(clipboard->response_data_event, 50);
if (waitRes == WAIT_TIMEOUT) if (waitRes == WAIT_TIMEOUT)
{
if (clipboard->context->CheckEnabled(connID))
{ {
continue; continue;
} }
else
{
break;
}
}
if (waitRes != WAIT_OBJECT_0) if (waitRes != WAIT_OBJECT_0)
{ {
@ -1541,16 +1530,9 @@ UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, co
{ {
DWORD waitRes = WaitForSingleObject(clipboard->req_fevent, 50); DWORD waitRes = WaitForSingleObject(clipboard->req_fevent, 50);
if (waitRes == WAIT_TIMEOUT) if (waitRes == WAIT_TIMEOUT)
{
if (clipboard->context->CheckEnabled(connID))
{ {
continue; continue;
} }
else
{
break;
}
}
if (waitRes != WAIT_OBJECT_0) if (waitRes != WAIT_OBJECT_0)
{ {

View File

@ -2,6 +2,7 @@ use std::{
collections::HashMap, collections::HashMap,
fs, fs,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
ops::{Deref, DerefMut},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{Arc, Mutex, RwLock}, sync::{Arc, Mutex, RwLock},
time::{Duration, Instant, SystemTime}, time::{Duration, Instant, SystemTime},
@ -132,6 +133,18 @@ macro_rules! serde_field_bool {
UserDefaultConfig::read().get($field_name) == "Y" UserDefaultConfig::read().get($field_name) == "Y"
} }
} }
impl Deref for $struct_name {
type Target = bool;
fn deref(&self) -> &Self::Target {
&self.v
}
}
impl DerefMut for $struct_name {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.v
}
}
}; };
} }

View File

@ -2336,6 +2336,7 @@ pub enum Data {
CancelJob(i32), CancelJob(i32),
RemovePortForward(i32), RemovePortForward(i32),
AddPortForward((i32, String, i32)), AddPortForward((i32, String, i32)),
#[cfg(not(feature = "flutter"))]
ToggleClipboardFile, ToggleClipboardFile,
NewRDP, NewRDP,
SetConfirmOverrideFile((i32, i32, bool, bool, bool)), SetConfirmOverrideFile((i32, i32, bool, bool, bool)),

View File

@ -6,7 +6,7 @@ use std::sync::{
}; };
#[cfg(windows)] #[cfg(windows)]
use clipboard::{cliprdr::CliprdrClientContext, ContextSend}; use clipboard::{cliprdr::CliprdrClientContext, ClipboardFile, ContextSend};
use crossbeam_queue::ArrayQueue; use crossbeam_queue::ArrayQueue;
use hbb_common::config::{PeerConfig, TransferSerde}; use hbb_common::config::{PeerConfig, TransferSerde};
use hbb_common::fs::{ use hbb_common::fs::{
@ -58,7 +58,7 @@ pub struct Remote<T: InvokeUiSession> {
last_update_jobs_status: (Instant, HashMap<i32, u64>), last_update_jobs_status: (Instant, HashMap<i32, u64>),
first_frame: bool, first_frame: bool,
#[cfg(windows)] #[cfg(windows)]
client_conn_id: i32, // used for clipboard client_conn_id: i32, // used for file clipboard
data_count: Arc<AtomicUsize>, data_count: Arc<AtomicUsize>,
frame_count: Arc<AtomicUsize>, frame_count: Arc<AtomicUsize>,
video_format: CodecFormat, video_format: CodecFormat,
@ -207,8 +207,16 @@ impl<T: InvokeUiSession> Remote<T> {
#[cfg(windows)] #[cfg(windows)]
match _msg { match _msg {
Some(clip) => { Some(clip) => {
let mut send_msg = true;
if clip.is_stopping_allowed() {
if !(*self.handler.server_file_transfer_enabled.read().unwrap() && self.handler.lc.read().unwrap().enable_file_transfer.v) {
send_msg = false;
}
}
if send_msg {
allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await);
} }
}
None => { None => {
// unreachable!() // unreachable!()
} }
@ -389,6 +397,7 @@ impl<T: InvokeUiSession> Remote<T> {
.handle_login_from_ui(os_username, os_password, password, remember, peer) .handle_login_from_ui(os_username, os_password, password, remember, peer)
.await; .await;
} }
#[cfg(not(feature = "flutter"))]
Data::ToggleClipboardFile => { Data::ToggleClipboardFile => {
self.check_clipboard_file_context(); self.check_clipboard_file_context();
} }
@ -938,6 +947,7 @@ impl<T: InvokeUiSession> Remote<T> {
} }
Some(login_response::Union::PeerInfo(pi)) => { Some(login_response::Union::PeerInfo(pi)) => {
self.handler.handle_peer_info(pi); self.handler.handle_peer_info(pi);
#[cfg(not(feature = "flutter"))]
self.check_clipboard_file_context(); self.check_clipboard_file_context();
if !(self.handler.is_file_transfer() || self.handler.is_port_forward()) { if !(self.handler.is_file_transfer() || self.handler.is_port_forward()) {
#[cfg(feature = "flutter")] #[cfg(feature = "flutter")]
@ -1188,7 +1198,6 @@ impl<T: InvokeUiSession> Remote<T> {
if !p.enabled && self.handler.is_file_transfer() { if !p.enabled && self.handler.is_file_transfer() {
return true; return true;
} }
self.check_clipboard_file_context();
self.handler.set_permission("file", p.enabled); self.handler.set_permission("file", p.enabled);
} }
Ok(Permission::Restart) => { Ok(Permission::Restart) => {
@ -1525,12 +1534,13 @@ impl<T: InvokeUiSession> Remote<T> {
true true
} }
#[cfg(not(feature = "flutter"))]
fn check_clipboard_file_context(&self) { fn check_clipboard_file_context(&self) {
#[cfg(windows)] #[cfg(windows)]
{ {
let enabled = *self.handler.server_file_transfer_enabled.read().unwrap() let enabled = *self.handler.server_file_transfer_enabled.read().unwrap()
&& self.handler.lc.read().unwrap().enable_file_transfer.v; && self.handler.lc.read().unwrap().enable_file_transfer.v;
ContextSend::enable(enabled); ContextSend::enable(enabled, false, false);
} }
} }

View File

@ -122,6 +122,8 @@ pub fn core_main() -> Option<Vec<String>> {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
init_plugins(&args); init_plugins(&args);
if args.is_empty() { if args.is_empty() {
#[cfg(windows)]
clipboard::ContextSend::enable(true, false, false);
std::thread::spawn(move || crate::start_server(false)); std::thread::spawn(move || crate::start_server(false));
} else { } else {
#[cfg(windows)] #[cfg(windows)]

View File

@ -202,7 +202,6 @@ pub enum Data {
SyncConfig(Option<Box<(Config, Config2)>>), SyncConfig(Option<Box<(Config, Config2)>>),
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
ClipboardFile(ClipboardFile), ClipboardFile(ClipboardFile),
ClipboardFileEnabled(bool),
PrivacyModeState((i32, PrivacyModeState)), PrivacyModeState((i32, PrivacyModeState)),
TestRendezvousServer, TestRendezvousServer,
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
@ -242,7 +241,7 @@ pub async fn start(postfix: &str) -> ResultType<()> {
loop { loop {
match stream.next().await { match stream.next().await {
Err(err) => { Err(err) => {
log::trace!("ipc{} connection closed: {}", postfix, err); log::trace!("ipc '{}' connection closed: {}", postfix, err);
break; break;
} }
Ok(Some(data)) => { Ok(Some(data)) => {

View File

@ -282,6 +282,7 @@ impl Connection {
keyboard: Connection::permission("enable-keyboard"), keyboard: Connection::permission("enable-keyboard"),
clipboard: Connection::permission("enable-clipboard"), clipboard: Connection::permission("enable-clipboard"),
audio: Connection::permission("enable-audio"), audio: Connection::permission("enable-audio"),
// to-do: make sure is the option correct here
file: Connection::permission("enable-file-transfer"), file: Connection::permission("enable-file-transfer"),
restart: Connection::permission("enable-remote-restart"), restart: Connection::permission("enable-remote-restart"),
recording: Connection::permission("enable-record-session"), recording: Connection::permission("enable-record-session"),
@ -424,7 +425,6 @@ impl Connection {
} else if &name == "file" { } else if &name == "file" {
conn.file = enabled; conn.file = enabled;
conn.send_permission(Permission::File, enabled).await; conn.send_permission(Permission::File, enabled).await;
conn.send_to_cm(ipc::Data::ClipboardFileEnabled(conn.file_transfer_enabled()));
} else if &name == "restart" { } else if &name == "restart" {
conn.restart = enabled; conn.restart = enabled;
conn.send_permission(Permission::Restart, enabled).await; conn.send_permission(Permission::Restart, enabled).await;
@ -437,9 +437,9 @@ impl Connection {
allow_err!(conn.stream.send_raw(bytes).await); allow_err!(conn.stream.send_raw(bytes).await);
} }
#[cfg(windows)] #[cfg(windows)]
ipc::Data::ClipboardFile(_clip) => { ipc::Data::ClipboardFile(clip) => {
if conn.file_transfer_enabled() { if !clip.is_stopping_allowed() || conn.file_transfer_enabled() {
allow_err!(conn.stream.send(&clip_2_msg(_clip)).await); allow_err!(conn.stream.send(&clip_2_msg(clip)).await);
} }
} }
ipc::Data::PrivacyModeState((_, state)) => { ipc::Data::PrivacyModeState((_, state)) => {
@ -1136,7 +1136,7 @@ impl Connection {
clipboard: self.clipboard, clipboard: self.clipboard,
audio: self.audio, audio: self.audio,
file: self.file, file: self.file,
file_transfer_enabled: self.file_transfer_enabled(), file_transfer_enabled: self.file,
restart: self.restart, restart: self.restart,
recording: self.recording, recording: self.recording,
from_switch: self.from_switch, from_switch: self.from_switch,
@ -1636,13 +1636,11 @@ impl Connection {
} }
} }
Some(message::Union::Cliprdr(_clip)) => { Some(message::Union::Cliprdr(_clip)) => {
if self.file_transfer_enabled() {
#[cfg(windows)] #[cfg(windows)]
if let Some(clip) = msg_2_clip(_clip) { if let Some(clip) = msg_2_clip(_clip) {
self.send_to_cm(ipc::Data::ClipboardFile(clip)) self.send_to_cm(ipc::Data::ClipboardFile(clip))
} }
} }
}
Some(message::Union::FileAction(fa)) => { Some(message::Union::FileAction(fa)) => {
if self.file_transfer.is_some() { if self.file_transfer.is_some() {
match fa.union { match fa.union {
@ -2073,9 +2071,6 @@ impl Connection {
if let Ok(q) = o.enable_file_transfer.enum_value() { if let Ok(q) = o.enable_file_transfer.enum_value() {
if q != BoolOption::NotSet { if q != BoolOption::NotSet {
self.enable_file_transfer = q == BoolOption::Yes; self.enable_file_transfer = q == BoolOption::Yes;
self.send_to_cm(ipc::Data::ClipboardFileEnabled(
self.file_transfer_enabled(),
));
} }
} }
if let Ok(q) = o.disable_clipboard.enum_value() { if let Ok(q) = o.disable_clipboard.enum_value() {

View File

@ -11,14 +11,12 @@ use std::{
}, },
}; };
#[cfg(windows)]
use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, set_conn_enabled, ContextSend};
use serde_derive::Serialize;
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::ipc::Connection; use crate::ipc::Connection;
#[cfg(not(any(target_os = "ios")))] #[cfg(not(any(target_os = "ios")))]
use crate::ipc::{self, Data}; use crate::ipc::{self, Data};
#[cfg(windows)]
use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, ContextSend};
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
use hbb_common::tokio::sync::mpsc::unbounded_channel; use hbb_common::tokio::sync::mpsc::unbounded_channel;
#[cfg(windows)] #[cfg(windows)]
@ -37,6 +35,7 @@ use hbb_common::{
task::spawn_blocking, task::spawn_blocking,
}, },
}; };
use serde_derive::Serialize;
#[derive(Serialize, Clone)] #[derive(Serialize, Clone)]
pub struct Client { pub struct Client {
@ -131,8 +130,7 @@ impl<T: InvokeUiCM> ConnectionManager<T> {
restart: bool, restart: bool,
recording: bool, recording: bool,
from_switch: bool, from_switch: bool,
#[cfg(not(any(target_os = "ios")))] #[cfg(not(any(target_os = "ios")))] tx: mpsc::UnboundedSender<Data>,
tx: mpsc::UnboundedSender<Data>,
) { ) {
let client = Client { let client = Client {
id, id,
@ -303,42 +301,12 @@ pub fn switch_back(id: i32) {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
impl<T: InvokeUiCM> IpcTaskRunner<T> { impl<T: InvokeUiCM> IpcTaskRunner<T> {
#[cfg(windows)]
async fn enable_cliprdr_file_context(&mut self, conn_id: i32, enabled: bool) {
if conn_id == 0 {
return;
}
let pre_enabled = ContextSend::is_enabled();
ContextSend::enable(enabled);
if !pre_enabled && ContextSend::is_enabled() {
allow_err!(
self.stream
.send(&Data::ClipboardFile(clipboard::ClipboardFile::MonitorReady))
.await
);
}
set_conn_enabled(conn_id, enabled);
if !enabled {
ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 {
empty_clipboard(context, conn_id);
0
});
}
}
async fn run(&mut self) { async fn run(&mut self) {
use hbb_common::config::LocalConfig; use hbb_common::config::LocalConfig;
// for tmp use, without real conn id // for tmp use, without real conn id
let mut write_jobs: Vec<fs::TransferJob> = Vec::new(); let mut write_jobs: Vec<fs::TransferJob> = Vec::new();
#[cfg(windows)]
if self.conn_id > 0 {
self.enable_cliprdr_file_context(self.conn_id, self.file_transfer_enabled)
.await;
}
#[cfg(windows)] #[cfg(windows)]
let rx_clip1; let rx_clip1;
let mut rx_clip; let mut rx_clip;
@ -382,15 +350,11 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
break; break;
} }
Data::Close => { Data::Close => {
#[cfg(windows)]
self.enable_cliprdr_file_context(self.conn_id, false).await;
log::info!("cm ipc connection closed from connection request"); log::info!("cm ipc connection closed from connection request");
break; break;
} }
Data::Disconnected => { Data::Disconnected => {
self.close = false; self.close = false;
#[cfg(windows)]
self.enable_cliprdr_file_context(self.conn_id, false).await;
log::info!("cm ipc connection disconnect"); log::info!("cm ipc connection disconnect");
break; break;
} }
@ -414,20 +378,17 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
handle_fs(fs, &mut write_jobs, &self.tx).await; handle_fs(fs, &mut write_jobs, &self.tx).await;
} }
} }
#[cfg(windows)] #[cfg(not(any(target_os = "android", target_os = "ios")))]
Data::ClipboardFile(_clip) => { Data::ClipboardFile(_clip) => {
#[cfg(windows)] #[cfg(windows)]
{ {
if !_clip.is_stopping_allowed() || self.file_transfer_enabled {
let conn_id = self.conn_id; let conn_id = self.conn_id;
ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 { ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 {
clipboard::server_clip_file(context, conn_id, _clip) clipboard::server_clip_file(context, conn_id, _clip)
}); });
} }
} }
#[cfg(windows)]
Data::ClipboardFileEnabled(_enabled) => {
#[cfg(windows)]
self.enable_cliprdr_file_context(self.conn_id, _enabled).await;
} }
Data::Theme(dark) => { Data::Theme(dark) => {
self.cm.change_theme(dark); self.cm.change_theme(dark);
@ -457,6 +418,11 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
} }
} }
Some(data) = self.rx.recv() => { Some(data) = self.rx.recv() => {
if let Data::SwitchPermission{name, enabled} = &data {
if name == "file" {
self.file_transfer_enabled = *enabled;
}
}
if self.stream.send(&data).await.is_err() { if self.stream.send(&data).await.is_err() {
break; break;
} }
@ -464,8 +430,10 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
clip_file = rx_clip.recv() => match clip_file { clip_file = rx_clip.recv() => match clip_file {
Some(_clip) => { Some(_clip) => {
#[cfg(windows)] #[cfg(windows)]
if !_clip.is_stopping_allowed() || self.file_transfer_enabled {
allow_err!(self.tx.send(Data::ClipboardFile(_clip))); allow_err!(self.tx.send(Data::ClipboardFile(_clip)));
} }
}
None => { None => {
// //
} }
@ -517,6 +485,13 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
allow_err!(crate::privacy_win_mag::start()); allow_err!(crate::privacy_win_mag::start());
}); });
#[cfg(target_os = "windows")]
ContextSend::enable(
Config::get_option("enable-file-transfer").is_empty(),
true,
crate::is_server(),
);
match ipc::new_listener("_cm").await { match ipc::new_listener("_cm").await {
Ok(mut incoming) => { Ok(mut incoming) => {
while let Some(result) = incoming.next().await { while let Some(result) = incoming.next().await {

View File

@ -857,6 +857,8 @@ async fn check_connect_status_(reconnect: bool, rx: mpsc::UnboundedReceiver<ipc:
let mut rx = rx; let mut rx = rx;
let mut mouse_time = 0; let mut mouse_time = 0;
let mut id = "".to_owned(); let mut id = "".to_owned();
let mut enable_file_transfer = "".to_owned();
loop { loop {
if let Ok(mut c) = ipc::connect(1000, "").await { if let Ok(mut c) = ipc::connect(1000, "").await {
let mut timer = time::interval(time::Duration::from_secs(1)); let mut timer = time::interval(time::Duration::from_secs(1));
@ -875,6 +877,19 @@ async fn check_connect_status_(reconnect: bool, rx: mpsc::UnboundedReceiver<ipc:
Ok(Some(ipc::Data::Options(Some(v)))) => { Ok(Some(ipc::Data::Options(Some(v)))) => {
*OPTIONS.lock().unwrap() = v; *OPTIONS.lock().unwrap() = v;
*OPTION_SYNCED.lock().unwrap() = true; *OPTION_SYNCED.lock().unwrap() = true;
#[cfg(target_os="windows")]
{
let b = OPTIONS.lock().unwrap().get("enable-file-transfer").map(|x| x.to_string()).unwrap_or_default();
if b != enable_file_transfer {
clipboard::ContextSend::enable(
b.is_empty(),
true,
crate::is_server(),
);
enable_file_transfer = b;
}
}
} }
Ok(Some(ipc::Data::Config((name, Some(value))))) => { Ok(Some(ipc::Data::Config((name, Some(value))))) => {
if name == "id" { if name == "id" {

View File

@ -198,6 +198,7 @@ impl<T: InvokeUiSession> Session<T> {
pub fn toggle_option(&mut self, name: String) { pub fn toggle_option(&mut self, name: String) {
let msg = self.lc.write().unwrap().toggle_option(name.clone()); let msg = self.lc.write().unwrap().toggle_option(name.clone());
#[cfg(not(feature = "flutter"))]
if name == "enable-file-transfer" { if name == "enable-file-transfer" {
self.send(Data::ToggleClipboardFile); self.send(Data::ToggleClipboardFile);
} }