Explorar el Código

Merge pull request #1234 from openNAMU/dev

Dev
잉여개발기 (SPDV) hace 4 años
padre
commit
ce4ff81510

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 BSD 3-Clause License
 
-Copyright (c) 2017-2019, 2DU
+Copyright (c) 2017-2021, surplus-dev
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without

+ 341 - 193
app.py

@@ -125,78 +125,69 @@ if data_db_set['type'] == 'mysql':
 
 db_data_get(data_db_set['type'])
 conn = get_conn(data_db_set)
-load_conn(conn)
 curs = conn.cursor()
 
-# Init-Create_DB
-create_data = {}
-
-# 폐지 예정 (data_set으로 통합)
-create_data['data'] = ['title', 'data', 'type']
-create_data['history'] = ['id', 'title', 'data', 'date', 'ip', 'send', 'leng', 'hide', 'type']
-create_data['rc'] = ['id', 'title', 'date', 'type']
-create_data['acl'] = ['title', 'data', 'type']
-
-# 개편 예정 (data_link로 변경)
-create_data['back'] = ['title', 'link', 'type']
-
-# 폐지 예정 (topic_set으로 통합) [가장 시급]
-create_data['rd'] = ['title', 'sub', 'code', 'date', 'band', 'stop', 'agree', 'acl']
-create_data['topic'] = ['id', 'data', 'date', 'ip', 'block', 'top', 'code']
-
-# 폐지 예정 (user_set으로 통합)
-create_data['rb'] = ['block', 'end', 'today', 'blocker', 'why', 'band', 'login', 'ongoing']
-create_data['scan'] = ['user', 'title', 'type']
-
-# 개편 예정 (wiki_set과 wiki_filter과 wiki_vote으로 변경)
-create_data['other'] = ['name', 'data', 'coverage']
-create_data['html_filter'] = ['html', 'kind', 'plus', 'plus_t']
-create_data['vote'] = ['name', 'id', 'subject', 'data', 'user', 'type', 'acl']
-
-# 개편 예정 (auth_list와 auth_log로 변경)
-create_data['alist'] = ['name', 'acl']
-create_data['re_admin'] = ['who', 'what', 'time']
-
-# 개편 예정 (user_notice와 user_agent로 변경)
-create_data['alarm'] = ['name', 'data', 'date']
-create_data['ua_d'] = ['name', 'ip', 'ua', 'today', 'sub']
-
-create_data['user_set'] = ['name', 'id', 'data']
-for create_table in create_data:
-    try:
-        curs.execute(db_change('select test from ' + create_table + ' limit 1'))
-    except:
-        try:
-            curs.execute(db_change('create table ' + create_table + '(test longtext)'))
-        except:
-            curs.execute(db_change("alter table " + create_table + " add test longtext"))
-            
-    for create in create_data[create_table]:
-        try:
-            curs.execute(db_change(
-                'select ' + create + ' from ' + create_table + ' limit 1'
-            ))
-        except:
+setup_tool = ''
+try:
+    curs.execute(db_change('select data from other where name = "ver"'))
+except:
+    setup_tool = 'init'
+    
+if setup_tool != 'init':
+    ver_set_data = curs.fetchall()
+    if ver_set_data:
+        if int(version_list['beta']['c_ver']) > int(ver_set_data[0][0]):
+            setup_tool = 'update'
+        else:
+            setup_tool = 'normal'
+    else:
+        setup_tool = 'init'
+    
+if setup_tool != 'normal':
+    # Init-Create_DB
+    create_data = {}
+
+    # 폐지 예정 (data_set으로 통합)
+    create_data['data'] = ['title', 'data', 'type']
+    create_data['history'] = ['id', 'title', 'data', 'date', 'ip', 'send', 'leng', 'hide', 'type']
+    create_data['rc'] = ['id', 'title', 'date', 'type']
+    create_data['acl'] = ['title', 'data', 'type']
+
+    # 개편 예정 (data_link로 변경)
+    create_data['back'] = ['title', 'link', 'type']
+
+    # 폐지 예정 (topic_set으로 통합) [가장 시급]
+    create_data['rd'] = ['title', 'sub', 'code', 'date', 'band', 'stop', 'agree', 'acl']
+    create_data['topic'] = ['id', 'data', 'date', 'ip', 'block', 'top', 'code']
+
+    # 폐지 예정 (user_set으로 통합)
+    create_data['rb'] = ['block', 'end', 'today', 'blocker', 'why', 'band', 'login', 'ongoing']
+    create_data['scan'] = ['user', 'title', 'type']
+
+    # 개편 예정 (wiki_set과 wiki_filter과 wiki_vote으로 변경)
+    create_data['other'] = ['name', 'data', 'coverage']
+    create_data['html_filter'] = ['html', 'kind', 'plus', 'plus_t']
+    create_data['vote'] = ['name', 'id', 'subject', 'data', 'user', 'type', 'acl']
+
+    # 개편 예정 (auth_list와 auth_log로 변경)
+    create_data['alist'] = ['name', 'acl']
+    create_data['re_admin'] = ['who', 'what', 'time']
+
+    # 개편 예정 (user_notice와 user_agent로 변경)
+    create_data['alarm'] = ['name', 'data', 'date']
+    create_data['ua_d'] = ['name', 'ip', 'ua', 'today', 'sub']
+
+    create_data['user_set'] = ['name', 'id', 'data']
+    for create_table in create_data:
+        for create in ['test'] + create_data[create_table]:
             try:
-                curs.execute(db_change(
-                    "alter table " + create_table + " add " + create + " longtext default ''"
-                ))
+                curs.execute(db_change('select ' + create + ' from ' + create_table + ' limit 1'))
             except:
-                curs.execute(db_change(
-                    "alter table " + create_table + " add " + create + " longtext"
-                ))
-
-curs.execute(db_change('select data from other where name = "ver"'))
-ver_set_data = curs.fetchall()
-if ver_set_data:
-    if int(version_list['beta']['c_ver']) > int(ver_set_data[0][0]):
-        setup_tool = 'update'
-    else:
-        setup_tool = 'normal'
-else:
-    setup_tool = 'init'
+                try:
+                    curs.execute(db_change('create table ' + create_table + '(test longtext default "")'))
+                except:
+                    curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext default ''"))
 
-if setup_tool != 'normal':
     if setup_tool == 'update':
         update(int(ver_set_data[0][0]), set_data)
     else:
@@ -207,7 +198,7 @@ set_init_always(version_list['beta']['c_ver'])
 # Init-Route
 class EverythingConverter(werkzeug.routing.PathConverter):
     regex = '.*?'
-
+    
 class RegexConverter(werkzeug.routing.BaseConverter):
     def __init__(self, url_map, *items):
         super(RegexConverter, self).__init__(url_map)
@@ -232,24 +223,65 @@ app.secret_key = sql_data[0][0]
 print('----')
 
 # Init-DB_Data
-dislay_set_key = ['Host', 'Port', 'Language', 'Markup', 'Encryption method']
-server_set_key = ['host', 'port', 'language', 'markup', 'encode']
 server_set = {}
-
-server_init = server_init()
-for i in range(len(server_set_key)):
-    curs.execute(db_change('select data from other where name = ?'), [server_set_key[i]])
+server_set_var = {
+    'host' : {
+        'display' : 'Host',
+        'require' : 'conv',
+        'default' : '0.0.0.0'
+    }, 'port' : {
+        'display' : 'Port',
+        'require' : 'conv',
+        'default' : '3000'
+    }, 'language' : {
+        'display' : 'Language',
+        'require' : 'select',
+        'default' : 'ko-KR',
+        'list' : ['ko-KR', 'en-US']
+    }, 'markup' : {
+        'display' : 'Markup',
+        'require' : 'select',
+        'default' : 'namumark',
+        'list' : ['namumark', 'custom', 'raw']
+    }, 'encode' : {
+        'display' : 'Encryption method',
+        'require' : 'select',
+        'default' : 'sha3',
+        'list' : ['sha3', 'sha256']
+    }
+}
+server_set_env = {
+    'host' : os.getenv('NAMU_HOST'),
+    'port' : os.getenv('NAMU_PORT'),
+    'language' : os.getenv('NAMU_LANG'),
+    'markup' : os.getenv('NAMU_MARKUP'),
+    'encode' : os.getenv('NAMU_ENCRYPT')
+}
+for i in server_set_var:
+    curs.execute(db_change('select data from other where name = ?'), [i])
     server_set_val = curs.fetchall()
-    if not server_set_val:
-        server_set_val = server_init.init(server_set_key[i])
-
-        curs.execute(db_change('insert into other (name, data) values (?, ?)'), [server_set_key[i], server_set_val])
-    else:
+    if server_set_val:
         server_set_val = server_set_val[0][0]
-
-    print(dislay_set_key[i] + ' : ' + server_set_val)
-
-    server_set[server_set_key[i]] = server_set_val
+    elif server_set_env[i] != None:
+        server_set_val = server_set_env[i]
+    else:
+        if 'list' in server_set_var[i]:
+            print(server_set_var[i]['display'] + ' (' + server_set_var[i]['default'] + ') [' + ', '.join(server_set_var[i]['list']) + ']' + ' : ', end = '')
+        else:
+            print(server_set_var[i]['display'] + ' (' + server_set_var[i]['default'] + ') : ', end = '')
+            
+        server_set_val = input()
+        if server_set_val == '':
+            server_set_val = server_set_var[i]['default']
+        elif server_set_var[i]['require'] == 'select':
+            if not server_set_val in server_set_var[i]['list']:
+                server_set_val = server_set_var[i]['default']
+                
+        curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, server_set_val])
+        
+    print(server_set_var[i]['display'] + ' : ' + server_set_val)
+    
+    server_set[i] = server_set_val
 
 print('----')
     
@@ -307,138 +339,189 @@ else:
 
 print('Now running... http://localhost:' + server_set['port'])
 conn.commit()
+conn.close()
 
+conn = get_conn()
+
+# Init-custom
 if os.path.exists('custom.py'):
     from custom import custom_run
 
     custom_run(conn, app)
-
-# alarm과 watch_list의 user 편입
-
+    
 # Func
 # Func-inter_wiki
+@app.route('/inter_wiki')
+def inter_wiki():
+    return inter_wiki_2(conn, 'inter_wiki')
+
+@app.route('/inter_wiki/del/<name>')
+def inter_wiki_del(name = 'Test'):
+    return inter_wiki_del_2(conn, 'del_inter_wiki', name)
 
-# 개편 필요
-@app.route('/<regex("inter_wiki"):tools>')
-@app.route('/<regex("edit_top"):tools>')
-@app.route('/<regex("image_license"):tools>')
-@app.route('/<regex("(?:edit|email|file|name|extension)_filter"):tools>')
-def inter_wiki(tools = None):
-    return inter_wiki_2(conn, tools)
+@app.route('/edit_top')
+def inter_wiki_edit_top():
+    return inter_wiki_2(conn, 'edit_top')
 
