cloudpub_client/plugins/onec/
mod.rs1use crate::config::{ClientConfig, ClientOpts, EnvConfig, ENV_CONFIG};
2use crate::plugins::httpd::{setup_httpd, start_httpd};
3use crate::plugins::Plugin;
4use crate::shell::{find, get_cache_dir, SubProcess};
5use anyhow::{bail, Context, Result};
6use async_trait::async_trait;
7use cloudpub_common::protocol::message::Message;
8use cloudpub_common::protocol::ServerEndpoint;
9use parking_lot::RwLock;
10use std::path::PathBuf;
11use std::sync::Arc;
12use tokio::sync::mpsc;
13use xml::escape::escape_str_attribute;
14
15#[cfg(target_os = "windows")]
16const WSAP_MODULE: &str = "wsap24.dll";
17
18#[cfg(all(unix, debug_assertions))]
19const WSAP_MODULE: &str = "wsap24t.so";
20
21#[cfg(all(unix, not(debug_assertions)))]
22const WSAP_MODULE: &str = "wsap24.so";
23
24pub const ONEC_SUBDIR: &str = "1c";
25const ONEC_CONFIG: &str = include_str!("httpd.conf");
26const DEFAULT_VRD: &str = include_str!("default.vrd");
27
28fn detect_platform() -> Option<EnvConfig> {
29 for patform in ENV_CONFIG.iter() {
30 if std::path::Path::new(&patform.1.home_1c).exists() {
31 return Some((*patform.1).clone());
32 }
33 }
34 None
35}
36
37fn check_enviroment(config: Arc<RwLock<ClientConfig>>) -> Result<EnvConfig> {
38 let env = if let Some(platform) = config.read().one_c_platform.as_ref() {
39 ENV_CONFIG.get(platform).cloned()
40 } else {
41 detect_platform()
42 };
43
44 let mut env = if let Some(env) = env {
45 env
46 } else {
47 bail!(crate::t!("error-onec-platform-not-found"));
48 };
49
50 if let Some(one_c_home) = &config.read().one_c_home {
51 env.home_1c = PathBuf::from(one_c_home);
52 }
53
54 if !std::path::Path::new(&env.home_1c).exists() {
55 bail!(crate::t!("error-onec-path-not-found", "path" => env.home_1c.to_str().unwrap()));
56 }
57 Ok(env)
58}
59
60pub struct OneCPlugin;
61
62#[async_trait]
63impl Plugin for OneCPlugin {
64 fn name(&self) -> &'static str {
65 "onec"
66 }
67
68 async fn setup(
69 &self,
70 config: &Arc<RwLock<ClientConfig>>,
71 _opts: &ClientOpts,
72 command_rx: &mut mpsc::Receiver<Message>,
73 result_tx: &mpsc::Sender<Message>,
74 ) -> Result<()> {
75 let env = check_enviroment(config.clone())?;
76 setup_httpd(config, command_rx, result_tx, env).await
77 }
78
79 async fn publish(
80 &self,
81 endpoint: &ServerEndpoint,
82 config: &Arc<RwLock<ClientConfig>>,
83 _opts: &ClientOpts,
84 result_tx: &mpsc::Sender<Message>,
85 ) -> Result<SubProcess> {
86 let env = check_enviroment(config.clone())?;
87
88 #[cfg(not(target_os = "windows"))]
89 let one_c_publish_dir = config
90 .read()
91 .one_c_publish_dir
92 .as_ref()
93 .map(PathBuf::from)
94 .unwrap_or_else(|| get_cache_dir(ONEC_SUBDIR).unwrap());
95
96 #[cfg(target_os = "windows")]
97 let one_c_publish_dir = config
98 .read()
99 .one_c_publish_dir
100 .as_ref()
101 .map(PathBuf::from)
102 .unwrap_or_else(|| {
103 PathBuf::from(
104 std::env::var("PROGRAMDATA").unwrap_or_else(|_| "C:\\ProgramData".to_string()),
105 )
106 .join("CloudPub")
107 .join(ONEC_SUBDIR)
108 });
109
110 let publish_dir = one_c_publish_dir.join(&endpoint.guid);
111
112 std::fs::create_dir_all(publish_dir.clone()).context("Can't create publish dir")?;
113
114 let mut default_vrd = publish_dir.clone();
115 default_vrd.push("default.vrd");
116
117 let wsap_error = crate::t!("error-onec-wsap-not-found", "module" => WSAP_MODULE, "path" => env.home_1c.to_str().unwrap());
118
119 let wsap = if let Some(wsap) =
120 find(&env.home_1c, &PathBuf::from(WSAP_MODULE)).context(wsap_error.clone())?
121 {
122 wsap
123 } else {
124 bail!(wsap_error);
125 };
126
127 let local_addr = endpoint.client.as_ref().unwrap().local_addr.clone();
128 let ib = if std::path::Path::new(&local_addr).exists() {
130 format!("File=\"{}\"", local_addr)
131 } else {
132 local_addr.clone()
133 };
134
135 let vrd_config = DEFAULT_VRD.replace("[[IB]]", &escape_str_attribute(&ib));
136
137 if !default_vrd.exists() {
138 std::fs::write(&default_vrd, vrd_config)
139 .context(crate::t!("error-onec-writing-vrd"))?;
140 }
141
142 let httpd_config = ONEC_CONFIG.replace("[[WSAP_MODULE]]", wsap.to_str().unwrap());
143
144 start_httpd(
145 endpoint,
146 &httpd_config,
147 ONEC_SUBDIR,
148 publish_dir.to_str().unwrap(),
149 env,
150 result_tx.clone(),
151 )
152 .await
153 }
154}