From a77a15f6b665092bef89b0d6b030db84ee0c4ec2 Mon Sep 17 00:00:00 2001 From: "ekko.bao" Date: Wed, 7 Aug 2024 21:11:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E6=8F=90=E4=BA=A4=EF=BC=9A?= =?UTF-8?q?=201.=20=E6=B7=BB=E5=8A=A0=E7=99=BB=E9=99=86=E5=92=8C=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E7=9B=B8=E5=85=B3code=E3=80=82=E5=B7=B2ok=202.=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=95=B0=E6=8D=AE=E5=B9=B6=E6=94=BE=E7=BD=AE?= =?UTF-8?q?=E5=88=B0=E5=89=AA=E5=88=87=E6=9D=BF=E7=9B=B8=E5=85=B3code=20?= =?UTF-8?q?=E5=B7=B2ok=203.=20=E5=AE=9A=E4=B9=89=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=E5=A4=B4=EF=BC=8C=E4=BB=A5=E4=BE=BF?= =?UTF-8?q?=E4=BA=8E=E9=95=BFmsg=E7=9A=84=E5=88=87=E5=89=B2=EF=BC=9A=20=20?= =?UTF-8?q?=20=20=20${index}@${revicesize}@=20=20=20=20=20index=EF=BC=9A?= =?UTF-8?q?=20=E6=8B=86=E5=88=86=E5=90=8E=E7=9A=84=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=8C=85=E7=9A=84=E7=BC=96=E5=8F=B7=E4=B8=A4=E4=B8=AA=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=BD=BF=E7=94=A8ascii=E7=BC=96=E7=A0=81=20=20=20=20?= =?UTF-8?q?=20revicesize=EF=BC=9A=E5=B7=B2=E6=8E=A5=E6=94=B6=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=9A=84=E9=95=BF=E5=BA=A6=EF=BC=8C=E4=B8=89?= =?UTF-8?q?=E4=B8=AA=E5=AD=97=E7=AC=A6=204.=20=E6=96=B0=E5=BB=BA=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E7=BA=BF=E7=A8=8B=E5=8E=BB=E6=8C=81=E7=BB=AD=E7=9B=91?= =?UTF-8?q?=E5=90=AC=EF=BC=9A=E5=BD=93=E9=BC=A0=E6=A0=87=E7=84=A6=E7=82=B9?= =?UTF-8?q?=E7=A7=BB=E5=BC=80=E6=9F=90=E5=BA=94=E7=94=A8=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E6=97=B6=E8=A7=A6=E5=8F=91=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 17 +++++ src/lib.rs | 174 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 45 ++++++++++++ src/wclip/mod.rs | 21 ++++++ 4 files changed, 257 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 src/wclip/mod.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e70259a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "clipboard_sync" +version = "0.1.0" +edition = "2021" + +[dependencies] +tokio = { version = "1.39.2", features = ["macros", "rt-multi-thread"] } +tokio-macros = "2.4.0" +reqwest="0.12.5" +log="0.4.22" +env_logger="0.8" +url = "2.2" +percent-encoding = "2.1" +trust-dns-resolver = "0.20" +select = "0.5" +scraper = "0.12" +arboard = "3.4.0" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..11e0732 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,174 @@ +use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; +use reqwest::header::{HeaderMap, CONTENT_TYPE, COOKIE}; +use reqwest::{Client, Response}; +use scraper::{Html, Selector}; +use std::error::Error; +use std::io; +use std::thread; +extern crate log; + +pub mod wclip; +pub struct ClipboardSync { + user_name: String, + password: String, + web: Client, + ip: String, + cookies: String, + clip: wclip::Wclip, +} + +const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42"; + +fn quote(input: &String) -> String { + percent_encode(input.as_bytes(), NON_ALPHANUMERIC).to_string() +} + +pub struct ClipboardMsgs { + pub msgs: Vec, +} + +impl ClipboardSync { + pub fn new(ip: &str, user_name: &str, password: &str) -> ClipboardSync { + ClipboardSync { + user_name: user_name.to_string(), + password: password.to_string(), + web: Client::new(), + ip: ip.to_string(), + cookies: "".to_string(), + clip: wclip::Wclip::new(), + } + } + + pub async fn run(&mut self) Result<(), Box>{ + self.login()?; + let arctx = Arc::new(Mutex::new(self)); + let ctx = arctx.clone(); + let handle = thread::spawn(move || { + let mut ctx = ctx.lock().unwrap() + loop{ + ctx.update_msg().await; + + } + }) + thread::join(handle).unwrap(); + Ok(()) + } + + async fn verify(&self) -> Result> { + // 开始验证 + let security_check_url = format!("http://{}/SSWeb/rd/j_security_check", self.ip); + let mut headers = HeaderMap::new(); + headers.insert("Host", "ssweb".parse().unwrap()); + headers.insert("Connection", "keep-alive".parse().unwrap()); + headers.insert("Cache-Control", "max-age=0".parse().unwrap()); + headers.insert("Origin", "http://ssweb".parse().unwrap()); + headers.insert("DNT", "1".parse().unwrap()); + headers.insert("Upgrade-Insecure-Requests", "1".parse().unwrap()); + headers.insert( + "Content-Type", + "application/x-www-form-urlencoded".parse().unwrap(), + ); + headers.insert("User-Agent", USER_AGENT.parse().unwrap()); + headers.insert("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9".parse().unwrap()); + headers.insert( + "Referer", + "http://ssweb/SSWeb/rd/copy_paste.jsp".parse().unwrap(), + ); + headers.insert("Accept-Encoding", "gzip, deflate".parse().unwrap()); + headers.insert( + "Accept-Language", + "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6" + .parse() + .unwrap(), + ); + headers.insert("Cookie", self.cookies.parse().unwrap()); + let contents = format!( + "j_username={}&j_password={}", + quote(&self.user_name), + quote(&self.password) + ); + let resp = self + .web + .post(security_check_url) + .headers(headers) + .body(contents) + .send() + .await?; + Ok(resp) + } + fn get_cookies(response: &Response) -> String { + let mut session = String::new(); + let headers: &HeaderMap = response.headers(); + if let Some(header_value) = headers.get("Set-Cookie") { + if let Ok(value) = header_value.to_str() { + log::info!("Set-Cookie: {}", value); + session = value.split(';').next().unwrap().to_string(); + } + } else { + log::error!("cookies not found"); + } + session + } + pub async fn login(&mut self) -> Result<(), Box> { + let mut headers = HeaderMap::new(); + headers.insert("User-Agent", USER_AGENT.parse().unwrap()); + let url = format!("http://{}/SSWeb/rd/copy_paste.jsp", self.ip); + let response = self.web.get(url).headers(headers).send().await?; + self.cookies = ClipboardSync::get_cookies(&response); + log::info!("cookies is {}", self.cookies); + let mut resp = response.text().await?; + log::trace!("Response: {}", resp); + if resp.contains("loginForm") { + let response = self.verify().await?; + resp = response.text().await?; + log::trace!("verify Response: {}", resp); + } + if resp.contains("Copy & Paste") { + self.parse_msg(&resp).await; + Ok(()) + } else { + Err(Box::new(io::Error::new(io::ErrorKind::Other, "登录失败"))) + } + } + + pub asyn fn update_msg(&mut self) -> Result<(), Box> { + //http://ssweb/SSWeb/rd/copy_paste.jsp?d-16544-p=1&d-16544-s=2 + //d-16544-s 2:时间从靠近现在开始排序 1:时间从最早开始排序 + //d-16544-o mesage排序,不要设置 + //d-16544-p=1 页码 + let url = format!("http://{}/SSWeb/rd/copy_paste.jsp?d-16544-p=1&d-16544-s=2", self.ip); + let mut headers = HeaderMap::new(); + headers.insert("Host", "ssweb".parse().unwrap()); + headers.insert("Connection", "keep-alive".parse().unwrap()); + headers.insert("Cache-Control", "max-age=0".parse().unwrap()); + headers.insert("DNT", "1".parse().unwrap()); + headers.insert("Upgrade-Insecure-Requests", "1".parse().unwrap()); + headers.insert("User-Agent", USER_AGENT.parse().unwrap()); + headers.insert("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9".parse().unwrap()); + headers.insert("Accept-Encoding", "gzip, deflate".parse().unwrap()); + headers.insert("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6".parse().unwrap()); + let response = self.web.get(url).headers(headers).send().await?; + let resp = response.text().await?; + self.parse_msg(&resp).await; + Ok(()) + } + + pub async fn parse_msg(&mut self, html: &str) -> Result> { + // log::info!("html: {}", html); + let document = Html::parse_document(html); + let selector = Selector::parse("code").unwrap(); + for element in document.select(&selector) { + //let text = element.text().collect::>().concat(); + let text = element.text().collect::(); + log::info!("Found: [{}]", text); + if text[0] == '@' && text[6] == '@' { + items = text.split('@').map(|x| x.trim()).collect::>(); + index = items.next(); + index = items.next(); + } + self.clip.set(&text); + break; + } + Ok(ClipboardMsgs { msgs: vec![] }) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..32e27a3 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,45 @@ +extern crate log; +use clipboard_sync::ClipboardSync; +use std::net::IpAddr; +use trust_dns_resolver::{ + config::{ResolverConfig, ResolverOpts}, + Resolver, +}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + env_logger::init(); + // // 创建自定义 DNS 解析器 + // let resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap(); + + // // 要解析的域名 + // let response = resolver.lookup_ip("www.baidu.com"); + // match response { + // Ok(response) => { + // for ip in response { + // match ip { + // IpAddr::V4(v4) => println!("IPv4: {}", v4), + // IpAddr::V6(v6) => println!("IPv6: {}", v6), + // } + // } + // } + // Err(e) => { + // println!("Error: {}", e); + // } + // } + + let mut ins = ClipboardSync::new("172.19.36.79", "ekko.bao", "qwer12345;"); + match ins.login().await { + Ok(()) => log::info!("登录成功"), + Err(e) => { + log::error!("登录失败: {}", e); + } + } + // 获取 Cookies + //if let Some(cookies) = response.headers().get(COOKIE) { + // println!("Cookies: {:?}", cookies); + //} else { + // println!("No cookies found."); + //} + Ok(()) +} diff --git a/src/wclip/mod.rs b/src/wclip/mod.rs new file mode 100644 index 0000000..40e34de --- /dev/null +++ b/src/wclip/mod.rs @@ -0,0 +1,21 @@ +use arboard::Clipboard; + +pub struct Wclip { + clipboard: Clipboard, +} + +impl Wclip { + pub fn new() -> Wclip { + Wclip { + clipboard: Clipboard::new().unwrap(), + } + } + + pub fn set(&mut self, text: &str) { + self.clipboard.set_text(text).unwrap(); + } + + pub fn get(&mut self) -> String { + self.clipboard.get_text().unwrap() + } +}