-@app.route('/<regex("del_(?:inter_wiki|edit_top|image_license|(?:edit|email|file|name|extension)_filter)"):tools>/<name>')
-def inter_wiki_del(tools = None, name = None):
-    return inter_wiki_del_2(conn, tools, name)
+@app.route('/edit_top/del/<name>')
+def inter_wiki_edit_top_del(name = 'Test'):
+    return inter_wiki_del_2(conn, 'del_edit_top', name)
 
-@app.route('/<regex("plus_(?:inter_wiki|edit_top|image_license|(?:edit|email|file|name|extension)_filter)"):tools>', methods = ['POST', 'GET'])
-@app.route('/<regex("plus_(?:inter_wiki|edit_top|image_license|(?:edit|email|file|name|extension)_filter)"):tools>/<name>', methods = ['POST', 'GET'])
+@app.route('/image_license')
+def inter_wiki_image_license():
+    return inter_wiki_2(conn, 'image_license')
+
+@app.route('/image_license/del/<name>')
+def inter_wiki_image_license_del(name = 'Test'):
+    return inter_wiki_del_2(conn, 'del_image_license', name)
+
+@app.route('/edit_filter')
+def inter_wiki_edit_filter():
+    return inter_wiki_2(conn, 'edit_filter')
+
+@app.route('/edit_filter/del/<name>')
+def inter_wiki_edit_filter_del(name = 'Test'):
+    return inter_wiki_del_2(conn, 'del_edit_filter', name)
+
+@app.route('/email_filter')
+def inter_wiki_email_filter():
+    return inter_wiki_2(conn, 'email_filter')
+
+@app.route('/email_filter/del/<name>')
+def inter_wiki_email_filter_del(name = 'Test'):
+    return inter_wiki_del_2(conn, 'del_email_filter', name)
+
+@app.route('/file_filter')
+def inter_wiki_file_filter():
+    return inter_wiki_2(conn, 'file_filter')
+
+@app.route('/file_filter/del/<name>')
+def inter_wiki_file_filter_del(name = 'Test'):
+    return inter_wiki_del_2(conn, 'del_file_filter', name)
+
+@app.route('/name_filter')
+def inter_wiki_name_filter():
+    return inter_wiki_2(conn, 'name_filter')
+
+@app.route('/name_filter/del/<name>')
+def inter_wiki_name_filter_del(name = 'Test'):
+    return inter_wiki_del_2(conn, 'del_name_filter', name)
+
+@app.route('/extension_filter')
+def inter_wiki_extension_filter():
+    return inter_wiki_2(conn, 'extension_filter')
+
+@app.route('/extension_filter/del/<name>')
+def inter_wiki_extension_filter_del(name = 'Test'):
+    return inter_wiki_del_2(conn, 'del_extension_filter', name)
+
+@app.route('/<regex("(?:inter_wiki|edit_top|image_license|(?:edit|email|file|name|extension)_filter)"):tools>/add', methods = ['POST', 'GET'])
+@app.route('/<regex("(?:inter_wiki|edit_top|image_license|(?:edit|email|file|name|extension)_filter)"):tools>/add/<name>', methods = ['POST', 'GET'])
 def inter_wiki_plus(tools = None, name = None):
-    return inter_wiki_plus_2(conn, tools, name)
+    return inter_wiki_plus_2(conn, 'plus_' + tools, name)
 
 # Func-list
+# /list/topic/open
 @app.route('/not_close_topic')
 def list_not_close_topic():
     return list_not_close_topic_2(conn)
 
+# /list/document/old
 @app.route('/old_page')
 def list_old_page():
     return list_old_page_2(conn)
 
+# /list/document/acl
 @app.route('/acl_list')
 def list_acl():
     return list_acl_2(conn)
 
+# /list/document/acl/add
+@app.route('/acl/<everything:name>', methods = ['POST', 'GET'])
+def give_acl(name = None):
+    return give_acl_2(conn, name)
+
+# /list/document/need
+@app.route('/please')
+def list_please():
+    return list_please_2(conn)
+
+# /list/document/all
+@app.route('/title_index')
+def list_title_index():
+    return list_title_index_2(conn)
+
+# /list/document/long
+@app.route('/long_page')
+def list_long_page():
+    return list_long_page_2(conn, 'long_page')
+
+# /list/document/short
+@app.route('/short_page')
+def list_short_page():
+    return list_long_page_2(conn, 'short_page')
+
+# /list/file
 @app.route('/image_file_list')
 def list_image_file():
     return list_image_file_2(conn)
 
+# /list/admin
+# /list/admin/list
 @app.route('/admin_list')
 def list_admin():
     return list_admin_2(conn)
 
-@app.route('/user_log')
-def list_user():
-    return list_user_2(conn)
-
+# /list/admin/auth_use
 @app.route('/admin_log', methods = ['POST', 'GET'])
 def list_admin_use():
     return list_admin_use_2(conn)
 
-@app.route('/admin_group')
-def list_admin_group():
-    return list_admin_group_2(conn)
-
-@app.route('/please')
-def list_please():
-    return list_please_2(conn)
-
-@app.route('/title_index')
-def list_title_index():
-    return list_title_index_2(conn)
-
-@app.route('/<regex("long_page"):tool>')
-@app.route('/<regex("short_page"):tool>')
-def list_long_page(tool = 'long_page'):
-    return list_long_page_2(conn, tool)
-
-# Func-give
-@app.route('/admin_plus/<name>', methods = ['POST', 'GET'])
-def give_admin_groups(name = None):
-    return give_admin_groups_2(conn, name)
-
-# 다듬어야할 듯
-@app.route('/delete_admin_group/<name>', methods = ['POST', 'GET'])
-def give_delete_admin_group(name = None):
-    return give_delete_admin_group_2(conn, name)
+# /list/user
+@app.route('/user_log')
+def list_user():
+    return list_user_2(conn)
 
+# /list/user/check
 @app.route('/check/<name>')
 def give_user_check(name = None):
     return give_user_check_2(conn, name)
     
+# /list/user/check/delete
 @app.route('/check_delete', methods = ['POST', 'GET'])
 def give_user_check_delete():
     return give_user_check_delete_2(conn)
 
-@app.route('/ban', methods = ['POST', 'GET'])
-@app.route('/ban/<name>', methods = ['POST', 'GET'])
-def give_user_ban(name = None):
-    return give_user_ban_2(conn, name)
-
-@app.route('/acl/<everything:name>', methods = ['POST', 'GET'])
-def give_acl(name = None):
-    return give_acl_2(conn, name)
-
+# Func-auth
+# /auth/give
+# /auth/give/<name>
 @app.route('/admin/<name>', methods = ['POST', 'GET'])
 def give_admin(name = None):
     return give_admin_2(conn, name)
 
-# Func-view
-@app.route('/xref/<everything:name>')
-def view_xref(name = None):
-    return view_xref_2(conn, name)
-
-@app.route('/raw/<everything:name>')
-@app.route('/thread/<int:topic_num>/raw/<int:num>')
-def view_raw(name = None, topic_num = None, num = None):
-    return view_raw_2(conn, name, topic_num, num)
-
-@app.route('/diff/<everything:name>')
-def view_diff_data(name = None):
-    return view_diff_data_2(conn, name)
+# /auth/give
+# /auth/give/<name>
+@app.route('/ban', methods = ['POST', 'GET'])
+@app.route('/ban/<name>', methods = ['POST', 'GET'])
+def give_user_ban(name = None):
+    return give_user_ban_2(conn, name)
 
-@app.route('/down/<everything:name>')
-def view_down(name = None):
-    return view_down_2(conn, name)
+# /auth/list
+@app.route('/admin_group')
+def list_admin_group():
+    return list_admin_group_2(conn)
 
-@app.route('/w/<everything:name>')
-def view_read(name = None):
-    return view_read_2(conn, name)
+# /auth/list/add/<name>
+@app.route('/admin_plus/<name>', methods = ['POST', 'GET'])
+def give_admin_groups(name = None):
+    return give_admin_groups_2(conn, name)
 
-# Func-recent
-@app.route('/recent_discuss')
-def recent_discuss():
-    return recent_discuss_2(conn)
+# /auth/list/delete/<name>
+@app.route('/delete_admin_group/<name>', methods = ['POST', 'GET'])
+def give_delete_admin_group(name = None):
+    return give_delete_admin_group_2(conn, name)
 
+# /auth/history
 # ongoing 반영 필요
 @app.route('/block_log')
 @app.route('/block_log/<regex("user"):tool>/<name>')
@@ -446,7 +529,7 @@ def recent_discuss():
 def recent_block(name = 'Test', tool = 'all'):
     return recent_block_2(conn, name, tool)
 
-# 이 쪽 분리 필요
+# Func-history
 @app.route('/recent_change')
 @app.route('/recent_changes')
 def recent_change(name = None):
@@ -492,6 +575,7 @@ def recent_record_reset(name = 'Test'):
 def recent_record_topic(name = 'Test'):
     return recent_record_topic_2(conn, name)
 
+# 거처를 고심중
 @app.route('/app_submit', methods = ['POST', 'GET'])
 def recent_app_submit():
     return recent_app_submit_2(conn)
@@ -510,6 +594,30 @@ def search_goto(name = 'test'):
 def search_deep(name = 'test'):
     return search_deep_2(conn, name)
 
+# Func-view
+@app.route('/xref/<everything:name>')
+def view_xref(name = None):
+    return view_xref_2(conn, name)
+
+@app.route('/raw/<everything:name>')
+@app.route('/thread/<int:topic_num>/raw/<int:num>')
+def view_raw(name = None, topic_num = None, num = None):
+    return view_raw_2(conn, name, topic_num, num)
+
+@app.route('/diff/<int:num_a>/<int:num_b>/<everything:name>')
+def view_diff(name = 'Test', num_a = 1, num_b = 1):
+    return view_diff_2(conn, name, num_a, num_b)
+
+@app.route('/down/<everything:name>')
+def view_down(name = None):
+    return view_down_2(conn, name)
+
+@app.route('/w/<everything:name>/doc_rev/<int:doc_rev>')
+@app.route('/w/<everything:name>/doc_from/<everything:doc_from>')
+@app.route('/w/<everything:name>')
+def view_read(name = 'Test', doc_rev = 0, doc_from = ''):
+    return view_read_2(conn, name, doc_rev, doc_from)
+
 # Func-edit
 @app.route('/revert/<everything:name>', methods = ['POST', 'GET'])
 def edit_revert(name = None):
@@ -537,6 +645,10 @@ def edit_move(name = None):
     return edit_move_2(conn, name)
 
 # Func-topic
+@app.route('/recent_discuss')
+def recent_discuss():
+    return recent_discuss_2(conn)
+
 @app.route('/thread/<int:topic_num>/b/<int:num>')
 def topic_block(topic_num = 1, num = 1):
     return topic_block_2(conn, topic_num, num)
