UtilityLibAPI 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2025 James Lin **UtilityLibAPI**
2
+
3
+ All rights reserved.
4
+
5
+ Permission is granted for **personal, educational, or non-commercial use only**.
6
+ You **may NOT**:
7
+
8
+ 1. Sell or otherwise commercially exploit this software or any part of it.
9
+ 2. Reproduce, distribute, or sublicense this software for commercial purposes.
10
+ 3. Modify or create derivative works for commercial purposes without explicit written permission from the copyright holder.
11
+
12
+ You **may**:
13
+
14
+ - Use the software for personal learning, research, or internal company evaluation (non-commercial).
15
+ - Share the software with attribution to the original author, as long as it is not for commercial gain.
16
+
17
+ **Disclaimer:**
18
+ This software is provided "AS IS", without any warranty of any kind, either expressed or implied,
19
+ including but not limited to the warranties of merchantability, fitness for a particular purpose, or non-infringement.
20
+ In no event shall the author be liable for any claim, damages, or other liability arising from, out of, or in connection with the software or its use.
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: UtilityLibAPI
3
+ Version: 0.1.0
4
+ Summary: UtilityLibAPI Python package
5
+ Author-email: James Lin <tylin123@ms27.hinet.net>
6
+ License: Copyright (c) 2025 James Lin **UtilityLibAPI**
7
+
8
+ All rights reserved.
9
+
10
+ Permission is granted for **personal, educational, or non-commercial use only**.
11
+ You **may NOT**:
12
+
13
+ 1. Sell or otherwise commercially exploit this software or any part of it.
14
+ 2. Reproduce, distribute, or sublicense this software for commercial purposes.
15
+ 3. Modify or create derivative works for commercial purposes without explicit written permission from the copyright holder.
16
+
17
+ You **may**:
18
+
19
+ - Use the software for personal learning, research, or internal company evaluation (non-commercial).
20
+ - Share the software with attribution to the original author, as long as it is not for commercial gain.
21
+
22
+ **Disclaimer:**
23
+ This software is provided "AS IS", without any warranty of any kind, either expressed or implied,
24
+ including but not limited to the warranties of merchantability, fitness for a particular purpose, or non-infringement.
25
+ In no event shall the author be liable for any claim, damages, or other liability arising from, out of, or in connection with the software or its use.
26
+
27
+ Project-URL: Homepage, https://mis.gotech.biz
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: pymysql
31
+ Dynamic: license-file
32
+
33
+ #UtilityLibAPI Classes
34
+
35
+ ## History of version
36
+ Version 0.1.0: 2025/10/13<BR>
37
+ Create UtilityLibAPI -- EnDeCodeLib + SessionVARLib<BR>
@@ -0,0 +1,5 @@
1
+ #UtilityLibAPI Classes
2
+
3
+ ## History of version
4
+ Version 0.1.0: 2025/10/13<BR>
5
+ Create UtilityLibAPI -- EnDeCodeLib + SessionVARLib<BR>
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "UtilityLibAPI"
7
+ version = "0.1.0"
8
+ description = "UtilityLibAPI Python package"
9
+ authors = [
10
+ { name="James Lin", email="tylin123@ms27.hinet.net" }
11
+ ]
12
+ readme = "README.md"
13
+ license = { file = "LICENSE" }
14
+ dependencies = [
15
+ "pymysql",
16
+ ]
17
+
18
+ [project.urls]
19
+ Homepage = "https://mis.gotech.biz"
20
+
21
+ [tools.setuptools.packages.find]
22
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,198 @@
1
+ # ============================================================================
2
+ # 通用 加密/解密 (跨平台)
3
+ # ============================================================================
4
+ import base64
5
+
6
+ # ================================================================================
7
+ class CLASS_EnDeCodeLib:
8
+ def __init__(self):
9
+ # 設定預設的 CROSS 加密金鑰
10
+ self.CVmba_CROSS_KEY = [];
11
+ self.CVmba_CROSS_KEY.append(0x3f);
12
+ self.CVmba_CROSS_KEY.append(0x6b);
13
+ self.CVmba_CROSS_KEY.append(0x59);
14
+ self.CVmba_CROSS_KEY.append(0x48);
15
+ # ------------------------------------------------------------------
16
+ self.CVms_CROSS_ASC = \
17
+ "AaBbFfGg 125~!@#$)HhIiLlMm_+`-=CcD34dEe:[]JjKk\\\'"\
18
+ "NnOoSsTt670%UuXxYyZz^&*Pp89QqRr(<>?VvWw,./;{}|\"";
19
+ self.CVms_CROSS_MAP = \
20
+ "~!@#$%^& ()_+QWERbnmTOP{}|ASghjkDFL:\"ZXiopCV<>?`" \
21
+ "125-=*qwert67890yuBNM[]\\asd34fGHJKl;\'zxYUIcv,./";
22
+ # ------------------------------------------------------------------
23
+
24
+
25
+ # ================================================================================
26
+ # PRIVATE
27
+ # ================================================================================
28
+ # ----------------------------------------------------------------------------
29
+ # 功能: CROSS 金鑰加密 (針對不可視字元: 使用金鑰加密)
30
+ # 傳入:
31
+ # 傳回:
32
+ # ----------------------------------------------------------------------------
33
+ def CVF_CROSS_XOR(self, Pmc_SRC_CH):
34
+ mia_SRCCH = [];
35
+ ms_ENCODE = "";
36
+ mi_ENCODE = 0;
37
+ mi_c = 0;
38
+
39
+ mia_SRCCH = Pmc_SRC_CH.encode('big5');
40
+ # ------------------------------------------------------------
41
+ for mi_c in range(0, len(mia_SRCCH)):
42
+ mi_ENCODE = mia_SRCCH[mi_c];
43
+ # ------------------------------------------------------------
44
+ for mi_d in range(0, len(self.CVmba_CROSS_KEY)):
45
+ mi_ENCODE ^= self.CVmba_CROSS_KEY[mi_d];
46
+ # ------------------------------------------------------------
47
+ ms_ENCODE += chr(mi_ENCODE);
48
+ # ------------------------------------------------------------
49
+ return(ms_ENCODE);
50
+
51
+
52
+ # ================================================================================
53
+ # PUBLIC
54
+ # ================================================================================
55
+ # ----------------------------------------------------------------------------
56
+ # 功能: 設定 CROSS 加密金鑰
57
+ # 傳入:
58
+ # 傳回:
59
+ # ----------------------------------------------------------------------------
60
+ def CUF_CROSS_SetKey(self, Rmca_KeyCode):
61
+ if(len(Rmca_KeyCode) <= 0):
62
+ return;
63
+ # ------------------------------------------------------------
64
+ self.CVmba_CROSS_KEY.clear();
65
+ # ------------------------------------------------------------
66
+ for mi_c in range(0, len(Rmca_KeyCode)):
67
+ self.CVmba_CROSS_KEY = Rmca_KeyCode[mi_c];
68
+
69
+ # ----------------------------------------------------------------------------
70
+ # 功能: 回傳 CROSS 加密金鑰
71
+ # 傳入:
72
+ # 傳回:
73
+ # ----------------------------------------------------------------------------
74
+ def CUF_CROSS_GetKey(self):
75
+ return(self.CVmba_CROSS_KEY);
76
+
77
+
78
+ # ----------------------------------------------------------------------------
79
+ # 功能: CROSS 加密程序
80
+ # 傳入:
81
+ # 傳回:
82
+ # ----------------------------------------------------------------------------
83
+ def CUF_CROSS_EnCode(self, Pms_SRC_Text):
84
+ ms_RET_STR = "";
85
+ mB_Found = False;
86
+ mi_c = 0;
87
+ mi_d = 0;
88
+ # ------------------------------------------------------------
89
+ if(type(Pms_SRC_Text) is bytes):
90
+ Pms_SRC_Text = str(Pms_SRC_Text);
91
+ # ------------------------------------------------------------
92
+ # (1) 判斷是否為 ASCII 可視字元,若是則搜尋對應的 CVms_CROSS_MAP[?] 字元
93
+ for mi_c in range(0, len(Pms_SRC_Text)):
94
+ mB_Found = False;
95
+ # --------------------------------------------
96
+ for mi_d in range(0, len(self.CVms_CROSS_ASC)):
97
+ if(Pms_SRC_Text[mi_c] == self.CVms_CROSS_ASC[mi_d]):
98
+ mB_Found = True;
99
+ break;
100
+ # --------------------------------------------
101
+ if(mB_Found):
102
+ # (1-1) 可視字元 : 找到可視字元對應的加密表字元
103
+ ms_RET_STR += self.CVms_CROSS_MAP[mi_d];
104
+ else:
105
+ # (1-2) 不可視字元: 使用金鑰加密
106
+ ms_RET_STR += self.CVF_CROSS_XOR(Pms_SRC_Text[mi_c]);
107
+ # ------------------------------------------------------------
108
+ return(ms_RET_STR);
109
+
110
+
111
+ # ----------------------------------------------------------------------------
112
+ # 功能: CROSS 解密程序
113
+ # 傳入:
114
+ # 傳回:
115
+ # ----------------------------------------------------------------------------
116
+ def CUF_CROSS_DeCode(self, Pms_ENC_Text):
117
+ ms_RET_STR = "";
118
+ mB_Found = False;
119
+ mi_c = 0;
120
+ mi_d = 0;
121
+ # ------------------------------------------------------------
122
+ # (1) 判斷是否為 ASCII 可視字元,若是則搜尋對應的 CVms_CROSS_MAP[?] 字元
123
+ for mi_c in range(0, len(Pms_ENC_Text)):
124
+ mB_Found = False;
125
+ # --------------------------------------------
126
+ for mi_d in range(0, len(self.CVms_CROSS_MAP)):
127
+ if(Pms_ENC_Text[mi_c] == self.CVms_CROSS_MAP[mi_d]):
128
+ mB_Found = True;
129
+ break;
130
+ # --------------------------------------------
131
+ if(mB_Found):
132
+ # (1-1) 可視字元 : 找到可視字元對應的解密表字元
133
+ ms_RET_STR += self.CVms_CROSS_ASC[mi_d];
134
+ else:
135
+ # (1-2) 不可視字元: 使用金鑰加密
136
+ ms_RET_STR += self.CVF_CROSS_XOR(Pms_ENC_Text[mi_c]);
137
+ # ------------------------------------------------------------
138
+ return(ms_RET_STR);
139
+
140
+
141
+ # ----------------------------------------------------------------------------
142
+ # 功能: CROSS 加密程序 (Base64 版本)
143
+ # 傳入:
144
+ # 傳回:
145
+ # ----------------------------------------------------------------------------
146
+ def CUF_CROSS_EnCodeBase64(self, Pms_SRC_Text):
147
+ ms_EnCode = "";
148
+ ms_BuffSTR = "";
149
+
150
+ ms_BuffSTR = Pms_SRC_Text.encode('big5');
151
+ # ------------------------------------------------------------
152
+ for mi_c in range(0, len(ms_BuffSTR)):
153
+ ms_EnCode += chr(ms_BuffSTR[mi_c]);
154
+ # ------------------------------------------------------------
155
+ # (1) Base64 轉碼
156
+ ms_EnCode = base64.b64encode(ms_EnCode.encode('utf-8'));
157
+ # ------------------------------------------------------------
158
+ # (2) 明文加密
159
+ ms_EnCode = self.CUF_CROSS_EnCode(ms_EnCode);
160
+ # ------------------------------------------------------------
161
+ ms_EnCode = ms_EnCode.encode("utf-8");
162
+ # ---------e---------------------------------------------------
163
+ return(ms_EnCode);
164
+
165
+
166
+ # ----------------------------------------------------------------------------
167
+ # 功能: CROSS 解密程序 (Base64 版本)
168
+ # 傳入:
169
+ # 傳回:
170
+ # ----------------------------------------------------------------------------
171
+ def CUF_CROSS_DeCodeBase64(self, Pms_ENC_Text):
172
+ ms_DeCode = "";
173
+
174
+ ms_EnCode = Pms_ENC_Text.encode('big5');
175
+ # ------------------------------------------------------------
176
+ # (1) Base64 解碼
177
+ ms_DeCode = base64.b64decode(ms_EnCode);
178
+ # ------------------------------------------------------------
179
+ # (2) 解密
180
+ ms_DeCode = self.CUF_CROSS_DeCode(ms_DeCode);
181
+ # ------------------------------------------------------------
182
+ ms_DeCode = ms_DeCode.encode("utf-8");
183
+ # ------------------------------------------------------------
184
+ return(ms_DeCode);
185
+
186
+
187
+ # ================================================================================
188
+ # EXAMPLE
189
+ # ================================================================================
190
+ if(__name__=="__main__"):
191
+ Gobj_EnDeCode = CLASS_EnDeCodeLib();
192
+
193
+ ms_TEXT1 = "abcd,123 4567";
194
+ ms_TEXT2 = "abc真正好123,Good 太棒了 ";
195
+ # ------------------------------------------------------------
196
+ print(Gobj_EnDeCode.CUF_CROSS_EnCode(ms_TEXT1));
197
+ print(Gobj_EnDeCode.CUF_CROSS_EnCode(ms_TEXT2.encode('big5')));
198
+ print(Gobj_EnDeCode.CUF_CROSS_EnCodeBase64(ms_TEXT2));
@@ -0,0 +1,143 @@
1
+ import pymysql
2
+ import pickle
3
+ import time
4
+ import uuid
5
+
6
+ class CLASS_SessionVAR:
7
+ def __init__(self):
8
+ self.conn = None
9
+ self.cursor = None
10
+ self.table_name = "_session_table"
11
+
12
+ # ----------------------------
13
+ # 建立 SessionID
14
+ # ----------------------------
15
+ def CUF_New_SessionID(self):
16
+ return(str(uuid.uuid4()))
17
+
18
+ # ----------------------------
19
+ # 建立連線與表
20
+ # ----------------------------
21
+ def CUF_Create(self, Pms_host:str, Pmi_port:int, Pms_user:str, Pms_password:str, Pms_db:str,
22
+ Pms_SessionID:str=None,
23
+ Pms_table_name:str="_session_table"):
24
+ self.conn = pymysql.connect(
25
+ host=Pms_host,
26
+ port=Pmi_port,
27
+ user=Pms_user,
28
+ password=Pms_password,
29
+ database=Pms_db,
30
+ charset='utf8mb4',
31
+ autocommit=True
32
+ )
33
+ self.cursor = self.conn.cursor()
34
+ self.table_name = Pms_table_name
35
+
36
+ # 建立表格,如果不存在
37
+ create_sql = f"""
38
+ CREATE TABLE IF NOT EXISTS `{self.table_name}` (
39
+ `SessionID` VARCHAR(36) NOT NULL,
40
+ `VarName` VARCHAR(255) NOT NULL,
41
+ `VarValue` LONGBLOB,
42
+ `UpdateTime` BIGINT NOT NULL,
43
+ PRIMARY KEY (`SessionID`, `VarName`)
44
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
45
+ """
46
+ self.cursor.execute(create_sql)
47
+
48
+ # 回傳 SessionID
49
+ if(Pms_SessionID == ""):
50
+ session_id = self.CUF_New_SessionID();
51
+ else:
52
+ session_id = Pms_SessionID;
53
+ return(session_id);
54
+
55
+ # ----------------------------
56
+ # 儲存變數
57
+ # ----------------------------
58
+ def CUF_SET(self, Pms_SessionID, Pms_VarName, Pms_VarValue):
59
+ blob_data = pickle.dumps(Pms_VarValue)
60
+ update_time = int(time.time())
61
+ sql = f"""
62
+ INSERT INTO `{self.table_name}` (SessionID, VarName, VarValue, UpdateTime)
63
+ VALUES (%s, %s, %s, %s)
64
+ ON DUPLICATE KEY UPDATE
65
+ VarValue = VALUES(VarValue),
66
+ UpdateTime = VALUES(UpdateTime)
67
+ """
68
+ self.cursor.execute(sql, (Pms_SessionID, Pms_VarName, blob_data, update_time))
69
+
70
+ # ----------------------------
71
+ # 取得變數
72
+ # ----------------------------
73
+ def CUF_GET(self, Pms_SessionID, Pms_VarName):
74
+ sql = f"SELECT VarValue FROM `{self.table_name}` WHERE SessionID=%s AND VarName=%s"
75
+ self.cursor.execute(sql, (Pms_SessionID, Pms_VarName))
76
+ result = self.cursor.fetchone()
77
+ if result:
78
+ return pickle.loads(result[0])
79
+ return None
80
+
81
+ # ----------------------------
82
+ # 釋放 Session
83
+ # ----------------------------
84
+ # 依 SessionID 刪除,或依秒數刪除舊資料
85
+ def CUF_Release(self, Pms_param):
86
+ if isinstance(Pms_param, str):
87
+ sql = f"DELETE FROM `{self.table_name}` WHERE SessionID=%s"
88
+ self.cursor.execute(sql, (Pms_param,))
89
+ elif isinstance(Pms_param, (int, float)):
90
+ threshold = int(time.time()) - int(Pms_param)
91
+ sql = f"DELETE FROM `{self.table_name}` WHERE UpdateTime < %s"
92
+ self.cursor.execute(sql, (threshold,))
93
+
94
+ # ----------------------------
95
+ # 關閉資源
96
+ # ----------------------------
97
+ def CUF_Close(self):
98
+ if self.cursor:
99
+ self.cursor.close()
100
+ self.cursor = None
101
+ if self.conn:
102
+ self.conn.close()
103
+ self.conn = None
104
+
105
+ # =============================
106
+ # 範例用法
107
+ # =============================
108
+ if(__name__ == "__main__"):
109
+ objSession = CLASS_SessionVAR()
110
+ session_id = objSession.CUF_Create(Pms_host="mis.gotech.biz",
111
+ Pmi_port=3300, Pms_db="df8000",
112
+ Pms_user="root",
113
+ Pms_password="gotechdf8000sys",
114
+ Pms_SessionID="xx-202510131127");
115
+
116
+ # 儲存資料
117
+ objSession.CUF_SET(session_id, "mylist", [1,2,3])
118
+ objSession.CUF_SET(session_id, "mydict", {"a":1, "b":2})
119
+
120
+ # 取得資料
121
+ mylist = objSession.CUF_GET(session_id, "mylist")
122
+ mydict = objSession.CUF_GET(session_id, "mydict")
123
+ print(mylist, mydict)
124
+
125
+ # 釋放單一 session
126
+ # objSession.CUF_Release(session_id)
127
+
128
+ # 釋放超過 600 秒的資料
129
+ # objSession.CUF_Release(600)
130
+
131
+
132
+ mylist = [5,6,7,8,9];
133
+ objSession.CUF_SET(session_id, "mylist", mylist);
134
+
135
+ mylist = [0];
136
+ print(mylist);
137
+
138
+ mylist = objSession.CUF_GET(session_id, "mylist");
139
+ print(mylist);
140
+
141
+ objSession.CUF_SET(session_id, "")
142
+
143
+ objSession.CUF_Close()
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: UtilityLibAPI
3
+ Version: 0.1.0
4
+ Summary: UtilityLibAPI Python package
5
+ Author-email: James Lin <tylin123@ms27.hinet.net>
6
+ License: Copyright (c) 2025 James Lin **UtilityLibAPI**
7
+
8
+ All rights reserved.
9
+
10
+ Permission is granted for **personal, educational, or non-commercial use only**.
11
+ You **may NOT**:
12
+
13
+ 1. Sell or otherwise commercially exploit this software or any part of it.
14
+ 2. Reproduce, distribute, or sublicense this software for commercial purposes.
15
+ 3. Modify or create derivative works for commercial purposes without explicit written permission from the copyright holder.
16
+
17
+ You **may**:
18
+
19
+ - Use the software for personal learning, research, or internal company evaluation (non-commercial).
20
+ - Share the software with attribution to the original author, as long as it is not for commercial gain.
21
+
22
+ **Disclaimer:**
23
+ This software is provided "AS IS", without any warranty of any kind, either expressed or implied,
24
+ including but not limited to the warranties of merchantability, fitness for a particular purpose, or non-infringement.
25
+ In no event shall the author be liable for any claim, damages, or other liability arising from, out of, or in connection with the software or its use.
26
+
27
+ Project-URL: Homepage, https://mis.gotech.biz
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: pymysql
31
+ Dynamic: license-file
32
+
33
+ #UtilityLibAPI Classes
34
+
35
+ ## History of version
36
+ Version 0.1.0: 2025/10/13<BR>
37
+ Create UtilityLibAPI -- EnDeCodeLib + SessionVARLib<BR>
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ setup.cfg
5
+ src/EnDeCodeLib.py
6
+ src/SessionVARLib.py
7
+ src/__init__.py
8
+ src/UtilityLibAPI.egg-info/PKG-INFO
9
+ src/UtilityLibAPI.egg-info/SOURCES.txt
10
+ src/UtilityLibAPI.egg-info/dependency_links.txt
11
+ src/UtilityLibAPI.egg-info/requires.txt
12
+ src/UtilityLibAPI.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ EnDeCodeLib
2
+ SessionVARLib
3
+ __init__
@@ -0,0 +1,6 @@
1
+ from .EnDeCodeLib import CLASS_EnDeCodeLib
2
+ from .SessionVARLib import TIniFile
3
+
4
+ __all__ = ["CLASS_EnDeCodeLib",
5
+ "CLASS_SessionVAR"
6
+ ]