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