@@ -578,13 +690,9 @@ def topic_close_list(name = 'test'):
     return topic_close_list_2(conn, name)
 
 # Func-user
-@app.route('/tool/<name>')
-def user_tool(name = None):
-    return user_tool_2(conn, name)
-
 @app.route('/change', methods = ['POST', 'GET'])
 def user_setting():
-    return user_setting_2(conn, server_init)
+    return user_setting_2(conn, server_set_var)
 
 @app.route('/change/email', methods = ['POST', 'GET'])
 def user_setting_email():
@@ -599,8 +707,9 @@ def user_setting_pw_change():
     return user_setting_pw_change_2(conn)
 
 @app.route('/user')
-def user_info():
-    return user_info_2(conn)
+@app.route('/user/<name>')
+def user_info(name = ''):
+    return user_info_2(conn, name)
 
 @app.route('/custom_head', methods=['GET', 'POST'])
 def user_custom_head_view():
@@ -612,20 +721,28 @@ def user_count_edit(name = None):
     return user_count_edit_2(conn, name)
     
 @app.route('/alarm')
-def alarm():
-    return alarm_2(conn)
+def user_alarm():
+    return user_alarm_2(conn)
 
 @app.route('/alarm/delete')
-def alarm_del():
-    return alarm_del_2(conn)
+def user_alarm_del():
+    return user_alarm_del_2(conn)
     
-@app.route('/<regex("watch_list|star_doc"):tool>')
-def watch_list(tool = 'star_doc'):
-    return watch_list_2(conn, tool)
+@app.route('/watch_list')
+def user_watch_list():
+    return user_watch_list_2(conn, 'watch_list')
+
+@app.route('/watch_list/<everything:name>')
+def user_watch_list_name(name = 'Test'):
+    return user_watch_list_name_2(conn, 'watch_list', name)
 
-@app.route('/<regex("watch_list|star_doc"):tool>/<everything:name>')
-def watch_list_name(tool = 'star_doc', name = 'Test'):
-    return watch_list_name_2(conn, tool, name)
+@app.route('/star_doc')
+def user_star_doc():
+    return user_watch_list_2(conn, 'star_doc')
+
+@app.route('/star_doc/<everything:name>')
+def user_star_doc_name(name = 'Test'):
+    return user_watch_list_name_2(conn, 'star_doc', name)
 
 # Func-login
 # 개편 예정
@@ -679,23 +796,30 @@ def login_logout():
     return login_logout_2(conn)
 
 # Func-vote
-@app.route('/vote/<num>', methods = ['POST', 'GET'])
-def vote_select(num = '1'):
-    return vote_select_2(conn, num)
+@app.route('/vote/<int:num>', methods = ['POST', 'GET'])
+def vote_select(num = 1):
+    return vote_select_2(conn, str(num))
 
-@app.route('/end_vote/<num>')
-def vote_end(num = '1'):
-    return vote_end_2(conn, num)
+@app.route('/vote/end/<int:num>')
+def vote_end(num = 1):
+    return vote_end_2(conn, str(num))
 
-@app.route('/close_vote/<num>')
-def vote_close(num = '1'):
-    return vote_close_2(conn, num)
+@app.route('/vote/close/<int:num>')
+def vote_close(num = 1):
+    return vote_close_2(conn, str(num))
 
 @app.route('/vote')
-def vote():
-    return vote_2(conn)
+@app.route('/vote/list')
+@app.route('/vote/list/<int:num>')
+def vote_list(num = 1):
+    return vote_list_2(conn, 'normal', num)
+
+@app.route('/vote/list/close')
+@app.route('/vote/list/close/<int:num>')
+def vote_list_close(num = 1):
+    return vote_list_2(conn, 'close', num)
 
-@app.route('/add_vote', methods = ['POST', 'GET'])
+@app.route('/vote/add', methods = ['POST', 'GET'])
 def vote_add():
     return vote_add_2(conn)
 
@@ -710,7 +834,11 @@ def api_raw(name = ''):
 
 @app.route('/api/version')
 def api_version():
-    return api_version_2(conn, version_list['beta']['r_ver'], version_list['beta']['c_ver'])
+    return api_version_2(
+        conn, 
+        version_list['beta']['r_ver'], 
+        version_list['beta']['c_ver']
+    )
 
 @app.route('/api/skin_info')
 @app.route('/api/skin_info/<name>')
@@ -737,6 +865,21 @@ def api_search(name = ''):
 def api_recent_change():
     return api_recent_change_2(conn)
 
+@app.route('/api/recent_discuss')
+@app.route('/api/recent_discuss/<int:num>')
+def api_recent_discuss(num = 10):
+    return api_recent_discuss_2(conn, num, 'normal')
+
+@app.route('/api/recent_discuss/stop')
+@app.route('/api/recent_discuss/<int:num>/stop')
+def api_recent_discuss_stop(num = 10):
+    return api_recent_discuss_2(conn, num, 'stop')
+
+@app.route('/api/recent_discuss/all')
+@app.route('/api/recent_discuss/<int:num>/all')
+def api_recent_discuss_all(num = 10):
+    return api_recent_discuss_2(conn, num, 'all')
+
 @app.route('/api/sha224/<everything:name>', methods = ['POST', 'GET'])
 def api_sha224(name = 'test'):
     return api_sha224_2(conn, name)
@@ -754,6 +897,7 @@ def api_sitemap():
     return api_sitemap_2(conn)
 
 # Func-main
+# 여기도 전반적인 조정 시행 예정
 @app.route('/restart', methods = ['POST', 'GET'])
 def main_restart():
     return main_restart_2(conn)
@@ -782,7 +926,11 @@ def main_other():
 @app.route('/manager', methods = ['POST', 'GET'])
 @app.route('/manager/<int:num>', methods = ['POST', 'GET'])
 def main_manager(num = 1):
-    return main_manager_2(conn, num, version_list['beta']['r_ver'])
+    return main_manager_2(
+        conn, 
+        num, 
+        version_list['beta']['r_ver']
+    )
 
 @app.route('/image/<everything:name>')
 def main_image_view(name = None):

+ 35 - 29
emergency_tool.py

@@ -12,7 +12,10 @@ if data_db_load == 'Y':
     # Init-DB
     if os.path.exists(os.path.join('data', 'set.json')):
         db_set_list = ['db', 'db_type']
-        set_data = json.loads(open(os.path.join('data', 'set.json'), encoding = 'utf8').read())
+        set_data = json.loads(open(
+            os.path.join('data', 'set.json'), 
+            encoding = 'utf8'
+        ).read())
         for i in db_set_list:
             if not i in set_data:
                 print('Please delete set.json')
@@ -65,15 +68,19 @@ if data_db_load == 'Y':
         with open(os.path.join('data', 'set.json'), 'w', encoding = 'utf8') as f:
             f.write(json.dumps(set_data))
 
-    db_data_get(set_data['db_type'])
+    data_db_set = {}
+    data_db_set['name'] = set_data['db']
+    data_db_set['type'] = set_data['db_type']
 
-    if set_data['db_type'] == 'mysql':
+    if data_db_set['type'] == 'mysql':
         if not os.path.exists(os.path.join('data', 'mysql.json')):
             db_set_list = ['user', 'password', 'host', 'port']
-            set_data = json.loads(open(
-                os.path.join('data', 'mysql.json'), 
-                encoding = 'utf8'
-            ).read())
+            set_data = json.loads(
+                open(
+                    os.path.join('data', 'mysql.json'),
+                    encoding = 'utf8'
+                ).read()
+            )
             for i in db_set_list:
                 if not i in set_data:
                     print('Please delete mysql.json')
@@ -96,29 +103,28 @@ if data_db_load == 'Y':
             if set_data_mysql['port'] == '':
                 set_data_mysql['port'] = '3306'
 
-            with open(os.path.join('data', 'mysql.json'), 'w', encoding = 'utf8') as f:
+            with open(
+                os.path.join('data', 'mysql.json'), 
+                'w', 
+                encoding = 'utf8'
+            ) as f:
                 f.write(json.dumps(set_data_mysql))
 
-        conn = pymysql.connect(
-            host = set_data_mysql['host'] if 'host' in set_data_mysql else 'localhost',
-            user = set_data_mysql['user'],
-            password = set_data_mysql['password'],
-            charset = 'utf8mb4',
-            port = int(set_data_mysql['port']) if 'port' in set_data_mysql else 3306
-        )
-        curs = conn.cursor()
-
-        try:
-            curs.execute(db_change('create database ' + set_data['db'] + ' default character set utf8mb4;'))
-        except:
-            pass
-
-        conn.select_db(set_data['db'])
-    else:
-        conn = sqlite3.connect(set_data['db'] + '.db')
-        curs = conn.cursor()
+        data_db_set['mysql_user'] = set_data_mysql['user']
+        data_db_set['mysql_pw'] = set_data_mysql['password']
+        if 'host' in set_data_mysql:
+            data_db_set['mysql_host'] = set_data_mysql['host']
+        else:
+            data_db_set['mysql_host'] = 'localhost'
+
+        if 'port' in set_data_mysql:
+            data_db_set['mysql_port'] = set_data_mysql['port']
+        else:
+            data_db_set['mysql_port'] = '3306'
 
-    load_conn(conn)
+    db_data_get(data_db_set['type'])
+    conn = get_conn(data_db_set)
+    curs = conn.cursor()
 else:
     print('----')
     print('You can use [9, 11]')
@@ -191,7 +197,7 @@ if what_i_do == '1':
 
         curs.execute(db_change("select data from data where title = ?"), [name[0]])
         data = curs.fetchall()
-        render_do(name[0], data[0][0], 3, None)
+        render_do(name[0], data[0][0], 'backlink', '')
 elif what_i_do == '2':
     curs.execute(db_change("delete from other where name = 'recaptcha'"))
     curs.execute(db_change("delete from other where name = 'sec_re'"))
@@ -329,4 +335,4 @@ if data_db_load == 'Y':
     conn.commit()
 
 print('----')
-print('OK')
+print('OK')

+ 2 - 0
lang/en-US.json

@@ -213,6 +213,8 @@
         "2fa_password_change" : "Change 2FA password",
         "history_reset" : "Document history reset",
         "record_reset" : "User edit log reset",
+        "today_doc" : "Today[s] document",
+        "send_edit" : "Modify reason",
         "_comment_2.1_" : "Filter",
             "_comment_2.1.1_" : "List",
                 "interwiki_list" : "Interwiki(s) list",

+ 3 - 1
lang/ko-KR.json

@@ -405,5 +405,7 @@
     "history_reset": "문서 역사 초기화",
     "record_reset": "사용자 편집 기록 초기화",
     "email_setting": "이메일 설정",
-    "oauth_client_id": "OAuth 클라이언트 ID"
+    "oauth_client_id": "OAuth 클라이언트 ID",
+    "today_doc" : "오늘의 문서",
+    "send_edit" : "편집 사유 수정"
 }

