Compare commits

..

74 commits

Author SHA1 Message Date
7b75da62a3 ホストURLをコマンドラインから指定できるように 2024-09-11 16:28:10 +09:00
ab6e77a99f 停止処理ができないバグを修正 2024-09-10 19:21:01 +09:00
a28df9ad77 logを除外 2024-09-10 19:18:25 +09:00
6bcb570b10 終了処理を簡略化 2024-09-10 18:11:41 +09:00
e4b99a85ff 使用目的が取得できないバグへの暫定的対応 2024-09-07 15:30:31 +09:00
9fe9330b13 この前の前のコミットのバグを今度今度こそ修正 2024-09-07 14:57:58 +09:00
65403a4cca この前のコミットのバグを今度こそ修正
ついでにメッセージの表示を見やすく
2024-09-07 14:47:47 +09:00
0fcfc8009f PCを自分が使用中なのに他人が使用中と出力されるバグを修正 2024-09-07 14:36:27 +09:00
ebef42cc55 内部エラーのときもパスワードが間違っていると出力するバグを修正 2024-09-07 14:06:26 +09:00
20fa6f1fb8 デバイスリストのキー名を修正 2024-09-07 14:01:05 +09:00
7e35bd6089 デバイスIDをデバイスインスタンスパスに変更
ワンタイムパスワードが消去されないバグを修正
デバイス登録の際USBデバイスではなく入力デバイスの一覧を出力するように
自前のデバイスは0番として処理するように
2024-09-07 13:40:13 +09:00
61e01ae055 アップデートを簡略化するバッチファイルを追加 2024-09-06 16:30:10 +09:00
cc771d5196 get_usb_devicesがclass内で動作しなかったバグを修正 2024-09-06 02:39:40 +09:00
4836e6ae8f リストの番号を修正 2024-09-06 02:29:19 +09:00
e97562b9b2 デバイス番号のボタンを削除 2024-09-06 02:26:52 +09:00
7282af55e0 デバイス一覧から参照する型名を修正 2024-09-06 02:04:51 +09:00
611bd03b80 strへの変換を撤回 2024-09-06 02:02:07 +09:00
75fa89497e selfなくす 2024-09-06 01:55:19 +09:00
3f31307164 改名できてなかった こっちで改名 2024-09-06 01:48:54 +09:00
9279edc8ca devicesetupをdeviceregisterに改名とちょっとのバグ修正 2024-09-06 01:47:45 +09:00
4713dc7a23 デバイス番号の入力の自動化 (#14) への対応 2024-09-06 01:30:44 +09:00
550cf83e86 ハッシュをSHA256へ変更
マスターパスワードの管理をデータベースで行うように
テーブルの一部カラム変更
2024-09-06 00:09:37 +09:00
e41324eae4 使用目的のプリセットが使えなくなるバグを修正 2024-09-05 21:11:34 +09:00
b1994c5def tempディレクトリを再度除外 2024-09-05 21:04:09 +09:00
a6c856cf48 tempの中を削除 2024-09-05 21:03:39 +09:00
036e1c0b0b 使用目的かけないバグ対処そのに 2024-09-05 10:43:34 +09:00
e50a5748c9 使用目的が書けなくなったバグへの対処 2024-09-05 10:38:17 +09:00
55f989d365 ログファイルが見ずらいのを修正 2024-09-04 19:47:58 +09:00
cf0013e53a 使用理由のプリセットを指定できるように
ログファイルを作成するように
いくつか説明の追加
2024-09-04 19:42:39 +09:00
5384cc9668 テスト用クライアントの追加 2024-08-31 16:13:25 +09:00
518eea2061 #6 のバグへの対策 2024-08-30 23:35:32 +09:00
77ada9a5e2 削除処理の繰り返しを修正 2024-08-30 23:29:50 +09:00
e585e9d596 password_hashがあったときの処理を修正 2024-08-26 00:51:31 +09:00
86a4ef8766 型を明示的に指定 2024-08-26 00:47:39 +09:00
631fd990cb printの実行順番を修正 2024-08-26 00:46:15 +09:00
3086f689ad ファイルの消去を設定できるように 2024-08-26 00:40:20 +09:00
b3687e8a2d ANDの,を消す 2024-08-26 00:35:18 +09:00
4366aa06ca json処理あたりを修正 2024-08-26 00:25:04 +09:00
25f3ae6404 UUID型をstr(VARCHAR)に変更 2024-08-26 00:19:53 +09:00
c6c602a34b if文のあたりのミスを修正 2024-08-26 00:16:53 +09:00
27361d40db returnコードを修正 2024-08-26 00:04:39 +09:00
b6b34ce315 参照するカラム名を修正 2024-08-26 00:02:24 +09:00
665b53c28d registerのワンタイムパスワードをstr型に指定 2024-08-25 23:58:53 +09:00
bd1aa2243c ワンタイムパスワードを入力できるように 2024-08-25 23:47:14 +09:00
de8412e4eb ワンタイムパスワードの長さを決定(8文字) 2024-08-25 23:35:02 +09:00
bf1dc817ab クライアント登録時のワンタイムパスワードを実装 2024-08-25 23:28:36 +09:00
2ddcc6626a user_idをdiscord_user_idに全面的に改める 2024-08-23 02:33:17 +09:00
d433f38d94 stopのKeyErrorを修正 2024-08-23 02:28:23 +09:00
26f5269ce5 PC使用登録時管理者側のメッセージでDiscordのユーザー名が見える問題を修正 2024-08-23 02:24:42 +09:00
35ba7e0dff それぞれ参照するカラム名の修正 2024-08-23 02:17:10 +09:00
668af84ca8 PC使用開始時に管理者側に送るメッセージを修正 2024-08-23 02:12:10 +09:00
698e629063 exportを修正 2024-08-23 02:09:13 +09:00
ef0bd4b509 Monitorを修正 2024-08-23 02:04:41 +09:00
3160f1c079 念の為、マウスとキーボード使用確認のcursorを上に持っていく 2024-08-23 01:53:09 +09:00
7bade8c366 printf攻撃 2024-08-23 01:48:01 +09:00
aae08d4701 こころぐを追加2 2024-08-23 01:42:02 +09:00
ca6ff5d050 ここログを追加 2024-08-23 01:38:54 +09:00
1e8ef35e3f cursorが見つからないエラーを修正したい 2024-08-23 01:30:58 +09:00
2d5ea6a48d PCの使用登録でデータベースのコミットを忘れてた 2024-08-23 01:18:02 +09:00
125ca3e601 キーボード、マウスの使用確認関数に自前のものかを判定する処理を追加 2024-08-23 01:15:21 +09:00
cd6461641c PCの使用チェックにmember_idで確認できる処理を追加
PC使用登録時にmember_idを使ってPCの使用確認をするように
2024-08-23 01:09:00 +09:00
69dbdd0bc3 PC使用登録時にユーザーが登録されていなかったときの返り値を修正 2024-08-23 00:58:38 +09:00
edd01a0d4d 登録のときにどうしてもエラーになるバグを修正 2024-08-23 00:55:49 +09:00
9269441051 custom_idで言うところのreasonregisterあたりの処理を修正 2024-08-23 00:53:03 +09:00
7d7cc17193 マウスを選ぶボタンのところのviewの名前が間違ってたので修正 2024-08-23 00:44:57 +09:00
4b4455694e かっこ閉じ必要だったのでロールバック 2024-08-23 00:39:34 +09:00
ee4113f95d 無駄なかっことじを削除 2024-08-23 00:34:07 +09:00
829184a91a club_memberテーブルのカラム名を修正 2024-08-23 00:26:42 +09:00
55b55046df スペースがなかったのが気になっただけ 2024-08-23 00:22:01 +09:00
db55479da9 ちょっとバグ修正 2024-08-23 00:19:33 +09:00
8e635eb92c Botの仕様変更に合わせて更新 2024-08-23 00:18:07 +09:00
c107400ed2 fstop側のマウス、キーボードの使用停止処理を追加 2024-08-23 00:17:51 +09:00
07fcc298a9 全部変えた
だいたいの関数で返り値をreturnで直接返すようにした
返り値の辞書の構造変更(resultはだいたいの状況がわかる番号で、aboutに従来のresultであった理由を記載)
データベース構造の変更(キーボード、マウスリスト追加、その他カラム名変更)
PC使用登録時にマウスとキーボードの番号をを別で尋ねるように
PC使用登録時にマウスとキーボードを自前で持ってきている場合のボタンと処理を追加
PC登録の関数内の一部の処理を別の関数に移した
2024-08-22 23:58:31 +09:00
03319676e9 tempディレクトリを除外 2024-08-22 23:53:37 +09:00
7 changed files with 1649 additions and 401 deletions

1
.gitignore vendored
View file

@ -166,3 +166,4 @@ test.py
data/ data/
export/ export/
temp/ temp/
log/

File diff suppressed because it is too large Load diff

View file

@ -2,9 +2,14 @@ import psycopg2
import os import os
import json import json
from flask import Flask, request, jsonify, render_template from flask import Flask, request, jsonify, render_template
import uuid
import string
import random
import hashlib
config_dir_path = "./config/" config_dir_path = "./config/"
server_config_path = config_dir_path + "server.json" server_config_path = config_dir_path + "server.json"
onetime_config_path = config_dir_path + "onetime.json"
if not os.path.isfile(server_config_path): if not os.path.isfile(server_config_path):
if not os.path.isdir(config_dir_path): if not os.path.isdir(config_dir_path):
os.mkdir(config_dir_path) os.mkdir(config_dir_path)
@ -40,85 +45,392 @@ class Auth():
def __init__(self, host, db, port, user, password): def __init__(self, host, db, port, user, password):
self.db = psycopg2.connect(f"host={host} dbname={db} port={port} user={user} password={password}") self.db = psycopg2.connect(f"host={host} dbname={db} port={port} user={user} password={password}")
def check(self, pc_number, password): def token_generate(self, length):
letters = string.ascii_letters + string.digits
token = ''.join(random.choice(letters) for _ in range(length))
return token
def master_password_generate(self, length):
characters = string.ascii_letters + string.digits + string.punctuation
master_password = ''.join(random.choice(characters) for _ in range(length))
return master_password
def hash_genarate(self, source):
hashed = hashlib.sha256(source.encode())
return hashed.hexdigest()
def check(self, **kwargs):
try: try:
cursor = self.db.cursor() cursor = self.db.cursor()
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s AND password_hash = %s", (pc_number, password)) pc_number = int(kwargs["pc_number"])
pc_info = cursor.fetchall() pc_uuid = str(kwargs["pc_uuid"])
if not pc_info: pc_token = str(kwargs["pc_token"])
return 1 if "device_list" in kwargs:
device_list = kwargs["device_list"]
else: else:
return 0 pass
keyboard_number = "own"
mouse_number = "own"
if "password_hash" in kwargs:
password_hash = str(kwargs["password_hash"])
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s AND password_hash = %s AND pc_uuid = %s AND pc_token = %s", (pc_number, password_hash, pc_uuid, pc_token))
pc_info = cursor.fetchall()
if pc_info:
for device in device_list:
cursor.execute("SELECT * FROM keyboard_list WHERE device_instance_path = %s", (device["device_instance_path"],))
keyboard_record = cursor.fetchall()
if keyboard_record:
keyboard_number = int(keyboard_record[0][0])
break
else:
pass
for device in device_list:
cursor.execute("SELECT * FROM mouse_list WHERE device_instance_path = %s", (device["device_instance_path"],))
mouse_record = cursor.fetchall()
if mouse_record:
mouse_number = int(mouse_record[0][0])
break
else:
pass
return {"result": 0, "about": "ok", "output_dict": {"keyboard_number": keyboard_number, "mouse_number": mouse_number}}
else:
return {"result": 1, "about": "incorrect_password"}
else:
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s AND pc_uuid = %s AND pc_token = %s", (pc_number, pc_uuid, pc_token))
pc_info = cursor.fetchall()
if pc_info:
return {"result": 0, "about": "ok"}
else:
return {"result": 1, "about": "unregistered_pc"}
except Exception as error:
print("PCの登録状況を調査中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally: finally:
cursor.close() cursor.close()
def device_use_register(self, **kwargs):
try:
pc_number = int(kwargs["pc_number"])
if kwargs["keyboard_number"] == "own":
keyboard_number = 0
else:
keyboard_number = int(kwargs["keyboard_number"])
if kwargs["mouse_number"] == "own":
mouse_number = 0
else:
mouse_number = int(kwargs["mouse_number"])
cursor = self.db.cursor()
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s", (pc_number,))
pc_list_record = cursor.fetchall()
pc_using_member_id = pc_list_record[0][1]
if pc_using_member_id == None:
return {"result": 1, "about": "not_used"}
else:
cursor.execute("SELECT * FROM pc_usage_history WHERE member_id = %s AND pc_number = %s ORDER BY id DESC LIMIT 1", (pc_using_member_id, pc_number))
pc_usage_history_record = cursor.fetchall()
pc_usage_history_record_id = pc_usage_history_record[0][0]
cursor.execute("UPDATE pc_usage_history SET keyboard_number = %s, mouse_number = %s WHERE id = %s", (keyboard_number, mouse_number, pc_usage_history_record_id))
if keyboard_number == 0:
pass
else:
cursor.execute("UPDATE keyboard_list SET using_member_id = %s WHERE keyboard_number = %s", (pc_using_member_id, keyboard_number))
if mouse_number == 0:
pass
else:
cursor.execute("UPDATE mouse_list SET using_member_id = %s WHERE mouse_number = %s", (pc_using_member_id, mouse_number))
self.db.commit()
return {"result": 0, "about": "ok"}
except Exception as error:
print("デバイスの使用登録中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
def device_register(self, **kwargs):
try:
cursor = self.db.cursor()
mode = kwargs["mode"]
number = kwargs["number"]
device_instance_path = kwargs["device_instance_path"]
device_name = kwargs["device_name"]
if mode == "keyboard":
keyboard_number = int(kwargs["number"])
cursor.execute("SELECT * FROM keyboard_list WHERE keyboard_number = %s", (keyboard_number,))
keyboard_record = cursor.fetchall()
if keyboard_record:
cursor.execute("UPDATE keyboard_list SET device_instance_path = %s, device_name = %s WHERE keyboard_number = %s", (device_instance_path, device_name, keyboard_number))
self.db.commit()
return {"result": 0, "about": "ok"}
else:
cursor.execute("INSERT INTO keyboard_list (keyboard_number, device_instance_path, device_name) VALUES (%s, %s, %s)", (keyboard_number, device_instance_path, device_name))
return {"result": 0, "about": "ok"}
elif mode == "mouse":
mouse_number = int(kwargs["number"])
cursor.execute("SELECT * FROM mouse_list WHERE mouse_number = %s", (mouse_number,))
mouse_record = cursor.fetchall()
if mouse_record:
cursor.execute("UPDATE mouse_list SET device_instance_path = %s, device_name = %s WHERE mouse_number = %s", (device_instance_path, device_name, mouse_number))
self.db.commit()
return {"result": 0, "about": "ok"}
else:
cursor.execute("INSERT INTO mouse_list (mouse_number, device_instance_path, device_name) VALUES (%s, %s, %s)", (mouse_number, device_instance_path, device_name))
return {"result": 0, "about": "ok"}
except Exception as error:
print("停止処理中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
def delete(self, pc_number): def delete(self, pc_number):
try: try:
cursor = self.db.cursor() cursor = self.db.cursor()
cursor.execute("UPDATE pc_list SET password_hash = NULL WHERE pc_number = %s", (pc_number,)) cursor.execute("UPDATE pc_list SET password_hash = NULL WHERE pc_number = %s", (pc_number,))
self.db.commit() self.db.commit()
return {"result": 0, "about": "ok"}
except Exception as error:
print("パスワードの削除中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally:
cursor.close()
def user_register_check(self, **kwargs):
try:
discord_user_id = str(kwargs["discord_user_id"])
cursor = self.db.cursor()
cursor.execute("SELECT * FROM club_member WHERE discord_user_id = %s", (discord_user_id,))
user_record = cursor.fetchall()
#ユーザーデータが見つかった場合(登録済みの場合)
if user_record:
member_id = user_record[0][0]
name = user_record[0][1]
discord_user_name = user_record[0][2]
return {"result": 0, "about": "exist", "user_info": {"member_id": member_id, "name": name, "discord_user_name": discord_user_name}}
#ユーザーデータがなかったら(未登録の場合)
else:
return {"result": 1, "about": "user_data_not_found"}
except Exception as error:
print("ユーザーの登録状況を調査中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally: finally:
cursor.close() cursor.close()
def stop(self, **kwargs): def stop(self, **kwargs):
# bot側のfstopを基に
try: try:
pc_number = int(kwargs["pc_number"]) pc_number = kwargs["pc_number"]
cursor = self.db.cursor() cursor = self.db.cursor()
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s", (pc_number,)) cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s", (pc_number,))
pc_list_record = cursor.fetchall() pc_list_record = cursor.fetchall()
if not pc_list_record[0][1] == None: pc_using_member_id = pc_list_record[0][1]
cursor.execute("UPDATE pc_list SET using_user_id = NULL WHERE pc_number = %s", (pc_number,)) pc_password_hash = pc_list_record[0][2]
if pc_using_member_id == None:
if not pc_list_record[0][2] == None: return {"result": 1, "about": "not_used"}
cursor.execute("UPDATE pc_list SET password_hash = NULL WHERE pc_number = %s", (pc_number,))
cursor.execute("SELECT * FROM pc_usage_history WHERE member_id = %s AND pc_number = %s ORDER BY id DESC LIMIT 1", (pc_list_record[0][1], pc_number))
pc_usage_history_record = cursor.fetchall()
cursor.execute("UPDATE pc_usage_history SET end_use_time = current_timestamp WHERE id = %s", (pc_usage_history_record[0][0],))
self.db.commit()
result = {"result": "ok"}
else: else:
result = {"result": "not_used"} cursor.execute("UPDATE pc_list SET using_member_id = NULL WHERE pc_number = %s", (pc_number,))
if pc_password_hash == None:
pass
else:
cursor.execute("UPDATE pc_list SET password_hash = NULL WHERE pc_number = %s", (pc_number,))
cursor.execute("SELECT * FROM pc_usage_history WHERE member_id = %s AND pc_number = %s ORDER BY id DESC LIMIT 1", (pc_using_member_id, pc_number))
pc_usage_history_record = cursor.fetchall()
pc_usage_history_record_id = pc_usage_history_record[0][0]
keyboard_number = pc_usage_history_record[0][3]
mouse_number = pc_usage_history_record[0][4]
if keyboard_number == None:
pass
else:
# keyboard_listの使用中ユーザーを消す
cursor.execute("UPDATE keyboard_list SET using_member_id = NULL WHERE keyboard_number = %s", (keyboard_number,))
if mouse_number == None:
pass
else:
# mouse_listの使用中ユーザーを消す
cursor.execute("UPDATE mouse_list SET using_member_id = NULL WHERE mouse_number = %s", (mouse_number,))
cursor.execute("UPDATE pc_usage_history SET end_use_time = clock_timestamp() WHERE id = %s", (pc_usage_history_record_id,))
self.db.commit()
return {"result": 0, "about": "ok"}
except: except Exception as error:
result = {"result": "error"} print("停止処理中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally: finally:
cursor.close() cursor.close()
return result
def register(self, **kwargs):
try:
cursor = self.db.cursor()
pc_number = int(kwargs["pc_number"])
pc_uuid = str(kwargs["pc_uuid"])
cursor.execute("SELECT pc_uuid FROM pc_list WHERE pc_number = %s", (pc_number,))
pc_record = cursor.fetchall()
pc_record_uuid = pc_record[0][0]
if pc_record_uuid == None:
pc_token = self.token_generate(36)
master_password = self.master_password_generate(16)
master_password_hash = self.hash_genarate(master_password)
cursor.execute("UPDATE pc_list SET pc_uuid = %s, pc_token = %s, master_password = %s WHERE pc_number = %s", (pc_uuid, pc_token, master_password, pc_number))
self.db.commit()
return {"result": 0, "about": "ok", "output_dict": {"pc_token": pc_token, "master_password": master_password, "master_password_hash": master_password_hash}}
else:
return {"result": 1, "about": "exist"}
except Exception as error:
print("停止処理中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally:
cursor.close()
app = Flask(__name__, static_folder="./resource/") app = Flask(__name__, static_folder="./resource/")
auth = Auth(server_config["db"]["host"], server_config["db"]["db_name"], server_config["db"]["port"], server_config["db"]["username"], server_config["db"]["password"]) auth = Auth(server_config["db"]["host"], server_config["db"]["db_name"], server_config["db"]["port"], server_config["db"]["username"], server_config["db"]["password"])
@app.route('/register', methods=['POST'])
def register():
pc_number = int(request.json.get('pc_number'))
pc_uuid = str(request.json.get('pc_uuid'))
onetime_password = str(request.json.get('onetime'))
if os.path.isfile(onetime_config_path):
with open(onetime_config_path, "r") as r:
onetime_config = json.load(r)
if onetime_password == onetime_config["onetime"]["pc_register"]:
register_result = auth.register(pc_number=pc_number, pc_uuid=pc_uuid)
pc_token = register_result["output_dict"]["pc_token"]
master_password = register_result["output_dict"]["master_password"]
master_password_hash = register_result["output_dict"]["master_password_hash"]
onetime_config["onetime"]["pc_register"] = None
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok', 'pc_token': pc_token, 'master_password': master_password, 'master_password_hash': master_password_hash}), 200
else:
return jsonify({'message': 'damedesu'}), 401
else:
return jsonify({'message': 'damedesu'}), 401
@app.route('/verify', methods=['POST']) @app.route('/verify', methods=['POST'])
def verify(): def verify():
pc_number = int(request.json.get('pc_number')) pc_number = int(request.json.get('pc_number'))
password = request.json.get('password') password_hash = request.json.get('password')
print(str(pc_number) + "の認証処理を開始...") pc_uuid = request.json.get('pc_uuid')
pc_token = request.json.get('pc_token')
devices = request.json.get('devices')
if auth.check(pc_number, password) == 0: print(str(pc_number) + "の認証処理を開始...")
pc_auth = auth.check(pc_number=pc_number, password_hash=password_hash, pc_uuid=pc_uuid, pc_token=pc_token, device_list=devices)
if pc_auth["result"] == 0:
auth.delete(pc_number) auth.delete(pc_number)
auth.device_use_register(pc_number=pc_number, keyboard_number=pc_auth["output_dict"]["keyboard_number"], mouse_number=pc_auth["output_dict"]["mouse_number"])
print(str(pc_number) + "の認証処理は成功しました.") print(str(pc_number) + "の認証処理は成功しました.")
return jsonify({'message': 'ok'}), 200 return jsonify({'message': 'ok'}), 200
else: elif pc_auth["result"] == 1:
print(str(pc_number) + "の認証処理は失敗しました.") if pc_auth["about"] == "incorrect_password":
return jsonify({'message': 'damedesu'}), 401 print(str(pc_number) + "の認証処理はパスワードが正しくないため失敗しました.")
return jsonify({'message': 'incorrect_password'}), 401
else:
print(str(pc_number) + "の認証処理は失敗しました.")
return jsonify({'message': 'damedesu'}), 500
@app.route('/stop', methods=['POST']) @app.route('/stop', methods=['POST'])
def stop(): def stop():
pc_number = int(request.json.get('pc_number')) pc_number = int(request.json.get('pc_number'))
pc_uuid = str(request.json.get('pc_uuid'))
pc_token = str(request.json.get('pc_token'))
print(str(pc_number) + "の使用停止処理を開始...") print(str(pc_number) + "の使用停止処理を開始...")
pc_stop = auth.stop(pc_number=pc_number)
if pc_stop["result"] == "ok":
print(str(pc_number) + "の使用停止処理は成功しました.")
return jsonify({'message': 'ok'}), 200
else:
print(str(pc_number) + "の使用停止処理は失敗しました.")
return jsonify({'message': 'error'}), 500
pc_auth = auth.check(pc_number=pc_number, pc_uuid=pc_uuid, pc_token=pc_token)
if pc_auth["result"] == 0:
pc_stop = auth.stop(pc_number=pc_number)
if pc_stop["result"] == 0:
print(str(pc_number) + "の使用停止処理は成功しました.")
return jsonify({'message': 'ok'}), 200
else:
print(str(pc_number) + "の使用停止処理は失敗しました.")
return jsonify({'message': 'error'}), 500
else:
return jsonify({'message': 'damedesu'}), 401
@app.route('/device_register', methods=['POST'])
def device_register():
onetime_password = str(request.json.get('onetime'))
mode = str(request.json.get('mode'))
number = int(request.json.get('number'))
device_instance_path = str(request.json.get('device_instance_path'))
device_name = str(request.json.get('device_name'))
if os.path.isfile(onetime_config_path):
with open(onetime_config_path, "r") as r:
onetime_config = json.load(r)
if onetime_password == onetime_config["onetime"]["device_register"]:
if mode == "keyboard":
print("キーボードの登録処理を開始...")
device_register = auth.device_register(mode="keyboard", number=number, device_instance_path=device_instance_path, device_name=device_name)
if device_register["result"] == 0:
print(f"キーボード {number} 番の登録処理は成功しました.")
onetime_config["onetime"]["device_register"] = None
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok'}), 200
else:
print(f"キーボード {number} 番の登録処理は失敗しました.")
return jsonify({'message': 'error'}), 500
elif mode == "mouse":
print("マウスの登録処理を開始...")
device_register = auth.device_register(mode="mouse", number=number, device_instance_path=device_instance_path, device_name=device_name)
if device_register["result"] == 0:
print(f"マウス {number} 番の登録処理は成功しました.")
onetime_config["onetime"]["device_register"] = None
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok'}), 200
else:
print(f"マウス {number} 番の登録処理は失敗しました.")
return jsonify({'message': 'error'}), 500
else:
return jsonify({'message': 'damedesu'}), 401
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -13,8 +13,10 @@ import tkinter
import threading import threading
import sys import sys
import shutil import shutil
import uuid
import time import time
import win32com.client
import pythoncom
app_name = "Dislocker" app_name = "Dislocker"
dislocker_dir = os.path.dirname(os.path.abspath(sys.argv[0])) dislocker_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
@ -34,13 +36,68 @@ if not os.path.isfile(client_config_path):
"pc_number": 1, "pc_number": 1,
"master_password_hash": "", "master_password_hash": "",
"testing": 0, "testing": 0,
"eraser": 1 "eraser": 1,
"pc_uuid": "",
"pc_token": ""
} }
elif os.path.isfile(client_config_path): elif os.path.isfile(client_config_path):
with open(client_config_path, "r") as r: with open(client_config_path, "r") as r:
client_config = json.load(r) client_config = json.load(r)
def get_input_devices():
str_computer = "."
obj_wmi_service = win32com.client.Dispatch("WbemScripting.SWbemLocator")
obj_swem_services = obj_wmi_service.ConnectServer(str_computer, "root\\cimv2")
col_items = obj_swem_services.ExecQuery("Select * from Win32_PnPEntity where PNPDeviceID like 'HID%'")
input_devices = []
for obj_item in col_items:
input_devices.append({
"device_id": obj_item.DeviceID,
"PNPDeviceID": obj_item.PNPDeviceID,
"Description": obj_item.Description,
"device_name": obj_item.Name,
"Manufacturer": obj_item.Manufacturer,
"Service": obj_item.Service,
"FriendlyName": obj_item.Name, # デバイスとプリンターで表示される名前
"device_instance_path": obj_item.DeviceID # デバイスインスタンスパス
})
return input_devices
def device_register(**kwargs):
onetime = str(kwargs["onetime"])
mode = str(kwargs["mode"])
number = int(kwargs["number"])
device_instance_path = str(kwargs["device_instance_path"])
device_name = str(kwargs["device_name"])
device_register_json = {
"number": number,
"device_instance_path": device_instance_path,
"device_name": device_name,
"mode": mode,
"onetime": onetime
}
register_url = client_config["auth_host_url"] + "/device_register"
responce = requests.post(register_url, json=device_register_json)
if responce.status_code == 200:
print("デバイスの登録に成功しました。")
return {"result": 0, "about": "ok"}
elif responce.status_code == 401:
print("認証に失敗しました。")
return {"result": 1, "about": "auth_failed"}
else:
print("内部エラーによりデバイスの登録に失敗しました。")
return {"result": 1, "about": "error"}
def master_password_gen():
numbers = string.digits # (1)
password = ''.join(random.choice(numbers) for _ in range(10)) # (2)
password_hash = hashlib.sha256(password.encode()).hexdigest()
result = {"password": password, "password_hash": password_hash}
return result
def init(**kwargs): def init(**kwargs):
sp_startupinfo = subprocess.STARTUPINFO() sp_startupinfo = subprocess.STARTUPINFO()
sp_startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW sp_startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
@ -54,17 +111,53 @@ def init(**kwargs):
return 1 return 1
if client_config["initial"] == 1: if client_config["initial"] == 1:
master_password = master_password_gen() pc_uuid = uuid.uuid4()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 初回起動を検出", message=f"初回起動のようです。\nマスターパスワードを記録しておいてください。\nこれ以降二度と表示されることはないでしょう。\n\n{master_password["password"]}\n\nまた、認証先サーバーの接続先を指定してください。ロックを解除できなくなります。") client_config["pc_uuid"] = str(pc_uuid)
client_config["master_password_hash"] = master_password["password_hash"]
client_config["initial"] = 0
if "pc_number" in kwargs: if "pc_number" in kwargs:
client_config["pc_number"] = int(kwargs["pc_number"]) client_config["pc_number"] = int(kwargs["pc_number"])
else: else:
client_config["pc_number"] = 1 tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nPC番号が指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
with open(client_config_path, "w") as w: return 2
json.dump(client_config, w, indent=4)
return 2 if "onetime" in kwargs:
onetime = str(kwargs["onetime"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
return 2
if "host_url" in kwargs:
client_config["auth_host_url"] = str(kwargs["host_url"])
else:
pass
register_url = client_config["auth_host_url"] + "/register"
register_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(pc_uuid),
"onetime": onetime
}
responce = requests.post(register_url, json=register_json)
if responce.status_code == 200:
print("PCの情報が登録されました。")
responce_json = responce.json()
pc_token = str(responce_json["pc_token"])
master_password_hash = str(responce_json["master_password_hash"])
master_password = str(responce_json["master_password"])
client_config["pc_token"] = pc_token
client_config["master_password_hash"] = master_password_hash
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 初回起動を検出", message=f"初回起動のようです。\nマスターパスワードを記録しておいてください。\nBotが起動している場合は、管理者がDiscordから確認することもできます。\n\n{master_password}\n\n")
client_config["initial"] = 0
with open(client_config_path, "w") as w:
json.dump(client_config, w, indent=4)
return 2
else:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが間違っている可能性があります。")
return 2
else: else:
return 0 return 0
@ -92,46 +185,6 @@ class App(customtkinter.CTk):
self.toast() self.toast()
self.destroy() self.destroy()
def delete_appdata(self, **kwargs):
process_name = kwargs["process_name"]
dir_path = kwargs["dir_path"]
if not os.path.exists(dir_path):
print(f"エラー: 指定されたディレクトリ {dir_path} が存在しません。")
return 1
i = 0
i_max = 10
result = 1
while i != i_max:
i += 1
try:
# プロセスの終了
subprocess.run(['taskkill', '/f', '/t', '/im', process_name])
print(f"{process_name} を終了しました。")
time.sleep(0.1)
# ディレクトリの削除
shutil.rmtree(dir_path)
if os.path.isdir(dir_path):
pass
else:
print(f"{dir_path} を削除しました。")
result = 0
i = i_max
except subprocess.CalledProcessError as e:
print(f"プロセス終了エラー: {e}")
except PermissionError as e:
print(f"権限エラー: {e}")
except Exception as e:
print("エラーが発生しました。\nエラー内容:")
print(f"エラータイプ: {e.__class__.__name__}")
print(f"エラー引数: {e.args}")
print(f"エラーメッセージ: {str(e)}")
def block_key(self): def block_key(self):
block_keys = ['ctrl', 'alt', 'windows', 'shift', 'delete'] block_keys = ['ctrl', 'alt', 'windows', 'shift', 'delete']
for i in block_keys: for i in block_keys:
@ -247,7 +300,7 @@ class Lock(customtkinter.CTkToplevel):
keyboard.add_hotkey('ctrl+shift+q', self.exit) keyboard.add_hotkey('ctrl+shift+q', self.exit)
def hash_genarate(self, source): def hash_genarate(self, source):
hashed = hashlib.md5(source.encode()) hashed = hashlib.sha256(source.encode())
return hashed.hexdigest() return hashed.hexdigest()
def auth_start(self): def auth_start(self):
@ -270,10 +323,38 @@ class Lock(customtkinter.CTkToplevel):
self.signin_button.configure(state="normal", fg_color="#3c8dd0") self.signin_button.configure(state="normal", fg_color="#3c8dd0")
self.signout_button.configure(state="normal", fg_color="#3c8dd0") self.signout_button.configure(state="normal", fg_color="#3c8dd0")
def get_input_devices(self):
try:
pythoncom.CoInitialize()
str_computer = "."
obj_wmi_service = win32com.client.Dispatch("WbemScripting.SWbemLocator")
obj_swem_services = obj_wmi_service.ConnectServer(str_computer, "root\\cimv2")
col_items = obj_swem_services.ExecQuery("Select * from Win32_PnPEntity where PNPDeviceID like 'HID%'")
input_devices = []
for obj_item in col_items:
input_devices.append({
"device_id": obj_item.DeviceID,
"PNPDeviceID": obj_item.PNPDeviceID,
"Description": obj_item.Description,
"device_name": obj_item.Name,
"Manufacturer": obj_item.Manufacturer,
"Service": obj_item.Service,
"FriendlyName": obj_item.Name, # デバイスとプリンターで表示される名前
"device_instance_path": obj_item.DeviceID # デバイスインスタンスパス
})
pythoncom.CoUninitialize()
return input_devices
except pythoncom.com_error as e:
print("Error:", e)
return []
def auth(self): def auth(self):
self.button_disable() self.button_disable()
password = str(self.password_entry.get()) password = str(self.password_entry.get())
devices = self.get_input_devices()
if len(password) == 10: if len(password) == 10:
print("マスターパスワードで認証を試行します。") print("マスターパスワードで認証を試行します。")
master_password_hash = self.hash_genarate(str(self.password_entry.get())) master_password_hash = self.hash_genarate(str(self.password_entry.get()))
@ -288,11 +369,13 @@ class Lock(customtkinter.CTkToplevel):
self.button_enable() self.button_enable()
self.deiconify() self.deiconify()
print("認証サーバーにアクセスします。") print("認証サーバーにアクセスします。")
auth_url = client_config["auth_host_url"] + "/verify" auth_url = client_config["auth_host_url"] + "/verify"
auth_json = { auth_json = {
"pc_number": int(client_config["pc_number"]), "pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"]),
"devices": devices,
"password": self.hash_genarate(str(self.password_entry.get())) "password": self.hash_genarate(str(self.password_entry.get()))
} }
try: try:
@ -300,13 +383,20 @@ class Lock(customtkinter.CTkToplevel):
if responce.status_code == 200: if responce.status_code == 200:
print("認証サーバー経由で認証しました。") print("認証サーバー経由で認証しました。")
self.exit() self.exit()
else: elif responce.status_code == 401:
print("認証サーバー経由での認証に失敗しました。") print("認証サーバー経由での認証に失敗しました。")
self.withdraw() self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!") msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
self.msg_subtitle_1.configure(text='パスワードが間違っています! ') self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
self.button_enable() self.button_enable()
self.deiconify() self.deiconify()
elif responce.status_code == 500:
print("内部エラーにより認証に失敗しました。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 内部エラー", message=f"内部エラーにより認証に失敗しました。")
self.msg_subtitle_1.configure(text='内部エラーにより認証に失敗しました。 ')
self.button_enable()
self.deiconify()
except: except:
print("認証サーバーにアクセスできません。マスターパスワードで認証を試行します。") print("認証サーバーにアクセスできません。マスターパスワードで認証を試行します。")
master_password_hash = self.hash_genarate(str(self.password_entry.get())) master_password_hash = self.hash_genarate(str(self.password_entry.get()))
@ -430,12 +520,16 @@ class Stop():
print("削除処理をスキップ。") print("削除処理をスキップ。")
stop_url = client_config["auth_host_url"] + "/stop" stop_url = client_config["auth_host_url"] + "/stop"
stop_json = { stop_json = {
"pc_number": int(client_config["pc_number"]) "pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"])
} }
try: try:
responce = requests.post(stop_url, json=stop_json) responce = requests.post(stop_url, json=stop_json)
if responce.status_code == 200: if responce.status_code == 200:
print("停止処理は成功しました。") print("停止処理は成功しました。")
elif responce.status_code == 401:
print("認証に失敗しました。")
else: else:
print("内部エラーにより停止処理に失敗しました。") print("内部エラーにより停止処理に失敗しました。")
except: except:
@ -444,34 +538,61 @@ class Stop():
self.shutdown() self.shutdown()
def master_password_gen():
numbers = string.digits # (1)
password = ''.join(random.choice(numbers) for _ in range(10)) # (2)
password_hash = hashlib.md5(password.encode()).hexdigest()
result = {"password": password, "password_hash": password_hash}
return result
if __name__ == '__main__': if __name__ == '__main__':
args = sys.argv args = sys.argv
if len(args) >= 2: if len(args) >= 2:
if args[1] == "stop": if args[1] == "stop":
init_result = init() init_result = init()
if init_result == 1: if init_result == 1:
print("多重起動エラー") print("多重起動を検出。")
elif init_result == 2: elif init_result == 2:
pass pass
else: else:
stop = Stop() stop = Stop()
stop.run() stop.run()
elif args[1] == "setup": elif args[1] == "setup":
init_result = init(pc_number=args[2]) if len(args) == 4:
init_result = init(pc_number=args[2], onetime=args[3])
elif len(args) == 5:
init_result = init(pc_number=args[2], onetime=args[3], host_url=args[4])
else:
print("引数エラー。")
error_msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 引数エラー", message=f"引数が多すぎるか、少なすぎます。\n引数がPC番号、ワンタイムパスワード、ホストURLの順で正しく指定されているか確認してください。")
if init_result == 1: if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。") warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2: elif init_result == 2:
pass pass
else: else:
pass pass
elif args[1] == "deviceregister":
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
mode = input('登録するデバイスはキーボードとマウスのどちらですか?(keyboard/mouse): ')
input_devices = get_input_devices()
i = 0
for device in input_devices:
print(f"{str(i + 1)} 番目 | デバイス名: {device['device_name']} \n製造元: {device['Manufacturer']} \nデバイスインスタンスパス: {device['device_instance_path']}")
print("-" * 20)
i += 1
device_num = input('どのデバイスを登録しますか?番号で指定してください: ')
device_register_num = input('そのデバイスは何番目のデバイスとして登録しますか?番号で指定してください: ')
onetime = input('ワンタイムパスワードを入力してください: ')
device_register_result = device_register(onetime=onetime, mode=mode, number=int(device_register_num), device_instance_path=input_devices[int(device_num) - 1]["device_instance_path"], device_name=input_devices[int(device_num) - 1]["device_name"])
if device_register_result["result"] == 0:
print("登録されました。")
elif device_register_result["result"] == 1:
if device_register_result["about"] == "auth_failed":
print("認証に失敗しました。")
else:
print("エラーが発生しました。")
else: else:
print("引数エラー。") print("引数エラー。")
else: else:

View file

@ -0,0 +1,441 @@
import os
import json
import tkinter.messagebox
import customtkinter
import subprocess
import requests
import hashlib
import string
import random
import tkinter
import threading
import sys
import shutil
import uuid
import time
app_name = "Dislocker"
dislocker_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(dislocker_dir)
resource_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "resource")
config_dir_path = "./config/"
client_config_path = config_dir_path + "client.json"
if not os.path.isfile(client_config_path):
if not os.path.isdir(config_dir_path):
os.mkdir(config_dir_path)
client_config = {
"initial": 1,
"auth_host_url": "http://localhost",
"pc_number": 1,
"master_password_hash": "",
"testing": 0,
"eraser": 1,
"pc_uuid": "",
"pc_token": ""
}
elif os.path.isfile(client_config_path):
with open(client_config_path, "r") as r:
client_config = json.load(r)
def master_password_gen():
numbers = string.digits # (1)
password = ''.join(random.choice(numbers) for _ in range(10)) # (2)
password_hash = hashlib.md5(password.encode()).hexdigest()
result = {"password": password, "password_hash": password_hash}
return result
def init(**kwargs):
if client_config["initial"] == 1:
pc_uuid = uuid.uuid4()
client_config["pc_uuid"] = str(pc_uuid)
if "pc_number" in kwargs:
client_config["pc_number"] = int(kwargs["pc_number"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nPC番号が指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
return 2
if "onetime" in kwargs:
onetime = str(kwargs["onetime"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
return 2
register_url = client_config["auth_host_url"] + "/register"
register_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(pc_uuid),
"onetime": onetime
}
responce = requests.post(register_url, json=register_json)
if responce.status_code == 200:
print("PCの情報が登録されました。")
responce_json = responce.json()
pc_token = str(responce_json["pc_token"])
client_config["pc_token"] = pc_token
master_password = master_password_gen()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 初回起動を検出", message=f"初回起動のようです。\nマスターパスワードを記録しておいてください。\nこれ以降二度と表示されることはないでしょう。\n\n{master_password["password"]}\n\nまた、認証先サーバーの接続先を指定してください。ロックを解除できなくなります。")
client_config["master_password_hash"] = master_password["password_hash"]
client_config["initial"] = 0
with open(client_config_path, "w") as w:
json.dump(client_config, w, indent=4)
return 2
else:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが間違っている可能性があります。")
return 2
else:
return 0
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
self.title(f"{app_name} | ロック中")
if client_config["testing"] == 1:
pass
else:
self.attributes('-fullscreen', True)
self.attributes('-topmost', True)
self.frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.frame.grid(row=0, column=0, sticky='nsew')
lock = Lock()
def exit(self):
self.unlock_taskmgr()
self.toast()
self.destroy()
def handler_close(self):
pass
class Lock(customtkinter.CTkToplevel):
def __init__(self):
super().__init__()
if client_config["testing"] == 1:
self.title(f'{app_name} | PC番号 {client_config["pc_number"]} | テストモード')
else:
self.title(f'{app_name} | PC番号 {client_config["pc_number"]} | ロックされています')
self.window_width = 600
self.window_height = 320
self.screen_width = self.winfo_screenwidth()
self.screen_height = self.winfo_screenheight()
self.center_x = int(self.screen_width/2 - self.window_width/2)
self.center_y = int(self.screen_height/2 - self.window_height/2)
self.geometry(f"{str(self.window_width)}x{str(self.window_height)}+{str(self.center_x)}+{str(self.center_y)}")
self.resizable(height=False, width=False)
self.attributes('-topmost', True)
self.grab_set()
self.lift()
self.protocol("WM_DELETE_WINDOW", self.handler_close)
self.emoji_font = customtkinter.CTkFont(family="Noto Color Emoji", size=32)
self.title_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=32, weight="bold")
self.pc_number_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=64, weight="bold")
self.title_small_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=16)
self.general_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=18)
self.general_small_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=12)
self.textbox_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=14)
self.button_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=14)
self.msg_title_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.msg_title_frame.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
self.icon_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text='😎', font=self.emoji_font, justify="left")
self.icon_title_1.grid(row=0, column=0, padx=10, sticky="w")
self.msg_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'ちょっと待って!! PC番号 | {client_config["pc_number"]}', font=self.title_font, justify="left")
self.msg_title_1.grid(row=0, column=1, padx=10, sticky="w")
self.msg_title_2 = customtkinter.CTkLabel(self.msg_title_frame, text="本当にあなたですか?", font=self.title_small_font, justify="left")
self.msg_title_2.grid(row=1, column=1, padx=10, sticky="w")
self.msg_subtitle_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.msg_subtitle_frame.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")
self.msg_subtitle_frame.grid_columnconfigure(0, weight=1)
self.msg_subtitle_1 = customtkinter.CTkLabel(self.msg_subtitle_frame, text='サインインするには、Discordのダイレクトメッセージに送信された\nパスワードを入力してください。', font=self.general_font, justify="left")
self.msg_subtitle_1.grid(row=0, column=0, padx=10, sticky="ew")
self.msg_subtitle_2 = customtkinter.CTkLabel(self.msg_subtitle_frame, text='※ パスワードの有効期限は23:59までです。', font=self.general_small_font, justify="left")
self.msg_subtitle_2.grid(row=1, column=0, padx=10, sticky="w")
self.input_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.input_frame.grid(row=2, column=0, padx=10, pady=10, sticky="nsew")
self.input_frame.columnconfigure(0, weight=1)
self.password_entry = customtkinter.CTkEntry(self.input_frame, placeholder_text='パスワード', show='*', font=self.textbox_font)
self.password_entry.grid(row=0, column=0, padx=10, sticky="ew")
self.password_entry.bind("<Return>", self.auth_start_ev)
self.button_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.button_frame.grid(row=3, column=0, padx=10, pady=10, sticky="nsew")
self.button_frame.columnconfigure(0, weight=3)
self.button_frame.columnconfigure(1, weight=1)
self.button_frame.columnconfigure(2, weight=1)
self.signin_button = customtkinter.CTkButton(self.button_frame, text='サインイン', command=self.auth_start, font=self.button_font)
self.signin_button.grid(row=0, column=2, padx=10, sticky="e")
self.signout_button = customtkinter.CTkButton(self.button_frame, text='サインアウト', command=self.signout, font=self.button_font)
self.signout_button.grid(row=0, column=1, padx=10, sticky="e")
self.help_button = customtkinter.CTkButton(self.button_frame, text='ヘルプ', command=self.help_dummy, font=self.button_font)
self.help_button.grid(row=0, column=0, padx=10, sticky="w")
def help_wakeup(self):
help = Help()
def hash_genarate(self, source):
hashed = hashlib.md5(source.encode())
return hashed.hexdigest()
def auth_start(self):
auth_thread = threading.Thread(target=self.auth)
auth_thread.daemon = True
auth_thread.start()
def auth_start_ev(self, event):
auth_thread = threading.Thread(target=self.auth)
auth_thread.daemon = True
auth_thread.start()
def button_disable(self):
self.help_button.configure(state="disabled", fg_color="gray")
self.signin_button.configure(state="disabled", fg_color="gray")
self.signout_button.configure(state="disabled", fg_color="gray")
def button_enable(self):
self.help_button.configure(state="normal", fg_color="#3c8dd0")
self.signin_button.configure(state="normal", fg_color="#3c8dd0")
self.signout_button.configure(state="normal", fg_color="#3c8dd0")
def auth(self):
self.button_disable()
password = str(self.password_entry.get())
if len(password) == 10:
print("マスターパスワードで認証を試行します。")
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
if client_config["master_password_hash"] == master_password_hash:
print("マスターパスワードで認証しました。")
self.exit()
else:
print("マスターパスワードで認証できませんでした。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
self.button_enable()
self.deiconify()
print("認証サーバーにアクセスします。")
auth_url = client_config["auth_host_url"] + "/verify"
auth_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"]),
"password": self.hash_genarate(str(self.password_entry.get()))
}
try:
responce = requests.post(auth_url, json=auth_json)
if responce.status_code == 200:
print("認証サーバー経由で認証しました。")
self.exit()
else:
print("認証サーバー経由での認証に失敗しました。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
self.button_enable()
self.deiconify()
except:
print("認証サーバーにアクセスできません。マスターパスワードで認証を試行します。")
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
if client_config["master_password_hash"] == master_password_hash:
print("マスターパスワードで認証しました。")
self.exit()
else:
print("マスターパスワードで認証できませんでした。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | ネットワークエラー", message=f"認証サーバーにアクセスできませんでした。\n続行するには、マスターパスワードを入力してください。")
self.msg_subtitle_1.configure(text='ネットワークエラーが発生しています。\n続行するには、マスターパスワードを入力して下さい。 ')
self.button_enable()
self.deiconify()
def signout(self):
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ログアウトは未実装です。")
self.deiconify()
def handler_close(self):
pass
def help_dummy(self):
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ヘルプページは製作途中です。\nDiscordサーバーの指示に従って、認証を進めてください。")
self.deiconify()
def exit(self):
self.destroy()
app.exit()
class Help(customtkinter.CTkToplevel):
def __init__(self):
super().__init__()
if client_config["testing"] == 1:
self.title(f'{app_name} | ヘルプ | テストモード')
else:
self.title(f'{app_name} | ヘルプ')
self.geometry("600x400")
self.resizable(height=False, width=False)
self.attributes('-topmost', True)
self.grab_set()
self.lift()
self.protocol("WM_DELETE_WINDOW", self.handler_close)
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ヘルプページは製作途中です。\nDiscordサーバーの指示に従って、認証を進めてください。")
self.destroy()
def handler_close(self):
self.destroy()
class Stop():
def __init__(self) -> None:
pass
def run(self):
print("停止処理を実行中...")
stop_thread = threading.Thread(target=self.stop)
stop_thread.run()
def delete_appdata(self, **kwargs):
process_name = kwargs["process_name"]
dir_path = kwargs["dir_path"]
if not os.path.exists(dir_path):
print(f"エラー: 指定されたディレクトリ {dir_path} が存在しません。")
return 1
try:
# プロセスの終了
subprocess.run(['taskkill', '/f', '/t', '/im', process_name])
print(f"{process_name} を終了しました。")
time.sleep(0.1)
# ディレクトリの削除
i = 1
ic = 0
while i == 1:
shutil.rmtree(dir_path)
if os.path.isdir(dir_path):
ic += 1
if ic == 10:
i = 0
else:
i = 0
print(f"{dir_path} を削除しました。")
return 0
except subprocess.CalledProcessError as e:
print(f"プロセス終了エラー: {e}")
return 1
except PermissionError as e:
print(f"権限エラー: {e}")
return 1
except Exception as error:
print("エラーが発生しました。\nエラー内容:")
print(f"エラータイプ: {error.__class__.__name__}")
print(f"エラー引数: {error.args}")
print(f"エラーメッセージ: {str(error)}")
return 1
def shutdown(self):
shutdown_command = subprocess.run(['shutdown', '/s', '/t', '1'])
def stop(self):
print("停止処理を実行。")
if client_config["eraser"] == 1:
#appdata_local = os.path.expandvars("%LOCALAPPDATA%")
#appdata_roaming = os.path.expandvars("%APPDATA%")
#epic_del = app.delete_appdata(process_name="EpicGamesLauncher.exe", dir_path=f"{appdata_local}\\EpicGamesLauncher\\Saved")
#chrome_del = app.delete_appdata(process_name="chrome.exe", dir_path=f"{appdata_local}\\Google\\Chrome\\User Data")
#discord_del = app.delete_appdata(process_name="discord.exe", dir_path=f"{appdata_roaming}\\discord")
#steam_del = app.delete_appdata(process_name="steam.exe", dir_path=f"{appdata_local}\\Steam")
#ea_del = app.delete_appdata(process_name="EADesktop.exe", dir_path=f"{appdata_local}\\Electronic Arts")
#riot_del = app.delete_appdata(process_name="RiotClientServices.exe", dir_path=f"{appdata_local}\\Riot Games\\Riot Client")
pass
else:
print("削除処理をスキップ。")
stop_url = client_config["auth_host_url"] + "/stop"
stop_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"])
}
try:
responce = requests.post(stop_url, json=stop_json)
if responce.status_code == 200:
print("停止処理は成功しました。")
elif responce.status_code == 401:
print("認証に失敗しました。")
tkinter.messagebox.showwarning(title=f"{app_name} | エラー", message=f"認証に失敗しました。\nDiscordサーバーの指示に従って、停止処理を自身で行ってください。")
else:
print("内部エラーにより停止処理に失敗しました。")
result_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | エラー", message=f"内部エラーにより停止処理に失敗しました。\nDiscordサーバーの指示に従って、停止処理を自身で行ってください。")
except:
print("ネットワークエラーにより停止処理に失敗しました。")
result_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | エラー", message=f"ネットワークエラーにより停止処理に失敗しました。\nDiscordサーバーの指示に従って、停止処理を自身で行ってください。")
finally:
self.shutdown()
if __name__ == '__main__':
args = sys.argv
if len(args) >= 2:
if args[1] == "stop":
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"もう終了処理を行っています。\nPCがシャットダウンするまで、もう少しお待ちください。")
elif init_result == 2:
pass
else:
stop = Stop()
stop.run()
elif args[1] == "setup":
init_result = init(pc_number=args[2], onetime=args[3])
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
pass
else:
print("引数エラー。")
else:
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
app = App()
app.protocol("WM_DELETE_WINDOW", app.handler_close)
app.mainloop()

