1. 完成消息的接收循环的编写,现在的逻辑是:

1. 如果当前的前台程序是xxx那么就进入等待移出状态,
    2. 如果当前是等待移出状态,然后切换了前台程序到其他程序那就触发一次同步
    3. 同步后进入idle状态等待聚焦到xxx
2. 完成消息的发送基础步骤的准备,自动获取剪切板数据并且根据长度进行拆包进行发送。
3. 创建一个python的flask应用方便快速测试
4. 完成命令行参数的CLI化,方便直接使用,l0就是consumer,l3就是producer
5. 完成用户名的加密解密,使用机器的硬盘序列号进行加密解密
6. 保存msg的magic和cookies,方便重启使用,
    但是目前来说cookies没有也是ok的。
    因为没有做cookies的过期处理还。每次启动都会登录处理,并且登录期间过期的话只会异常,不会恢复,
    所以这块还需要完善一下,如果登录期间发现过期了应当重新认证一下。
7. 等待完善发送的逻辑,这块本意是想要在l3的窗口鼠标移动到边缘之后保持不动就进行发送,
    但是会存在一些和l0之间时序上匹配的问题。
    如果l3另外启动一个用户界面用来交给用户触发交互呢,又做不到程序起初想要的无感的想法,这块还要再确认下
This commit is contained in:
Ekko.bao 2024-08-28 07:53:27 +08:00
parent 4d04dc2677
commit 089bf1e3ac
8 changed files with 1059 additions and 73 deletions

View File

@ -9,14 +9,20 @@ tokio-macros = "2.4.0"
reqwest = "0.12.5" reqwest = "0.12.5"
log = "0.4.22" log = "0.4.22"
env_logger = "0.8" env_logger = "0.8"
clap = "3.0"
url = "2.2" url = "2.2"
percent-encoding = "2.1" percent-encoding = "2.1"
trust-dns-resolver = "0.20" trust-dns-resolver = "0.20"
select = "0.5" select = "0.5"
scraper = "0.12" scraper = "0.12"
arboard = "3.4.0" arboard = "3.4.0"
aes = "0.7"
block-modes = "0.8"
rand = "0.8" # 哈希库
winapi = { version = "0.3.9", features = ["winuser", "psapi"] } winapi = { version = "0.3.9", features = ["winuser", "psapi"] }
base64 = "0.21"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
[profile.test] [profile.test]
env = { "RUST_LOG" = "debug" } env = { "RUST_LOG" = "debug" }

6
info.json Executable file
View File

@ -0,0 +1,6 @@
{
"cookies": "",
"magic": "3",
"password": "ZWtrb2Jhb19fX19fX19fXzlytojwgd3qVW7PNYs7Y9s=",
"user_name": "ekko.bao"
}

View File

@ -0,0 +1,24 @@
from flask import Flask, send_from_directory, request,jsonify
import sys
app = Flask(__name__)
@app.route('/SSWeb/rd/copy_paste.jsp')
def copy_paste():
return send_from_directory('templates', 'copy_paste.html')
@app.route('/SSWeb/rd/copy_paste.jsp', methods=['POST'])
def recive_msg():
# 获取查询参数
send_param = request.args.get('send')
if not send_param:
return jsonify({
"zz": "must send query param"
})
# 获取 JSON 数据
data = request.get_data().decode()
print(f"msg is [{data}]\n")
return send_from_directory('templates', 'copy_paste.html')
if __name__ == '__main__':
sys.stdout.reconfigure(encoding='utf-8')
app.run(host='0.0.0.0', port=5000)

View File