+ 0 - 2
requirements.txt

@@ -5,8 +5,6 @@ requests
 
 pymysql
 
-Pillow
-
 diff-match-patch
 
 pysha3; python_version < "3.6"

+ 19 - 0
route/api_recent_discuss.py

@@ -0,0 +1,19 @@
+from .tool.func import *
+
+def api_recent_discuss_2(conn, num, get_type):
+    curs = conn.cursor()
+
+    num = 50 if num > 50 else num
+    data_list = []
+    
+    if get_type == 'stop':
+        curs.execute(db_change("select title, sub, date, code, stop from rd where stop = 'O' order by date desc limit ?"), [num])
+    elif get_type == 'all':
+        curs.execute(db_change("select title, sub, date, code, stop from rd order by date desc limit ?"), [num])
+    else:
+        curs.execute(db_change("select title, sub, date, code, stop from rd where not stop = 'O' order by date desc limit ?"), [num])
+        
+    for i in curs.fetchall():
+        data_list += [i]
+        
+    return flask.jsonify(data_list if data_list else {}) 

+ 1 - 1
route/api_topic_sub.py

@@ -43,7 +43,7 @@ def api_topic_sub_2(conn, topic_num):
                 "data_pas" : render_set(
                     doc_data = data_v, 
                     data_type = 'api_view',
-                    data_in = i[0],
+                    data_in = 'topic_' + topic_num + '_' + i[0],
                     doc_acl = 0
                 )
             }

+ 1 - 1
route/edit.py

@@ -102,7 +102,7 @@ def edit_2(conn, name):
                 warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
             else:
                 warning_edit += '' + \
-                    '<a href="/diff/' + url_pas(name) + '?first=' + flask.request.form.get('ver', '1') + '&second=' + doc_ver + '">' + \
+                    '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
                         '(r' + doc_ver + ')' + \
                     '</a>' + \
                 ''

+ 39 - 49
route/inter_wiki.py

@@ -3,98 +3,88 @@ from .tool.func import *
 def inter_wiki_2(conn, tools):
     curs = conn.cursor()
 
-    div = ''
+    div = '<table id="main_table_set">'
+    div += '<tr id="main_table_top_tr">'
+    
+    div += '<td id="main_table_width">A</td>'
+    div += '<td id="main_table_width">B</td>'
+    div += '<td id="main_table_width">C</td>'
+    
+    div += '</tr>'
+    
     admin = admin_check()
 
     if tools == 'inter_wiki':
-        del_link = 'del_inter_wiki'
         plus_link = 'plus_inter_wiki'
         title = load_lang('interwiki_list')
-        div = ''
 
-        curs.execute(db_change("select html, plus from html_filter where kind = 'inter_wiki'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'inter_wiki'"))
     elif tools == 'email_filter':
-        del_link = 'del_email_filter'
         plus_link = 'plus_email_filter'
         title = load_lang('email_filter_list')
-        div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'email'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'email'"))
     elif tools == 'name_filter':
-        del_link = 'del_name_filter'
         plus_link = 'plus_name_filter'
         title = load_lang('id_filter_list')
-        div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'name'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'name'"))
     elif tools == 'edit_filter':
-        del_link = 'del_edit_filter'
         plus_link = 'plus_edit_filter'
         title = load_lang('edit_filter_list')
-        div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'regex_filter'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'regex_filter'"))
     elif tools == 'file_filter':
-        del_link = 'del_file_filter'
         plus_link = 'plus_file_filter'
         title = load_lang('file_filter_list')
-        div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'file'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'file'"))
     elif tools == 'file_filter':
-        del_link = 'del_file_filter'
         plus_link = 'plus_file_filter'
         title = load_lang('file_filter_list')
-        div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'file'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'file'"))
     elif tools == 'image_license':
-        del_link = 'del_image_license'
         plus_link = 'plus_image_license'
         title = load_lang('image_license_list')
-        div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'image_license'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'image_license'"))
     elif tools == 'extension_filter':
-        del_link = 'del_extension_filter'
         plus_link = 'plus_extension_filter'
         title = load_lang('extension_filter_list')
-        div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'extension'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'extension'"))
     else:
-        del_link = 'del_edit_top'
         plus_link = 'plus_edit_top'
         title = load_lang('edit_tool_list')
-        div = ''
 
-        curs.execute(db_change("select html, plus from html_filter where kind = 'edit_top'"))
+        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'edit_top'"))
 
     db_data = curs.fetchall()
-    if db_data:
-        div += '<ul class="inside_ul">'
-
-        for data in db_data:
-            div += '<li>' + data[0]
-
-            if tools == 'edit_top':
-                div += ' : ' + data[1]
-            elif tools == 'inter_wiki':
-                div += ' : <a id="out_link" href="' + data[1] + '">' + data[1] + '</a>'
-
-            if admin == 1:
-                div += ' <a href="/' + plus_link + '/' + url_pas(data[0]) + '">(' + load_lang('edit') + ')</a>'
-                div += ' <a href="/' + del_link + '/' + url_pas(data[0]) + '">(' + load_lang('delete') + ')</a>'
-                
-            div += '</li>'
-
-        div += '</ul>'
+    for data in db_data:
+        div += '<tr>'
+        div += '<td>'
 
+        div += data[0]
         if admin == 1:
-            div += '<hr class="main_hr">'
+            div += ' <a href="/' + tools + '/add/' + url_pas(data[0]) + '">(' + load_lang('edit') + ')</a>'
+            div += ' <a href="/' + tools + '/del/' + url_pas(data[0]) + '">(' + load_lang('delete') + ')</a>'
+        
+        div += '</td>'
+
+        if tools == 'inter_wiki':
+            div += '<td><a id="out_link" href="' + data[1] + '">' + data[1] + '</a></td>'
+        else:
+            div += '<td>' + data[1] + '</td>'
+            
+        div += '<td>' + data[2] + '</td>'
+        div += '</tr>'
+        
+    div += '</table>'
             
