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