@ -0,0 +1,513 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="/SSWeb/css/ajaxtags.css" />
<link rel="stylesheet" type="text/css" href="/SSWeb/css/screen.css" />
<link rel="stylesheet" type="text/css" href="/SSWeb/css/select2.min.css" />
<link rel="stylesheet" type="text/css" href="/SSWeb/js/jquery-ui.min.css" media="print" />
<link rel="stylesheet" type="text/css" href="/SSWeb/js/themes/base/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="/SSWeb/js/Searchable-Multi-select/jquery.dropdown.css" />
<script type="text/javascript" src="/SSWeb/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="/SSWeb/js/prototype-1.7.3.js"></script>
<script type="text/javascript" src="/SSWeb/js/scriptaculous/scriptaculous.js"></script>
<script type="text/javascript" src="/SSWeb/js/overlibmws/overlibmws.js"></script>
<script type="text/javascript" src="/SSWeb/js/ajaxtags.js"></script>
<script type="text/javascript" src="/SSWeb/js/common.js"></script>
<script type="text/javascript" src="/SSWeb/js/show_line.js"></script>
<script type="text/javascript" src="/SSWeb/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="/SSWeb/js/select2/dist/js/select2.min.js"></script>
<script type="text/javascript" src="/SSWeb/js/jquery-ui.min.js"></script>
<script type="text/javascript" src="/SSWeb/js/Searchable-Multi-select/jquery.dropdown.js"></script>
<style>
.input {
width: 100%;
}
.fixline {
white-space: nowrap;
}
.btn-lg {
padding: 5px 8px;
font-size: 12px;
line-height: 1.33;
border-radius: 6px;
}
.btn-primary {
color: #fff;
background-color: #428bca;
border-color: #357ebd;
}
.noteMacro {
border-style: solid;
border-width: 1px;
border-color: #F0C000;
background-color: #FFFFCE;
text-align: left;
margin-top: 5px;
margin-bottom: 5px
}
.infoMacro {
border-style: solid;
border-width: 1px;
border-color: #3c78b5;
background-color: #D8E4F1;
text-align: left;
margin-top: 5px;
margin-bottom: 5px
}
</style>
<title>Copy & Paste</title>
</head>
<body>
<script>
var jBPM = jQuery.noConflict();
</script>
<form id="copy_paste" name="copy_paste" method="post" action="copy_paste.jsp?send=y">
<table style="width:100%" class="simple">
<thead>
<tr>
<th>Message (maxiumn 300 characters)</th>
<th>Execute</th>
<th>Tips</th>
</tr>
</thead>
<tbody>
<tr>
<td style="width:80%;"><textarea id="message" name="message"
style="width:100%;height:80px"></textarea></td>
<td style="width:10%;vertical-align:middle;"><input type="submit" value="Send Message" /></td>
<td style="width:10%;vertical-align:middle;"><input type="button" value="Show Tips"
onclick='javascript: jBPM("#page_tips").show();' /></td>
</tr>
</tbody>
</table>
</form>
<table id="page_tips" style="display:none;" cellpadding="5" width="80%" cellspacing="8px" class="infoMacro"
border="0">
<colgroup>
<col width="24">
<col>
</colgroup>
<tr>
<td>
</td>
<td style="text-align:left;width:80%">
1. ..................300......<br />
2. .................................<br />
3. .......................................
</td>
<td style="text-align:right;"><input type="button" value="X"
onclick='javascript:jBPM("#page_tips").hide(); '></td>
</tr>
</table>
<span class="pagebanner">59 items found, displaying 1 to 50.</span><span class="pagelinks">[First/Prev]
<strong>1</strong>, <a href="/SSWeb/rd/copy_paste.jsp?d-16544-p=2" title="Go to page 2">2</a> [<a
href="/SSWeb/rd/copy_paste.jsp?d-16544-p=2">Next</a>/<a
href="/SSWeb/rd/copy_paste.jsp?d-16544-p=2">Last</a>]</span>
<table class="mars" style="width:100%;" id="row">
<caption><u>Message List</u></caption>
<thead>
<tr>
<th class="sortable">
<a href="/SSWeb/rd/copy_paste.jsp?d-16544-p=1&amp;d-16544-o=2&amp;d-16544-s=0">Message</a>
</th>
<th class="sortable sorted order2">
<a href="/SSWeb/rd/copy_paste.jsp?d-16544-p=1&amp;d-16544-o=2&amp;d-16544-s=1">Create_Date_Time</a>
</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#eec;'>剪切板测试函数</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-10-20 11:25:09.92</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>C:\Users\ekko.bao\Desktop\......</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-10-20 11:24:14.543</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki:8090/pages/viewpage.action?pageId=41925635</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-10-11 17:15:46.733</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#ccb;'> ldc stop channel too long,so force stop&destroy channel resource,then when ldc pass task use channel resources, crash happen
</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-09-15 10:06:45.327</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>the return value is the number of milliseconds remaining in the originally requested sleep period</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-09-14 15:18:48.05</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>find ./cmodel_ut/output -name "Dst*" |xargs ls -t | xargs -i md5sum {} > ./md5.txt</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-09-08 11:53:33.86</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>https://blog.csdn.net/weixin_42319283/article/details/85089887</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-09-05 10:04:31.997</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>eval $(find ./ -name "*0.bmp" | xargs -i printf "\"/mnt/d/software/Beyond\ Compare\ 4/BCompare.exe\" %s ../../%s;\n" {} {} | xargs -i printf "date;echo \"start %s\";%s echo end;" {} {})</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-08-09 20:08:09.93</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>eval $(cat check_ut_result/test7/result.txt | grep FAIL | awk '{printf "./prog_ldc_ut -c %s -C;\n", $3}')</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-08-09 20:01:22.627</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>f82d0b02-3a00-43ed-b33b-18e5766035e5</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-07-11 11:20:22.407</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>92b100a1-8981-4c74-8a0e-ba4ab8975adb</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-06-22 11:05:09.673</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>5fbf21f4-d9ed-4325-97ed-4109220d9021</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-06-20 16:00:29.843</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>a173712a-3c38-4e38-9f61-75b03c9d5a68</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-06-14 19:56:49.29</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#ccb;'>............: [LDC] ......LDC EIS .........bypass......
............: 1. ..............................vpe_ldc...ldc............
2. ......ldc&vpe_ldc.....................
..................review..................</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-03-02 21:45:44.06</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#eec;'>..................review..................
............: [LDC] EIS..............................
............: 1. ............L3...CV......................................................</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-03-02 21:45:16.637</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>1. ...............LDC mi_eptz_linux.h.................................lib.............................................................................................................................................................................................-----------............
2.wiki...... eptz user guide...............................................................-----...........................</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-03-01 21:42:29.107</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#eec;'>1. ......ldc..................
EPTZ ...Cylinder Projection... EquiRectangularProjection...........................WM DM CM..................
Donut.................................
Bypass...RCS...MAP2BIN......
.........STITCH...PERSPECTIVE......
........................lib.......................................</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-03-01 21:42:15.73</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>............: [LDC] EIS..............................
............: 1. ......LDC.......................................mjson...............
.......................................................................................
......claude.................................................................................UTjson.....................LDC................................................</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-02-28 21:46:52.983</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>machine hcgit04 login ekko.bao password ve5hVjZePgMfo8YOBXeH09BzaLufKw+xBdNOq9h5Yw</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-02-25 16:51:25.16</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#ccb;'>machine hcgit04 login USER_NAME password HTTP_PASSWORD
machine hcgit04-master login USER_NAME password HTTP_PASSWORD
machine hcgit04-sz login USER_NAME password HTTP_PASSWORD
machine hcgit04-sh login USER_NAME password HTTP_PASSWORD</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-02-25 15:40:49.633</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#eec;'>............: [LDC] EIS......... (SOC_I7)
............: 1. .....................proc fs..............................proc fs...............
http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-MI-LDC%28EIS%29-flow
http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-mi_ldcx_procfs_parse</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-02-24 21:34:01.697</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-create-mi-ldc-eis-demo-env</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-02-23 21:41:34.017</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-devlop_flow</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-02-21 21:40:54.953</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learn-fourth_week-0207-0213#Ekko-learn-fourth_week-0207-0213-CMDQ%E6%80%BB%E7%BB%93</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-02-08 21:26:28.69</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learn-fourth_week-0207-0213</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-02-07 18:04:37.017</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>https://blog.csdn.net/abcwoabcwo/article/details/93099982</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-27 10:10:16.68</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/MHAL_DIS-interface_doc</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-27 10:10:14.037</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>http://sswiki.sigmastar.com.tw:8090/display/MI/MHAL_DIS-interface_doc</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-26 21:51:48.77</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/pages/editpage.action?pageId=28944730</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-26 21:51:32.287</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>f output image height is 1512, then the height of each slice is 1512/6=252, which is close to 256 if align to 32. If you choose LdcDisSlice=7, then the height of each slice is 1512/7=216, which is not close to 256</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-26 11:05:20.77</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>Set higher for more stable image but at the expense of CPU usage</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-26 11:04:23.627</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>http://sswiki.sigmastar.com.tw:8090/display/MI/MHAL_DIS-interface_doc</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-25 21:35:52.353</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learn-third_week-0124-0130</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-25 21:35:44.177</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learn-third_week-0124-0130#Ekko-learn-third_week-0124-0130-%E5%A2%9E%E5%8A%A0procfs</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-24 21:33:03.9</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learn-second_week-0117-0123#Ekko-learn-second_week-0117-0123-%E7%BC%96%E8%AF%91%E6%A1%86%E6%9E%B6%E8%A7%A3%E8%AF%BB</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-24 21:32:46.773</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learn-second_week-0117-0123#Ekko-learn-second_week-0117-0123-%E8%B7%9F%E8%B8%AA%EF%BC%9A</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-21 21:39:55.213</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learn-second_week-0117-0123#Ekko-learn-second_week-0117-0123-2022/01/19</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-19 21:34:06.807</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>http://www.cnblogs.com/king-77024128/articles/2666230.html</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-19 10:12:20.44</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>file://szswfs01/SSARTIFACTS/NONSYNC/</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-18 16:48:57.65</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>sigmastar/L3/autorelease/alkaid/sdk/docs</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-18 10:37:18.5</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learn-second_week-0117-0123</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-17 21:40:56.903</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>Digital Overlap High Dynamic Range</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-17 18:00:31.783</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learning-2022_01_14</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-14 21:01:21.743</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>in/map/fisheye/new_AMTK_FHD/CalibPoly_new.bin</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-14 10:06:00.52</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>in/map/fisheye/new_AMTK_FHD/CalibPoly_new.bin</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-14 09:45:05.487</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>cfg/bin/TableMode/multiband/sh/dualsensor/1920x1080x2_st.bin</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-14 09:44:40.43</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#eec;'>http://sswiki.sigmastar.com.tw:8090/display/MI/Ekko-learning-2022_01_13</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-13 21:55:37.52</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre
style='font-size:12px;'><code style='background-color:#ccb;'>boot.bin = IPL.bin + IPL_CUST.bin + u-boot </code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-13 21:49:28.853</td>
</tr>
<tr class="odd">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#eec;'>MI LDC Training</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-13 16:39:14.647</td>
</tr>
<tr class="even">
<td style="text-align:left;width:80%;">
<pre style='font-size:12px;'><code style='background-color:#ccb;'>declare -x</code></pre>
</td>
<td class="fixline" style="width:10%;vertical-align:middle;">2022-01-13 11:24:59.05</td>
</tr>
</tbody>
</table>
</body>
</html>
<script>
jBPM("#copy_paste").submit(function () {
var msg = jBPM("#message").val();
var len = msg.replace(/[^\x00-\xff]/g, "xx").length;
if (len > 300) {
alert("Input text length " + len + " is more than limit characters.");
return false;
}
});
</script>