-    if admin == 1:    
-        div += '<a href="/' + plus_link + '">(' + load_lang('add') + ')</a>'
+    if admin == 1:
+        div += '<hr class="main_hr">'
+        div += '<a href="/' + tools + '/add">(' + load_lang('add') + ')</a>'
 
     return easy_minify(flask.render_template(skin_check(),
         imp = [title, wiki_set(), wiki_custom(), wiki_css([0, 0])],

+ 0 - 3
route/main_manager.py

@@ -34,7 +34,6 @@ def main_manager_2(conn, num, r_ver):
                     <li><a href="/manager/17">''' + load_lang('release') + '''</a></li>
                     <li><a href="/manager/5">''' + load_lang('authorize') + '''</a></li>
                 </ul>
-                <br>
                 <h2>''' + load_lang('owner') + '''</h2>
                 <ul class="inside_ul">
                     <li><a href="/admin_group">''' + load_lang('admin_group_list') + '''</a></li>
@@ -55,14 +54,12 @@ def main_manager_2(conn, num, r_ver):
                     <li><a href="/file_filter">''' + load_lang('file_filter_list') + '''</a></li>
                     <li><a href="/extension_filter">''' + load_lang('extension_filter_list') + '''</a></li>
                 </ul>
-                <br>
                 <h2>''' + load_lang('server') + '''</h2>
                 <ul class="inside_ul">
                     <li><a href="/restart">''' + load_lang('wiki_restart') + '''</a></li>
                     <li><a href="/shutdown">''' + load_lang('wiki_shutdown') + '''</a></li>
                     <li><a href="/update">''' + load_lang('update') + '''</a></li>
                 </ul>
-                <br>
                 <h2>''' + load_lang('version') + '''</h2>
                 <ul class="inside_ul">
                     <li>

+ 48 - 35
route/main_other.py

@@ -6,41 +6,54 @@ def main_other_2(conn):
     return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('other_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = '''
-            <h2>''' + load_lang('record') + '''</h2>
-            <ul class="inside_ul">
-                <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
-                <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
-            </ul>
-            <br>
-            <h2>''' + load_lang('list') + '''</h2>
-            <ul class="inside_ul">
-                <li><a href="/recent_changes">''' + load_lang('recent_change') + '''</a></li>
-                <li><a href="/recent_discuss">''' + load_lang('recent_discussion') + '''</a></li>
-                <li><a href="/admin_list">''' + load_lang('admin_list') + '''</a></li>
-                <li><a href="/not_close_topic">''' + load_lang('open_discussion_list') + '''</a></li>
-                <li><a href="/title_index">''' + load_lang('all_document_list') + '''</a></li>
-                <li><a href="/acl_list">''' + load_lang('acl_document_list') + '''</a></li>
-                <li><a href="/please">''' + load_lang('need_document') + '''</a></li>
-                <li><a href="/block_log">''' + load_lang('recent_ban') + '''</a></li>
-                <li><a href="/user_log">''' + load_lang('member_list') + '''</a></li>
-                <li><a href="/admin_log">''' + load_lang('authority_use_list') + '''</a></li>
-                <li><a href="/old_page">''' + load_lang('old_page') + '''</a></li>
-                <li><a href="/image_file_list">''' + load_lang('image_file_list') + '''</a></li>
-                <li><a href="/vote">''' + load_lang('vote_list') + '''</a></li>
-                <li><a href="/long_page">''' + load_lang('long_page') + '''</a></li>
-                <li><a href="/short_page">''' + load_lang('short_page') + '''</a></li>
-            </ul>
-            <br>
-            <h2>''' + load_lang('other') + '''</h2>
-            <ul class="inside_ul">
-                <li><a href="/upload">''' + load_lang('upload') + '''</a></li>
-                <li><a href="/manager/10">''' + load_lang('search') + '''</a></li>
-            </ul>
-            <br>
-            <h2>''' + load_lang('admin') + '''</h2>
-            <ul class="inside_ul">
-                <li><a href="/manager/1">''' + load_lang('admin_tool') + '''</a></li>
-            </ul>
+            <div id="other_simple_render">
+                <h2>1. ''' + load_lang('record') + '''</h2>
+                <ul class="inside_ul">
+                    <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
+                    <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
+                </ul>
+                <h2>2. ''' + load_lang('list') + '''</h2>
+                <h3>2.1. ''' + load_lang('admin') + '''</h3>
+                <ul class="inside_ul">               
+                    <li><a href="/admin_list">''' + load_lang('admin_list') + '''</a></li>
+                    <li><a href="/admin_log">''' + load_lang('authority_use_list') + '''</a></li>
+                </ul>
+                <h3>2.2. ''' + load_lang('discussion') + '''</h3>
+                <ul class="inside_ul">
+                    <li><a href="/recent_discuss">''' + load_lang('recent_discussion') + '''</a></li>
+                    <li><a href="/not_close_topic">''' + load_lang('open_discussion_list') + '''</a></li>
+                </ul>
+                <h3>2.3. ''' + load_lang('document') + '''</h3>
+                <ul class="inside_ul">
+                    <li><a href="/recent_changes">''' + load_lang('recent_change') + '''</a></li>
+                    <li><a href="/title_index">''' + load_lang('all_document_list') + '''</a></li>
+                    <li><a href="/acl_list">''' + load_lang('acl_document_list') + '''</a></li>
+                    <li><a href="/please">''' + load_lang('need_document') + '''</a></li>
+                    <li><a href="/long_page">''' + load_lang('long_page') + '''</a></li>
+                    <li><a href="/short_page">''' + load_lang('short_page') + '''</a></li>
+                    <li><a href="/old_page">''' + load_lang('old_page') + '''</a></li>
+                </ul>
+                <h3>2.4. ''' + load_lang('user') + '''</h3>
+                <ul class="inside_ul">
+                    <li><a href="/block_log">''' + load_lang('recent_ban') + '''</a></li>
+                    <li><a href="/user_log">''' + load_lang('member_list') + '''</a></li>
+                </ul>
+                <h3>2.5. ''' + load_lang('other') + '''</h3>
+                <ul class="inside_ul">
+                    <li><a href="/image_file_list">''' + load_lang('image_file_list') + '''</a></li>
+                    <li><a href="/vote">''' + load_lang('vote_list') + '''</a></li>
+                </ul>
+                <h2>3. ''' + load_lang('other') + '''</h2>
+                <ul class="inside_ul">
+                    <li><a href="/upload">''' + load_lang('upload') + '''</a></li>
+                    <li><a href="/manager/10">''' + load_lang('search') + '''</a></li>
+                </ul>
+                <h2>4. ''' + load_lang('admin') + '''</h2>
+                <ul class="inside_ul">
+                    <li><a href="/manager/1">''' + load_lang('admin_tool') + '''</a></li>
+                </ul>
+            </div>
+            <script>simple_render('other_simple_render');</script>
         ''',
         menu = 0
     ))

+ 6 - 5
route/recent_change.py

@@ -5,9 +5,10 @@ def recent_change_2(conn, name, tool):
 
     if flask.request.method == 'POST':
         return redirect(
-            '/diff/' + url_pas(name) +
-            '?first=' + flask.request.form.get('b', '1') +
-            '&second=' + flask.request.form.get('a', '1')
+            '/diff' + 
+            '/' + flask.request.form.get('b', '1') +
+            '/' + flask.request.form.get('a', '1') +
+            '/' + url_pas(name)
         )
     else:
         ban = ''
@@ -118,13 +119,13 @@ def recent_change_2(conn, name, tool):
                     style[1] = 'id="toron_color_grey"'
 
             if tool == 'history':
-                title = '<a href="/w/' + url_pas(name) + '?num=' + data[0] + '">r' + data[0] + '</a> '
+                title = '<a href="/w/' + url_pas(name) + '/doc_rev/' + data[0] + '">r' + data[0] + '</a> '
             else:
                 title = '<a href="/w/' + url_pas(data[1]) + '">' + html.escape(data[1]) + '</a> '
                 if int(data[0]) < 2:
                     title += '<a href="/history/' + url_pas(data[1]) + '">(r' + data[0] + ')</a> '
                 else:
-                    title += '<a href="/diff/' + url_pas(data[1]) + '?first=' + str(int(data[0]) - 1) + '&second=' + data[0] + '">(r' + data[0] + ')</a> '
+                    title += '<a href="/diff/' + str(int(data[0]) - 1) + '/' + data[0] + '/' + url_pas(data[1]) + '">(r' + data[0] + ')</a> '
 
             div += '''
                 <tr ''' + style[0] + '''>

+ 1 - 1
route/recent_history_tool.py

@@ -16,7 +16,7 @@ def recent_history_tool_2(conn, name, rev):
         data += '<li><a href="/revert/' + url_pas(name) + '?num=' + str(rev - 1) + '">' + load_lang('revert') + ' | r' + str(rev - 1) + '</a></li>'
     
     if rev - 1 > 0:
-        data += '<li><a href="/diff/' + url_pas(name) + '?first=' + str(rev - 1) + '&second=' + num + '">' + load_lang('compare') + '</a></li>'
+        data += '<li><a href="/diff/' + str(rev - 1) + '/' + num + '/' + url_pas(name) + '">' + load_lang('compare') + '</a></li>'
 
     data += '<li><a href="/history/' + url_pas(name) + '">' + load_lang('history') + '</a></li>'
     data += '</ul>'

+ 19 - 85
route/tool/func.py

@@ -75,8 +75,6 @@ import requests
 
 import pymysql
 
-import PIL
-
 if sys.version_info < (3, 6):
     import sha3
    
@@ -84,7 +82,9 @@ if sys.version_info < (3, 6):
 global_lang = {}
 global_wiki_set = {}
 
-data_css_ver = '111'
+global_db_set = ''
+
+data_css_ver = '114'
 data_css = ''
 
 conn = ''
@@ -102,75 +102,13 @@ def load_conn(data):
     load_conn2(data)
     
 # Func-init
-class server_init:
-    def __init__(self):
-        self.env_dict = {
-            'host' : os.getenv('NAMU_HOST'),
-            'port' : os.getenv('NAMU_PORT'),
-            'language' : os.getenv('NAMU_LANG'),
-            'markup' : os.getenv('NAMU_MARKUP'),
-            'encode' : os.getenv('NAMU_ENCRYPT')
-        }
-
-        self.server_set_var = {
-            'host' : {
-                'display' : 'Host',
-                'require' : 'conv',
-                'default' : '0.0.0.0'
-            }, 'port' : {
-                'display' : 'Port',
-                'require' : 'conv',
-                'default' : '3000'
-            }, 'language' : {
-                'display' : 'Language',
-                'require' : 'select',
-                'default' : 'ko-KR',
-                'list' : ['ko-KR', 'en-US']
-            }, 'markup' : {
-                'display' : 'Markup',
-                'require' : 'select',
-                'default' : 'namumark',
-                'list' : ['namumark', 'custom', 'raw']
-            }, 'encode' : {
-                'display' : 'Encryption method',
-                'require' : 'select',
-                'default' : 'sha3',
-                'list' : ['sha3', 'sha256']
-            }
-        }
-        
-    def server_init(self):
-        return self.server_set_var
+def get_conn(db_set = ''):
+    global global_db_set
+    if db_set != '':
+        global_db_set = db_set
+    else:
+        db_set = global_db_set
     
-    def init(self, key):
-        if self.env_dict[key] != None:
-            return self.env_dict[key]
-        else:
-            while 1:
-                if self.server_set_var[key]['require'] == 'select':
-                    list_ = '[' + ', '.join(self.server_set_var[key]['list']) + ']'
-                else:
-                    list_ = ''
-
-                print('{} ({}) {} : '.format(
-                    self.server_set_var[key]['display'],
-                    self.server_set_var[key]['default'],
-                    list_
-                ), end = '')
-
-                server_set_val = input()
-                if server_set_val:
-                    if self.server_set_var[key]['require'] == 'select':
-                        if server_set_val not in self.server_set_var[key]['list']:
-                            pass
-                        else:
-                            return server_set_val
-                    else:
-                        return server_set_val
-                else:
-                    return self.server_set_var[key]['default']
-
-def get_conn(db_set):
     if db_set['type'] == 'sqlite':
         conn = sqlite3.connect(db_set['name'] + '.db')
         curs = conn.cursor()
@@ -194,6 +132,8 @@ def get_conn(db_set):
         
         conn.select_db(db_set['name'])
         
+    load_conn(conn)
+        
     return conn
 
 def update(ver_num, set_data):
@@ -429,14 +369,14 @@ def set_init():
     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) values (?, 'email')"
+                "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) values (?, 'extension')"
+                "insert into html_filter (html, kind, plus, plus_t) values (?, 'extension', '', '')"
             ), [i])
 
     curs.execute(db_change(
@@ -456,8 +396,7 @@ def set_init():
     curs.execute(db_change('select data from other where name = "key"'))
     rep_data = curs.fetchall()
     if not rep_data:
-        rep_key = ''.join(random.choice("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") for i in range(64))
-        curs.execute(db_change('insert into other (name, data) values ("key", ?)'), [rep_key])
+        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():
@@ -565,15 +504,10 @@ def next_fix(link, num, page, end = 50):
 
     return list_data
 
-def leng_check(first, second):
-    if first < second:
-        all_plus = '+' + str(second - first)
-    elif second < first:
-        all_plus = '-' + str(first - second)
-    else:
-        all_plus = '0'
-
-    return all_plus
+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:
@@ -1379,7 +1313,7 @@ def ip_pas(raw_ip, type_d = 0):
                 ip = '<a href="/w/' + url_pas('user:' + raw_ip) + '">' + raw_ip + '</a>'
                 
             if change_ip == 0:
-                ip += ' <a href="/tool/' + url_pas(raw_ip) + '">(' + load_lang('tool') + ')</a>'
+                ip += ' <a href="/user/' + url_pas(raw_ip) + '">(' + load_lang('tool') + ')</a>'
 
         end_ip[raw_ip] = ip
     

+ 0 - 2
route/topic_admin.py

@@ -17,7 +17,6 @@ def topic_admin_2(conn, topic_num, num):
             <li>''' + load_lang('writer') + ' : ''' + ip_pas(data[0][1]) + '''</li>
             <li>''' + load_lang('time') + ' : ' + data[0][2] + '''</li>
         </ul>
-        <br>
         <h2>''' + load_lang('other_tool') + '''</h2>
         <ul class="inside_ul">
             <li>
@@ -38,7 +37,6 @@ def topic_admin_2(conn, topic_num, num):
         user_ban_d = curs.fetchall()
 
         ban += '''
-            <br>
             <h2>''' + load_lang('admin_tool') + '''</h2>
             <ul class="inside_ul">
                 <li>

+ 1 - 1
route/topic_close_list.py

@@ -39,7 +39,7 @@ def topic_close_list_2(conn, name):
             <form style="''' + display + '" method="post" action="/thread/' + topic_num + '''">
                 <input placeholder="''' + load_lang('discussion_name') + '''" name="title">
                 <hr class="main_hr">
-                <textarea rows="10" id="content" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
+                <textarea rows="10" id="textarea_edit_view" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
                 <hr class="main_hr">
                 ''' + captcha_get() + (ip_warning() if display == '' else '') + '''
                 <input style="display: none;" name="topic" value="''' + name + '''">

+ 1 - 1
route/user_alarm.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def alarm_2(conn):
+def user_alarm_2(conn):
     curs = conn.cursor()
 
     num = int(number_check(flask.request.args.get('num', '1')))

+ 1 - 1
route/user_alarm_del.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def alarm_del_2(conn):
+def user_alarm_del_2(conn):
     curs = conn.cursor()
 
     curs.execute(db_change("delete from alarm where name = ?"), [ip_check()])

+ 55 - 43
route/user_info.py

@@ -1,64 +1,76 @@
 from .tool.func import *
 
-def user_info_2(conn):
+def user_info_2(conn, name):
     curs = conn.cursor()
 
-    ip = ip_check()
-
-    curs.execute(db_change("select count(*) from alarm where name = ?"), [ip])
-    count = curs.fetchall()
-    if count and count[0][0] != 0:
-        plus2 = '<li><a id="not_thing" href="/alarm">' + load_lang('alarm') + ' (' + str(count[0][0]) + ')</a></li>'
+    if name == '':
+        ip = ip_check()
     else:
-        plus2 = '<li><a href="/alarm">' + load_lang('alarm') + ' (0)</a></li>'
+        ip = name
 
-    if ip_or_user(ip) == 0:
-        plus = '''
-            <li><a href="/logout">''' + load_lang('logout') + '''</a></li>
-            <li><a href="/change">''' + load_lang('user_setting') + '''</a></li>
-        '''
+    login_menu = ''
+    tool_menu = ''
+    
+    if name == '':
+        curs.execute(db_change("select count(*) from alarm where name = ?"), [ip])
+        count = curs.fetchall()
+        if count and count[0][0] != 0:
+            tool_menu += '<li><a id="not_thing" href="/alarm">' + load_lang('alarm') + ' (' + str(count[0][0]) + ')</a></li>'
+        else:
+            tool_menu += '<li><a href="/alarm">' + load_lang('alarm') + '</a></li>'
 
-        plus2 += '<li><a href="/watch_list">' + load_lang('watchlist') + '</a></li>'
-        plus2 += '<li><a href="/star_doc">' + load_lang('star_doc') + '</a></li>'
-        plus3 = '<li><a href="/acl/user:' + url_pas(ip) + '">' + load_lang('user_document_acl') + '</a></li>'
-    else:
-        plus = '''
-            <li><a href="/login">''' + load_lang('login') + '''</a></li>
-            <li><a href="/register">''' + load_lang('register') + '''</a></li>
-            <li><a href="/change">''' + load_lang('user_setting') + '''</a></li>
-        '''
-        plus3 = ''
+        if ip_or_user(ip) == 0:
+            login_menu += '''
+                <li><a href="/logout">''' + load_lang('logout') + '''</a></li>
+                <li><a href="/change">''' + load_lang('user_setting') + '''</a></li>
+            '''
 
-        curs.execute(db_change("select data from other where name = 'email_have'"))
-        test = curs.fetchall()
-        if test and test[0][0] != '':
-            plus += '<li><a href="/pass_find">' + load_lang('password_search') + '</a></li>'
+            tool_menu += '<li><a href="/watch_list">' + load_lang('watchlist') + '</a></li>'
+            tool_menu += '<li><a href="/star_doc">' + load_lang('star_doc') + '</a></li>'
+            tool_menu += '<li><a href="/acl/user:' + url_pas(ip) + '">' + load_lang('user_document_acl') + '</a></li>'
+        else:
+            login_menu += '''
+                <li><a href="/login">''' + load_lang('login') + '''</a></li>
+                <li><a href="/register">''' + load_lang('register') + '''</a></li>
+                <li><a href="/change">''' + load_lang('user_setting') + '''</a></li>
+                <li><a href="/pass_find">''' + load_lang('password_search') + '''</a></li>
+            '''
+            
+        tool_menu += '<li><a href="/custom_head">' + load_lang('user_head') + '</a></li>'
+            
+        login_menu = '<h2>' + load_lang('login') + '</h2><ul class="inside_ul">' + login_menu + '</ul>'
+        tool_menu = '<h2>' + load_lang('tool') + '</h2><ul class="inside_ul">' + tool_menu + '</ul>'
 
+    if admin_check(1) == 1:
+        curs.execute(db_change("select block from rb where block = ? and ongoing = '1'"), [ip])
+        ban_name = load_lang('release') if curs.fetchall() else load_lang('ban')
+        
+        admin_menu = '''
+            <h2>''' + load_lang('admin') + '''</h2>
+            <ul class="inside_ul">
+                <li><a href="/ban/''' + url_pas(ip) + '''">''' + ban_name + '''</a></li>
+                <li><a href="/check/''' + url_pas(ip) + '''">''' + load_lang('check') + '''</a></li>
+            </ul>
+        '''
+    else:
+        admin_menu = ''
+            
     return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('user_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = '''
             <h2>''' + load_lang('state') + '''</h2>
             <div id="get_user_info"></div>
             <script>load_user_info("''' + ip + '''");</script>
-            <br>
-            <h2>''' + load_lang('login') + '''</h2>
-            <ul class="inside_ul">
-                ''' + plus + '''
-            </ul>
-            <br>
-            <h2>''' + load_lang('tool') + '''</h2>
-            <ul class="inside_ul">
-                ''' + plus3 + '''
-                <li><a href="/custom_head">''' + load_lang('user_head') + '''</a></li>
-            </ul>
-            <br>
+            ''' + login_menu + '''
+            ''' + tool_menu + '''
             <h2>''' + load_lang('other') + '''</h2>
             <ul class="inside_ul">
-            ''' + plus2 + '''
-            <li>
-                <a href="/count">''' + load_lang('count') + '''</a>
-            </li>
+                <li><a href="/record/''' + url_pas(ip) + '''">''' + load_lang('record') + '''</a></li>
+                <li><a href="/record/topic/''' + url_pas(ip) + '''">''' + load_lang('discussion_record') + '''</a></li>
+                <li><a href="/topic/user:''' + url_pas(ip) + '''">''' + load_lang('user_discussion') + '''</a></li>
+                <li><a href="/count/''' + url_pas(ip) + '''">''' + load_lang('count') + '''</a></li>
             </ul>
+            ''' + admin_menu + '''
         ''',
         menu = 0
     ))

+ 2 - 2
route/user_setting.py

@@ -1,9 +1,9 @@
 from .tool.func import *
 
-def user_setting_2(conn, server_init):
+def user_setting_2(conn, server_set_var):
     curs = conn.cursor()
 
-    support_language = ['default'] + server_init.server_init()['language']['list']
+    support_language = ['default'] + server_set_var['language']['list']
     ip = ip_check()
 
     if ban_check() == 1:

+ 0 - 31
route/user_tool.py

@@ -1,31 +0,0 @@
-from .tool.func import *
-
-def user_tool_2(conn, name):
-    curs = conn.cursor()
-
-    data = '''
-        <h2>''' + load_lang('tool') + '''</h2>
-        <ul class="inside_ul">
-            <li><a href="/record/''' + url_pas(name) + '''">''' + load_lang('record') + '''</a></li>
-            <li><a href="/record/topic/''' + url_pas(name) + '''">''' + load_lang('discussion_record') + '''</a></li>
-            <li><a href="/topic/user:''' + url_pas(name) + '''">''' + load_lang('user_discussion') + '''</a></li>
-        </ul>
-    '''
-
-    if admin_check(1) == 1:
-        curs.execute(db_change("select block from rb where block = ? and ongoing = '1'"), [name])
-        ban_name = load_lang('release') if curs.fetchall() else load_lang('ban')
-        
-        data += '''
-            <h2>''' + load_lang('admin') + '''</h2>
-            <ul class="inside_ul">
-                <li><a href="/ban/''' + url_pas(name) + '''">''' + ban_name + '''</a></li>
-                <li><a href="/check/''' + url_pas(name) + '''">''' + load_lang('check') + '''</a></li>
-            </ul>
-        '''
-
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('tool') + ')', 0])],
-        data = data,
-        menu = 0
-    ))

+ 1 - 1
route/user_watch_list.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def watch_list_2(conn, tool):
+def user_watch_list_2(conn, tool):
     curs = conn.cursor()
 
     if tool == 'watch_list':

+ 1 - 1
route/user_watch_list_name.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def watch_list_name_2(conn, tool, name):
+def user_watch_list_name_2(conn, tool, name):
     curs = conn.cursor()
 
     ip = ip_check()

+ 4 - 4
route/view_diff_data.py → route/view_diff.py

@@ -1,14 +1,14 @@
 from .tool.func import *
 
-def view_diff_data_2(conn, name):
+def view_diff_2(conn, name, num_a, num_b):
     curs = conn.cursor()
+    
+    first = str(num_a)
+    second = str(num_b)
 
     if acl_check(name, 'render') == 1:
         return re_error('/ban')
 
-    first = number_check(flask.request.args.get('first', '1'))
-    second = number_check(flask.request.args.get('second', '1'))
-
     curs.execute(db_change("select title from history where title = ? and (id = ? or id = ?) and hide = 'O'"), [name, first, second])
     if curs.fetchall() and admin_check(6) != 1:
         return re_error('/error/3')

+ 26 - 33
route/view_read.py

@@ -1,16 +1,14 @@
 from .tool.func import *
 
-def view_read_2(conn, name):
+def view_read_2(conn, name, doc_rev, doc_from):
     curs = conn.cursor()
 
     sub = ''
     div = ''
     ip = ip_check()
-    name_doc_pass = flask.request.args.get('from', '')
+    name_doc_pass = doc_from
     uppage = re.sub(r"/([^/]+)$", '', name)
-
-    num = flask.request.args.get('num', None)
-    num = int(number_check(num)) if num else None
+    num = str(doc_rev)        
 
     curs.execute(db_change("select sub from rd where title = ? and not stop = 'O' order by date desc"), [name])
     topic = 1 if curs.fetchall() else 0
@@ -19,37 +17,31 @@ def view_read_2(conn, name):
     down = 1 if curs.fetchall() else 0
     
     if re.search(r'^category:', name):
+        category_doc = ''
+        category_sub = ''
+        
         curs.execute(db_change("select link from back where title = ? and type = 'cat' order by link asc"), [name])
-        back = curs.fetchall()
-        if back:
-            u_div = ''
-
-            for data in back:
-                if div == '':
-                    div = '<br><h2 id="cate_normal">' + load_lang('category_title') + '</h2><ul class="inside_ul">'
-
-                if re.search(r'^category:', data[0]):
-                    u_div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
-                else:
-                    curs.execute(db_change("select title from back where title = ? and type = 'include'"), [data[0]])
-                    db_data = curs.fetchall()
-                    if db_data:
-                        div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a> <a id="inside" href="/xref/' + url_pas(data[0]) + '">(' + load_lang('backlink') + ')</a></li>'
-                    else:
-                        div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
-
-            if div != '':
-                div += '</ul>'
-
-            if u_div != '':
-                div += '<br><h2 id="cate_under">' + load_lang('under_category') + '</h2><ul class="inside_ul">' + u_div + '</ul>'
+        category_sql = curs.fetchall()
+        for data in category_sql:
+            if re.search(r'^category:', data[0]):
+                category_sub += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
+            else:
+                category_doc += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a> <a id="inside" href="/xref/' + url_pas(data[0]) + '">(' + load_lang('backlink') + ')</a></li>'
+
+        if category_doc != '':
+            category_doc = '<h2 id="cate_normal">' + load_lang('category_title') + '</h2><ul class="inside_ul">' + category_doc + '</ul>'
+
+        if category_sub != '':
+            category_doc += '<h2 id="cate_under">' + load_lang('under_category') + '</h2><ul class="inside_ul">' + category_sub + '</ul>'
+            
+        div += category_doc
 
-    if num:
-        curs.execute(db_change("select title from history where title = ? and id = ? and hide = 'O'"), [name, str(num)])
+    if num != '0':
+        curs.execute(db_change("select title from history where title = ? and id = ? and hide = 'O'"), [name, num])
         if curs.fetchall() and admin_check(6) != 1:
             return redirect('/history/' + url_pas(name))
 
-        curs.execute(db_change("select data from history where title = ? and id = ?"), [name, str(num)])
+        curs.execute(db_change("select data from history where title = ? and id = ?"), [name, num])
     else:
         curs.execute(db_change("select data from data where title = ?"), [name])
 
@@ -99,7 +91,7 @@ def view_read_2(conn, name):
     else:
         response_data = 200
 
-    if num:
+    if num != '0':
         menu = [['history/' + url_pas(name), load_lang('history')]]
         sub = ' (r' + str(num) + ')'
         acl = 0
@@ -124,7 +116,7 @@ def view_read_2(conn, name):
             menu += [['w/' + url_pas(name), load_lang('pass')]]
             end_data = '''
                 <div id="redirect">
-                    <a href="/w/''' + url_pas(name_doc_pass) + '?from=' + url_pas(name) + '">' + name_doc_pass + '</a> ⇨ <b>' + name + '''</b>
+                    <a href="/w/''' + url_pas(name_doc_pass) + '/doc_from/' + url_pas(name) + '">' + name_doc_pass + '</a> ⇨ <b>' + name + '''</b>
                 </div>
                 <br>
             ''' + end_data
@@ -148,6 +140,7 @@ def view_read_2(conn, name):
             <div id="get_user_info"></div>
             <script>load_user_info("''' + user_name + '''");</script>
         ''' + div
+        menu += [['w/' + url_pas(name) + '/' + url_pas(get_time().split()[0]), load_lang('today_doc')]]
 
     curs.execute(db_change("select data from other where name = 'body'"))
     body = curs.fetchall()

+ 2 - 2
route/vote_end.py

@@ -17,12 +17,12 @@ def vote_end_2(conn, num):
         if data_list[0][3] == 'open' or data_list[0][3] == 'n_open':
             data += '' + \
                 '<hr class="main_hr">' + \
-                '<a href="/close_vote/' + num + '">(' + load_lang('close_vote') + ')</a>' + \
+                '<a href="/vote/close/' + num + '">(' + load_lang('close_vote') + ')</a>' + \
             ''
         else:
             data += '' + \
                 '<hr class="main_hr">' + \
-                '<a href="/close_vote/' + num + '">(' + load_lang('re_open_vote') + ')</a>' + \
+                '<a href="/vote/close/' + num + '">(' + load_lang('re_open_vote') + ')</a>' + \
             ''
 
     vote_data = re.findall(r'([^\n]+)', data_list[0][2].replace('\r\n', '\n'))

+ 10 - 11
route/vote.py → route/vote_list.py

@@ -1,14 +1,13 @@
 from .tool.func import *
 
-def vote_2(conn):
+def vote_list_2(conn, list_type, num):
     curs = conn.cursor()
 
-    sql_num_1 = int(number_check(flask.request.args.get('num', '1')))
-    sql_num = (sql_num_1 * 50 - 50) if sql_num_1 * 50 > 0 else 0
+    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
     data = ''
-    if flask.request.args.get('close', 'n') == 'n':
-        data += '<a href="/vote?close=y">(' + load_lang('close_vote_list') + ')</a>'
+    if list_type == 'normal':
+        data += '<a href="/vote/list/close">(' + load_lang('close_vote_list') + ')</a>'
         sub = 0
         curs.execute(db_change('select name, id, type from vote where type = "open" or type = "n_open" limit ?, 50'), [sql_num])
     else:
@@ -20,19 +19,19 @@ def vote_2(conn):
 
     data_list = curs.fetchall()
     for i in data_list:
-        if flask.request.args.get('close', 'n') == 'n':
+        if list_type == 'normal':
             open_select = load_lang('open_vote') if i[2] == 'open' else load_lang('not_open_vote')
         else:
             open_select = load_lang('open_vote') if i[2] == 'close' else load_lang('not_open_vote')
 
-        data += '<li><a href="/vote/' + i[1] + '">' + html.escape(i[0]) + ' (' + open_select + ')</a></li>'
+        data += '<li><a href="/vote/' + i[1] + '">' + html.escape(i[0]) + '</a> (' + open_select + ')</li>'
 
     data += '</ul>'
-    if flask.request.args.get('close', 'n') == 'n':
-        data += ('<a href="/add_vote">(' + load_lang('add_vote') + ')</a>') if admin_check() == 1 else ''
-        data += next_fix('/vote?num=', sql_num_1, data_list)
+    if list_type == 'normal':
+        data += ('<a href="/vote/add">(' + load_lang('add_vote') + ')</a>') if admin_check() == 1 else ''
+        data += next_fix('/vote/list/', num, data_list)
     else:
-        data += next_fix('/vote?close=y&num=', sql_num_1, data_list)
+        data += next_fix('/vote/list/close/', num, data_list)
 
     return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('vote_list'), wiki_set(), wiki_custom(), wiki_css([sub, 0])],

+ 4 - 4
route/vote_select.py

@@ -9,14 +9,14 @@ def vote_select_2(conn, num):
         return redirect('/vote')
 
     if data_list[0][3] == 'close' or data_list[0][3] == 'n_close':
-        return redirect('/end_vote/' + num)
+        return redirect('/vote/end/' + num)
 
     if acl_check('', 'vote', num) == 1:
-        return redirect('/end_vote/' + num)
+        return redirect('/vote/end/' + num)
 
     curs.execute(db_change('select user from vote where id = ? and user = ?'), [num, ip_check()])
     if curs.fetchall():
-        return redirect('/end_vote/' + num)
+        return redirect('/vote/end/' + num)
 
     vote_data = re.findall(r'([^\n]+)', data_list[0][2].replace('\r\n', '\n'))
 
@@ -36,7 +36,7 @@ def vote_select_2(conn, num):
         ])
         conn.commit()
 
