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!("Платформа 1C не найдена, укажите ее битность (x32/x64) и путь в настройках");
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!(
56            "Путь до платформы 1C ({}) не найден, укажите его в настройках",
57            env.home_1c.to_str().unwrap()
58        );
59    }
60    Ok(env)
61}
62
63pub struct OneCPlugin;
64
65#[async_trait]
66impl Plugin for OneCPlugin {
67    fn name(&self) -> &'static str {
68        "onec"
69    }
70
71    async fn setup(
72        &self,
73        config: &Arc<RwLock<ClientConfig>>,
74        _opts: &ClientOpts,
75        command_rx: &mut mpsc::Receiver<Message>,
76        result_tx: &mpsc::Sender<Message>,
77    ) -> Result<()> {
78        let env = check_enviroment(config.clone())?;
79        setup_httpd(config, command_rx, result_tx, env).await
80    }
81
82    async fn publish(
83        &self,
84        endpoint: &ServerEndpoint,
85        config: &Arc<RwLock<ClientConfig>>,
86        _opts: &ClientOpts,
87        result_tx: &mpsc::Sender<Message>,
88    ) -> Result<SubProcess> {
89        let env = check_enviroment(config.clone())?;
90
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        let publish_dir = one_c_publish_dir.join(&endpoint.guid);
99
100        std::fs::create_dir_all(publish_dir.clone()).context("Can't create publish dir")?;
101
102        let mut default_vrd = publish_dir.clone();
103        default_vrd.push("default.vrd");
104
105        let wsap_error = format!(
106            "Модуль {} на найден в {}. Проверьте настройки и убедитесь что у вас установлены модули расширения веб-сервера для 1С", WSAP_MODULE, &env.home_1c.to_str().unwrap());
107
108        let wsap = if let Some(wsap) =
109            find(&env.home_1c, &PathBuf::from(WSAP_MODULE)).context(wsap_error.clone())?
110        {
111            wsap
112        } else {
113            bail!(wsap_error);
114        };
115
116        let local_addr = endpoint.client.as_ref().unwrap().local_addr.clone();
117        // if local_addr is existing path and folder, append File= else use as is
118        let ib = if std::path::Path::new(&local_addr).exists() {
119            format!("File=\"{}\"", local_addr)
120        } else {
121            local_addr.clone()
122        };
123
124        let vrd_config = DEFAULT_VRD.replace("[[IB]]", &escape_str_attribute(&ib));
125
126        if !default_vrd.exists() {
127            std::fs::write(&default_vrd, vrd_config).context("Ошибка записи default.vrd")?;
128        }
129
130        let httpd_config = ONEC_CONFIG.replace("[[WSAP_MODULE]]", wsap.to_str().unwrap());
131
132        start_httpd(
133            endpoint,
134            &httpd_config,
135            ONEC_SUBDIR,
136            publish_dir.to_str().unwrap(),
137            env,
138            result_tx.clone(),
139        )
140        .await
141    }
142}