96
src/encrypt/mod.rs Executable file
View File

@ -0,0 +1,96 @@
use std::error::Error;
use std::process::Command;
extern crate log;
use aes::Aes128;
use block_modes::{BlockMode, Cbc};
use block_modes::block_padding::Pkcs7;
use base64::{Engine as _, engine::general_purpose};
type Aes128Cbc = Cbc<Aes128, Pkcs7>;
use std::fmt;
#[derive(Debug)]
pub enum EncryptErr {
NotBase64,
}
impl fmt::Display for EncryptErr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
EncryptErr::NotBase64 => write!(f, "String is not base64"),
}
}
}
impl std::error::Error for EncryptErr {}
pub fn get_key() -> String {
let output = Command::new("wmic")
.args(&["DISKDRIVE", "get", "serialnumber"])
.output()
.expect("Failed to execute command");
let serial = String::from_utf8_lossy(&output.stdout)
.lines()
.nth(1) // 获取第二行,通常是序列号
.unwrap()
.trim()
.to_string();
log::trace!("hdd serial is {}", serial);
serial
}
pub fn is_base64(encrypted_data: &str) -> bool {
match general_purpose::STANDARD.decode(encrypted_data) {
Ok(_) => true,
Err(_) => false,
}
}
pub fn encrypt(raw_data: &str, key: &str, iv:&str) -> String {
let key = append_align(key);
let iv = append_align(iv);
let cipher = Aes128Cbc::new_from_slices(&key, &iv).unwrap();
let pos = cipher.encrypt_vec(&raw_data.as_bytes());
// println!("pos buff size is {} {}, {}", general_purpose::STANDARD.encode(&pos), pos.len(), data.len());
let ret = [iv.to_vec(), pos.to_vec()].concat();// Prepend IV for decryption
general_purpose::STANDARD.encode(ret)
}
pub fn decrypt(encrypted_data: &str, key: &str) -> Result<String, Box<dyn Error>> {
let key: Vec<u8> = append_align(key);
let encrypted_data = general_purpose::STANDARD.decode(encrypted_data)?;
let (iv, data) = encrypted_data.split_at(16); // First 16 bytes are IV
let cipher = Aes128Cbc::new_from_slices(&key, &iv)?;
let decrypted_data = cipher.decrypt_vec(data).unwrap();
let result = String::from_utf8(decrypted_data)?;
Ok(result)
}
fn append_align(uuid: &str) -> Vec<u8> {
let mut key = uuid.as_bytes().to_vec();
key.resize(16, b'_');
key
}
#[test]
fn test_get_key(){
get_key();
}
#[test]
fn test_encrypt_decrypt() {
let user_name = "ekko.bao";
let password = "PASSWORD";
let machine_id = get_key();
let encrypted_data = encrypt(password,&machine_id, user_name);
// println!("encrypted_data is {}", encrypted_data);
let ret = decrypt(&encrypted_data, &machine_id).unwrap();
println!("decrypt is {}", ret);
assert_eq!(password, ret);
}