-        return redirect('/end_vote/' + num)
+        return redirect('/vote/end/' + num)
     else:
         data = '' + \
             '<h2>' + data_list[0][0] + '</h2>' + \

+ 3 - 3
version.json

@@ -1,7 +1,7 @@
 {
     "beta" : {
-        "r_ver" : "v3.4.0-stable (stable2) (beta7) (dev23)",
-        "c_ver" : "3400101",
-        "s_ver" : "13"
+        "r_ver" : "v3.5.0-dev (stable1) (beta1) (dev3)",
+        "c_ver" : "3500101",
+        "s_ver" : "3500101"
     }
 }

+ 114 - 123
views/main_css/css/main.css

@@ -1,32 +1,28 @@
-body, html, video, table, iframe, input, textarea, img, hr, blockquote, pre, iframe {
+/* 기본 전체 옵션 */
+body, html, video, table, iframe, input, textarea, img, hr, blockquote, pre, iframe, .table_safe {
     max-width: 100%;
 }
 
-textarea {
-    width: 100%;
+body {
+    word-break: break-all;
+    
+    overflow: auto;
 }
 
-input {
+/* 텍스트 필드 */
+textarea, input {
     width: 100%;
-    box-sizing: border-box;
 }
 
-#last {
-    margin-top: 30px;
+input {
+    box-sizing: border-box;
 }
 
-#toc {
-    border: 1px solid gainsboro;
-    padding: 20px;
-    
-    width: fit-content;
-    width: -moz-fit-content;
-    
-    clear: both;
-    
-    margin-top: 10px;
+input[type="checkbox"], input[type="radio"] {
+    width: auto;
 }
 
+/* 테이블 */
 table {
     border-collapse: collapse;
 }
@@ -37,19 +33,18 @@ td {
     padding: 5px 10px;
 }
 
+/* 링크 */
 a {
+    color: dodgerblue;
+    
     text-decoration: none;
 }
 
-.inside_ul li {
-    margin-left: 20px;
-}
-
 #not_thing {
     color: red;
 }
 
-#inside, #out_link, #open {
+#inside, #out_link, #out_link::before {
     color: green;
 }
 
@@ -59,17 +54,26 @@ a {
     font-weight: lighter;
     
     background: transparent;
-    color: green;
 }
 
-input[type="checkbox"], input[type="radio"] {
-    width: auto;
+#include_link {
+    display: none;
 }
 
-#list {
-    padding: 10px;
+.hidden_link {
+    filter: blur(3px);
+}
+
+.hidden_link:hover {
+    filter: none;
+}
+
+/* 리스트 */
+.inside_ul li {
+    margin-left: 20px;
 }
 
+/* 토론 관련 */
 #toron {
     width: 100%;
 }
