cloudpub_client/plugins/onec/
mod.rs

1use 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        // if local_addr is existing path and folder, append File= else use as is
129        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}