View File

@ -1,34 +1,136 @@
use log::Log;
use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
use rand::{random, Rng};
use reqwest::header::HeaderMap; use reqwest::header::HeaderMap;
use reqwest::{Client, Response}; use reqwest::{Client, Response};
use scraper::{Html, Selector}; use scraper::{Html, Selector};
use core::ascii;
use std::error::Error; use std::error::Error;
use std::io; use std::io::{self, Write};
use std::time::Duration; use std::time::Duration;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use std::sync::Arc; use std::sync::Arc;
use tokio::{task, time}; use tokio::{task, time};
use std::collections::BTreeMap; use std::collections::BTreeMap;
extern crate log; extern crate log;
use serde_json::{self, to_string, Value};
use serde::Serialize;
use std::fs::File;
use std::io::BufReader;
pub mod wclip; pub mod wclip;
pub mod sys_res; pub mod sys_res;
pub mod encrypt;
use sys_res::*; use sys_res::*;
pub struct ClipboardSync {
#[derive(Debug, Serialize, Default)]
pub struct Config {
user_name: String, user_name: String,
password: String, password: String,
cookies: String,
magic: String,
save_path: String,
}
impl Config {
pub fn new(json_file: &str) -> Result<Config, Box<dyn Error>> {
let file = File::open(json_file)?;
let reader = BufReader::new(file);
let json: Value = serde_json::from_reader(reader)?;
let user_name = json.get("user_name").expect("not found user_name in info.json").as_str().unwrap().to_string();
log::info!("user_name is {}", user_name);
let mut password = json.get("password").expect("not found password in info.json").as_str().unwrap().to_string();
let magic = match json.get("magic") {
Some(magic) => magic.as_str().unwrap().to_string(),
None => "~".to_string(),
};
let cookies = match json.get("cookies") {
Some(cookies) => cookies.as_str().unwrap().to_string(),
None => "".to_string(),
};
let gen_cfg = move |user_name:String, password:String|{
let cfg = Config {
user_name,
password,
cookies,
magic,
save_path: json_file.to_string()
};
cfg
};
drop(json);
if encrypt::is_base64(&password) {
let key = encrypt::get_key();
let _ = encrypt::decrypt(&password, &key)?;
Ok(gen_cfg(user_name, password))
} else {
let key = encrypt::get_key();
password = encrypt::encrypt(&password, &key, &user_name);
let cfg = gen_cfg(user_name, password);
cfg.update();
Ok(cfg)
}
}
pub fn update(&self) {
let json = serde_json::json!({
"user_name": self.user_name,
"password": self.password,
"cookies": self.cookies,
"magic": self.magic,
});
let json = serde_json::to_string_pretty(&json).unwrap();
let mut f = File::options().truncate(true).write(true).create(true).open(&self.save_path).unwrap();
let _ = f.write(json.as_bytes());
}
pub fn user_name(&mut self, value: Option<&str>) -> &str {
if let Some(value) = value {
self.user_name = value.to_string();
self.update();
}
&self.user_name
}
pub fn password(&mut self, value: Option<&str>) -> String {
if let Some(value) = value {
let key = encrypt::get_key();
self.password = encrypt::encrypt(&value, &key, &self.user_name);
self.update();
}
let key = encrypt::get_key();
encrypt::decrypt(&self.password, &key).expect("password cant decrypt")
}
pub fn cookies(&mut self, value: Option<&str>) -> &str {
if let Some(value) = value {
self.cookies = value.to_string();
self.update();
}
&self.cookies
}
pub fn magic(&mut self, value: Option<&str>) -> &str {
if let Some(value) = value {
self.magic = value.to_string();
self.update();
}
&self.magic
}
}
pub struct ClipboardSync {
web: Client, web: Client,
ip: String, ip: String,
cookies: String,
clip: wclip::Wclip, clip: wclip::Wclip,
//last message magic cfg: Config,
cache_magic: String,
} }
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"; 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 { fn quote(input: &str) -> String {
percent_encode(input.as_bytes(), NON_ALPHANUMERIC).to_string() percent_encode(input.as_bytes(), NON_ALPHANUMERIC).to_string()
} }
@ -36,14 +138,49 @@ pub struct ClipboardMsgs {
pub msgs: Vec<String>, pub msgs: Vec<String>,
} }
#[derive(Debug)]
enum MsgSyncState {
None,
ForceInVM,
NeedSync,
}
// 同步获取消息的线程 // 同步获取消息的线程
async fn msg_sync(ctx:Arc<Mutex<ClipboardSync>>) { async fn msg_sync(ctx:Arc<Mutex<ClipboardSync>>) {
let VM_EXE_NAME = "Code.exe".to_string();
let mut ctx = ctx.lock().await; let mut ctx = ctx.lock().await;
let mut sta = MsgSyncState::None;
let mut turn_time;
//let _ = ctx.update_msg().await;
loop{ loop{
let _ = ctx.update_msg().await; log::trace!("current state is {:?}", sta);
time::sleep(Duration::new(10, 0)).await; match sta{
MsgSyncState::None => {
turn_time = 200;
let prog_name = get_foredround_window_name(); let prog_name = get_foredround_window_name();
if prog_name == "VMware Horizon Client"{ if prog_name == VM_EXE_NAME {
sta = MsgSyncState::ForceInVM;
turn_time = 0;
} else {
log::trace!("foreground prog is [{}] {}, waiting: [{}] {}", prog_name, prog_name.len(), VM_EXE_NAME, VM_EXE_NAME.len());
}
},
MsgSyncState::ForceInVM => {
turn_time = 100;
let prog_name = get_foredround_window_name();
if prog_name != VM_EXE_NAME {
turn_time = 0;
sta = MsgSyncState::NeedSync;
}
},
MsgSyncState::NeedSync => {
turn_time = 0;
let _ = ctx.update_msg().await;
sta = MsgSyncState::None;
},
}
if turn_time != 0 {
time::sleep(Duration::new(0, turn_time*1000*1000)).await;
} }
} }
} }
@ -54,26 +191,24 @@ pub async fn start_msg_sync(ctx:Arc<Mutex<ClipboardSync>>) -> Result<task::JoinH
enum Msg <'a>{ enum Msg <'a>{
// magic str, message context // magic str, message context
Msg((String, &'a str)), Msg(&'a str),
//index of message pack, total message pack number, magic str, message context //index of message pack, total message pack number, magic str, message context
Sub((u8, u8, String, &'a str)), Sub((u8, u8, String, &'a str)),
} }
impl ClipboardSync { impl ClipboardSync {
pub fn new(ip: &str, user_name: &str, password: &str) -> ClipboardSync { pub fn new(ip: &str, info_file:&str) -> Result<ClipboardSync, Box<dyn Error>> {
ClipboardSync { let cfg = Config::new(info_file)?;
user_name: user_name.to_string(), Ok(ClipboardSync {
password: password.to_string(),
web: Client::new(), web: Client::new(),
ip: ip.to_string(), ip: ip.to_string(),
cookies: "".to_string(),
clip: wclip::Wclip::new(), clip: wclip::Wclip::new(),
cache_magic: "0xff".to_string(), cfg,
} })
} }
async fn verify(&self) -> Result<Response, Box<dyn Error>> { async fn verify(&mut self) -> Result<Response, Box<dyn Error>> {
// 开始验证 // 开始验证
let security_check_url = format!("http://{}/SSWeb/rd/j_security_check", self.ip); let security_check_url = format!("http://{}/SSWeb/rd/j_security_check", self.ip);
let mut headers = HeaderMap::new(); let mut headers = HeaderMap::new();
@ -100,11 +235,11 @@ impl ClipboardSync {
.parse() .parse()
.unwrap(), .unwrap(),
); );
headers.insert("Cookie", self.cookies.parse().unwrap()); headers.insert("Cookie", self.cfg.cookies(None).parse().unwrap());
let contents = format!( let contents = format!(
"j_username={}&j_password={}", "j_username={}&j_password={}",
quote(&self.user_name), quote(self.cfg.user_name(None)),
quote(&self.password) quote(&self.cfg.password(None))
); );
let resp = self let resp = self
.web .web
@ -124,7 +259,7 @@ impl ClipboardSync {
session = value.split(';').next().unwrap().to_string(); session = value.split(';').next().unwrap().to_string();
} }
} else { } else {
log::error!("cookies not found"); log::warn!("cookies not found");
} }
session session
} }
@ -132,9 +267,10 @@ impl ClipboardSync {
let mut headers = HeaderMap::new(); let mut headers = HeaderMap::new();
headers.insert("User-Agent", USER_AGENT.parse().unwrap()); headers.insert("User-Agent", USER_AGENT.parse().unwrap());
let url = format!("http://{}/SSWeb/rd/copy_paste.jsp", self.ip); let url = format!("http://{}/SSWeb/rd/copy_paste.jsp", self.ip);
let response = self.web.get(url).headers(headers).send().await?; let response = self.web.get(url).headers(headers).send().await?;
self.cookies = ClipboardSync::get_cookies(&response); self.cfg.cookies(Some(&ClipboardSync::get_cookies(&response)));
log::info!("cookies is {}", self.cookies); log::info!("cookies is [{}]", self.cfg.cookies(None));
let mut resp = response.text().await?; let mut resp = response.text().await?;
log::trace!("Response: {}", resp); log::trace!("Response: {}", resp);
if resp.contains("loginForm") { if resp.contains("loginForm") {
@ -149,7 +285,7 @@ impl ClipboardSync {
} }
} }
pub async fn update_msg(&mut self) -> Result<(), Box<dyn Error>> { pub async fn get_newest_msg(&mut self) -> Result<String, Box<dyn Error>> {
//http://ssweb/SSWeb/rd/copy_paste.jsp?d-16544-p=1&d-16544-s=2 //http://ssweb/SSWeb/rd/copy_paste.jsp?d-16544-p=1&d-16544-s=2
//d-16544-s 2:时间从靠近现在开始排序 1:时间从最早开始排序 //d-16544-s 2:时间从靠近现在开始排序 1:时间从最早开始排序
//d-16544-o mesage排序不要设置 //d-16544-o mesage排序不要设置
@ -167,6 +303,11 @@ impl ClipboardSync {
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("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 response = self.web.get(url).headers(headers).send().await?;
let resp = response.text().await?; let resp = response.text().await?;
Ok(resp)
}
pub async fn update_msg(&mut self) -> Result<(), Box<dyn Error>> {
let resp = self.get_newest_msg().await?;
self.msg2clip(&resp).await; self.msg2clip(&resp).await;
Ok(()) Ok(())
} }
@ -174,23 +315,21 @@ impl ClipboardSync {
//解析可能存在的消息数据 //解析可能存在的消息数据
fn parse_msg<'a>(msg: &'a str) -> Msg { fn parse_msg<'a>(msg: &'a str) -> Msg {
//x|x|x| -> index|total|magic| //x|x|x| -> index|total|magic|
let head = &msg[0..7]; let bmsg = msg.as_bytes();
let body = &msg[7..]; let head = &bmsg[0..7];
let check = head.split('|').filter(|text| { let check = head.split(|c| *c == b'|').filter(|text| {
let text = text.as_bytes();
if text.len() == 1 { if text.len() == 1 {
if text[0] >= b'!' && text[0] < b'|' {true} else {false} if text[0] >= b'!' && text[0] < b'|' {true} else {false}
} else { } else {
false false
} }
}).map(|x|x.as_bytes()[0] - b'!').collect::<Vec<_>>(); }).map(|x|x[0] - b'!').collect::<Vec<_>>();
if check.len() != 3 { if check.len() != 3 {
//TODO: get magic return Msg::Msg(msg)
return Msg::Msg(("maigic".to_string(), msg))
} }
return Msg::Sub((check[0], check[1], check[2].to_string(), body)); return Msg::Sub((check[0], check[1], check[2].to_string(), &msg[7..]));
} }
//将message解析并放置到剪切板上 //将message解析并放置到剪切板上
@ -199,19 +338,27 @@ impl ClipboardSync {
let document = Html::parse_document(html); let document = Html::parse_document(html);
// 所有剪切板的数据都是在code这个html lable上的 // 所有剪切板的数据都是在code这个html lable上的
let selector = Selector::parse("code").unwrap(); let selector = Selector::parse("code").unwrap();
//对于单个消息我们希望发送的时间作为magic所以这里通过构建一个date selector获得
let date_selector = Selector::parse("td.fixline").unwrap();
let mut msg_map = BTreeMap::new(); let mut msg_map = BTreeMap::new();
let mut magic_ref = "0xff".to_string(); let mut magic_ref = "0xff".to_string();
let mut is_first = true; let mut msg_index = 0;
for element in document.select(&selector).into_iter() { for element in document.select(&selector).into_iter() {
//let text = element.text().collect::<Vec<_>>().concat(); //let text = element.text().collect::<Vec<_>>().concat();
let text = element.text().collect::<String>(); let text = element.text().collect::<String>();
log::info!("Found: [{}]", text); log::trace!("Found: [{}]", text);
let msg = ClipboardSync::parse_msg(text.as_str()); let msg = ClipboardSync::parse_msg(text.as_str());
match msg { match msg {
//一整个消息。直接复制到剪切板即可 //一整个完整的消息。直接复制到剪切板即可
Msg::Msg(msg) => { Msg::Msg(msg) => {
if magic_ref == "0xff" { if magic_ref == "0xff" {
self.clip.set(msg.1); // 因为每个date和str都是对应的所以这里直接获取指定位置的date作为magic
let magic = document.select(&date_selector).into_iter().nth(msg_index).unwrap().text().collect::<String>();
if self.cfg.magic(None) != magic {
self.clip.set(msg);
self.cfg.magic(Some(&magic));
log::info!("magic is {}, msg is {}", self.cfg.magic(None), msg);
}
break;//处理完毕。直接退出 break;//处理完毕。直接退出
} }
}, },
@ -220,13 +367,13 @@ impl ClipboardSync {
magic_ref = magic; magic_ref = magic;
} else { } else {
if magic_ref != magic { // other message ignore if magic_ref != magic { // other message ignore
is_first = false; msg_index += 1;
continue continue
} }
} }
if msg_map.len() == 0 && ( if msg_map.len() == 0 && (
self.cache_magic == magic_ref // message is repeated ignore it self.cfg.magic(None) == magic_ref // message is repeated ignore it
|| !is_first // we only process the newest msg || (msg_index != 0) // we only process the newest msg
) { ) {
break; break;
} }
@ -234,13 +381,140 @@ impl ClipboardSync {
msg_map.insert(index, body.to_string()); msg_map.insert(index, body.to_string());
if msg_map.len() as u8 == total { if msg_map.len() as u8 == total {
let msg = msg_map.into_iter().map(|(_key, v)| v).collect::<String>(); let msg = msg_map.into_iter().map(|(_key, v)| v).collect::<String>();
self.cache_magic = magic_ref; // save for next msg if self.cfg.magic(None) != magic_ref {
log::info!("magic is {}, msg is {}", self.cfg.magic(None), msg);
self.clip.set(&msg); self.clip.set(&msg);
self.cfg.magic(Some(&magic_ref)); // save for next msg
}
break; break;
} }
} }
} }
is_first = false; msg_index += 1;
}
}
pub async fn send_msg(&mut self, msg: &str) -> Result<(), Box<dyn Error>> {
let url = format!("http://{}/SSWeb/rd/copy_paste.jsp?send=y", 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?d-16544-p=1&d-16544-s=2".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", format!("{}", self.cfg.cookies(None)).parse().unwrap());
let contents = format!("message={}", msg);
let _ = self.web.post(url).headers(headers).body(contents).send().await?;
// let resp = response.text().await?;
// Ok(resp)
Ok(())
}
pub async fn split_msg(&mut self, msg: &str) -> Result<Vec<String>, i32> {
let mut start = 0;
let mut msgs = Vec::new();
let mut cur = 0;
for c in msg.chars() {
let byte_count = c.len_utf8();
if cur - start + byte_count + 7 >= 300 {
//超过限额300个字符构造一个消息进行发送
msgs.push(&msg[start..cur]);
start = cur;
if msgs.len() > b'|' as usize - b'!' as usize {
log::warn!("msg is too long, ignore it");
return Err(-1);
}
}
cur += byte_count;
}
//如果拆包了的话。那么要把最后一点点数据打包一下不然会丢msg
if msgs.len() > 0 && cur != start {
msgs.push(&msg[start..cur]);
}
fn gen_magic(cache: char) -> char {
let mut rng = rand::thread_rng();
// ASCII 范围从 '!' (33) 到 '|' (124)
let start = b'!' as u8;
let end = b'|' as u8;
let mut ret = cache;
//随机生成一个和上次不一样的值即可
while ret == cache {
ret = rng.gen_range(start..end) as char;
}
ret
}
let mut ret = Vec::new();
let total = msgs.len() as u32;
if total > 0 { //大消息切片为多个小消息
let magic = gen_magic(self.cfg.magic(None).chars().next().unwrap());
for index in 0..total {
//x|x|x| -> index|total|magic|
let msg = format!("{}|{}|{}", char::from_u32(b'0' as u32 + index).unwrap(),
char::from_u32(b'0' as u32 + total).unwrap(), magic);
ret.push(msg + msgs[index as usize]);
}
self.cfg.magic(Some(&magic.to_string()));
} else { //单个消息
ret.push(msg.to_string());
}
Ok(ret)
}
pub async fn clip2msg(&mut self) {
let msg = match self.clip.get() {
Some(msg) => match self.split_msg(&msg).await {
Ok(msgs) => msgs,
Err(_) => return,
},
None => return,
};
//遍历所有分包并进行发送
for item in msg {
let _ = self.send_msg(&item).await;
} }
} }
} }
#[tokio::test]
async fn test_message2clip()
{
use std::fs::File;
use std::io::Read;
let mut ins = ClipboardSync::new("127.0.0.1", "info.json").unwrap();
let mut html = String::new();
File::open("message.html").unwrap().read_to_string(&mut html).unwrap();
ins.msg2clip(&html).await;
}
#[tokio::test]
async fn test_start_msg_sync()
{
let ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
let ctx = Arc::new(Mutex::new(ins));
let handle = start_msg_sync(ctx.clone()).await.unwrap();
time::sleep(Duration::new(10, 0)).await;
handle.abort();
}
#[tokio::test]
async fn test_split_msg() {
let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
let raw_msg = "在这个快速发展的世界中technology is evolving at an unprecedented rate! 我们需要不断学习和适应新的变化。#创新@未来$梦想%实现^挑战&机遇*合作+成长=成功~体验|分享<知识>探索{可能性}。Let's work together to create a better tomorrow! 生活充满了各种可能性我们要勇敢面对每一个挑战。1234567890!@#$%^&*()_+-=<>?[]{},.。;:‘’“”()【】《》——";
let msgs = ins.split_msg(raw_msg).await.unwrap();
println!("{:?}", msgs);
}
#[tokio::test]
async fn test_send_send_msg() {
let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
let raw_msg = "在这个快速发展的世界中technology is evolving at an unprecedented rate! 我们需要不断学习和适应新的变化。#创新@未来$梦想%实现^挑战&机遇*合作+成长=成功~体验|分享<知识>探索{可能性}。Let's work together to create a better tomorrow! 生活充满了各种可能性我们要勇敢面对每一个挑战。1234567890!@#$%^&*()_+-=<>?[]{},.。;:‘’“”()【】《》——";
ins.clip.set(&raw_msg);
ins.clip2msg().await;
}

