UtilityLibAPI 0.1.0__py3-none-any.whl
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.
- EnDeCodeLib.py +198 -0
- SessionVARLib.py +143 -0
- __init__.py +6 -0
- utilitylibapi-0.1.0.dist-info/METADATA +37 -0
- utilitylibapi-0.1.0.dist-info/RECORD +8 -0
- utilitylibapi-0.1.0.dist-info/WHEEL +5 -0
- utilitylibapi-0.1.0.dist-info/licenses/LICENSE +20 -0
- utilitylibapi-0.1.0.dist-info/top_level.txt +3 -0
EnDeCodeLib.py
ADDED
|
@@ -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));
|
SessionVARLib.py
ADDED
|
@@ -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()
|
__init__.py
ADDED
|
@@ -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,8 @@
|
|
|
1
|
+
EnDeCodeLib.py,sha256=YPaqzZJXl5f0xwPv4V4zMRWaH6-6K5MNlKMsyUcQ95U,9189
|
|
2
|
+
SessionVARLib.py,sha256=WGzozRfENQrjNuI5vuRC8CXbz9jSKvE5d612e5WB2q8,4821
|
|
3
|
+
__init__.py,sha256=mwbw7cT0InGLpYGQx_kEsiqk4Dw8L_vjYreuRCQJF4w,161
|
|
4
|
+
utilitylibapi-0.1.0.dist-info/licenses/LICENSE,sha256=fpKsUxampChuMsbZd_ww_SEJqK88RFiYAvqzAsklgFI,1072
|
|
5
|
+
utilitylibapi-0.1.0.dist-info/METADATA,sha256=jVETIZG-ic99wrHPtZUHE8f0ScrknbVZZIxVFIU2Sz4,1690
|
|
6
|
+
utilitylibapi-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
+
utilitylibapi-0.1.0.dist-info/top_level.txt,sha256=AUrER5HwXxS5yGFjN1FkwoZDPCWEUrjQXKiHHxAQnxE,35
|
|
8
|
+
utilitylibapi-0.1.0.dist-info/RECORD,,
|
|
@@ -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.
|