View file

@ -17,5 +17,6 @@ if %ERRORLEVEL% == 1 (
echo ショートカットの作成でエラーが発生しました。 echo ショートカットの作成でエラーが発生しました。
) )
set /P pc_number=PC番号を入力 set /P pc_number=PC番号を入力
start %dir%dislocker_client.exe setup %pc_number% set /P onetime=ワンタイムパスワードを入力
start %dir%dislocker_client.exe setup %pc_number% %onetime%
pause pause

19
script/update.cmd Normal file
View file

@ -0,0 +1,19 @@
@echo off
set dir=%~dp0
cd %dir%
set update_package_path="0"
set /P update_package_path=アップデート元のzipファイルのパスを入力 :
if %update_package_path%=="0" (set update_package_path=C:%HOMEPATH%\Downloads\dislocker_client_latest.zip)
set dislocker_dir_path="0"
set /P dislocker_dir_path=Dislockerのディレクトリのパスを入力 :
if %dislocker_dir_path%=="0" (set dislocker_dir_path=C:\Dislocker)
mkdir %dir%\temp_ds
tar -xf %update_package_path% -C %dir%\temp_ds
rmdir /s /q %dislocker_dir_path%\_internal
mkdir %dislocker_dir_path%\_internal
xcopy /e %dir%\temp_ds\_internal %dislocker_dir_path%\_internal
xcopy /Y %dir%\temp_ds\dislocker_client.exe %dislocker_dir_path%\dislocker_client.exe
rmdir /s /q %dir%\temp_ds
echo アップデート完了。Defenderの警告を消すため、一度起動しておいてください。
pause