View File

@ -7,6 +7,83 @@ use trust_dns_resolver::{
}; };
use tokio::sync::{Mutex}; use tokio::sync::{Mutex};
use std::sync::Arc; use std::sync::Arc;
use clap::{App, Arg, ArgGroup};
// const SERVER:&str = "172.19.36.79";
const SERVER:&str = "127.0.0.1:5000";
enum Character {
Producer,
Consumer,
}
fn param_parser() -> (Character, String) {
let mut character = Character::Consumer;
let matches = App::new("sstar_clipboard_sync")
.version("1.0")
.author("Ekko.bao")
.about("sstar clipboard sync")
.arg(
Arg::with_name("producer")
.short('p')
.long("producer")
.conflicts_with("consumer")
.help("Data producer")
)
.arg(
Arg::with_name("consumer")
.short('c')
.long("consumer")
.conflicts_with("producer")
.help("Data consumer")
)
.group(clap::ArgGroup::new("Character")
.args(&["consumer", "producer"])
.required(true)
.multiple(false))
.arg(
Arg::with_name("info")
.short('i')
.long("info")
.value_name("info")
.default_value("info.json")
.help("The file of running info")
)
.get_matches();
character = if matches.is_present("producer") {
Character::Producer
} else if matches.is_present("consumer") {
Character::Consumer
} else {
character
};
let info_file = matches.value_of("info").unwrap();
(character, info_file.to_string())
}
async fn producer(info: &str) {
let mut ins: ClipboardSync = match ClipboardSync::new(SERVER, &info) {
Ok(ins) => ins,
Err(e) => {
log::error!("create syns instance fail: {}", e);
return;
}
};
match ins.login().await {
Ok(()) => log::info!("login success"),
Err(e) => {
log::error!("login fail: {}", e);
return;
}
}
let ctx = Arc::new(Mutex::new(ins));
let handle = clipboard_sync::start_msg_sync(ctx.clone()).await.unwrap();
let _ = handle.await;
}
async fn consumer(_info: &str) {
log::warn!("TODO: support Producer in the feature")
}
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
@ -29,22 +106,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// println!("Error: {}", e); // println!("Error: {}", e);
// } // }
// } // }
let (character, info) = param_parser();
let mut ins = ClipboardSync::new("172.19.36.79", "ekko.bao", "qwer12345;"); match character{
match ins.login().await { Character::Producer => {
Ok(()) => log::info!("登录成功"), producer(&info).await;
Err(e) => { }
log::error!("登录失败: {}", e); Character::Consumer => {
consumer(&info).await;
} }
} }
let ctx = Arc::new(Mutex::new(ins));
let handle = clipboard_sync::start_msg_sync(ctx.clone()).await.unwrap();
let _ = handle.await;
// 获取 Cookies
//if let Some(cookies) = response.headers().get(COOKIE) {
// println!("Cookies: {:?}", cookies);
//} else {
// println!("No cookies found.");
//}
Ok(()) Ok(())
} }