@@ -98,146 +102,81 @@ input[type="checkbox"], input[type="radio"] {
     display: none;
 }
 
-#main_table_top_tr {
-    background: aquamarine;
-}
-
-#cate {
-    border: 1px solid gainsboro;
-    padding: 5px;
-    margin-top: 20px;
-}
-
-pre {
-    border: 1px solid gainsboro;
-    padding: 10px;
-    white-space: pre-wrap;
-}
-
-#in {
-    margin-left: 20px;
-}
-
-#out {
-    margin-left: 5px;
-}
-
-s, strike, del {
-    color: gray;
-}
-
-s:hover, strike:hover, del:hover {
-    color: gray;
-    background-color: gainsboro;
-    text-decoration: none;
-}
+#topic_scroll {
+    max-height: 500px;
+    
+    overflow: scroll;
+    -ms-overflow-style: none;
 
-#main_table_set {
-    width: 100%;
-    text-align: center;
+    scrollbar-width: none;
 }
 
-#main_table_width {
-    width: 33.3%;
+#topic_scroll::-webkit-scrollbar {
+    display: none;
 }
 
-#main_table_width_half {
-    width: 50%;
+.topic_content {
+    height: 200px;
 }
 
-#main_table_width_quarter {
-    width: 25%;
+/* 위키 내용 관련 */
+#toc {
+    border: 1px solid gainsboro;
+    padding: 20px;
+    
+    width: fit-content;
+    width: -moz-fit-content;
+    
+    clear: both;
+    
+    margin-top: 10px;
 }
 
-#redirect {
+#cate, pre, #redirect {
     border: 1px solid gainsboro;
+    
     padding: 10px;
 }
 
-body {
-    word-break: break-all;
-    overflow: auto;
-}
-
-.main_hr {
-    border: none;
-    margin-top: 8px;
-    margin-bottom: 8px;
+#cate {
+    margin-top: 20px;
 }
 
