from bottle import * from bottle.ext import beaker import bcrypt import difflib import shutil import threading import logging logging.basicConfig(level = logging.ERROR) session_opts = { 'session.type': 'dbm', 'session.data_dir': './app_session/', 'session.auto': 1 } app = beaker.middleware.SessionMiddleware(app(), session_opts) BaseRequest.MEMFILE_MAX = 1000 ** 4 r_ver = '2.4.7' from set_mark.mark import * from set_mark.mid_pas import * from set_mark.macro import savemark from func import * try: json_data = open('set.json').read() set_data = json.loads(json_data) except: while(1): new_json = [] print('DB 이름 : ', end = '') new_json += [input()] print('포트 : ', end = '') new_json += [input()] if(new_json[0] != '' and new_json[1] != ''): with open("set.json", "w") as f: f.write('{ "db" : "' + new_json[0] + '", "port" : "' + new_json[1] + '" }') json_data = open('set.json').read() set_data = json.loads(json_data) break else: print('모든 값을 입력하세요.') pass conn = sqlite3.connect(set_data['db'] + '.db') curs = conn.cursor() # 스킨 불러오기 부분 TEMPLATE_PATH.insert(0, skin_check(conn)) try: try: plus_all_data = '' start_replace = 0 curs.execute('select data from other where name = "css"') for m_lo in curs.fetchall(): plus_all_data += '\r\n' curs.execute('select data from other where name = "js"') for m_lo in curs.fetchall(): plus_all_data += '\r\n' if(plus_all_data != ''): curs.execute("insert into other (name, data) values ('head', ?)", [plus_all_data]) curs.execute("delete from other where name = 'css'") curs.execute("delete from other where name = 'js'") start_replace = 1 curs.execute('select user from custom') if(curs.fetchall()): curs.execute("select user from custom where user like ?", ['% (head)%']) if(not curs.fetchall()): curs.execute("select user, css from custom") for data_lo in curs.fetchall(): plus_all_data = '' if(re.search(' \(js\)$', data_lo[0])): name_data_is = data_lo[0].replace(' (js)', '') plus_all_data = '\r\n' else: name_data_is = data_lo[0] plus_all_data = '\r\n' curs.execute("select css from custom where user = ?", [name_data_is + ' (head)']) data_is_it = curs.fetchall() if(data_is_it): curs.execute("update custom set css = ? where user = ?", [data_is_it[0][0] + plus_all_data, name_data_is + ' (head)']) else: curs.execute("insert into custom (user, css) values (?, ?)", [name_data_is + ' (head)', plus_all_data]) curs.execute("delete from custom where user = ?", [data_lo[0]]) start_replace = 1 if(start_replace == 1): print('CSS, JS 데이터 변환') except: pass try: curs.execute('select name from ok_login limit 1') except: curs.execute("create table ok_login(ip text, sub text)") print('ok_login 테이블 생성') try: curs.execute("drop table move") print("move 테이블 삭제") except: pass conn.commit() except: pass # 이미지 폴더 생성 if(not os.path.exists('image')): os.makedirs('image') # 스킨 폴더 생성 if(not os.path.exists('views')): os.makedirs('views') def back_up(): try: shutil.copyfile(set_data['db'] + '.db', 'back_' + set_data['db'] + '.db') print('백업 성공') except: print('백업 오류') threading.Timer(60 * 60 * back_time, back_up).start() try: curs.execute('select data from other where name = "back_up"') back_up_time = curs.fetchall() back_time = int(back_up_time[0][0]) except: back_time = 0 if(back_time != 0): print(str(back_time) + '시간 간격으로 백업') if(__name__ == '__main__'): back_up() else: print('백업하지 않음') @route('/setup', method=['GET', 'POST']) def setup(): try: curs.execute("select title from data limit 1") except: try: curs.execute("create table data(title text, data text, acl text)") except: pass try: curs.execute("create table history(id text, title text, data text, date text, ip text, send text, leng text)") except: pass try: curs.execute("create table rd(title text, sub text, date text)") except: pass try: curs.execute("create table user(id text, pw text, acl text)") except: pass try: curs.execute("create table ban(block text, end text, why text, band text)") except: pass try: curs.execute("create table topic(id text, title text, sub text, data text, date text, ip text, block text, top text)") except: pass try: curs.execute("create table stop(title text, sub text, close text)") except: pass try: curs.execute("create table rb(block text, end text, today text, blocker text, why text)") except: pass try: curs.execute("create table back(title text, link text, type text)") except: pass try: curs.execute("create table hidhi(title text, re text)") except: pass try: curs.execute("create table agreedis(title text, sub text)") except: pass try: curs.execute("create table custom(user text, css text)") except: pass try: curs.execute("create table other(name text, data text)") except: pass try: curs.execute("create table alist(name text, acl text)") curs.execute("insert into alist (name, acl) values ('소유자', 'owner')") except: pass try: curs.execute("create table re_admin(who text, what text, time text)") except: pass try: curs.execute("create table alarm(name text, data text, date text)") except: pass try: curs.execute("create table ua_d(name text, ip text, ua text, today text, sub text)") except: pass try: curs.execute("create table ok_login(ip text, sub text)") except: pass conn.commit() return(redirect('/')) @route('/del_alarm') def del_alarm(): curs.execute("delete from alarm where name = ?", [ip_check()]) conn.commit() return(redirect('/alarm')) @route('/alarm') def alarm(): ip = ip_check() if(re.search('(?:\.|:)', ip)): return(redirect('/login')) da = '' return(html_minify(template('index', imp = ['알림', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = da, menu = [['user', '사용자']] ))) @route('/edit_set', method=['POST', 'GET']) @route('/edit_set/', method=['POST', 'GET']) def edit_set(num = 0): if(num != 0 and admin_check(conn, None, None) != 1): return(re_error(conn, '/ban')) if(num == 0): li_list = ['기본 설정', '문구 관련', '전역 HEAD', 'robots.txt', '구글 관련'] x = 0 li_data = '' for li in li_list: x += 1 li_data += '
  • ' + str(x) + '. ' + li + '
  • ' return(html_minify(template('index', imp = ['설정 편집', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '', menu = [['manager', '관리자']] ))) elif(num == 1): if(request.method == 'POST'): curs.execute("update other set data = ? where name = ?", [request.forms.name, 'name']) curs.execute("update other set data = ? where name = ?", [request.forms.logo, 'logo']) curs.execute("update other set data = ? where name = 'frontpage'", [request.forms.frontpage]) curs.execute("update other set data = ? where name = 'license'", [request.forms.license]) curs.execute("update other set data = ? where name = 'upload'", [request.forms.upload]) curs.execute("update other set data = ? where name = 'skin'", [request.forms.skin]) curs.execute("update other set data = ? where name = 'edit'", [request.forms.edit]) curs.execute("update other set data = ? where name = 'reg'", [request.forms.reg]) curs.execute("update other set data = ? where name = 'ip_view'", [request.forms.ip_view]) curs.execute("update other set data = ? where name = 'back_up'", [request.forms.back_up]) curs.execute("update other set data = ? where name = 'all_title'", [request.forms.all_title]) conn.commit() TEMPLATE_PATH.insert(0, skin_check(conn)) admin_check(conn, None, 'edit_set') return(redirect('/edit_set/1')) else: i_list = ['name', 'logo', 'frontpage', 'license', 'upload', 'skin', 'edit', 'reg', 'ip_view', 'back_up', 'all_title'] n_list = ['무명위키', '', '위키:대문', 'CC 0', '2', '', 'normal', '', '', '0', ''] d_list = [] x = 0 for i in i_list: curs.execute('select data from other where name = ?', [i]) sql_d = curs.fetchall() if(sql_d): d_list += [sql_d[0][0]] else: curs.execute('insert into other (name, data) values (?, ?)', [i, n_list[x]]) d_list += [n_list[x]] x += 1 conn.commit() div = '' if(d_list[6] == 'login'): div += '' div += '' div += '' elif(d_list[6] == 'admin'): div += '' div += '' div += '' else: div += '' div += '' div += '' ch_1 = '' ch_2 = '' ch_3 = '' if(d_list[7]): ch_1 = 'checked="checked"' if(d_list[8]): ch_2 = 'checked="checked"' if(d_list[10]): ch_3 = 'checked="checked"' return(html_minify(template('index', imp = ['기본 설정', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
    \ 이름

    \

    \ 로고 (HTML)

    \

    \ 대문

    \

    \ 라이선스 (HTML)

    \

    \ 파일 크기 [메가]

    \

    \ 스킨

    \

    \ 전역 ACL

    \

    \ 가입불가

    \ 아이피 비공개

    \ 모든 문서 보기 비활성화

    \ 백업 간격 [시간] (끄기 : 0) {재시작 필요}

    \

    \ \
    ', menu = [['edit_set', '설정 편집']] ))) elif(num == 2): if(request.method == 'POST'): curs.execute("update other set data = ? where name = ?", [request.forms.contract, 'contract']) conn.commit() admin_check(conn, None, 'edit_set') return(redirect('/edit_set/2')) else: i_list = ['contract'] n_list = [''] d_list = [] x = 0 for i in i_list: curs.execute('select data from other where name = ?', [i]) sql_d = curs.fetchall() if(sql_d): d_list += [sql_d[0][0]] else: curs.execute('insert into other (name, data) values (?, ?)', [i, n_list[x]]) d_list += [n_list[x]] x += 1 conn.commit() return(html_minify(template('index', imp = ['문구 관련', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
    \ 가입 약관

    \

    \ \
    ', menu = [['edit_set', '설정 편집']] ))) elif(num == 3): if(request.method == 'POST'): curs.execute("select name from other where name = 'head'") if(curs.fetchall()): curs.execute("update other set data = ? where name = 'head'", [request.forms.content]) else: curs.execute("insert into other (name, data) values ('head', ?)", [request.forms.content]) conn.commit() admin_check(conn, None, 'edit_set') return(redirect('/edit_set/3')) else: curs.execute("select data from other where name = 'head'") head = curs.fetchall() if(head): data = head[0][0] else: data = '' return(html_minify(template('index', imp = ['전역 HEAD', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '<style>CSS</style>
    <script>JS</script>


    \
    \

    \ \
    ', menu = [['edit_set', '설정 편집']] ))) elif(num == 4): if(request.method == 'POST'): curs.execute("select name from other where name = 'robot'") if(curs.fetchall()): curs.execute("update other set data = ? where name = 'robot'", [request.forms.content]) else: curs.execute("insert into other (name, data) values ('robot', ?)", [request.forms.content]) conn.commit() admin_check(conn, None, 'edit_set') return(redirect('/edit_set/4')) else: curs.execute("select data from other where name = 'robot'") robot = curs.fetchall() if(robot): data = robot[0][0] else: data = '' return(html_minify(template('index', imp = ['robots.txt', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '상태 보기

    \
    \

    \ \
    ', menu = [['edit_set', '설정 편집']] ))) elif(num == 5): if(request.method == 'POST'): curs.execute("update other set data = ? where name = 'recaptcha'", [request.forms.recaptcha]) conn.commit() admin_check(conn, None, 'edit_set') return(redirect('/edit_set/5')) else: i_list = ['recaptcha'] n_list = [''] d_list = [] x = 0 for i in i_list: curs.execute('select data from other where name = ?', [i]) sql_d = curs.fetchall() if(sql_d): d_list += [sql_d[0][0]] else: curs.execute('insert into other (name, data) values (?, ?)', [i, n_list[x]]) d_list += [n_list[x]] x += 1 conn.commit() return(html_minify(template('index', imp = ['구글 관련', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
    \ 리캡차 (HTML)

    \

    \ \
    ', menu = [['edit_set', '설정 편집']] ))) else: return(redirect('/')) @route('/not_close_topic') def not_close_topic(): div = '' return(html_minify(template('index', imp = ['열린 토론 목록', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = div, menu = [['manager', '관리자']] ))) @route('/image/') def static(name = None): if(os.path.exists(os.path.join('image', name))): return(static_file(name, root = 'image')) else: return(redirect('/')) @route('/acl_list') def acl_list(): div = '' return(html_minify(template('index', imp = ['ACL 문서 목록', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = div, menu = [['other', '기타']] ))) @route('/admin_plus/', method=['POST', 'GET']) def admin_plus(name = None): if(request.method == 'POST'): if(admin_check(conn, None, 'admin_plus (' + name + ')') != 1): return(re_error(conn, '/error/3')) curs.execute("delete from alist where name = ?", [name]) if(request.forms.ban): curs.execute("insert into alist (name, acl) values (?, 'ban')", [name]) if(request.forms.mdel): curs.execute("insert into alist (name, acl) values (?, 'mdel')", [name]) if(request.forms.toron): curs.execute("insert into alist (name, acl) values (?, 'toron')", [name]) if(request.forms.check): curs.execute("insert into alist (name, acl) values (?, 'check')", [name]) if(request.forms.acl): curs.execute("insert into alist (name, acl) values (?, 'acl')", [name]) if(request.forms.hidel): curs.execute("insert into alist (name, acl) values (?, 'hidel')", [name]) if(request.forms.give): curs.execute("insert into alist (name, acl) values (?, 'give')", [name]) if(request.forms.owner): curs.execute("insert into alist (name, acl) values (?, 'owner')", [name]) conn.commit() return(redirect('/admin_plus/' + url_pas(name))) else: curs.execute('select acl from alist where name = ?', [name]) acl_list = curs.fetchall() data = '
      ' exist_list = ['', '', '', '', '', '', '', ''] for go in acl_list: if(go[0] == 'ban'): exist_list[0] = 'checked="checked"' elif(go[0] == 'mdel'): exist_list[1] = 'checked="checked"' elif(go[0] == 'toron'): exist_list[2] = 'checked="checked"' elif(go[0] == 'check'): exist_list[3] = 'checked="checked"' elif(go[0] == 'acl'): exist_list[4] = 'checked="checked"' elif(go[0] == 'hidel'): exist_list[5] = 'checked="checked"' elif(go[0] == 'give'): exist_list[6] = 'checked="checked"' elif(go[0] == 'owner'): exist_list[7] = 'checked="checked"' if(admin_check(conn, None, None) != 1): state = 'disabled' else: state = '' data += '
    • 차단
    • ' data += '
    • 많은 문서 삭제
    • ' data += '
    • 토론 관리
    • ' data += '
    • 사용자 검사
    • ' data += '
    • 문서 ACL
    • ' data += '
    • 역사 숨김
    • ' data += '
    • 권한 부여
    • ' data += '
    • 소유자
    ' return(html_minify(template('index', imp = ['관리 그룹 추가', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
    ' + data + '
    ', menu = [['manager', '관리자']] ))) @route('/admin_list') def admin_list(): div = '
      ' curs.execute("select id, acl from user where not acl = 'user'") user_data = curs.fetchall() for data in user_data: name = ip_pas(conn, data[0]) + ' (' + data[1] + ')' div += '
    • ' + name + '
    • ' div += '
    ' return(html_minify(template('index', imp = ['관리자 목록', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = div, menu = [['other', '기타']] ))) @route('/record/') @route('/record//') @route('/recent_changes') def recent_changes(name = None, num = 1): ydmin = admin_check(conn, 1, None) zdmin = admin_check(conn, 6, None) ban = '' send = '
    ' div = ' \ \ \ \ \ \ ' if(name): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 div = '(토론 기록)

    ' + div curs.execute("select id, title, date, ip, send, leng from history where ip = ? order by date desc limit ?, '50'", [name, str(sql_num)]) else: curs.execute("select id, title, date, ip, send, leng from history where not date = 'Dump' order by date desc limit 50") for data in curs.fetchall(): send = '
    ' if(data[4]): if(not re.search("^(?: *)$", data[4])): send = data[4] title = html.escape(data[1]) if(re.search("\+", data[5])): leng = '' + data[5] + '' elif(re.search("\-", data[5])): leng = '' + data[5] + '' else: leng = '' + data[5] + '' if(ydmin == 1): curs.execute("select * from ban where block = ?", [data[3]]) if(curs.fetchall()): ban = ' (해제)' else: ban = ' (차단)' ip = ip_pas(conn, data[3]) if((int(data[0]) - 1) == 0): revert = '' else: revert = '(비교)(되돌리기)' style = '' curs.execute("select title from hidhi where title = ? and re = ?", [data[1], data[0]]) h = curs.fetchall() if(zdmin == 1): if(h): ip += ' (숨김)' hidden = ' (공개)' else: hidden = ' (숨김)' else: if(h): ip = '숨김' hidden = '' send = '숨김' ban = '' style = 'display:none;' else: hidden = '' div += ' \ \ \ \ \ \ \ ' else: div += '
    문서명편집자시간
    \ ' + title + ' (' + data[0] + '판) ' + revert + ' (' + leng + ') \ ' + ip + ban + hidden + '' + data[2] + '
    ' + send + '
    ' if(name): curs.execute("select end, why from ban where block = ?", [name]) ban_it = curs.fetchall() if(ban_it): sub = '(차단)' else: sub = 0 title = '편집 기록' menu = [['other', '기타'], ['user', '사용자'], ['count/' + url_pas(name), '횟수']] div += '
    (이전) (이후)' else: sub = 0 menu = 0 title = '최근 변경내역' return(html_minify(template('index', imp = [title, wiki_set(conn, 1), custom(conn), other2([sub, 0])], data = div, menu = menu ))) @route('/history//r//hidden') def history_hidden(name = None, num = None): if(admin_check(conn, 6, 'history_hidden (' + name + '#' + str(num) + ')') == 1): curs.execute("select * from hidhi where title = ? and re = ?", [name, str(num)]) exist = curs.fetchall() if(exist): curs.execute("delete from hidhi where title = ? and re = ?", [name, str(num)]) else: curs.execute("insert into hidhi (title, re) values (?, ?)", [name, str(num)]) conn.commit() return(redirect('/history/' + url_pas(name))) @route('/user_log') @route('/user_log/') def user_log(num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 list_data = '
      ' admin_one = admin_check(conn, 1, None) curs.execute("select id from user limit ?, '50'", [str(sql_num)]) user_list = curs.fetchall() for data in user_list: if(admin_one == 1): curs.execute("select block from ban where block = ?", [data[0]]) ban_exist = curs.fetchall() if(ban_exist): ban_button = ' (해제)' else: ban_button = ' (차단)' else: ban_button = '' ip = ip_pas(conn, data[0]) list_data += '
    • ' + ip + ban_button + '
    • ' curs.execute("select count(id) from user") user_count = curs.fetchall() if(user_count): count = user_count[0][0] else: count = 0 list_data += '

    • 이 위키에는 ' + str(count) + '명의 사람이 있습니다.
    • ' list_data += '

    (이전) (이후)' return(html_minify(template('index', imp = ['사용자 가입 기록', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = list_data, menu = [['other', '기타']] ))) @route('/admin_log') @route('/admin_log/') def user_log(num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 list_data = '
      ' curs.execute("select who, what, time from re_admin order by time desc limit ?, '50'", [str(sql_num)]) get_list = curs.fetchall() for data in get_list: ip = ip_pas(conn, data[0]) list_data += '
    • ' + ip + ' / ' + data[1] + ' / ' + data[2] + '
    • ' list_data += '

    주의 : 권한 사용 안하고 열람만 해도 기록되는 경우도 있습니다.

    ' list_data += '(이전) (이후)' return(html_minify(template('index', imp = ['관리자 권한 기록', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = list_data, menu = [['other', '기타']] ))) @route('/give_log') @route('/give_log/') def give_log(num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 list_data = '
      ' back = '' curs.execute("select distinct name from alist order by name asc limit ?, '50'", [str(sql_num)]) get_list = curs.fetchall() for data in get_list: if(back != data[0]): back = data[0] list_data += '
    • ' + data[0] + '
    • ' list_data += '
    (생성)' list_data += '

    (이전) (이후)' return(html_minify(template('index', imp = ['권한 목록', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = list_data, menu = [['other', '기타']] ))) @route('/indexing') def indexing(): if(admin_check(conn, None, 'indexing') != 1): return(re_error(conn, '/error/3')) curs.execute("select name from sqlite_master where type in ('table', 'view') and name not like 'sqlite_%' union all select name from sqlite_temp_master where type in ('table', 'view') order by 1;") data = curs.fetchall() for table in data: print('----- ' + table[0] + ' -----') curs.execute('select sql from sqlite_master where name = ?', [table[0]]) cul = curs.fetchall() r_cul = re.findall('(?:([^ (]*) text)', str(cul[0])) for n_cul in r_cul: print(n_cul) sql = 'create index index_' + table[0] + '_' + n_cul + ' on ' + table[0] + '(' + n_cul + ')' try: curs.execute(sql) except: pass conn.commit() return(redirect('/')) @route('/xref/') @route('/xref//') def xref(name = None, num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 div = '
      ' curs.execute("select link, type from back where title = ? and not type = 'cat' and not type = 'no' order by link asc limit ?, '50'", [name, str(sql_num)]) for data in curs.fetchall(): div += '
    • ' + data[0] + '' if(data[1]): if(data[1] == 'include'): side = '포함' elif(data[1] == 'file'): side = '파일' else: side = '넘겨주기' div += ' (' + side + ')' div += '
    • ' if(re.search('^틀:', data[0])): div += '
    • ' + data[0] + ' (역링크)
    • ' div += '

    (이전) (이후)' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (역링크)', 0])], data = div, menu = [['w/' + url_pas(name), '문서']] ))) @route('/please') @route('/please/') def please(num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 div = '
      ' var = '' curs.execute("select distinct title from back where type = 'no' order by title asc limit ?, '50'", [str(sql_num)]) for data in curs.fetchall(): if(var != data[0]): div += '
    • ' + data[0] + '
    • ' var = data[0] div += '

    (이전) (이후)' return(html_minify(template('index', imp = ['필요한 문서', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = div, menu = [['other', '기타']] ))) @route('/recent_discuss') @route('/recent_discuss/') def recent_discuss(tools = 'normal'): if(tools == 'normal' or tools == 'close'): div = '' if(tools == 'normal'): div += '(닫힌 토론)' m_sub = 0 else: div += '(열린 토론)' m_sub = ' (닫힘)' div += '

    ' else: return(redirect('/')) curs.execute("select title, sub, date from rd order by date desc limit 50") for data in curs.fetchall(): title = html.escape(data[0]) sub = html.escape(data[1]) close = 0 if(tools == 'normal'): curs.execute("select title from stop where title = ? and sub = ? and close = 'O'", [data[0], data[1]]) if(curs.fetchall()): close = 1 else: curs.execute("select title from stop where title = ? and sub = ? and close = 'O'", [data[0], data[1]]) if(not curs.fetchall()): close = 1 if(close == 0): div += ' \ \ \ ' else: div += ' \
    토론명시간
    \ ' + title + ' (' + sub + ') \ ' + data[2] + '
    ' return(html_minify(template('index', imp = ['최근 토론내역', wiki_set(conn, 1), custom(conn), other2([m_sub, 0])], data = div, menu = 0 ))) @route('/block_log') @route('/block_log/') def block_log(num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 div = ' \ \ \ \ \ \ \ \ \ \ ' curs.execute("select why, block, blocker, end, today from rb order by today desc limit ?, '50'", [str(sql_num)]) for data in curs.fetchall(): why = html.escape(data[0]) b = re.search("^([0-9]{1,3}\.[0-9]{1,3})$", data[1]) if(b): ip = data[1] + ' (대역)' else: ip = ip_pas(conn, data[1]) if(data[3] != ''): end = data[3] else: end = '무기한' div += '' div += '' else: div += '
    차단자관리자기간
    이유시간
    ' + ip + '' + ip_pas(conn, data[2]) + '' + end + '
    ' + why + '' + data[4] + '

    ' div += '(이전) (이후)' return(html_minify(template('index', imp = ['차단 기록', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = div, menu = [['other', '기타']] ))) @route('/history/', method=['POST', 'GET']) @route('/history//', method=['POST', 'GET']) def history_view(name = None, num = 1): if(request.method == 'POST'): return(redirect('/w/' + url_pas(name) + '/r/' + request.forms.b + '/diff/' + request.forms.a)) else: select = '' if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 admin1 = admin_check(conn, 1, None) admin2 = admin_check(conn, 6, None) div = ' \ \ \ \ \ \ ' curs.execute("select send, leng, ip, date, title, id from history where title = ? order by id + 0 desc limit ?, '50'", [name, str(sql_num)]) all_data = curs.fetchall() for data in all_data: select += '' if(data[0]): send = data[0] else: send = '
    ' if(re.search("^\+", data[1])): leng = '' + data[1] + '' elif(re.search("^\-", data[1])): leng = '' + data[1] + '' else: leng = '' + data[1] + '' ip = ip_pas(conn, data[2]) curs.execute("select block from ban where block = ?", [data[2]]) ban_it = curs.fetchall() if(ban_it): if(admin1 == 1): ban = ' (해제)' else: ban = ' (X)' else: if(admin1 == 1): ban = ' (차단)' else: ban = '' curs.execute("select * from hidhi where title = ? and re = ?", [name, data[5]]) hid_it = curs.fetchall() if(hid_it): if(admin2): hidden = ' (공개)' hid = 0 else: hid = 1 else: if(admin2): hidden = ' (숨김)' hid = 0 else: hidden = '' hid = 0 if(hid == 1): div += ' \ \ ' else: div += ' \ \ \ \ \ \ \ ' else: div += ' \
    편집자시간
    숨김
    \ ' + data[5] + '판 (보기) \ (원본) \ (되돌리기) (' + leng + ') \ ' + ip + ban + hidden + '' + data[3] + '
    ' + send + '
    \
    \
    (이전) (이후)' div = '
    \ \ \ \

    ' + div return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (역사)', 0])], data = div, menu = [['w/' + url_pas(name), '문서'], ['move_data/' + url_pas(name), '이동 기록']] ))) @route('/search', method=['POST']) def search(): return(redirect('/search/' + url_pas(request.forms.search))) @route('/goto', method=['POST']) def goto(): curs.execute("select title from data where title = ?", [request.forms.search]) data = curs.fetchall() if(data): return(redirect('/w/' + url_pas(request.forms.search))) else: return(redirect('/search/' + url_pas(request.forms.search))) @route('/search/') @route('/search//') def deep_search(name = None, num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 div = '
      ' div_plus = '' no = 0 curs.execute("select distinct title from data where title like ? or data like ? order by case when title like ? then 1 else 2 end limit ?, '50'", ['%' + name + '%', '%' + name + '%', '%' + name + '%', str(sql_num)]) all_list = curs.fetchall() curs.execute("select title from data where title = ?", [name]) exist = curs.fetchall() if(exist): div = '
      • 문서로 바로가기


      • ' else: div = '
        • 문서가 없습니다. 바로가기


        • ' start = 2 if(all_list): for data in all_list: try: var_re = re.search(name, data[0]) except: var_re = re.search('\\' + name, data[0]) if(var_re): if(no == 0): div_plus += '
        • ' + data[0] + ' (제목)
        • ' start = 0 else: if(start == 0 and div_plus != ''): start = 1 div_plus += '
          ' div_plus += '
        • ' + data[0] + ' (내용)
        • ' else: no = 1 if(start == 0 and div_plus != ''): start = 1 div_plus += '
          ' div_plus += '
        • ' + data[0] + ' (내용)
        • ' else: div += '
        • 검색 결과 없음
        • ' div += div_plus div += '

        (이전) (이후)' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (검색)', 0])], data = div, menu = 0 ))) @route('/raw/') @route('/raw//r/') @route('/topic//sub//raw/') def raw_view(name = None, sub_t = None, num = None): v_name = name sub = ' (원본)' if(not sub_t and num): curs.execute("select title from hidhi where title = ? and re = ?", [name, str(num)]) hid = curs.fetchall() if(hid and admin_check(conn, 6, None) != 1): return(re_error(conn, '/error/3')) curs.execute("select data from history where title = ? and id = ?", [name, str(num)]) sub += ' (' + str(num) + '판)' menu = [['history/' + url_pas(name), '역사']] elif(sub_t): curs.execute("select data from topic where id = ? and title = ? and sub = ? and block = ''", [str(num), name, sub_t]) v_name = '토론 원본' sub = ' (' + str(num) + '번)' menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub_t) + '#' + str(num), '토론']] else: curs.execute("select data from data where title = ?", [name]) menu = [['w/' + url_pas(name), '문서']] data = curs.fetchall() if(data): p_data = html.escape(data[0][0]) p_data = '' return(html_minify(template('index', imp = [v_name, wiki_set(conn, 1), custom(conn), other2([sub, 0])], data = p_data, menu = menu ))) else: return(redirect('/w/' + url_pas(name))) @route('/revert//r/', method=['POST', 'GET']) def revert(name = None, num = None): ip = ip_check() can = acl_check(conn, name) today = get_time() if(request.method == 'POST'): if(not request.forms.get('g-recaptcha-response')): if(captcha_post(conn) == 1): return(re_error(conn, '/error/13')) else: captcha_post(conn, 0) curs.execute("select title from hidhi where title = ? and re = ?", [name, str(num)]) if(curs.fetchall() and admin_check(conn, 6, None) != 1): return(re_error(conn, '/error/3')) if(can == 1): return(re_error(conn, '/ban')) curs.execute("delete from back where link = ?", [name]) conn.commit() curs.execute("select data from history where title = ? and id = ?", [name, str(num)]) data = curs.fetchall() if(data): curs.execute("select data from data where title = ?", [name]) d = curs.fetchall() if(d): leng = leng_check(len(d[0][0]), len(data[0][0])) curs.execute("update data set data = ? where title = ?", [data[0][0], name]) else: leng = '+' + str(len(data[0][0])) curs.execute("insert into data (title, data, acl) values (?, ?, '')", [name, data[0][0]]) history_plus(conn, name, data[0][0], today, ip, request.forms.send + ' (' + str(num) + '판)', leng) namumark(conn, name, data[0][0], 1, 0, 0) conn.commit() return(redirect('/w/' + url_pas(name))) else: curs.execute("select title from hidhi where title = ? and re = ?", [name, str(num)]) hid = curs.fetchall() if(hid and admin_check(conn, 6, None) != 1): return(re_error(conn, '/error/3')) if(can == 1): return(re_error(conn, '/ban')) curs.execute("select title from history where title = ? and id = ?", [name, str(num)]) if(not curs.fetchall()): return(redirect('/w/' + url_pas(name))) custom_data = custom(conn) captcha = captcha_get(conn) if(custom_data[2] == 0): ip_warring = '비 로그인 상태입니다. 비 로그인으로 진행 시 아이피가 역사에 기록됩니다.

        ' else: ip_warring = '' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom_data, other2([' (되돌리기)', 0])], data = ip_warring + ' \
        \
        \ ' + captcha + ' \ \
        ', menu = [['history/' + url_pas(name), '역사'], ['recent_changes', '최근 변경']] ))) @route('/big_delete', method=['POST', 'GET']) def big_delete(): if(admin_check(conn, 2, 'big_delete') != 1): return(re_error(conn, '/error/3')) if(request.method == 'POST'): today = get_time() ip = ip_check() data = request.forms.content + '\r\n' m = re.findall('(.*)\r\n', data) for g in m: curs.execute("select data from data where title = ?", [g]) d = curs.fetchall() if(d): curs.execute("delete from back where title = ?", [g]) leng = '-' + str(len(d[0][0])) curs.execute("delete from data where title = ?", [g]) history_plus(conn, g, '', today, ip, request.forms.send + ' (대량 삭제)', leng) data = re.sub('(.*)\r\n', '', data, 1) conn.commit() return(redirect('/')) else: return(html_minify(template('index', imp = ['많은 문서 삭제', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '문서명 A
        문서명 B
        문서명 C

        이런 식으로 적으세요.


        \
        \

        \

        \ \
        ', menu = [['manager', '관리자']] ))) @route('/edit/', method=['POST', 'GET']) @route('/edit//from/', method=['POST', 'GET']) @route('/edit//section/', method=['POST', 'GET']) def edit(name = None, name2 = None, num = None): ip = ip_check() can = acl_check(conn, name) if(can == 1): return(re_error(conn, '/ban')) if(request.method == 'POST'): if(not request.forms.get('g-recaptcha-response')): if(captcha_post(conn) == 1): return(re_error(conn, '/error/13')) else: captcha_post(conn, 0) if(len(request.forms.send) > 500): return(re_error(conn, '/error/15')) if(request.forms.otent == request.forms.content): return(re_error(conn, '/error/18')) today = get_time() content = savemark(request.forms.content) curs.execute("select data from data where title = ?", [name]) old = curs.fetchall() if(old): if(not num and request.forms.otent != old[0][0]): return(re_error(conn, '/error/12')) leng = leng_check(len(request.forms.otent), len(content)) if(num): content = old[0][0].replace(request.forms.otent, content) curs.execute("update data set data = ? where title = ?", [content, name]) else: leng = '+' + str(len(content)) curs.execute("insert into data (title, data, acl) values (?, ?, '')", [name, content]) history_plus(conn, name, content, today, ip, send_p(request.forms.send), leng) curs.execute("delete from back where link = ?", [name]) curs.execute("delete from back where title = ? and type = 'no'", [name]) namumark(conn, name, content, 1, 0, 0) conn.commit() return(redirect('/w/' + url_pas(name))) else: curs.execute("select data from data where title = ?", [name]) new = curs.fetchall() if(new): if(num): i = 0 j = 0 data = new[0][0] + '\r\n' while(1): m = re.search("((?:={1,6})\s?(?:[^=]*)\s?(?:={1,6})(?:\s+)?\n(?:(?:(?:(?!(?:={1,6})\s?(?:[^=]*)\s?(?:={1,6})(?:\s+)?\n).)*)(?:\n)?)+)", data) if(m): if(i == num - 1): g = m.groups() data = re.sub("\r\n$", "", g[0]) break else: data = re.sub("((?:={1,6})\s?(?:[^=]*)\s?(?:={1,6})(?:\s+)?\n(?:(?:(?:(?!(?:={1,6})\s?(?:[^=]*)\s?(?:={1,6})(?:\s+)?\n).)*)(?:\n)?)+)", "", data, 1) i += 1 else: j = 1 break if(j == 0): data = re.sub("\r\n$", "", data) else: data = new[0][0] else: data = '' if(num): action = '/section/' + str(num) else: action = '' data2 = data if(not num): get_name = '
        \ \ \

        ' else: get_name = '' captcha = captcha_get(conn) if(name2): curs.execute("select data from data where title = ?", [name2]) get_data = curs.fetchall() if(get_data): data = get_data[0][0] get_name = '' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (수정)', 0])], data = get_name + ' \
        \ \

        \

        \ ' + captcha + ' \ \ \
        ', menu = [['w/' + url_pas(name), '문서']] ))) @route('/edit_get/', method=['POST']) def edit_get(name = None): return(redirect('/edit/' + url_pas(name) + '/from/' + url_pas(request.forms.name))) @route('/preview/', method=['POST']) @route('/preview//section/', method=['POST']) def preview(name = None, num = None): if(not request.forms.get('g-recaptcha-response')): if(captcha_post(conn) == 1): return(re_error(conn, '/error/13')) else: captcha_post(conn, 0) ip = ip_check() can = acl_check(conn, name) captcha = captcha_get(conn) if(can == 1): return(re_error(conn, '/ban')) newdata = request.forms.content newdata = re.sub('^#(?:redirect|넘겨주기) (?P[^\n]*)', ' * [[\g]] 문서로 넘겨주기', newdata) enddata = namumark(conn, name, newdata, 0, 0, 0) if(num): action = '/section/' + str(num) else: action = '' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (미리보기)', 0])], data = '
        \ \

        \

        \ ' + captcha + ' \ \ \


        ' + enddata, menu = [['w/' + url_pas(name), '문서']] ))) @route('/delete/', method=['POST', 'GET']) def delete(name = None): ip = ip_check() can = acl_check(conn, name) if(can == 1): return(re_error(conn, '/ban')) if(request.method == 'POST'): if(not request.forms.get('g-recaptcha-response')): if(captcha_post(conn) == 1): return(re_error(conn, '/error/13')) else: captcha_post(conn, 0) curs.execute("select data from data where title = ?", [name]) data = curs.fetchall() if(data): today = get_time() leng = '-' + str(len(data[0][0])) history_plus(conn, name, '', today, ip, request.forms.send + ' (삭제)', leng) curs.execute("select title, link from back where title = ? and not type = 'cat' and not type = 'no'", [name]) for data in curs.fetchall(): curs.execute("insert into back (title, link, type) values (?, ?, 'no')", [data[0], data[1]]) curs.execute("delete from back where link = ?", [name]) curs.execute("delete from data where title = ?", [name]) conn.commit() return(redirect('/w/' + url_pas(name))) else: curs.execute("select title from data where title = ?", [name]) if(not curs.fetchall()): return(redirect('/w/' + url_pas(name))) custom_data = custom(conn) captcha = captcha_get(conn) if(custom_data[2] == 0): ip_warring = '비 로그인 상태입니다. 비 로그인으로 진행 시 아이피가 역사에 기록됩니다.

        ' else: ip_warring = '' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom_data, other2([' (삭제)', 0])], data = '
        \ ' + ip_warring + ' \
        \ ' + captcha + ' \ \
        ', menu = [['w/' + url_pas(name), '문서']] ))) @route('/move_data/') @route('/move_data//') def move_data(name = None, num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 data = '(이전) (이후)' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (이동 기록)', 0])], data = data, menu = [['history/' + url_pas(name), '역사']] ))) @route('/move/', method=['POST', 'GET']) def move(name = None): ip = ip_check() can = acl_check(conn, name) today = get_time() if(can == 1): return(re_error(conn, '/ban')) if(request.method == 'POST'): if(not request.forms.get('g-recaptcha-response')): if(captcha_post(conn) == 1): return(re_error(conn, '/error/13')) else: captcha_post(conn, 0) curs.execute("select title from history where title = ?", [request.forms.title]) if(curs.fetchall()): return(re_error(conn, '/error/19')) curs.execute("select data from data where title = ?", [name]) data = curs.fetchall() leng = '0' if(data): curs.execute("update data set title = ? where title = ?", [request.forms.title, name]) curs.execute("update back set link = ? where link = ?", [request.forms.title, name]) d = data[0][0] else: d = '' history_plus(conn, name, d, today, ip, request.forms.send + ' (' + name + ' - ' + request.forms.title + ' 이동)', leng) curs.execute("select title, link from back where title = ? and not type = 'cat' and not type = 'no'", [name]) for data in curs.fetchall(): curs.execute("insert into back (title, link, type) values (?, ?, 'no')", [data[0], data[1]]) curs.execute("update history set title = ? where title = ?", [request.forms.title, name]) conn.commit() return(redirect('/w/' + url_pas(request.forms.title))) else: custom_data = custom(conn) captcha = captcha_get(conn) if(custom_data[2] == 0): ip_warring = '비 로그인 상태입니다. 비 로그인으로 진행 시 아이피가 역사에 기록됩니다.

        ' else: ip_warring = '' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom_data, other2([' (이동)', 0])], data = '
        \ ' + ip_warring + ' \
        \
        \ ' + captcha + ' \ \
        ', menu = [['w/' + url_pas(name), '문서']] ))) @route('/other') def other(): return(html_minify(template('index', imp = ['기타 메뉴', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = namumark(conn, '', '[목차(없음)]\r\n' + \ '== 기록 ==\r\n' + \ ' * [[wiki:block_log|차단 기록]]\r\n' + \ ' * [[wiki:user_log|가입 기록]]\r\n' + \ ' * [[wiki:admin_log|권한 기록]]\r\n' + \ ' * [[wiki:manager/6|편집 기록]]\r\n' + \ ' * [[wiki:not_close_topic|열린 토론 목록]]\r\n' + \ '== 기타 ==\r\n' + \ ' * [[wiki:title_index|모든 문서]]\r\n' + \ ' * [[wiki:acl_list|ACL 문서]]\r\n' + \ ' * [[wiki:admin_list|관리자 목록]]\r\n' + \ ' * [[wiki:give_log|권한 목록]]\r\n' + ' * [[wiki:please|필요한 문서]]\r\n' + \ ' * [[wiki:upload|파일 올리기]]\r\n' + \ '== 관리자 ==\r\n' + \ ' * [[wiki:manager/1|관리자 메뉴]]\r\n' + \ '== 버전 ==\r\n' + \ '이 오픈나무는 [[https://github.com/2DU/openNAMU/blob/SQLite/version.md|' + r_ver + ']]판 입니다.', 0, 0, 0), menu = 0 ))) @route('/manager', method=['POST', 'GET']) @route('/manager/', method=['POST', 'GET']) def manager(num = 1): title_list = [['ACL 이동', '문서명', 'acl'], ['검사 이동', 0, 'check'], ['차단 이동', 0, 'ban'], ['권한 이동', 0, 'admin'], ['기록 이동', 0, 'record'], [], ['그룹 생성 이동', '그룹명', 'admin_plus']] if(num == 1): return(html_minify(template('index', imp = ['관리자 메뉴', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = namumark(conn, '', '[목차(없음)]\r\n' + \ '== 목록 ==\r\n' + \ ' * [[wiki:manager/2|문서 ACL]]\r\n' + \ ' * [[wiki:manager/3|사용자 검사]]\r\n' + \ ' * [[wiki:manager/10|사용자 비교]]\r\n' + \ ' * [[wiki:manager/4|사용자 차단]]\r\n' + \ ' * [[wiki:manager/5|권한 주기]]\r\n' + \ ' * [[wiki:big_delete|여러 문서 삭제]]\r\n' + \ '== 소유자 ==\r\n' + \ ' * [[wiki:indexing|인덱싱]]\r\n' + \ ' * [[wiki:manager/8|관리 그룹 생성]]\r\n' + \ ' * [[wiki:edit_set|설정 편집]]\r\n' + \ '== 기타 ==\r\n' + \ ' * 이 메뉴에 없는 기능은 해당 문서의 역사나 토론에서 바로 사용 가능함', 0, 0, 0), menu = [['other', '기타']] ))) elif(num in range(2, 6) or num == 8): if(request.method == 'POST'): return(redirect('/' + title_list[(num - 2)][2] + '/' + url_pas(request.forms.name))) else: if(title_list[(num - 2)][1] == 0): placeholder = '문서명' else: placeholder = title_list[(num - 2)][1] return(html_minify(template('index', imp = [title_list[(num - 2)][0], wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
        \

        \ \
        ', menu = [['manager', '관리자']] ))) elif(num == 10): if(request.method == 'POST'): return(redirect('/check/' + url_pas(request.forms.name) + '/' + url_pas(request.forms.name2))) else: return(html_minify(template('index', imp = ['검사 이동', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
        \

        \

        \ \
        ', menu = [['manager', '관리자']] ))) else: return(redirect('/')) @route('/title_index') @route('/title_index//') def title_index(num = 100, page = 1): if(page * num > 0): sql_num = page * num - num else: sql_num = 0 if(num != 0): all_list = sql_num + 1 else: all_list = 0 if(num > 1000): return(re_error(conn, '/error/3')) data = '
          (전체) (250) (500) (1000)

          ' if(num == 0): curs.execute("select data from other where name = 'all_title'") all_title_can = curs.fetchall() if(all_title_can and all_title_can[0][0] != ''): return(re_error(conn, '/error/3')) curs.execute("select title from data order by title asc") else: curs.execute("select title from data order by title asc limit ?, ?", [str(sql_num), str(num)]) title_list = curs.fetchall() for list_data in title_list: data += '
        • ' + str(all_list) + '. ' + list_data[0] + '
        • ' all_list += 1 count_end = [] curs.execute("select count(title) from data") count = curs.fetchall() if(count): count_end += [count[0][0]] else: count_end += [0] sql_list = ['틀:', '분류:', '사용자:', '파일:'] for sql in sql_list: curs.execute("select count(title) from data where title like ?", [sql + '%']) count = curs.fetchall() if(count): count_end += [count[0][0]] else: count_end += [0] count_end += [count_end[0] - count_end[1] - count_end[2] - count_end[3] - count_end[4]] data += '

        • 이 위키에는 총 ' + str(count_end[0]) + '개의 문서가 있습니다.


        • ' data += '
        • 틀 문서는 총 ' + str(count_end[1]) + '개의 문서가 있습니다.
        • ' data += '
        • 분류 문서는 총 ' + str(count_end[2]) + '개의 문서가 있습니다.
        • ' data += '
        • 사용자 문서는 총 ' + str(count_end[3]) + '개의 문서가 있습니다.
        • ' data += '
        • 파일 문서는 총 ' + str(count_end[4]) + '개의 문서가 있습니다.
        • ' data += '
        • 나머지 문서는 총 ' + str(count_end[5]) + '개의 문서가 있습니다.
        • ' if(num != 0): data += '

        (이전) (이후)' return(html_minify(template('index', imp = ['모든 문서', wiki_set(conn, 1), custom(conn), other2([' (' + str(num) + ')', 0])], data = data, menu = [['other', '기타']] ))) @route('/topic//sub//b/') def topic_block(name = None, sub = None, num = None): if(admin_check(conn, 3, 'blind (' + name + ' - ' + sub + '#' + str(num) + ')') != 1): return(re_error(conn, '/error/3')) curs.execute("select block from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)]) block = curs.fetchall() if(block): if(block[0][0] == 'O'): curs.execute("update topic set block = '' where title = ? and sub = ? and id = ?", [name, sub, str(num)]) else: curs.execute("update topic set block = 'O' where title = ? and sub = ? and id = ?", [name, sub, str(num)]) rd_plus(conn, name, sub, get_time()) conn.commit() return(redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num))) @route('/topic//sub//notice/') def topic_top(name = None, sub = None, num = None): if(admin_check(conn, 3, 'notice (' + name + ' - ' + sub + '#' + str(num) + ')') != 1): return(re_error(conn, '/error/3')) curs.execute("select * from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)]) topic_data = curs.fetchall() if(topic_data): curs.execute("select top from topic where id = ? and title = ? and sub = ?", [str(num), name, sub]) top_data = curs.fetchall() if(top_data): if(top_data[0][0] == 'O'): curs.execute("update topic set top = '' where title = ? and sub = ? and id = ?", [name, sub, str(num)]) else: curs.execute("update topic set top = 'O' where title = ? and sub = ? and id = ?", [name, sub, str(num)]) rd_plus(conn, name, sub, get_time()) conn.commit() return(redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num))) @route('/topic//sub//tool/') def topic_stop(name = None, sub = None, tool = None): if(tool == 'close'): set_list = ['O', '', '토론 닫기', '토론 열림'] elif(tool == 'stop'): set_list = ['', 'O', '토론 정지', '토론 재개'] elif(tool == 'agree'): pass else: return(redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))) if(admin_check(conn, 3, 'topic ' + tool + ' (' + name + ' - ' + sub + ')') != 1): return(re_error(conn, '/error/3')) ip = ip_check() time = get_time() curs.execute("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1", [name, sub]) topic_check = curs.fetchall() if(topic_check): if(tool == 'agree'): curs.execute("select title from agreedis where title = ? and sub = ?", [name, sub]) if(curs.fetchall()): curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, '합의 결렬', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip]) curs.execute("delete from agreedis where title = ? and sub = ?", [name, sub]) else: curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, '합의 완료', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip]) curs.execute("insert into agreedis (title, sub) values (?, ?)", [name, sub]) else: curs.execute("select title from stop where title = ? and sub = ? and close = ?", [name, sub, set_list[0]]) if(curs.fetchall()): curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[3], time, ip]) curs.execute("delete from stop where title = ? and sub = ? and close = ?", [name, sub, set_list[0]]) else: curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[2], time, ip]) curs.execute("insert into stop (title, sub, close) values (?, ?, ?)", [name, sub, set_list[0]]) curs.execute("delete from stop where title = ? and sub = ? and close = ?", [name, sub, set_list[1]]) rd_plus(conn, name, sub, time) conn.commit() return(redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))) @route('/topic//sub//admin/') def topic_admin(name = None, sub = None, num = None): curs.execute("select block, ip from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)]) data = curs.fetchall() if(not data): return(redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))) is_ban = '
      • ' if(data[0][0] == 'O'): is_ban += '가림 해제' else: is_ban += '가림' is_ban += '
      • ' curs.execute("select id from topic where title = ? and sub = ? and id = ? and top = 'O'", [name, sub, str(num)]) is_ban += '
      • ' if(curs.fetchall()): is_ban += '공지 해제' else: is_ban += '공지' is_ban += '
      • ' curs.execute("select end from ban where block = ?", [data[0][1]]) ban = '
      • ' if(curs.fetchall()): ban += '차단 해제' else: ban += '차단' ban += '
      • ' + is_ban return(html_minify(template('index', imp = ['토론 관리', wiki_set(conn, 1), custom(conn), other2([' (' + str(num) + '번)', 0])], data = '
          ' + ban + '
        ', menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num), '토론']] ))) @route('/topic//sub/', method=['POST', 'GET']) def topic(name = None, sub = None): ban = topic_check(conn, name, sub) admin = admin_check(conn, 3, None) if(request.method == 'POST'): if(not request.forms.get('g-recaptcha-response')): if(captcha_post(conn) == 1): return(re_error(conn, '/error/13')) else: captcha_post(conn, 0) ip = ip_check() today = get_time() if(ban == 1 and admin != 1): return(re_error(conn, '/ban')) curs.execute("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1", [name, sub]) old_num = curs.fetchall() if(old_num): num = int(old_num[0][0]) + 1 else: num = 1 match = re.search('^사용자:([^/]+)', name) if(match): curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [match.groups()[0], ip + '님이 사용자 토론을 시작했습니다.', today]) data = re.sub("\[\[(분류:(?:(?:(?!\]\]).)*))\]\]", "[br]", request.forms.content) match = re.findall("(?:#([0-9]+))", data) for rd_data in match: curs.execute("select ip from topic where title = ? and sub = ? and id = ?", [name, sub, rd_data]) ip_data = curs.fetchall() if(ip_data and not re.search('(\.|:)', ip_data[0][0])): curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [ip_data[0][0], ip + '님이 토론에서 언급 했습니다.', today]) data = re.sub("(?P#(?:[0-9]+))", '[[\g]]', data) data = savemark(data) rd_plus(conn, name, sub, today) curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '')", [str(num), name, sub, data, today, ip]) conn.commit() return(redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))) else: curs.execute("select title from stop where title = ? and sub = ? and close = 'O'", [name, sub]) close_data = curs.fetchall() curs.execute("select title from stop where title = ? and sub = ? and close = ''", [name, sub]) stop_data = curs.fetchall() curs.execute("select id from topic where title = ? and sub = ? limit 1", [name, sub]) topic_exist = curs.fetchall() display = '' all_data = '' data = '' number = 1 if(admin == 1 and topic_exist): if(close_data): all_data += '(열기) ' else: all_data += '(닫기) ' if(stop_data): all_data += '(재개) ' else: all_data += '(정지) ' curs.execute("select title from agreedis where title = ? and sub = ?", [name, sub]) if(curs.fetchall()): all_data += '(취소)' else: all_data += '(합의)' all_data += '

        ' if((close_data or stop_data) and admin != 1): display = 'display: none;' curs.execute("select data, id, date, ip, block, top from topic where title = ? and sub = ? order by id + 0 asc", [name, sub]) topic_1 = curs.fetchall() curs.execute("select data, id, date, ip from topic where title = ? and sub = ? and top = 'O' order by id + 0 asc", [name, sub]) topic_2 = curs.fetchall() for topic_data in topic_2: who_plus = '' curs.execute("select who from re_admin where what = ? order by time desc limit 1", ['notice (' + name + ' - ' + sub + '#' + topic_data[1] + ')']) topic_data_top = curs.fetchall() if(topic_data_top): who_plus += ' @' + topic_data_top[0][0] all_data += '
        ' all_data += '#' + topic_data[1] + ' ' + ip_pas(conn, topic_data[3]) + who_plus + ' ' + topic_data[2] + '' all_data += '
        ' + namumark(conn, '', topic_data[0], 0, 0, 0) + '

        ' for topic_data in topic_1: if(number == 1): start = topic_data[3] if(topic_data[4] == 'O'): blind_data = 'style="background: gainsboro;"' if(admin != 1): curs.execute("select who from re_admin where what = ? order by time desc limit 1", ['blind (' + name + ' - ' + sub + '#' + str(number) + ')']) who_blind = curs.fetchall() if(who_blind): user_write = '[[사용자:' + who_blind[0][0] + ']]님이 가림' else: user_write = '관리자가 가림' else: blind_data = '' user_write = namumark(conn, '', topic_data[0], 0, 0, 0) ip = ip_pas(conn, topic_data[3]) curs.execute('select acl from user where id = ?', [topic_data[3]]) user_acl = curs.fetchall() if(user_acl and user_acl[0][0] != 'user'): ip += ' ' if(admin == 1 or blind_data == ''): ip += ' (원본)' if(admin == 1): ip += ' (관리)' curs.execute("select end from ban where block = ?", [topic_data[3]]) if(curs.fetchall()): ip += ' ' if(topic_data[5] == '1'): color = '_blue' elif(topic_data[3] == start): color = '_green' else: color = '' if(user_write == ''): user_write = '
        ' all_data += '
        ' all_data += '#' + str(number) + ' ' + ip + ' ' + topic_data[2] + '' all_data += '
        ' + user_write + '

        ' number += 1 custom_data = custom(conn) captcha = captcha_get(conn) if(ban != 1 or admin == 1): data += '' data += '



        ' + captcha if(custom_data[2] == 0 and display == ''): data += '비 로그인 상태입니다. 비 로그인으로 진행 시 아이피가 토론에 기록됩니다.

        ' data += '
        ' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom_data, other2([' (토론)', 0])], data = '

        ' + sub + '

        ' + all_data + data, menu = [['topic/' + url_pas(name), '목록']] ))) @route('/topic/', method=['POST', 'GET']) @route('/topic//', method=['GET']) def close_topic_list(name = None, tool = None): div = '' list_d = 0 if(request.method == 'POST'): t_num = '' while(1): curs.execute("select title from topic where title = ? and sub = ? limit 1", [name, request.forms.topic + t_num]) if(curs.fetchall()): if(t_num == ''): t_num = ' 2' else: t_num = ' ' + str(int(t_num.replace(' ', '')) + 1) else: break return(redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(request.forms.topic + t_num))) else: plus = '' menu = [['topic/' + url_pas(name), '목록']] if(tool == 'close'): curs.execute("select sub from stop where title = ? and close = 'O' order by sub asc", [name]) sub = '닫힘' elif(tool == 'agree'): curs.execute("select sub from agreedis where title = ? order by sub asc", [name]) sub = '합의' else: curs.execute("select sub from rd where title = ? order by date desc", [name]) sub = '토론 목록' menu = [['w/' + url_pas(name), '문서']] plus = '(닫힘) (합의)

        \
        \ ' for data in curs.fetchall(): curs.execute("select data, date, ip, block from topic where title = ? and sub = ? and id = '1'", [name, data[0]]) if(curs.fetchall()): it_p = 0 if(sub == '토론 목록'): curs.execute("select title from stop where title = ? and sub = ? and close = 'O' order by sub asc", [name, data[0]]) close = curs.fetchall() if(close): it_p = 1 if(it_p != 1): div += '

        ' + data[0] + '

        ' if(div == ''): plus = re.sub('^
        ', '', plus) return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (' + sub + ')', 0])], data = '
        ' + div + plus + '
        ', menu = menu ))) @route('/login', method=['POST', 'GET']) def login(): session = request.environ.get('beaker.session') agent = request.environ.get('HTTP_USER_AGENT') if(session.get('Now') == 1): return(re_error(conn, '/error/11')) ip = ip_check() curs.execute("select ip from ok_login where ip = ?", [ip]) if(not curs.fetchall()): ban = ban_check(conn) else: ban = 0 if(ban == 1): return(re_error(conn, '/ban')) if(session.get('Now') == 1): return(re_error(conn, '/error/11')) if(request.method == 'POST'): if(not request.forms.get('g-recaptcha-response')): if(captcha_post(conn) == 1): return(re_error(conn, '/error/13')) else: captcha_post(conn, 0) curs.execute("select pw from user where id = ?", [request.forms.id]) user = curs.fetchall() if(not user): return(re_error(conn, '/error/5')) if(not bcrypt.checkpw(bytes(request.forms.pw, 'utf-8'), bytes(user[0][0], 'utf-8'))): return(re_error(conn, '/error/10')) session['Now'] = 1 session['DREAMER'] = request.forms.id curs.execute("select css from custom where user = ?", [request.forms.id]) css_data = curs.fetchall() if(css_data): session['Daydream'] = css_data[0][0] else: session['Daydream'] = '' curs.execute("insert into ua_d (name, ip, ua, today, sub) values (?, ?, ?, ?, '')", [request.forms.id, ip, agent, get_time()]) conn.commit() return(redirect('/user')) else: captcha = captcha_get(conn) return(html_minify(template('index', imp = ['로그인', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
        \

        \

        \ ' + captcha + ' \

        \ 주의 : 만약 HTTPS 연결이 아닌 경우 데이터가 유출될 가능성이 있습니다. 이에 대해 책임지지 않습니다. \
        ', menu = [['user', '사용자']] ))) @route('/change', method=['POST', 'GET']) def change_password(): session = request.environ.get('beaker.session') ip = ip_check() ban = ban_check(conn) if(request.method == 'POST'): if(request.forms.pw2 != request.forms.pw3): return(re_error(conn, '/error/20')) if(ban == 1): return(re_error(conn, '/ban')) curs.execute("select pw from user where id = ?", [session['DREAMER']]) user = curs.fetchall() if(not user): return(re_error(conn, '/error/10')) if(re.search('(\.|:)', ip)): return(redirect('/login')) if(not bcrypt.checkpw(bytes(request.forms.pw, 'utf-8'), bytes(user[0][0], 'utf-8'))): return(re_error(conn, '/error/5')) hashed = bcrypt.hashpw(bytes(request.forms.pw2, 'utf-8'), bcrypt.gensalt()) curs.execute("update user set pw = ? where id = ?", [hashed.decode(), session['DREAMER']]) conn.commit() return(redirect('/user')) else: if(ban == 1): return(re_error(conn, '/ban')) if(re.search('(\.|:)', ip)): return(redirect('/login')) return(html_minify(template('index', imp = ['비밀번호 변경', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
        \

        \

        \

        \

        \ 주의 : 만약 HTTPS 연결이 아닌 경우 데이터가 유출될 가능성이 있습니다. 이에 대해 책임지지 않습니다. \
        ', menu = [['user', '사용자']] ))) @route('/check/') @route('/check//') def user_check(name = None, name2 = None): curs.execute("select acl from user where id = ? or id = ?", [name, name2]) user = curs.fetchall() if(user and user[0][0] != 'user'): if(admin_check(conn, None, None) != 1): return(re_error(conn, '/error/4')) if(admin_check(conn, 4, 'check (' + name + ')') != 1): return(re_error(conn, '/error/3')) if(name2): if(re.search('(?:\.|:)', name)): if(re.search('(?:\.|:)', name2)): curs.execute("select name, ip, ua, today from ua_d where ip = ? or ip = ? order by today desc", [name, name2]) else: curs.execute("select name, ip, ua, today from ua_d where ip = ? or name = ? order by today desc", [name, name2]) else: if(re.search('(?:\.|:)', name2)): curs.execute("select name, ip, ua, today from ua_d where name = ? or ip = ? order by today desc", [name, name2]) else: curs.execute("select name, ip, ua, today from ua_d where name = ? or name = ? order by today desc", [name, name2]) elif(re.search('(?:\.|:)', name)): curs.execute("select name, ip, ua, today from ua_d where ip = ? order by today desc", [name]) else: curs.execute("select name, ip, ua, today from ua_d where name = ? order by today desc", [name]) record = curs.fetchall() if(record): div = '' div = '' for data in record: if(data[2]): ua = data[2] else: ua = '
        ' div += '' div += '' div += '
        이름아이피언제
        ' + ip_pas(conn, data[0]) + '' + ip_pas(conn, data[1]) + '' + data[3] + '
        ' + ua + '
        ' else: div = '' return(html_minify(template('index', imp = ['다중 검사', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = div, menu = [['manager', '관리자']] ))) @route('/register', method=['POST', 'GET']) def register(): ip = ip_check() ban = ban_check(conn) if(ban == 1): return(re_error(conn, '/ban')) if(not admin_check(conn, None, None) == 1): curs.execute('select data from other where name = "reg"') set_d = curs.fetchall() if(set_d and set_d[0][0] == 'on'): return(re_error(conn, '/ban')) if(request.method == 'POST'): if(not request.forms.get('g-recaptcha-response')): if(captcha_post(conn) == 1): return(re_error(conn, '/error/13')) else: captcha_post(conn, 0) if(request.forms.pw != request.forms.pw2): return(re_error(conn, '/error/20')) if(re.search('(?:[^A-Za-zㄱ-힣0-9 ])', request.forms.id)): return(re_error(conn, '/error/8')) if(len(request.forms.id) > 32): return(re_error(conn, '/error/7')) curs.execute("select id from user where id = ?", [request.forms.id]) if(curs.fetchall()): return(re_error(conn, '/error/6')) hashed = bcrypt.hashpw(bytes(request.forms.pw, 'utf-8'), bcrypt.gensalt()) curs.execute("select id from user limit 1") user_ex = curs.fetchall() if(not user_ex): curs.execute("insert into user (id, pw, acl) values (?, ?, '소유자')", [request.forms.id, hashed.decode()]) else: curs.execute("insert into user (id, pw, acl) values (?, ?, 'user')", [request.forms.id, hashed.decode()]) conn.commit() return(redirect('/login')) else: contract = '' curs.execute('select data from other where name = "contract"') data = curs.fetchall() if(data and data[0][0] != ''): contract = data[0][0] + '

        ' captcha = captcha_get(conn) return(html_minify(template('index', imp = ['회원가입', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
        \ ' + contract + ' \

        \

        \

        \ ' + captcha + ' \

        \ 주의 : 만약 HTTPS 연결이 아닌 경우 데이터가 유출될 가능성이 있습니다. 이에 대해 책임지지 않습니다. \
        ', menu = [['user', '사용자']] ))) @route('/logout') def logout(): session = request.environ.get('beaker.session') session['Now'] = 0 session.pop('DREAMER', None) return(redirect('/user')) @route('/ban/', method=['POST', 'GET']) def user_ban(name = None): curs.execute("select acl from user where id = ?", [name]) user = curs.fetchall() if(user and user[0][0] != 'user'): if(admin_check(conn, None, None) != 1): return(re_error(conn, '/error/4')) if(request.method == 'POST'): if(admin_check(conn, 1, 'ban (' + name + ')') != 1): return(re_error(conn, '/error/3')) ip = ip_check() time = get_time() if(request.forms.year == '09'): end = '' else: end = request.forms.year + '-' + request.forms.month + '-' + request.forms.day + ' ' + request.forms.hour + ':' + request.forms.minu + ':00' curs.execute("select block from ban where block = ?", [name]) if(curs.fetchall()): rb_plus(conn, name, '해제', time, ip, '') curs.execute("delete from ban where block = ?", [name]) else: if(re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name)): band_d = 'O' else: band_d = '' rb_plus(conn, name, end, time, ip, request.forms.why) curs.execute("insert into ban (block, end, why, band) values (?, ?, ?, ?)", [name, end, request.forms.why, band_d]) if(request.forms.login_ok != ''): curs.execute("insert into ok_login (ip, sub) values (?, '')", [name]) conn.commit() return(redirect('/ban/' + url_pas(name))) else: if(admin_check(conn, 1, None) != 1): return(re_error(conn, '/error/3')) curs.execute("select end from ban where block = ?", [name]) end = curs.fetchall() if(end): now = '차단 해제' if(end[0][0] == ''): data = '영구 차단

        ' else: data = end[0][0] + ' 까지 차단

        ' else: if(re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name)): now = '대역 차단' else: now = '차단' now_time = get_time() m = re.search('^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):[0-9]{2}', now_time) g = m.groups() year = '' for i in range(int(g[0]), int(g[0]) + 11): if(i == int(g[0])): year += '' else: year += '' month = '' for i in range(1, 13): if(i == int(g[1])): month += '' else: month += '' day = '' for i in range(1, 32): if(i == int(g[2])): day += '' else: day += '' hour = '' for i in range(0, 24): if(i == int(g[3])): hour += '' else: hour += '' minu = '' for i in range(0, 61): if(i == int(g[4])): minu += '' else: minu += '' is_it = '' if(re.search('(\.|:)', name)): plus = ' 로그인 가능 \
        \
        ' else: plus = '' data = ' 년' data += ' 월' data += '

        ' data += ' 시' data += ' 분 까지

        ' data += '
        ' + plus return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (' + now + ')', 0])], data = '
        ' + data + '
        ', menu = [['manager', '관리자']] ))) @route('/user_acl/', method=['POST', 'GET']) def acl(name = None): ip = ip_check() if(ip != name or re.search("(\.|:)", name)): return(redirect('/login')) if(request.method == 'POST'): curs.execute("select acl from data where title = ?", ['사용자:' + name]) acl_d = curs.fetchall() if(acl_d): if(request.forms.select == 'all'): curs.execute("update data set acl = 'all' where title = ?", ['사용자:' + name]) elif(request.forms.select == 'user'): curs.execute("update data set acl = 'user' where title = ?", ['사용자:' + name]) else: curs.execute("update data set acl = '' where title = ?", ['사용자:' + name]) conn.commit() return(redirect('/w/' + url_pas('사용자:' + name))) curs.execute("select acl from data where title = ?", ['사용자:' + name]) acl_d = curs.fetchall() if(acl_d): if(acl_d[0][0] == 'all'): now = '모두' elif(acl_d[0][0] == 'user'): now = '가입자' else: now = '일반' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (SET)', 0])], data = '현재 ACL : ' + now + '

        \
        \

        \ \
        ', menu = [['user', '사용자']] ))) else: return(redirect('/w/' + url_pas(name))) @route('/acl/', method=['POST', 'GET']) def acl(name = None): if(request.method == 'POST'): if(admin_check(conn, 5, 'acl (' + name + ')') != 1): return(re_error(conn, '/error/3')) curs.execute("select acl from data where title = ?", [name]) if(curs.fetchall()): if(request.forms.select == 'admin'): acl = 'admin' elif(request.forms.select == 'user'): acl = 'user' else: acl = '' curs.execute("update data set acl = ? where title = ?", [acl, name]) conn.commit() return(redirect('/w/' + url_pas(name))) else: if(admin_check(conn, 5, None) != 1): return(re_error(conn, '/error/3')) curs.execute("select acl from data where title = ?", [name]) acl = curs.fetchall() if(acl): if(acl[0][0] == 'admin'): now = '관리자' elif(acl[0][0] == 'user'): now = '가입자' else: now = '일반' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (ACL)', 0])], data = '현재 ACL : ' + now + '

        \
        \

        \

        \ \
        ', menu = [['w/' + url_pas(name), '문서'], ['manager', '관리자']] ))) else: return(redirect('/w/' + url_pas(name))) @route('/admin/', method=['POST', 'GET']) def user_admin(name = None): owner = admin_check(conn, None, None) curs.execute("select acl from user where id = ?", [name]) user = curs.fetchall() if(not user): return(re_error(conn, '/error/5')) else: if(owner != 1): curs.execute('select name from alist where name = ? and acl = "owner"', [user[0][0]]) if(curs.fetchall()): return(re_error(conn, '/error/3')) if(ip_check() == name): return(re_error(conn, '/error/3')) if(request.method == 'POST'): if(admin_check(conn, 7, 'admin (' + name + ')') != 1): return(re_error(conn, '/error/3')) curs.execute('select name from alist where name = ? and acl = "owner"', [request.forms.select]) if(curs.fetchall()): return(re_error(conn, '/error/3')) if(request.forms.select == 'X'): curs.execute("update user set acl = 'user' where id = ?", [name]) else: curs.execute("update user set acl = ? where id = ?", [request.forms.select, name]) conn.commit() return(redirect('/admin/' + url_pas(name))) else: if(admin_check(conn, 7, None) != 1): return(re_error(conn, '/error/3')) div = '' curs.execute('select distinct name from alist order by name asc') get_alist = curs.fetchall() if(get_alist): i = 0 name_rem = '' for data in get_alist: if(user[0][0] == data[0]): div += '' else: if(owner != 1): curs.execute('select name from alist where name = ? and acl = "owner"', [data[0]]) if(not curs.fetchall()): div += '' else: div += '' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (권한 부여)', 0])], data = '
        \

        \ \
        ', menu = [['manager', '관리자']] ))) @route('/w//r//diff/') def diff_data(name = None, first = None, second = None): curs.execute("select data from history where id = ? and title = ?", [str(first), name]) first_raw_data = curs.fetchall() if(first_raw_data): curs.execute("select data from history where id = ? and title = ?", [str(second), name]) second_raw_data = curs.fetchall() if(second_raw_data): first_data = html.escape(first_raw_data[0][0]) second_data = html.escape(second_raw_data[0][0]) if(first == second): result = '내용이 같습니다.' else: diff_data = difflib.SequenceMatcher(None, first_data, second_data) result = diff(diff_data) return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (비교)', 0])], data = '
        ' + result + '
        ', menu = [['history/' + url_pas(name), '역사']] ))) return(redirect('/history/' + url_pas(name))) @route('/down/') def down(name = None): curs.execute("select title from data where title like ?", ['%' + name + '/%']) under = curs.fetchall() div = '' return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([' (하위)', 0])], data = div, menu = [['w/' + url_pas(name), '문서']] ))) @route('/w/') @route('/w//r/') @route('/w//from/') def read_view(name = None, num = None, redirect = None): data_none = 0 sub = '' acl = '' div = '' topic = 0 if(not num): session = request.environ.get('beaker.session') if(session.get('View_List')): m = re.findall('([^\n]+)\n', session.get('View_List')) if(m[-1] != name): d = re.sub(name + '\n', '', session.get('View_List')) d += name + '\n' if(len(m) > 50): d = re.sub('([^\n]+)\n', '', d, 1) session['View_List'] = d else: session['View_List'] = name + '\n' curs.execute("select sub from rd where title = ? order by date desc", [name]) rd = curs.fetchall() for data in rd: curs.execute("select title from stop where title = ? and sub = ? and close = 'O'", [name, data[0]]) if(not curs.fetchall()): topic = 1 break curs.execute("select title from data where title like ?", ['%' + name + '/%']) if(curs.fetchall()): down = 1 else: down = 0 m = re.search("^(.*)\/(.*)$", name) if(m): uppage = m.groups()[0] else: uppage = 0 if(admin_check(conn, 5, None) == 1): admin_memu = 1 else: admin_memu = 0 if(re.search("^분류:", name)): curs.execute("select link from back where title = ? and type='cat' order by link asc", [name]) back = curs.fetchall() if(back): div = '[목차(없음)]\r\n== 분류 ==\r\n' u_div = '' i = 0 for data in back: if(re.search('^분류:', data[0])): if(u_div == ''): u_div = '=== 하위 분류 ===\r\n' u_div += ' * [[:' + data[0] + ']]\r\n' elif(re.search('^틀:', data[0])): curs.execute("select data from data where title = ?", [data[0]]) d = mid_pas(curs.fetchall()[0][0], 0, 1, 0)[0] if(re.search('\[\[' + name + ']]', d)): div += ' * [[' + data[0] + ']]\r\n * [[wiki:xref/' + url_pas(data[0]) + '|' + data[0] + ']] (역링크)\r\n' else: div += ' * [[' + data[0] + ']]\r\n' else: div += ' * [[' + data[0] + ']]\r\n' div += u_div if(num): curs.execute("select title from hidhi where title = ? and re = ?", [name, str(num)]) hid = curs.fetchall() if(hid and admin_check(conn, 6, None) != 1): return(redirect('/history/' + url_pas(name))) curs.execute("select title, data from history where title = ? and id = ?", [name, str(num)]) else: curs.execute("select acl, data from data where title = ?", [name]) data = curs.fetchall() if(data): if(not num): if(data[0][0] == 'admin'): acl = ' (관리자)' elif(data[0][0] == 'user'): acl = ' (가입자)' else: curs.execute('select data from other where name = "edit"') set_data = curs.fetchall() if(set_data): if(set_data[0][0] == 'admin'): acl = ' (관리자)' elif(set_data[0][0] == 'user'): acl = ' (가입자)' elsedata = data[0][1] else: curs.execute('select data from other where name = "edit"') set_data = curs.fetchall() if(set_data): if(set_data[0][0] == 'admin'): acl = ' (관리자)' elif(set_data[0][0] == 'user'): acl = ' (가입자)' data_none = 1 response.status = 404 elsedata = '' m = re.search("^사용자:([^/]*)", name) if(m): g = m.groups() curs.execute("select acl from user where id = ?", [g[0]]) test = curs.fetchall() if(test and test[0][0] != 'user'): acl = ' (관리자)' else: acl = '' if(data): if(data[0][0] == 'all'): acl += ' (모두)' elif(data[0][0] == 'user'): acl += ' (가입자)' curs.execute("select block from ban where block = ?", [g[0]]) user = curs.fetchall() if(user): sub = ' (차단)' if(redirect): elsedata = re.sub("^#(?:redirect|넘겨주기) (?P[^\n]*)", " * [[\g]] 문서로 넘겨주기", elsedata) enddata = namumark(conn, name, elsedata, 0, 0, 1) if(data_none == 1): menu = [['edit/' + url_pas(name), '생성'], ['topic/' + url_pas(name), topic], ['history/' + url_pas(name), '역사'], ['move/' + url_pas(name), '이동'], ['xref/' + url_pas(name), '역링크']] else: menu = [['edit/' + url_pas(name), '수정'], ['topic/' + url_pas(name), topic], ['history/' + url_pas(name), '역사'], ['delete/' + url_pas(name), '삭제'], ['move/' + url_pas(name), '이동'], ['raw/' + url_pas(name), '원본'], ['xref/' + url_pas(name), '역링크']] if(admin_memu == 1): menu += [['acl/' + url_pas(name), 'ACL']] if(redirect): menu += [['w/' + url_pas(name), '넘기기']] enddata = '
        ' + enddata if(uppage != 0): menu += [['w/' + url_pas(uppage), '상위']] if(down): menu += [['down/' + url_pas(name), '하위']] if(num): menu = [['history/' + url_pas(name), '역사']] sub = ' (' + str(num) + '판)' acl = '' r_date = 0 else: curs.execute("select date from history where title = ? order by date desc limit 1", [name]) date = curs.fetchall() if(date): r_date = date[0][0] else: r_date = 0 return(html_minify(template('index', imp = [name, wiki_set(conn, 1), custom(conn), other2([sub + acl, r_date])], data = enddata + namumark(conn, name, div, 0, 0, 0), menu = menu ))) @route('/topic_record/') @route('/topic_record//') def user_topic_list(name = None, num = 1): if(num * 50 > 0): sql_num = num * 50 - 50 else: sql_num = 0 ydmin = admin_check(conn, 1, None) div = ' \ \ \ \ \ \ ' div = '(편집 기록)

        ' + div curs.execute("select title, id, sub, ip, date from topic where ip = ? order by date desc limit ?, '50'", [name, str(sql_num)]) for data in curs.fetchall(): title = html.escape(data[0]) sub = html.escape(data[2]) if(ydmin == 1): curs.execute("select * from ban where block = ?", [data[3]]) if(curs.fetchall()): ban = ' (해제)' else: ban = ' (차단)' else: ban = '' ip = ip_pas(conn, data[3]) div += ' \ \ \ \ ' div += '
        토론명작성자시간
        \ ' + title + '#' + data[1] + ' (' + sub + ') \ ' + ip + ban + '' + data[4] + '
        ' div += '
        (이전) (이후)' curs.execute("select end, why from ban where block = ?", [name]) ban_it = curs.fetchall() if(ban_it): sub = ' (차단)' else: sub = 0 return(html_minify(template('index', imp = ['토론 기록', wiki_set(conn, 1), custom(conn), other2([sub, 0])], data = div, menu = [['other', '기타'], ['user', '사용자'], ['count/' + url_pas(name), '횟수']] ))) @route('/upload', method=['GET', 'POST']) def upload(): if(ban_check(conn) == 1): return(re_error(conn, '/ban')) if(request.method == 'POST'): data = request.files.f_data if(not data): return(re_error(conn, '/error/9')) if(int(wiki_set(conn, 3)) * 1024 * 1024 < request.content_length): return(re_error(conn, '/error/17')) value = os.path.splitext(data.filename)[1] if(not value): return(re_error(conn, '/error/16')) if(not value in ['.jpeg', '.jpg', '.gif', '.png', '.webp', '.JPEG', '.JPG', '.GIF', '.PNG', '.WEBP']): return(re_error(conn, '/error/14')) if(request.forms.get('f_name')): name = request.forms.get('f_name') + value else: name = data.filename piece = os.path.splitext(name) e_data = sha224(piece[0]) + piece[1] ip = ip_check() if(request.forms.get('f_lice')): lice = request.forms.get('f_lice') else: if(re.search('(?:\.|:)', ip)): lice = ip + ' 올림' else: lice = '[[사용자:' + ip + ']] 올림' if(os.path.exists(os.path.join('image', e_data))): return(re_error(conn, '/error/16')) data.save(os.path.join('image', e_data)) curs.execute("select title from data where title = ?", ['파일:' + name]) exist = curs.fetchall() if(exist): curs.execute("delete from data where title = ?", ['파일:' + name]) curs.execute("insert into data (title, data, acl) values (?, ?, 'admin')", ['파일:' + name, '[[파일:' + name + ']][br][br]{{{[[파일:' + name + ']]}}}[br][br]' + lice]) history_plus(conn, '파일:' + name, '[[파일:' + name + ']][br][br]{{{[[파일:' + name + ']]}}}[br][br]' + lice, get_time(), ip, '(파일 올림)', '0') conn.commit() return(redirect('/w/파일:' + name)) else: return(html_minify(template('index', imp = ['파일 올리기', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = '
        \

        \

        \

        \ \
        ', menu = [['other', '기타']] ))) @route('/user') def user_info(): ip = ip_check() raw_ip = ip curs.execute("select acl from user where id = ?", [ip]) data = curs.fetchall() if(ban_check(conn) == 0): if(data): if(data[0][0] != 'user'): acl = data[0][0] else: acl = '가입자' else: acl = '일반' else: acl = '차단' curs.execute("select ip from ok_login where ip = ?", [ip]) if(curs.fetchall()): acl += ' (로그인 가능)' ip = ip_pas(conn, ip) custom_data = custom(conn) if(custom_data[2] != 0): plus = ' * [[wiki:logout|로그아웃]]\r\n * [[wiki:change|비밀번호 변경]]' else: plus = ' * [[wiki:login|로그인]]' return(html_minify(template('index', imp = ['사용자 메뉴', wiki_set(conn, 1), custom_data, other2([0, 0])], data = ip + '

        ' + namumark(conn, '', '권한 상태 : ' + acl + '\r\n' + \ '[목차(없음)]\r\n' + \ '== 로그인 ==\r\n' + \ plus + '\r\n' + \ ' * [[wiki:register|회원가입]]\r\n' + \ '== 사용자 기능 ==\r\n' + \ ' * [[wiki:user_acl/' + url_pas(raw_ip) + '|사용자 문서 ACL]]\r\n' + \ ' * [[wiki:custom_head|사용자 HEAD]]\r\n' + \ '== 기타 ==\r\n' + \ ' * [[wiki:alarm|알림]]\r\n' + \ ' * [[wiki:view_log|지나온 문서]]\r\n' + \ ' * [[wiki:record/' + raw_ip + '|편집 기록]]\r\n' + \ ' * [[wiki:topic_record/' + raw_ip + '|토론 기록]]\r\n' + \ ' * [[wiki:count|편집 횟수]]\r\n', 0, 0, 0), menu = 0 ))) @route('/view_log') def view_log(): session = request.environ.get('beaker.session') data = '
          ' if(session.get('View_List')): data += '
        • 최근 50개


        • ' m = re.findall('([^\n]+)\n', session.get('View_List')) for d in m: data += '
        • ' + d + '
        • ' else: data += '
        • 기록 없음
        • ' data += '
        ' return(html_minify(template('index', imp = ['지나온 문서', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = data, menu = [['user', '사용자']] ))) @route('/custom_head', method=['GET', 'POST']) def custom_head_view(): session = request.environ.get('beaker.session') ip = ip_check() if(request.method == 'POST'): if(not re.search('(\.|:)', ip)): curs.execute("select user from custom where user = ?", [ip + ' (head)']) if(curs.fetchall()): curs.execute("update custom set css = ? where user = ?", [request.forms.content, ip + ' (head)']) else: curs.execute("insert into custom (user, css) values (?, ?)", [ip + ' (head)', request.forms.content]) conn.commit() session['MyMaiToNight'] = request.forms.content return(redirect('/user')) else: if(not re.search('(\.|:)', ip)): start = '' curs.execute("select css from custom where user = ?", [ip + ' (head)']) head_data = curs.fetchall() if(head_data): data = head_data[0][0] else: data = '' else: start = '비 로그인의 경우에는 로그인하거나 브라우저 닫으면 날아갑니다.

        ' try: data = session['MyMaiToNight'] except: data = '' start += '<style>CSS</style>
        <script>JS</script>


        ' return(html_minify(template('index', imp = ['사용자 HEAD', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = start + ' \
        \

        \ \
        ', menu = [['user', '사용자']] ))) @route('/count') @route('/count/') def count_edit(name = None): if(name == None): that = ip_check() else: that = name curs.execute("select count(title) from history where ip = ?", [that]) count = curs.fetchall() if(count): data = count[0][0] else: data = 0 curs.execute("select count(title) from topic where ip = ?", [that]) count = curs.fetchall() if(count): t_data = count[0][0] else: t_data = 0 return(html_minify(template('index', imp = ['활동 횟수', wiki_set(conn, 1), custom(conn), other2([0, 0])], data = namumark(conn, "", "||<-2><:> " + that + " ||\r\n||<:> 편집 횟수 ||<:> " + str(data) + "||\r\n||<:> 토론 횟수 ||<:> " + str(t_data) + "||", 0, 0, 0), menu = [['user', '사용자'], ['record/' + url_pas(that), '편집 기록'], ['topic_record/' + url_pas(that), '토론 기록']] ))) @route('/random') def random(): curs.execute("select title from data order by random() limit 1") d = curs.fetchall() if(d): return(redirect('/w/' + url_pas(d[0][0]))) else: return(redirect('/')) @route('/views/') def views(name = None): if(re.search('\/', name)): m = re.search('^(.*)\/(.*)$', name) if(m): n = m.groups() plus = '/' + n[0] rename = n[1] else: plus = '' rename = name else: plus = '' rename = name m = re.search('\.(.+)$', name) if(m): g = m.groups() else: g = [''] if(g == 'css'): return(css_minify(static_file(rename, root = './views' + plus))) elif(g == 'js'): return(js_minify(static_file(rename, root = './views' + plus))) elif(g == 'html'): return(html_minify(static_file(rename, root = './views' + plus))) else: return(static_file(rename, root = './views' + plus)) @route('/robots.txt') def random(): curs.execute("select data from other where name = 'robot'") d = curs.fetchall() if(d): return('
        ' + d[0][0] + '
        ') else: return('') @error(404) def error_404(error): try: curs.execute("select title from data limit 1") return('' + redirect('/w/' + url_pas(wiki_set(conn, 2)))) except: return('' + redirect('/setup')) @error(500) def error_500(error): try: curs.execute("select title from data limit 1") return('' + error) except: return('' + redirect('/setup')) run(app = app, server = 'tornado', host = '0.0.0.0', port = int(set_data['port']), debug = True)