View File

@ -1,6 +1,5 @@
extern crate winapi; extern crate winapi;
extern crate log; extern crate log;
use std::path::Path;
use winapi::um::winuser::{ use winapi::um::winuser::{
GetCursorPos, GetSystemMetrics, SM_CXSCREEN, SM_CYSCREEN,GetWindowRect GetCursorPos, GetSystemMetrics, SM_CXSCREEN, SM_CYSCREEN,GetWindowRect
}; };
@ -9,8 +8,6 @@ use winapi::shared::windef::{
RECT, RECT,
}; };
use winapi::um::winuser::{GetForegroundWindow, GetWindowThreadProcessId}; use winapi::um::winuser::{GetForegroundWindow, GetWindowThreadProcessId};
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use winapi::um::processthreadsapi::OpenProcess; use winapi::um::processthreadsapi::OpenProcess;
use winapi::um::winnt::PROCESS_QUERY_INFORMATION; use winapi::um::winnt::PROCESS_QUERY_INFORMATION;
use winapi::um::psapi::GetProcessImageFileNameW; use winapi::um::psapi::GetProcessImageFileNameW;
@ -42,15 +39,14 @@ pub fn get_foredround_window_rect() -> Option<(i32, i32, i32, i32)> {
println!("GetWindowRect: {:?}", rect); println!("GetWindowRect: {:?}", rect);
Some((rect.left, rect.top, rect.right, rect.bottom)) Some((rect.left, rect.top, rect.right, rect.bottom))
} else { } else {
println!("cant get foregtound window rect"); log::error!("cant get foregtound window rect");
None None
} }
} }
} }
pub fn get_foredround_window_name() -> String { pub fn get_foredround_window_name() -> String {
let mut name = OsString::new(); let mut name = String::new();
unsafe { unsafe {
let foreground_window = GetForegroundWindow(); let foreground_window = GetForegroundWindow();
@ -62,24 +58,26 @@ pub fn get_foredround_window_name() -> String {
let process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0, process_id); let process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0, process_id);
if process_handle.is_null() { if process_handle.is_null() {
panic!("Cant open foreground process with {}!", process_id) log::error!("Cant open foreground process with {}!", process_id);
return "".to_string();
} }
let mut image_name = [0u16; 1024]; let mut image_name = [0u16; 1024];
if GetProcessImageFileNameW(process_handle, image_name.as_mut_ptr() as *mut _, image_name.len() as u32) == 0 { if GetProcessImageFileNameW(process_handle, image_name.as_mut_ptr() as *mut _, image_name.len() as u32) == 0 {
panic!("Cant Get foreground prog name!") log::error!("Cant Get foreground prog name!");
return "".to_string();
} }
// let mut class_name: [u16; 256] = [0; 256]; // let mut class_name: [u16; 256] = [0; 256];
// GetClassNameW(foreground_window, class_name.as_mut_ptr(), 256); // GetClassNameW(foreground_window, class_name.as_mut_ptr(), 256);
name = OsString::from_wide(&image_name); name = String::from_utf16_lossy(&image_name);
// let mut class_name_str = OsString::from_wide(&class_name); // let mut class_name_str = OsString::from_wide(&class_name);
// log::info!("Class Name: {}", class_name_str.to_string_lossy().to_string()); // log::info!("Class Name: {}", class_name_str.to_string_lossy().to_string());
} }
let path = Path::new(&name); let name = name.split('\\').last().unwrap().trim_end_matches('\0').to_string();
let name = path.file_name().unwrap().to_string_lossy().to_string(); //let name = path.file_name().unwrap().to_string_lossy().to_string();
println!("Current Proc Name: [{}]", name); // println!("Current Proc Name: [{}]", name);
name name
} }