# Init import os import sys import platform import json import smtplib import zipfile import shutil import logging import random import email.mime.text import email.utils import email.header import urllib.request # Init-Version version_list = json.loads(open('version.json', encoding = 'utf8').read()) print('Version : ' + version_list['beta']['r_ver']) print('DB set version : ' + version_list['beta']['c_ver']) print('Skin set version : ' + version_list['beta']['s_ver']) print('----') # Init-PIP_Install data_up_date = 1 if os.path.exists(os.path.join('data', 'version.json')): data_load_ver = open(os.path.join('data', 'version.json'), encoding = 'utf8').read() if data_load_ver == version_list['beta']['r_ver']: data_up_date = 0 if data_up_date == 1: with open(os.path.join('data', 'version.json'), 'w', encoding = 'utf8') as f: f.write(version_list['beta']['r_ver']) if platform.system() in ('Linux', 'Windows'): os.system( 'python' + ('3' if platform.system() != 'Windows' else '') + ' ' + \ '-m pip install --upgrade --user -r requirements.txt' ) print('----') try: os.execl(sys.executable, sys.executable, *sys.argv) except: pass try: os.execl(sys.executable, '"' + sys.executable + '"', *sys.argv) except: print('Error : restart failed') raise else: print('Error : automatic installation is not supported.') print('Help : try "python3 -m pip install -r requirements.txt"') else: print('PIP check pass') print('----') # Init-Load from .func_mark import * from diff_match_patch import diff_match_patch import netius.servers import werkzeug.routing import werkzeug.debug import flask import requests import pymysql if sys.version_info < (3, 6): import sha3 # Init-Global global_lang = {} global_wiki_set = {} global_db_set = '' data_css_ver = '118' data_css = '' conn = '' # Func # Func-main def load_conn(data): global conn conn = data load_conn2(data) # Func-init class get_db_connect: def __init__(self, db_set): self.db_set = db_set self.conn = '' def db_load(self): if self.db_set['type'] == 'sqlite': self.conn = sqlite3.connect(self.db_set['name'] + '.db') else: self.conn = pymysql.connect( host = self.db_set['mysql_host'], user = self.db_set['mysql_user'], password = self.db_set['mysql_pw'], charset = 'utf8mb4', port = int(self.db_set['mysql_port']), ) curs = self.conn.cursor() try: curs.execute(db_change( 'create database ' + self.db_set['name'] + ' ' + \ 'default character set utf8mb4;' )) except: pass self.conn.select_db(self.db_set['name']) load_conn(self.conn) return self.conn def db_get(self): # if self.db_set['type'] != 'sqlite': # self.conn.ping(reconnect = True) return self.conn def update(ver_num, set_data): curs = conn.cursor() print('----') # 업데이트 하위 호환 유지 함수 if ver_num < 3160027: print('Add init set') set_init() if ver_num < 3170002: curs.execute(db_change("select html from html_filter where kind = 'extension'")) if not curs.fetchall(): for i in ['jpg', 'jpeg', 'png', 'gif', 'webp']: curs.execute(db_change( "insert into html_filter (html, kind) values (?, 'extension')" ), [i]) if ver_num < 3170400: curs.execute(db_change("select title, sub, code from topic where id = '1'")) for i in curs.fetchall(): curs.execute(db_change( "update topic set code = ? where title = ? and sub = ?" ), [ i[2], i[0], i[1] ]) curs.execute(db_change( "update rd set code = ? where title = ? and sub = ?" ), [ i[2], i[0], i[1] ]) if ver_num < 3171800: curs.execute(db_change("select data from other where name = 'recaptcha'")) change_rec = curs.fetchall() if change_rec and change_rec[0][0] != '': new_rec = re.search(r'data-sitekey="([^"]+)"', change_rec[0][0]) if new_rec: curs.execute(db_change( "update other set data = ? where name = 'recaptcha'" ), [new_rec.group(1)]) else: curs.execute(db_change("update other set data = '' where name = 'recaptcha'")) curs.execute(db_change("update other set data = '' where name = 'sec_re'")) if ver_num < 3172800 and \ set_data['db_type'] == 'mysql': get_data_mysql = json.loads(open('data/mysql.json', encoding = 'utf8').read()) with open('data/mysql.json', 'w') as f: f.write('{ "user" : "' + get_data_mysql['user'] + '", "password" : "' + get_data_mysql['password'] + '", "host" : "localhost" }') if ver_num < 3183603: curs.execute(db_change("select block from ban where band = 'O'")) for i in curs.fetchall(): curs.execute(db_change( "update ban set block = ?, band = 'regex' where block = ? and band = 'O'" ), [ '^' + i[0].replace('.', '\\.'), i[0] ]) curs.execute(db_change("select block from rb where band = 'O'")) for i in curs.fetchall(): curs.execute(db_change( "update rb set block = ?, band = 'regex' where block = ? and band = 'O'" ), [ '^' + i[0].replace('.', '\\.'), i[0] ]) if ver_num < 3190201: today_time = get_time() curs.execute(db_change("select block, end, why, band, login from ban")) for i in curs.fetchall(): curs.execute(db_change( "insert into rb (block, end, today, why, band, login, ongoing) " + \ "values (?, ?, ?, ?, ?, ?, ?)" ), [ i[0], i[1], today_time, i[2], i[3], i[4], '1' ]) if ver_num < 3191301: curs.execute(db_change('' + \ 'select id, title, date from history ' + \ 'where not title like "user:%" ' + \ 'order by date desc ' + \ 'limit 50' + \ '')) data_list = curs.fetchall() for get_data in data_list: curs.execute(db_change( "insert into rc (id, title, date, type) values (?, ?, ?, 'normal')" ), [ get_data[0], get_data[1], get_data[2] ]) if ver_num < 3202400: curs.execute(db_change("select data from other where name = 'update'")) get_data = curs.fetchall() if get_data and get_data[0][0] == 'master': curs.execute(db_change("update other set data = 'beta' where name = 'update'"), []) if ver_num < 3202600: curs.execute(db_change("select name, regex, sub from filter")) for i in curs.fetchall(): curs.execute(db_change( "insert into html_filter (html, kind, plus, plus_t) " + \ "values (?, 'regex_filter', ?, ?)" ), [ i[0], i[1], i[2] ]) curs.execute(db_change("select title, link, icon from inter")) for i in curs.fetchall(): curs.execute(db_change( "insert into html_filter (html, kind, plus, plus_t) " + \ "values (?, 'inter_wiki', ?, ?)"), [ i[0], i[1], i[2] ]) if ver_num < 3203400: curs.execute(db_change("select user, css from custom")) for i in curs.fetchall(): curs.execute(db_change( "insert into user_set (name, id, data) values ('custom_css', ?, ?)" ), [ re.sub(r' \(head\)$', '', i[0]), i[1] ]) if ver_num < 3205500: curs.execute(db_change("select title, decu, dis, view, why from acl")) for i in curs.fetchall(): curs.execute(db_change( "insert into acl (title, data, type) values (?, ?, ?)" ), [i[0], i[1], 'decu']) curs.execute(db_change( "insert into acl (title, data, type) values (?, ?, ?)" ), [i[0], i[2], 'dis']) curs.execute(db_change( "insert into acl (title, data, type) values (?, ?, ?)" ), [i[0], i[3], 'view']) curs.execute(db_change( "insert into acl (title, data, type) values (?, ?, ?)" ), [i[0], i[4], 'why']) if ver_num < 3300101: # 캐시 초기화 curs.execute(db_change('delete from cache_data')) if ver_num < 3300301: # regex_filter 오류 해결 curs.execute(db_change( 'delete from html_filter where kind = "regex_filter" and html is null' )) if ver_num < 3302302: # user이랑 user_set 테이블의 통합 curs.execute(db_change('select id, pw, acl, date, encode from user')) for i in curs.fetchall(): curs.execute(db_change( "insert into user_set (name, id, data) values (?, ?, ?)" ), ['pw', i[0], i[1]]) curs.execute(db_change( "insert into user_set (name, id, data) values (?, ?, ?)" ), ['acl', i[0], i[2]]) curs.execute(db_change( "insert into user_set (name, id, data) values (?, ?, ?)" ), ['date', i[0], i[3]]) curs.execute(db_change( "insert into user_set (name, id, data) values (?, ?, ?)" ), ['encode', i[0], i[4]]) if ver_num < 3400101: # user_set이랑 user_application 테이블의 통합 curs.execute(db_change('' + \ 'select id, pw, date, encode, question, answer, ip, ua, email ' + \ 'from user_application' + \ '')) for i in curs.fetchall(): sql_data = {} sql_data['id'] = i[0] sql_data['pw'] = i[1] sql_data['date'] = i[2] sql_data['encode'] = i[3] sql_data['question'] = i[4] sql_data['answer'] = i[5] sql_data['ip'] = i[6] sql_data['ua'] = i[7] sql_data['email'] = i[8] curs.execute(db_change( "insert into user_set (name, id, data) values (?, ?, ?)" ), ['application', i[0], json.dumps(sql_data)]) conn.commit() print('Update completed') def set_init_always(ver_num): curs = conn.cursor() curs.execute(db_change('delete from other where name = "ver"')) curs.execute(db_change('insert into other (name, data) values ("ver", ?)'), [ver_num]) curs.execute(db_change('delete from alist where name = "owner"')) curs.execute(db_change('insert into alist (name, acl) values ("owner", "owner")')) if not os.path.exists(load_image_url()): os.makedirs(load_image_url()) conn.commit() def set_init(): curs = conn.cursor() # 초기값 설정 함수 curs.execute(db_change("select html from html_filter where kind = 'email'")) if not curs.fetchall(): for i in ['naver.com', 'gmail.com', 'daum.net', 'kakao.com']: curs.execute(db_change( "insert into html_filter (html, kind, plus, plus_t) values (?, 'email', '', '')" ), [i]) curs.execute(db_change("select html from html_filter where kind = 'extension'")) if not curs.fetchall(): for i in ['jpg', 'jpeg', 'png', 'gif', 'webp']: curs.execute(db_change( "insert into html_filter (html, kind, plus, plus_t) values (?, 'extension', '', '')" ), [i]) curs.execute(db_change( 'select data from other ' + \ 'where name = "smtp_server" or name = "smtp_port" or name = "smtp_security"' )) if not curs.fetchall(): for i in [ ['smtp_server', 'smtp.gmail.com'], ['smtp_port', '587'], ['smtp_security', 'starttls'] ]: curs.execute(db_change( "insert into other (name, data) values (?, ?)" ), [i[0], i[1]]) curs.execute(db_change('select data from other where name = "key"')) rep_data = curs.fetchall() if not rep_data: curs.execute(db_change('insert into other (name, data) values ("key", ?)'), [load_random_key()]) curs.execute(db_change('select data from other where name = "count_all_title"')) if not curs.fetchall(): curs.execute(db_change('insert into other (name, data) values ("count_all_title", "0")')) conn.commit() # Func-simple ## Func-simple-without_DB def get_default_admin_group(): return ['owner', 'ban'] def load_random_key(long = 64): return ''.join( random.choice( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ) for i in range(long) ) def http_warning(): return '''
''' def next_fix(link, num, page, end = 50): list_data = '' if num == 1: if len(page) == end: list_data += '' + \ '
' + \ '(' + load_lang('next') + ')' + \ '' elif len(page) != end: list_data += '' + \ '
' + \ '(' + load_lang('previous') + ')' + \ '' else: list_data += '' + \ '
' + \ '(' + load_lang('previous') + ') (' + load_lang('next') + ')' + \ '' return list_data def leng_check(A, B): # B -> new # A -> old return '0' if A == B else (('-' + str(A - B)) if A > B else ('+' + str(B - A))) def number_check(data): try: int(data) return data except: return '1' def redirect(data = '/'): return flask.redirect(flask.request.host_url[:-1] + data) def get_acl_list(type_d = 'normal'): if type_d == 'user': return ['', 'user', 'all'] else: return ['', 'all', 'user', 'admin', 'owner', '50_edit', 'email', 'ban', 'before', '30_day', 'ban_admin'] ## Func-simple-with_DB def load_image_url(): curs = conn.cursor() curs.execute(db_change('select data from other where name = "image_where"')) image_where = curs.fetchall() image_where = image_where[0][0] if image_where else os.path.join('data', 'images') return image_where def load_domain(): curs = conn.cursor() curs.execute(db_change("select data from other where name = 'domain'")) domain = curs.fetchall() domain = domain[0][0] if domain and domain[0][0] != '' else flask.request.host_url return domain def edit_button(editor_display = '0'): curs = conn.cursor() insert_list = [] curs.execute(db_change("select html, plus from html_filter where kind = 'edit_top'")) db_data = curs.fetchall() for get_data in db_data: insert_list += [[get_data[1], get_data[0]]] data = '' for insert_data in insert_list: data += '' + \ '(' + insert_data[1] + ') ' + \ '' data += (' ' if data != '' else '') + '(' + load_lang('add') + ')' data += '
' return data def ip_warning(): curs = conn.cursor() if ip_or_user() != 0: curs.execute(db_change('select data from other where name = "no_login_warning"')) data = curs.fetchall() if data and data[0][0] != '': text_data = '' + \ '' + data[0][0] + '' + \ '
' + \ '' else: text_data = '' + \ '' + load_lang('no_login_warning') + '' + \ '
' + \ '' else: text_data = '' return text_data # Func-login def pw_encode(data, type_d = ''): curs = conn.cursor() if type_d == '': curs.execute(db_change('select data from other where name = "encode"')) set_data = curs.fetchall() type_d = set_data[0][0] if type_d == 'sha256': return hashlib.sha256(bytes(data, 'utf-8')).hexdigest() else: if sys.version_info < (3, 6): return sha3.sha3_256(bytes(data, 'utf-8')).hexdigest() else: return hashlib.sha3_256(bytes(data, 'utf-8')).hexdigest() def pw_check(data, data2, type_d = 'no', id_d = ''): curs = conn.cursor() curs.execute(db_change('select data from other where name = "encode"')) db_data = curs.fetchall() if type_d != 'no': if type_d == '': set_data = 'sha3' else: set_data = type_d else: set_data = db_data[0][0] re_data = 1 if pw_encode(data, set_data) == data2 else 0 if db_data[0][0] != set_data and re_data == 1 and id_d != '': curs.execute(db_change("update user_set set data = ? where id = ? and name = 'pw'"), [ pw_encode(data), id_d ]) curs.execute(db_change("update user_set set data = ? where id = ? and name = 'encode'"), [ db_data[0][0], id_d ]) return re_data # Func-skin def easy_minify(data, tool = None): # without_DB return data def load_lang(data, safe = 0): curs = conn.cursor() global global_lang ip = ip_check() if ip_or_user(ip) == 0: curs.execute(db_change('select data from user_set where name = "lang" and id = ?'), [ip]) rep_data = curs.fetchall() elif 'lang' in flask.session: rep_data = [[flask.session['lang']]] else: curs.execute(db_change("select data from other where name = 'language'")) rep_data = curs.fetchall() if not rep_data or rep_data[0][0] in ('', 'default'): curs.execute(db_change("select data from other where name = 'language'")) rep_data = curs.fetchall() if rep_data: lang_name = rep_data[0][0] else: lang_name = 'en-US' if lang_name in global_lang: lang = global_lang[lang_name] else: lang_list = os.listdir('lang') if (lang_name + '.json') in lang_list: lang = json.loads(open( os.path.join('lang', lang_name + '.json'), encoding = 'utf8' ).read()) global_lang[lang_name] = lang else: lang = {} if data in lang: if safe == 1: return lang[data] else: return html.escape(lang[data]) return html.escape(data + ' (' + lang_name + ')') def skin_check(set_n = 0): curs = conn.cursor() # 개편 필요? skin_list = load_skin('tenshi', 1) skin = skin_list[0] ip = ip_check() user_need_skin = '' if ip_or_user(ip) == 0: curs.execute(db_change('select data from user_set where name = "skin" and id = ?'), [ip]) skin_exist = curs.fetchall() if skin_exist: user_need_skin = skin_exist[0][0] else: if 'skin' in flask.session: user_need_skin = flask.session['skin'] if user_need_skin == '': curs.execute(db_change('select data from other where name = "skin"')) skin_exist = curs.fetchall() if skin_exist: user_need_skin = skin_exist[0][0] if user_need_skin != '' and user_need_skin in skin_list: skin = user_need_skin if set_n == 0: return './views/' + skin + '/index.html' else: return skin def wiki_css(data): # without_DB global data_css global data_css_ver data += ['' for _ in range(0, 3 - len(data))] if data_css == '': for i_data in os.listdir(os.path.join("views", "main_css", "css")): if i_data != 'sub': data_css += '' for i_data in os.listdir(os.path.join("views", "main_css", "js")): if i_data != 'sub': data_css += '' data = data[0:2] + ['', ''' ''' + data_css + ''] + data[2:] return data def cut_100(data): # without_DB data = re.search(r'