-#include_link {
-    display: none;
+pre {    
+    white-space: pre-wrap;
 }
 
 #toc_title {
     font-size: 1.2rem;
 }
 
-#admin_log_search {
-    width: 100px;
-}
-
 @media (max-width: 768px) {
     table {
         min-width: 100%;
     }
+    
     .table_safe {
         min-width: 100%;
     }
 }
 
-.table_safe {
-    max-width: 100%;
-}
-
-.change_space {
-    white-space: pre-line;
-}
-
-#topic_scroll {
-    max-height: 500px;
-    
-    overflow: scroll;
-    -ms-overflow-style: none;
-
-    scrollbar-width: none;
-}
-
-#topic_scroll::-webkit-scrollbar {
-    display: none;
-}
-
-.hidden_link {
-    filter: blur(3px);
-}
-
-.hidden_link:hover {
-    filter: none;
-}
-
 .content {
     height: 500px;
 }
 
-.topic_content {
-    height: 200px;
-}
-
 .spead_footnote {
-    background-color: #efefef;
     color: #555;
+    background-color: #efefef;
+    
     border: 1px solid #cecece;
 }
 
 #footnote_data {
     border-top: 1px solid gainsboro;
+    
     padding-top: 10px;
 }
 
-a {
-    color: dodgerblue;
-}
-
 hr {
     border: 0;
     border-top: 1px solid gainsboro;
@@ -245,6 +184,7 @@ hr {
 
 .render_content {
     white-space: pre-wrap;
+    
     line-break: anywhere;
 }
 
@@ -261,4 +201,55 @@ blockquote {
     background-position: calc(100% - 10px) 10px;
     background-repeat: no-repeat;
     background-size: 25px;
+}
+
+/* 취소선 */
+s, strike, del {
+    color: gray;
+}
+
+s:hover, strike:hover, del:hover {
+    color: gray;
+    background-color: gainsboro;
+    
+    text-decoration: none;
+}
+
+/* 최근 변경 관련 테이블 */
+#main_table_set {
+    width: 100%;
+    
+    text-align: center;
+}
+
+#main_table_width {
+    width: 33.3%;
+}
+
+#main_table_width_half {
+    width: 50%;
+}
+
+#main_table_width_quarter {
+    width: 25%;
+}
+
+#main_table_top_tr {
+    background: aquamarine;
+}
+
+/* 기타 */
+.main_hr {
+    border: none;
+    
+    margin-top: 8px;
+    margin-bottom: 8px;
+}
+
+#admin_log_search {
+    width: 100px;
+}
+
+.change_space {
+    white-space: pre-line;
 }

BIN
views/main_css/file/quote.png


+ 0 - 15
views/main_css/js/load_something.js

@@ -65,21 +65,6 @@ function do_twofa_check(init = 0) {
     }
 }
 
-function do_ip_pas(i = 0) {
-    var get_class = document.getElementsByClassName('need_ip_pas')[i];
-    if(undefined) {
-        // 완성해야함
-        do_ip_pas(i + 1);
-        
-        var ip = get_class.innerHTML;
-        
-        ip = '<a href="' + encodeURIComponent(ip) + '">' + ip + '</a>';
-        ip += ' <a href="/tool/' + encodeURIComponent(ip) + '">(T)</a>';
-        
-        document.getElementsByClassName('need_ip_pas')[i].innerHTML = ip;
-    }
-}
-
 function send_render(i = 0) {
     var get_class = document.getElementsByClassName('send_content')[i];
     if(get_class) {

+ 9 - 0
views/main_css/js/render_markdown.js

@@ -0,0 +1,9 @@
+function do_markdown_render(
+    test_mode = 'test', 
+    name_id = '', 
+    name_include = '', 
+    name_doc = '', 
+    doc_data = ''
+) {
+    
+}

+ 15 - 12
views/main_css/js/render_onmark.js

@@ -1,4 +1,3 @@
-// 표 캡션
 // 중괄호 문법 정리
 // Tool
 function do_url_change(data) {
@@ -141,7 +140,7 @@ function do_onmark_text_render(data) {
     return data;
 }
 
-function do_onmark_heading_render(data, name_doc, name_include) {
+function do_onmark_heading_render(data, data_js, name_doc, name_include) {
     var heading_re = /\n(={1,6})(#)? ?([^=]+) ?#?={1,6}\n/;
     var heading_level_all = [0, 0, 0, 0, 0, 0];
     var toc_data = '';
@@ -181,6 +180,7 @@ function do_onmark_heading_render(data, name_doc, name_include) {
         
         var heading_level_string_no_end = heading_level_string.replace(/\.$/, '');
         var heading_data_text = heading_data[3].replace(/ #$/, '');
+        heading_data_text = heading_data_text.replace(/ $/, '');
         
         toc_data += '' +
             '<span style="margin-left: ' + String((heading_level_string.match(/\./g).length - 1) * 10) + 'px;">' +
@@ -193,8 +193,8 @@ function do_onmark_heading_render(data, name_doc, name_include) {
         data = data.replace(heading_re, 
             '\n<start_point>' +
             (toc_n === 1 ? '' : '</div>') +
-            '<h' + heading_level + ' id="s-' + heading_level_string_no_end + '">' + 
-                '<a href="#toc">' + heading_level_string + '</a> ' + 
+            '<h' + heading_level + ' class="render_heading_text">' + 
+                '<a href="#toc" id="s-' + heading_level_string_no_end + '">' + heading_level_string + '</a> ' + 
                 heading_data_text + 
                 '<a id="edit_load_' + String(toc_n) + '" ' +
                     'style="font-size: 70%;"' +
@@ -539,7 +539,7 @@ function do_onmark_footnote_render(data, name_include) {
 function do_onmark_macro_render(data, data_js) {
     data = data.replace(/\[([^[\](]+)\(((?:(?!\)\]).)+)\)\]/g, function(x, x_1, x_2) {
         x_1 = x_1.toLowerCase();
-        if(x_1 === 'youtube' || x_1 === 'kakaotv' || x_1 === 'nicovideo') {
+        if(x_1 === 'youtube' || x_1 === 'kakaotv' || x_1 === 'nicovideo' || x_1 === 'navertv') {
             var video_code = x_2.match(/^([^,]+)/);
             video_code = video_code ? video_code[1] : '';
             
@@ -551,7 +551,7 @@ function do_onmark_macro_render(data, data_js) {
             
             if(x_1 === 'youtube') {
                 var video_start = x_2.match(/,(?: *)start=([0-9]+)/);
-                video_start = video_start ? ('?' + video_start[1]) : '';
+                video_start = video_start ? ('?start=' + video_start[1]) : '';
                 
                 video_code = video_code.replace(/^https:\/\/www\.youtube\.com\/watch\?v=/, '');
                 video_code = video_code.replace(/^https:\/\/youtu\.be\//, '');
@@ -562,9 +562,11 @@ function do_onmark_macro_render(data, data_js) {
                 video_code = video_code.replace(/^http:\/\/tv\.kakao\.com\/v\//, '');
                 
                 var video_src = 'https://tv.kakao.com/embed/player/cliplink/' + video_code +'?service=kakao_tv'
-            } else {
+            } else if(x_1 === 'nicovideo') {
                 var video_src = 'https://embed.nicovideo.jp/watch/' + video_code
-            }
+            } else {
+				var video_src = 'https://tv.naver.com/embed/' + video_code
+			}
             
             return '<iframe style="width: ' + video_width + '; height: ' + video_height + ';" src="' + video_src + '" frameborder="0" allowfullscreen></iframe>';
         } else if(x_1 === 'anchor') {
@@ -1004,7 +1006,7 @@ function do_onmark_table_render_sub(data, data_col) {
 }
 
 function do_onmark_table_render_main(data) {
-    var table_re = /\n((?:(?:(?:(?:\|\|)+)|(?:\|[^|]+\|(?:\|\|)*))(?!\n)(?:(?:(?!\|\|).)+))(?:(?:\|\||\|\|\n|(?:\|\|)+(?!\n)(?:(?:(?!\|\|).)+))*)\|\|)\n/gs;
+    var table_re = /\n((?:(?:(?:(?:\|\|)+)|(?:\|[^|]+\|(?:\|\|)*))\n?(?:(?:(?!\|\|).)+))(?:(?:\|\||\|\|\n|(?:\|\|)+(?!\n)(?:(?:(?!\|\|).)+)\n*)*)\|\|)\n/gs;
     data = data.replace(table_re, function(x, x_1) {
         var table_cel_re = /((?:\|\|)+)((?:(?!\|\|).)*)/gs;
         var table_data = '';
@@ -1246,11 +1248,11 @@ function do_onmark_redirect_render(data, data_js, name_doc) {
             window.location.search === '' &&
             window.location.pathname.match(/^\/w\//)
         ) {
-            window.location.href = '/w/' + do_url_change(link_main) + '?from=' + do_url_change(name_doc) + link_sub;
+            window.location.href = '/w/' + do_url_change(link_main) + '/doc_from/' + do_url_change(name_doc) + link_sub;
         }
         
         return [
-            data.replace(redirect_re, '/w/' + do_url_change(link_main) + '?from=' + do_url_change(name_doc) + link_sub), 
+            data.replace(redirect_re, '/w/' + do_url_change(link_main) + '/doc_from/' + do_url_change(name_doc) + link_sub), 
             data_js, 
             1
         ];
@@ -1343,6 +1345,7 @@ function do_onmark_render(
     data_js += '' + 
         'get_link_state("' + name_include + '");\n' + 
         'get_file_state("' + name_include + '");\n' + 
+		'get_heading_name();'
     ''
     data_js += 'render_html("' + name_include + 'nowiki_html");\n'
     
@@ -1354,4 +1357,4 @@ function do_onmark_render(
     } else {
     	console.log([data, data_js]);
     }
-}
+}

+ 7 - 0
views/main_css/js/render_namumark.js → views/main_css/js/render_wiki.js

@@ -52,6 +52,13 @@ function get_link_state(data) {
     }
 }
 
+function get_heading_name() {
+	let heading_name = document.getElementsByClassName('render_heading_text');
+	for(let i = 0; i < heading_name.length; i++) {
+		heading_name[i].id = heading_name[i].innerText.replace(/^([0-9]+\.)+ /, '').replace(/✎ ⊖$/, '');
+	}
+}
+
 function load_image_link(data) {
     data.innerHTML = '' +
         '<img   style="' + data.getAttribute('under_style') + '" ' + 

+ 4 - 2
views/tenshi/css/main.css

@@ -460,8 +460,10 @@ div#last_edit {
 }
 
 blockquote {
-    background: #ffefff;
-    padding: 20px;
+    background-color: #ffefff;
+
+    padding: 15px 40px 15px 15px;
     border-left: 4px solid #ffb3ff;
+    
     margin-bottom: 20px;
 }