Selaa lähdekoodia

Merge pull request #1982 from openNAMU/dev

Dev
잉여개발기 2 vuotta sitten
vanhempi
sitoutus
ee3d36bba8

+ 2 - 0
.dockerignore

@@ -11,6 +11,7 @@ route/tool/set_mark/custom.py
 images
 
 .vscode
+.vs
 goorm.manifest
 .DS_Store
 
@@ -29,6 +30,7 @@ views/before_namu
 views/acme
 views/sl_open
 views/nitori
+views/jsonnamu
 
 sitemap.xml
 sitemap_0.xml

+ 59 - 44
app.py

@@ -3,6 +3,7 @@ import os
 import re
 import logging
 import shutil
+import datetime
 
 from route.tool.func import *
 from route import *
@@ -225,7 +226,7 @@ with get_db_connect() as conn:
             try:
                 shutil.copyfile(
                     data_db_set['name'] + '.db', 
-                    back_up_where
+                    back_up_where.replace('%t', datetime.datetime.now().strftime('%Y-%m-%d_%H.%M.%S'))
                 )
 
                 print('Back up : OK')
@@ -240,7 +241,7 @@ with get_db_connect() as conn:
 
         curs.execute(db_change('select data from other where name = "back_up"'))
         back_time = curs.fetchall()
-        back_time = int(number_check(back_time[0][0])) if back_time and back_time[0][0] != '' else 0
+        back_time = float(number_check(back_time[0][0], True)) if back_time and back_time[0][0] != '' else 0
         if back_time != 0:
             curs.execute(db_change('select data from other where name = "backup_where"'))
             back_up_where = curs.fetchall()
@@ -268,44 +269,49 @@ db_set_str = json.dumps(data_db_set)
 
 # Func
 # Func-inter_wiki
-app.route('/inter_wiki', defaults = { 'tool' : 'inter_wiki' })(filter_inter_wiki)
-app.route('/inter_wiki/del/<everything:name>', defaults = { 'tool' : 'del_inter_wiki' })(filter_inter_wiki_delete)
-app.route('/inter_wiki/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_inter_wiki' })(filter_inter_wiki_add)
-app.route('/inter_wiki/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_inter_wiki' })(filter_inter_wiki_add)
-
-app.route('/filter/document/list')(filter_document)
-app.route('/filter/document/add/<everything:name>', methods = ['POST', 'GET'])(filter_document_add)
-app.route('/filter/document/add', methods = ['POST', 'GET'])(filter_document_add)
-app.route('/filter/document/del/<name>')(filter_document_delete)
-
-app.route('/edit_top', defaults = { 'tool' : 'edit_top' })(filter_inter_wiki)
-app.route('/edit_top/del/<everything:name>', defaults = { 'tool' : 'del_edit_top' })(filter_inter_wiki_delete)
-app.route('/edit_top/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_top' })(filter_inter_wiki_add)
-
-app.route('/image_license', defaults = { 'tool' : 'image_license' })(filter_inter_wiki)
-app.route('/image_license/del/<everything:name>', defaults = { 'tool' : 'del_image_license' })(filter_inter_wiki_delete)
-app.route('/image_license/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_image_license' })(filter_inter_wiki_add)
-
-app.route('/edit_filter', defaults = { 'tool' : 'edit_filter' })(filter_inter_wiki)
-app.route('/edit_filter/del/<everything:name>', defaults = { 'tool' : 'del_edit_filter' })(filter_inter_wiki_delete)
-app.route('/edit_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_filter' })(filter_inter_wiki_add)
-app.route('/edit_filter/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_filter' })(filter_inter_wiki_add)
-
-app.route('/email_filter', defaults = { 'tool' : 'email_filter' })(filter_inter_wiki)
-app.route('/email_filter/del/<everything:name>', defaults = { 'tool' : 'del_email_filter' })(filter_inter_wiki_delete)
-app.route('/email_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_email_filter' })(filter_inter_wiki_add)
-
-app.route('/file_filter', defaults = { 'tool' : 'file_filter' })(filter_inter_wiki)
-app.route('/file_filter/del/<everything:name>', defaults = { 'tool' : 'del_file_filter' })(filter_inter_wiki_delete)
-app.route('/file_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_file_filter' })(filter_inter_wiki_add)
-
-app.route('/name_filter', defaults = { 'tool' : 'name_filter' })(filter_inter_wiki)
-app.route('/name_filter/del/<everything:name>', defaults = { 'tool' : 'del_name_filter' })(filter_inter_wiki_delete)
-app.route('/name_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_name_filter' })(filter_inter_wiki_add)
-
-app.route('/extension_filter', defaults = { 'tool' : 'extension_filter' })(filter_inter_wiki)
-app.route('/extension_filter/del/<everything:name>', defaults = { 'tool' : 'del_extension_filter' })(filter_inter_wiki_delete)
-app.route('/extension_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_extension_filter' })(filter_inter_wiki_add)
+app.route('/filter/inter_wiki', defaults = { 'tool' : 'inter_wiki' })(filter_all)
+app.route('/filter/inter_wiki/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'inter_wiki' })(filter_all_add)
+app.route('/filter/inter_wiki/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'inter_wiki' })(filter_all_add)
+app.route('/filter/inter_wiki/del/<everything:name>', defaults = { 'tool' : 'inter_wiki' })(filter_all_delete)
+
+app.route('/filter/outer_link', defaults = { 'tool' : 'outer_link' })(filter_all)
+app.route('/filter/outer_link/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'outer_link' })(filter_all_add)
+app.route('/filter/outer_link/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'outer_link' })(filter_all_add)
+app.route('/filter/outer_link/del/<everything:name>', defaults = { 'tool' : 'outer_link' })(filter_all_delete)
+
+app.route('/filter/document', defaults = { 'tool' : 'document' })(filter_all)
+app.route('/filter/document/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'document' })(filter_all_add)
+app.route('/filter/document/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'document' })(filter_all_add)
+app.route('/filter/document/del/<everything:name>', defaults = { 'tool' : 'document' })(filter_all_delete)
+
+app.route('/filter/edit_top', defaults = { 'tool' : 'edit_top' })(filter_all)
+app.route('/filter/edit_top/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'edit_top' })(filter_all_add)
+app.route('/filter/edit_top/del/<everything:name>', defaults = { 'tool' : 'edit_top' })(filter_all_delete)
+
+app.route('/filter/image_license', defaults = { 'tool' : 'image_license' })(filter_all)
+app.route('/filter/image_license/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'image_license' })(filter_all_add)
+app.route('/filter/image_license/del/<everything:name>', defaults = { 'tool' : 'image_license' })(filter_all_delete)
+
+app.route('/filter/edit_filter', defaults = { 'tool' : 'edit_filter' })(filter_all)
+app.route('/filter/edit_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'edit_filter' })(filter_all_add)
+app.route('/filter/edit_filter/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'edit_filter' })(filter_all_add)
+app.route('/filter/edit_filter/del/<everything:name>', defaults = { 'tool' : 'edit_filter' })(filter_all_delete)
+
+app.route('/filter/email_filter', defaults = { 'tool' : 'email_filter' })(filter_all)
+app.route('/filter/email_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'email_filter' })(filter_all_add)
+app.route('/filter/email_filter/del/<everything:name>', defaults = { 'tool' : 'email_filter' })(filter_all_delete)
+
+app.route('/filter/file_filter', defaults = { 'tool' : 'file_filter' })(filter_all)
+app.route('/filter/file_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'file_filter' })(filter_all_add)
+app.route('/filter/file_filter/del/<everything:name>', defaults = { 'tool' : 'file_filter' })(filter_all_delete)
+
+app.route('/filter/name_filter', defaults = { 'tool' : 'name_filter' })(filter_all)
+app.route('/filter/name_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'name_filter' })(filter_all_add)
+app.route('/filter/name_filter/del/<everything:name>', defaults = { 'tool' : 'name_filter' })(filter_all_delete)
+
+app.route('/filter/extension_filter', defaults = { 'tool' : 'extension_filter' })(filter_all)
+app.route('/filter/extension_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'extension_filter' })(filter_all_add)
+app.route('/filter/extension_filter/del/<everything:name>', defaults = { 'tool' : 'extension_filter' })(filter_all_delete)
 
 # Func-list
 app.route('/list/document/old')(list_old_page)
@@ -376,14 +382,20 @@ app.route('/block_log/<regex("user"):tool>/<name>')(recent_block_2)
 app.route('/block_log/<regex("admin"):tool>/<name>')(recent_block_2)
 
 # Func-history
-app.route('/recent_change')(recent_change)
-app.route('/recent_changes')(recent_change)
+app.route('/recent_change', defaults = { 'tool' : 'recent' })(recent_change)
+app.route('/recent_change/<int:num>/<set_type>', defaults = { 'tool' : 'recent' })(recent_change)
+app.route('/recent_changes', defaults = { 'tool' : 'recent' })(recent_change)
+app.route('/recent_changes/<int:num>/<set_type>', defaults = { 'tool' : 'recent' })(recent_change)
 
 app.route('/record/<name>', defaults = { 'tool' : 'record' })(recent_change)
+app.route('/record/<int:num>/<set_type>/<name>', defaults = { 'tool' : 'record' })(recent_change)
+
 app.route('/record/reset/<name>', methods = ['POST', 'GET'])(recent_record_reset)
 app.route('/record/topic/<name>')(recent_record_topic)
 
 app.route('/history/<everything:name>', defaults = { 'tool' : 'history' }, methods = ['POST', 'GET'])(recent_change)
+app.route('/history_page/<int:num>/<set_type>/<everything:name>', defaults = { 'tool' : 'history' }, methods = ['POST', 'GET'])(recent_change)
+
 app.route('/history_tool/<int(signed = True):rev>/<everything:name>')(recent_history_tool)
 app.route('/history_delete/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])(recent_history_delete)
 app.route('/history_hidden/<int(signed = True):rev>/<everything:name>')(recent_history_hidden)
@@ -527,6 +539,8 @@ app.route('/vote/add', methods = ['POST', 'GET'])(vote_add)
 app.route('/bbs/main', defaults = { 'tool' : 'main' })(bbs_w)
 app.route('/bbs/make', methods = ['POST', 'GET'])(bbs_make)
 # app.route('/bbs/main/set')
+app.route('/bbs/hide/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_hide)
+app.route('/bbs/delete/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_delete)
 app.route('/bbs/w/<int:bbs_num>')(bbs_w)
 app.route('/bbs/set/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_w_set)
 app.route('/bbs/edit/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_w_edit)
@@ -639,5 +653,6 @@ if __name__ == "__main__":
         app,
         host = server_set['host'],
         port = int(server_set['port']),
-        clear_untrusted_proxy_headers = True
-    )
+        clear_untrusted_proxy_headers = True,
+        threads = os.cpu_count()
+    )

+ 3 - 1
lang/en-US.json

@@ -118,6 +118,7 @@
         "spread" : "Speard",
         "popup" : "Popup",
         "popover" : "Popover",
+        "trace" : "Trace",
         "_comment_1.1_" : "Time",
             "second" : "Second(s)",
             "hour" : "Hour(s)",
@@ -300,6 +301,7 @@
                 "list_view_change" : "Change how the number list is viewed",
                 "view_joke" : "Show contents of joke macro",
                 "math_scroll" : "Use scroll in math macros",
+                "view_history" : "Use trace in view",
             "_comment_" : "Option",
                 "change_to_normal" : "Change to plain text.",
                 "change_to_link" : "Change to Link.",
@@ -601,7 +603,7 @@
             "error_title_length_too_long" : "Documents title or Discussion topic length is too long. Maximum number of characters : ",
             "error_password_length_too_short" : "Password length is too short. Minimum number of characters : ",
             "error_password_require_for_wiki_access" : "A password is required to access the wiki.",
-            "timeout_error" : "Running is taking too long. Maximum running time (Second(s)) : ",
+            "timeout_error" : "Rendering time is too long. Maximum rendering time (Second(s)) : ",
         "_comment_3.2_" : "Warning",
             "http_warning" : "Warning: If you are not on HTTPS connection, your information can be leaked. The users themselves have responsibility to any problems that happen because of this.",
             "user_head_warning" : "User data will be deleted if you close the browser or when you sign in.",

+ 7 - 5
lang/ko-KR.json

@@ -548,7 +548,7 @@
     "hide_user_name": "가입자 이름 숨기기",
     "comment": "댓글",
     "reply": "대댓글",
-    "timeout_error": "실행 시간이 너무 오래 걸립니다. 최대 실행 시간 (초) : ",
+    "timeout_error": "렌더링 시간이 너무 오래 걸립니다. 최대 실행 시간 (초) : ",
     "footnote_render": "각주 렌더링",
     "footnote_number": "각주 번호 출력",
     "only_number": "숫자만",
@@ -570,8 +570,10 @@
     "table_scroll": "표에 스크롤 사용",
     "data": "데이터",
     "volume": "용량",
-    "list_view_change" : "숫자 리스트의 보기 방식 변경",
-    "view_joke" : "농담 매크로 내용 보이기",
-    "math_scroll" : "Math 매크로에서 스크롤 사용",
-    "remove_blind_thread" : "숨겨진 토론 보이지 않기"
+    "list_view_change": "숫자 리스트의 보기 방식 변경",
+    "view_joke": "농담 매크로 내용 보이기",
+    "math_scroll": "Math 매크로에서 스크롤 사용",
+    "remove_blind_thread": "숨겨진 토론 보이지 않기",
+    "trace": "추적",
+    "view_history": "문서 열람 추적 사용"
 }

+ 5 - 6
route/__init__.py

@@ -19,6 +19,8 @@ from route.api_bbs_w_comment_one import api_bbs_w_comment_one
 
 from route.bbs_w_edit import bbs_w_edit
 from route.bbs_make import bbs_make
+from route.bbs_hide import bbs_hide
+from route.bbs_delete import bbs_delete
 from route.bbs_w import bbs_w
 from route.bbs_w_post import bbs_w_post
 from route.bbs_w_set import bbs_w_set
@@ -34,12 +36,9 @@ from route.edit_move import edit_move
 from route.edit_revert import edit_revert
 from route.edit_upload import edit_upload
 
-from route.filter_document import filter_document
-from route.filter_document_add import filter_document_add
-from route.filter_document_delete import filter_document_delete
-from route.filter_inter_wiki import filter_inter_wiki
-from route.filter_inter_wiki_add import filter_inter_wiki_add
-from route.filter_inter_wiki_delete import filter_inter_wiki_delete
+from route.filter_all import filter_all
+from route.filter_all_add import filter_all_add
+from route.filter_all_delete import filter_all_delete
 
 from route.give_admin_groups import give_admin_groups_2
 from route.give_auth import give_auth

+ 22 - 0
route/bbs_delete.py

@@ -0,0 +1,22 @@
+from .tool.func import *
+
+def bbs_delete(bbs_num = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        curs.execute(db_change('select set_data from bbs_set where set_id = ? and set_name = "bbs_name"'), [bbs_num])
+        db_data = curs.fetchall()
+        if not db_data:
+            return redirect('/bbs/main')
+        else:
+            bbs_name = db_data[0][0]
+        
+        bbs_num_str = str(bbs_num)
+
+        if admin_check() != 1:
+            return redirect('/bbs/w/' + bbs_num_str)
+        
+        if flask.request.method == 'POST':
+            pass
+        else:
+            pass

+ 30 - 0
route/bbs_hide.py

@@ -0,0 +1,30 @@
+from .tool.func import *
+
+def bbs_hide(bbs_num = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        curs.execute(db_change('select set_data from bbs_set where set_id = ? and set_name = "bbs_name"'), [bbs_num])
+        db_data = curs.fetchall()
+        if not db_data:
+            return redirect('/bbs/main')
+        else:
+            bbs_name = db_data[0][0]
+        
+        bbs_num_str = str(bbs_num)
+
+        if admin_check() != 1:
+            return redirect('/bbs/w/' + bbs_num_str)
+        
+        if flask.request.method == 'POST':
+            pass
+        else:
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('bbs_hide'), wiki_set(), wiki_custom(), wiki_css(['(' + bbs_name + ')', 0])],
+                data = render_simple_set('''
+                    <form method="post">
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                '''),
+                menu = [['bbs/set/' + bbs_num_str, load_lang('return')]]
+            ))

+ 6 - 2
route/bbs_w.py

@@ -7,6 +7,8 @@ def bbs_w(bbs_num = '', tool = 'bbs'):
         data = ''
         title_name = ''
 
+        admin_auth = admin_check()
+
         if tool == 'bbs':
             curs.execute(db_change('select set_data from bbs_set where set_id = ? and set_name = "bbs_name"'), [bbs_num])
             db_data = curs.fetchall()
@@ -37,14 +39,16 @@ def bbs_w(bbs_num = '', tool = 'bbs'):
                     db_data_2 = curs.fetchall()
                     last_date = ('(' + db_data_2[0][0] + ')') if db_data_2 else ''
 
-                    data += '<li><a href="/bbs/w/' + for_a[1] + '">' + html.escape(for_a[0]) + ' (' + bbs_type + ') ' + last_date + '</a></li>'
+                    data += '<li>'
+                    data += '<a href="/bbs/w/' + for_a[1] + '">' + html.escape(for_a[0]) + '</a> (' + bbs_type + ') ' + last_date
+                    data += '</li>'
 
                 data += '</ul>'
             
             data += '<hr class="main_hr">'
 
             title_name = load_lang('bbs_main')
-            menu = [['other', load_lang('return')]] + ([['bbs/make', load_lang('add')]] if admin_check() == 1 else [])
+            menu = [['other', load_lang('return')]] + ([['bbs/make', load_lang('add')]] if admin_auth == 1 else [])
 
         data += '''
             <table id="main_table_set">

+ 1 - 1
route/bbs_w_edit.py

@@ -108,7 +108,7 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = ''):
                 for data_list in acl_list:
                     acl_div[for_a] += '<option value="' + data_list + '">' + (data_list if data_list != '' else 'normal') + '</option>'
     
-            editor_top_text = '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
+            editor_top_text = '<a href="/filter/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
 
             if editor_top_text != '':
                 editor_top_text += '<hr class="main_hr">'

+ 6 - 3
route/bbs_w_set.py

@@ -8,11 +8,12 @@ def bbs_w_set(bbs_num = ''):
         db_data = curs.fetchall()
         if not db_data:
             return redirect('/bbs/main')
+        else:
+            bbs_name = db_data[0][0]
         
-        bbs_name = db_data[0][0]
+        bbs_num_str = str(bbs_num)
 
         i_list = ['bbs_acl', 'bbs_edit_acl', 'bbs_comment_acl', 'bbs_view_acl', 'bbs_markup']
-        bbs_num_str = str(bbs_num)
 
         if flask.request.method == 'POST':
             if admin_check(None, 'bbs_set (acl)') != 1:
@@ -31,10 +32,12 @@ def bbs_w_set(bbs_num = ''):
         else:
             d_list = ['' for _ in range(0, len(i_list))]
 
+            other_menu = []
             if admin_check() != 1:
                 disable = 'disabled'
             else:
                 disable = ''
+                other_menu += [['bbs/hide/' + bbs_num_str, load_lang('hide')], ['bbs/delete/' + bbs_num_str, load_lang('delete')]]
 
             for for_a in range(len(i_list)):
                 curs.execute(db_change('select set_data from bbs_set where set_name = ? and set_id = ?'), [i_list[for_a], bbs_num])
@@ -88,5 +91,5 @@ def bbs_w_set(bbs_num = ''):
                         <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 '''),
-                menu = [['bbs/w/' + bbs_num_str, load_lang('return')]]
+                menu = [['bbs/w/' + bbs_num_str, load_lang('return')]] + other_menu
             ))

+ 1 - 1
route/edit.py

@@ -310,7 +310,7 @@ def edit(name = 'Test', section = 0, do_type = ''):
             if data_section == '':
                 data_section = data
     
-            editor_top_text += '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
+            editor_top_text += '<a href="/filter/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
     
             if editor_top_text != '':
                 editor_top_text += '<hr class="main_hr">'

+ 2 - 2
route/edit_upload.py

@@ -63,7 +63,7 @@ def edit_upload():
                 for i in db_data:
                     t_re = re.compile(i[0])
                     if t_re.search(name):
-                        return redirect('/file_filter')
+                        return redirect('/filter/file_filter')
 
                 data_url_image = load_image_url()
                 if os.path.exists(os.path.join(data_url_image, e_data)):
@@ -137,7 +137,7 @@ def edit_upload():
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('upload'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    <a href="/file_filter">(''' + load_lang('file_filter_list') + ''')</a> <a href="/extension_filter">(''' + load_lang('extension_filter_list') + ''')</a>
+                    <a href="/filter/file_filter">(''' + load_lang('file_filter_list') + ''')</a> <a href="/filter/extension_filter">(''' + load_lang('extension_filter_list') + ''')</a>
                     ''' + upload_help + '''
                     <hr class="main_hr">
                     ''' + load_lang('max_file_size') + ''' : ''' + str(file_max) + '''MB

+ 18 - 19
route/filter_inter_wiki.py → route/filter_all.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def filter_inter_wiki(tool):
+def filter_all(tool):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -17,35 +17,33 @@ def filter_inter_wiki(tool):
 
         if tool == 'inter_wiki':
             title = load_lang('interwiki_list')
-
             curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'inter_wiki'"))
         elif tool == 'email_filter':
             title = load_lang('email_filter_list')
-
             curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'email'"))
         elif tool == 'name_filter':
             title = load_lang('id_filter_list')
-
             curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'name'"))
         elif tool == 'edit_filter':
             title = load_lang('edit_filter_list')
-
             curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'regex_filter'"))
         elif tool == 'file_filter':
             title = load_lang('file_filter_list')
-
             curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'file'"))
         elif tool == 'image_license':
             title = load_lang('image_license_list')
-
             curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'image_license'"))
         elif tool == 'extension_filter':
             title = load_lang('extension_filter_list')
-
             curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'extension'"))
+        elif tool == 'document':
+            title = load_lang('document_filter_list')
+            curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'document'"))
+        elif tool == 'outer_link':
+            title = load_lang('outer_link_filter_list')
+            curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'outer_link'"))
         else:
             title = load_lang('edit_tool_list')
-
             curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'edit_top'"))
 
         db_data = curs.fetchall()
@@ -55,21 +53,22 @@ def filter_inter_wiki(tool):
 
             div += html.escape(data[0])
             if admin == 1:
-                if tool in ('inter_wiki', 'edit_filter'):
-                    div += ' <a href="/' + tool + '/add/' + url_pas(data[0]) + '">(' + load_lang('edit') + ')</a>'
+                if tool in ('inter_wiki', 'outer_link', 'edit_filter', 'document'):
+                    div += ' <a href="/filter/' + tool + '/add/' + url_pas(data[0]) + '">(' + load_lang('edit') + ')</a>'
                     
-                div += ' <a href="/' + tool + '/del/' + url_pas(data[0]) + '">(' + load_lang('delete') + ')</a>'
+                div += ' <a href="/filter/' + tool + '/del/' + url_pas(data[0]) + '">(' + load_lang('delete') + ')</a>'
 
             div += '</td>'
 
-            if tool == 'inter_wiki':
-                div += '<td><a class="opennamu_link_out" href="' + html.escape(data[1]) + '">' + html.escape(data[1]) + '</a></td>'
-            else:
-                div += '<td>' + html.escape(data[1]) + '</td>'
-
-            if tool == 'inter_wiki':
+            if tool in ('inter_wiki', 'outer_link'):
+                if tool == 'inter_wiki':
+                    div += '<td><a class="opennamu_link_out" href="' + html.escape(data[1]) + '">' + html.escape(data[1]) + '</a></td>'
+                else:
+                    div += '<td>' + html.escape(data[1]) + '</td>'
+                
                 div += '<td>' + data[2] + '</td>'
             else:
+                div += '<td>' + html.escape(data[1]) + '</td>'
                 div += '<td>' + html.escape(data[2]) + '</td>'
             
             div += '</tr>'
@@ -78,7 +77,7 @@ def filter_inter_wiki(tool):
 
         if admin == 1:
             div += '<hr class="main_hr">'
-            div += '<a href="/' + tool + '/add">(' + load_lang('add') + ')</a>'
+            div += '<a href="/filter/' + tool + '/add">(' + load_lang('add') + ')</a>'
 
         return easy_minify(flask.render_template(skin_check(),
             imp = [title, wiki_set(), wiki_custom(), wiki_css([0, 0])],

+ 94 - 92
route/filter_inter_wiki_add.py → route/filter_all_add.py

@@ -1,151 +1,130 @@
 from .tool.func import *
 
-def filter_inter_wiki_add(tool, name = None):
+def filter_all_add(tool, name = None):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
-        if not name and tool == 'plus_edit_filter':
+        if not name and tool == 'edit_filter':
             return redirect('/manager/9')
 
         if flask.request.method == 'POST':
             if admin_check() != 1:
                 return re_error('/error/3')
 
-            if tool == 'plus_inter_wiki':
-                if name:
-                    curs.execute(db_change("delete from html_filter where html = ? and kind = 'inter_wiki'"), [name])
-
-                curs.execute(db_change("delete from html_filter where html = ? and kind = 'inter_wiki'"), [
-                    flask.request.form.get('title', 'test')
-                ])
-                curs.execute(db_change('insert into html_filter (html, plus, plus_t, kind) values (?, ?, ?, "inter_wiki")'), [
-                    flask.request.form.get('title', 'test'),
-                    flask.request.form.get('link', 'test'),
-                    flask.request.form.get('icon', '')
-                ])
-
-                admin_check(None, 'inter_wiki_plus')
-            elif tool == 'plus_edit_filter':
-                if admin_check(None, 'edit_filter edit') != 1:
-                    return re_error('/error/3')
-
-                if flask.request.form.get('second', '0') == '0':
-                    end = 'X'
-                else:
-                    end = flask.request.form.get('second', 'X')
+            title = flask.request.form.get('title', 'test')
+            if tool in ('inter_wiki', 'outer_link'):
+                link = flask.request.form.get('link', 'test')
+                icon = flask.request.form.get('icon', '')
 
+                curs.execute(db_change("delete from html_filter where html = ? and kind = ?"), [title, tool])
+                curs.execute(db_change('insert into html_filter (html, plus, plus_t, kind) values (?, ?, ?, ?)'), [title, link, icon, tool])
+                admin_check(None, tool + ' edit')
+            elif tool == 'edit_filter':
+                sec = flask.request.form.get('second', '0')
+                end = 'X' if sec == '0' else sec
+
+                content = flask.request.form.get('content', 'test')
                 try:
-                    re.compile(flask.request.form.get('content', 'test'))
-
-                    curs.execute(db_change("delete from html_filter where html = ? and kind = 'regex_filter'"), [name])
-                    curs.execute(db_change("insert into html_filter (html, plus, plus_t, kind) values (?, ?, ?, 'regex_filter')"), [
-                        name,
-                        flask.request.form.get('content', 'test'),
-                        end
-                    ])
+                    re.compile(content)
                 except:
                     return re_error('/error/23')
+                
+                curs.execute(db_change("delete from html_filter where html = ? and kind = 'regex_filter'"), [name])
+                curs.execute(db_change("insert into html_filter (html, plus, plus_t, kind) values (?, ?, ?, 'regex_filter')"), [name, content, end])
+                admin_check(None, 'edit_filter edit')
+            elif tool == 'document':
+                post_name = flask.request.form.get('name', '')
+                if post_name == '':
+                    return redirect('/filter/document')
+            
+                post_acl = flask.request.form.get('acl', '')
+                post_regex = flask.request.form.get('regex', '')
+                try:
+                    re.compile(post_regex)
+                except:
+                    return re_error('/error/23')
+                
+                curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, "document", ?, ?)'), [post_name, post_regex, post_acl])
+                admin_check(None, 'document_filter edit')
             else:
                 plus_d = ''
-
-                if tool == 'plus_name_filter':
+                if tool == 'name_filter':
                     try:
-                        re.compile(flask.request.form.get('title', 'test'))
+                        re.compile(title)
                     except:
                         return re_error('/error/23')
 
                     admin_check(None, 'name_filter edit')
-
                     type_d = 'name'
-                elif tool == 'plus_file_filter':
+                elif tool == 'file_filter':
                     try:
-                        re.compile(flask.request.form.get('title', 'test'))
+                        re.compile(title)
                     except:
                         return re_error('/error/23')
 
                     admin_check(None, 'file_filter edit')
-
                     type_d = 'file'
-                elif tool == 'plus_email_filter':
+                elif tool == 'email_filter':
                     admin_check(None, 'email_filter edit')
-
                     type_d = 'email'
-                elif tool == 'plus_image_license':
+                elif tool == 'image_license':
                     admin_check(None, 'image_license edit')
-
                     type_d = 'image_license'
-                elif tool == 'plus_extension_filter':
+                elif tool == 'extension_filter':
                     admin_check(None, 'extension_filter edit')
-
                     type_d = 'extension'
                 else:
                     admin_check(None, 'edit_top edit')
-
                     type_d = 'edit_top'
                     plus_d = flask.request.form.get('markup', 'test')
 
                 if name:
-                    curs.execute(db_change("delete from html_filter where html = ? and kind = ?"), [
-                        name,
-                        type_d
-                    ])
-
-                curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, ?, ?, ?)'), [
-                    flask.request.form.get('title', 'test'),
-                    type_d,
-                    plus_d,
-                    ''
-                ])
+                    curs.execute(db_change("delete from html_filter where html = ? and kind = ?"), [name, type_d])
+
+                curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, ?, ?, ?)'), [title, type_d, plus_d, ''])
 
             conn.commit()
 
-            return redirect('/' + re.sub(r'^plus_', '', tool))
+            return redirect('/filter/' + tool)
         else:
-            # 추가 편집 구분 필요
-            # 각 파일 별로 분리 필요
             get_sub = 0
             stat = 'disabled' if admin_check() != 1 else ''
+            name = name if name else ''
 
-            if tool == 'plus_inter_wiki':
-                if name:
-                    curs.execute(db_change("select html, plus, plus_t from html_filter where html = ? and kind = 'inter_wiki'"), [name])
+            if tool in ('inter_wiki', 'outer_link'):
+                value = ['', '', '']
+                if name != '':
+                    curs.execute(db_change("select html, plus, plus_t from html_filter where html = ? and kind = ?"), [name, tool])
                     exist = curs.fetchall()
-                    if exist:
-                        value = exist[0]
-                    else:
-                        value = ['', '', '']
+                    value = exist[0] if exist else value
+
+                if tool == 'inter_wiki':
+                    ex = 'https://namu.wiki/w/'
                 else:
-                    value = ['', '', '']
+                    ex = 'youtube.com'
 
-                title = load_lang('interwiki_add')
+                title = load_lang('interwiki_add') if tool == 'inter_wiki' else load_lang('outer_link_add')
                 form_data = '''
                     ''' + load_lang('name') + '''
                     <hr class="main_hr">
                     <input value="''' + html.escape(value[0]) + '''" type="text" name="title">
                     <hr class="main_hr">
-                    ''' + load_lang('link') + '''
+                    ''' + load_lang('link') + ''' (EX : ''' + ex + ''')
                     <hr class="main_hr">
                     <input value="''' + html.escape(value[1]) + '''" type="text" name="link">
                     <hr class="main_hr">
-                    ''' + load_lang('icon') + ''' (HTML)
+                    ''' + load_lang('icon') + ''' (''' + ('HTML' if tool == 'inter_wiki' else load_lang('html_or_link')) + ''') (''' + load_lang('link') + ' EX' + ''' : /image/Test.svg)
                     <hr class="main_hr">
                     <input value="''' + html.escape(value[2]) + '''" type="text" name="icon">
                 '''
-            elif tool == 'plus_edit_filter':            
+            elif tool == 'edit_filter':            
                 curs.execute(db_change("select plus, plus_t from html_filter where html = ? and kind = 'regex_filter'"), [name])
                 exist = curs.fetchall()
                 if exist:
                     textarea = exist[0][0]
-
-                    if exist[0][1] == 'X':
-                        time_check = 'checked="checked"'
-                        time_data = ''
-                    else:
-                        time_check = ''
-                        time_data = exist[0][1]
+                    time_data = '' if exist[0][1] == 'X' else exist[0][1]
                 else:
                     textarea = ''
-                    time_check = ''
                     time_data = ''
 
                 insert_data = ''
@@ -169,41 +148,64 @@ def filter_inter_wiki_add(tool, name = None):
                     <hr class="main_hr">
                     <input placeholder="''' + load_lang('regex') + '''" name="content" value="''' + html.escape(textarea) + '''" type="text">
                 '''
-            elif tool == 'plus_name_filter':
+            elif tool == 'name_filter':
                 title = load_lang('id_filter_add')
                 form_data = '' + \
                     load_lang('regex') + \
                     '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
                 ''
-            elif tool == 'plus_file_filter':
+            elif tool == 'file_filter':
                 title = load_lang('file_filter_add')
                 form_data = '' + \
                     load_lang('regex') + \
                     '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
                 ''
-            elif tool == 'plus_email_filter':
+            elif tool == 'email_filter':
                 title = load_lang('email_filter_add')
                 form_data = '' + \
                     load_lang('email') + \
                     '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
                 ''
-            elif tool == 'plus_image_license':
+            elif tool == 'image_license':
                 title = load_lang('image_license_add')
                 form_data = '' + \
                     load_lang('license') + \
                     '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
                 ''
-            elif tool == 'plus_extension_filter':
+            elif tool == 'extension_filter':
                 title = load_lang('extension_filter_add')
                 form_data = '' + \
                     load_lang('extension') + \
                     '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
                 ''
+            elif tool == 'document':
+                acl_list = get_acl_list()
+                
+                curs.execute(db_change("select plus, plus_t from html_filter where html = ? and kind = 'document'"), [name])
+                db_data = curs.fetchall()
+                acl_list = [['selected' if db_data and db_data[0][1] == for_a else '', for_a] for for_a in acl_list]
+
+                title = load_lang('document_filter_add')
+                form_data = '''
+                    ''' + load_lang('name') + '''
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(name) + '''" type="text" name="name">
+                    <hr class="main_hr">
+                    ''' + load_lang('regex') + '''
+                    <hr class="main_hr">
+                    <input value="''' + (html.escape(db_data[0][0]) if db_data else '') + '''" type="text" name="regex">
+                    <hr class="main_hr">
+                    <a href="/acl/Test#exp">''' + load_lang('acl') + '''</a>
+                    <hr class="main_hr">
+                    <select name="acl">
+                        ''' + ''.join(['<option ' + for_a[0] + ' value=' + for_a[1] + '>' + ('normal' if for_a[1] == '' else for_a[1]) + '</option>' for for_a in acl_list]) + '''
+                    </select>
+                '''
             else:
                 title = load_lang('edit_tool_add')
                 if name:
@@ -219,7 +221,7 @@ def filter_inter_wiki_add(tool, name = None):
                 form_data = '''
                     ''' + load_lang('title') + '''
                     <hr class="main_hr">
-                    <input value="''' + html.escape(name if name else '') + '''" type="text" name="title">
+                    <input value="''' + html.escape(name) + '''" type="text" name="title">
                     <hr class="main_hr">
                     ''' + load_lang('markup') + '''
                     <hr class="main_hr">
@@ -235,5 +237,5 @@ def filter_inter_wiki_add(tool, name = None):
                             <button ''' + stat + ''' type="submit">''' + load_lang('add') + '''</button>
                         </form>
                         ''',
-                menu = [[re.sub('^plus_', '', tool), load_lang('return')]]
+                menu = [['filter/' + tool, load_lang('return')]]
             ))

+ 12 - 10
route/filter_inter_wiki_delete.py → route/filter_all_delete.py

@@ -1,29 +1,31 @@
 from .tool.func import *
 
-def filter_inter_wiki_delete(tool, name = 'Test'):
+def filter_all_delete(tool, name = 'Test'):
     with get_db_connect() as conn:
         curs = conn.cursor()
         
-        if admin_check(None, tool) != 1:
+        if admin_check(None, 'del_' + tool) != 1:
             return re_error('/error/3')
 
-        if tool == 'del_inter_wiki':
+        if tool == 'inter_wiki':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'inter_wiki'"), [name])
-        elif tool == 'del_edit_filter':
+        elif tool == 'edit_filter':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'regex_filter'"), [name])
-        elif tool == 'del_name_filter':
+        elif tool == 'name_filter':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'name'"), [name])
-        elif tool == 'del_file_filter':
+        elif tool == 'file_filter':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'file'"), [name])
-        elif tool == 'del_email_filter':
+        elif tool == 'email_filter':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'email'"), [name])
-        elif tool == 'del_image_license':
+        elif tool == 'image_license':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'image_license'"), [name])
-        elif tool == 'del_extension_filter':
+        elif tool == 'extension_filter':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'extension'"), [name])
+        elif tool == 'document':
+            curs.execute(db_change("delete from html_filter where html = ? and kind = 'document'"), [name])
         else:
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'edit_top'"), [name])
 
         conn.commit()
 
-        return redirect('/' + re.sub(r'^del_', '', tool))
+        return redirect('/filter/' + tool)

+ 0 - 41
route/filter_document.py

@@ -1,41 +0,0 @@
-from .tool.func import *
-
-def filter_document():
-    with get_db_connect() as conn:
-        curs = conn.cursor()
-
-        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()
-        title = load_lang('document_filter_list')
-        
-        curs.execute(db_change("select html, plus, plus_t from html_filter where kind = 'document'"))
-        db_data = curs.fetchall()
-        for data in db_data:
-            div += '<tr>'
-            div += '<td>' + html.escape(data[0])
-            if admin == 1:
-                div += ' <a href="/filter/document/add/' + url_pas(data[0]) + '">(' + load_lang('edit') + ')</a>'
-                div += ' <a href="/filter/document/del/' + url_pas(data[0]) + '">(' + load_lang('delete') + ')</a>'
-
-            div += '</td>'
-            div += '<td>' + html.escape(data[1]) + '</td>'
-            div += '<td>' + html.escape(data[2]) + '</td>'
-            div += '</tr>'
-
-        div += '</table>'
-
-        if admin == 1:
-            div += '<hr class="main_hr">'
-            div += '<a href="/filter/document/add">(' + load_lang('add') + ')</a>'
-
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [title, wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = div,
-            menu = [['manager/1', load_lang('return')]]
-        ))

+ 0 - 62
route/filter_document_add.py

@@ -1,62 +0,0 @@
-from .tool.func import *
-
-def filter_document_add(name = ''):
-    with get_db_connect() as conn:
-        curs = conn.cursor()
-
-        if flask.request.method == 'POST':
-            if admin_check(None, 'plus_document_filter') != 1:
-                return re_error('/error/3')
-
-            post_name = flask.request.form.get('name', '')
-            if post_name == '':
-                return redirect('/filter/document/list')
-            
-            post_acl = flask.request.form.get('acl', '')
-            post_regex = flask.request.form.get('regex', '')
-            try:
-                re.compile(post_regex)
-            except:
-                return re_error('/error/23')
-
-            curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, ?, ?, ?)'), [
-                post_name,
-                'document',
-                post_regex,
-                post_acl
-            ])
-
-            conn.commit()
-
-            return redirect('/filter/document/list')
-        else:
-            stat = 'disabled' if admin_check() != 1 else ''
-            acl_list = get_acl_list()
-            
-            curs.execute(db_change("select plus, plus_t from html_filter where html = ? and kind = 'document'"), [name])
-            db_data = curs.fetchall()
-            acl_list = [['selected' if db_data and db_data[0][1] == i else '', i] for i in acl_list]
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('document_filter_add'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data =  '''
-                        <form method="post">
-                            ''' + load_lang('name') + '''
-                            <hr class="main_hr">
-                            <input value="''' + html.escape(name) + '''" type="text" name="name">
-                            <hr class="main_hr">
-                            ''' + load_lang('regex') + '''
-                            <hr class="main_hr">
-                            <input value="''' + (html.escape(db_data[0][0]) if db_data else '') + '''" type="text" name="regex">
-                            <hr class="main_hr">
-                            <a href="/acl/Test#exp">''' + load_lang('acl') + '''</a>
-                            <hr class="main_hr">
-                            <select name="acl">
-                                ''' + ''.join(['<option ' + i[0] + ' value=' + i[1] + '>' + ('normal' if i[1] == '' else i[1]) + '</option>' for i in acl_list]) + '''
-                            </select>
-                            <hr class="main_hr">
-                            <button ''' + stat + ''' type="submit">''' + load_lang('add') + '''</button>
-                        </form>
-                        ''',
-                menu = [['filter/document/list', load_lang('return')]]
-            ))

+ 0 - 13
route/filter_document_delete.py

@@ -1,13 +0,0 @@
-from .tool.func import *
-
-def filter_document_delete(name = ''):
-    with get_db_connect() as conn:
-        curs = conn.cursor()
-
-        if admin_check(None, 'del_document_filter') != 1:
-            return re_error('/error/3')
-
-        curs.execute(db_change("delete from html_filter where html = ? and kind = 'document'"), [name])
-        conn.commit()
-
-        return redirect('/filter/document/list')

+ 2 - 2
route/login_find_email.py

@@ -32,7 +32,7 @@ def login_find_email(tool):
                         for i in re_set_list:
                             flask.session.pop(i, None)
                         
-                        return redirect('/email_filter')
+                        return redirect('/filter/email_filter')
                 else:
                     for i in re_set_list:
                         flask.session.pop(i, None)
@@ -103,7 +103,7 @@ def login_find_email(tool):
                 return easy_minify(flask.render_template(skin_check(),
                     imp = [load_lang('email'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                     data = '''
-                        <a href="/email_filter">(''' + load_lang('email_filter_list') + ''')</a>
+                        <a href="/filter/email_filter">(''' + load_lang('email_filter_list') + ''')</a>
                         <hr class="main_hr">
                         ''' + b_text + '''
                         <form method="post">

+ 2 - 2
route/login_register_email.py

@@ -19,7 +19,7 @@ def login_register_email_2():
                     "select html from html_filter where html = ? and kind = 'email'"
                 ), [email_data])
                 if not curs.fetchall():                
-                    return redirect('/email_filter')
+                    return redirect('/filter/email_filter')
 
             curs.execute(db_change('select data from other where name = "email_title"'))
             sql_d = curs.fetchall()
@@ -54,7 +54,7 @@ def login_register_email_2():
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('email'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    <a href="/email_filter">(''' + load_lang('email_filter_list') + ''')</a>
+                    <a href="/filter/email_filter">(''' + load_lang('email_filter_list') + ''')</a>
                     <hr class="main_hr">
                     ''' + b_text + '''
                     <form method="post">

+ 15 - 20
route/main_setting_main.py

@@ -23,7 +23,7 @@ def main_setting_main(db_set):
             19 : ['slow_edit', ''],
             20 : ['requires_approval', ''],
             21 : ['backup_where', ''],
-            22 : ['domain', flask.request.host],
+            22 : ['domain', ''],
             23 : ['ua_get', ''],
             24 : ['enable_comment', ''],
             25 : ['enable_challenge', ''],
@@ -131,7 +131,7 @@ def main_setting_main(db_set):
                         <select name="http_select">''' + tls_select + '''</select>
                         <hr class="main_hr">
 
-                        <span>''' + load_lang('domain') + '''</span> (EX : 2du.pythonanywhere.com)
+                        <span>''' + load_lang('domain') + '''</span> (EX : 2du.pythonanywhere.com) (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="domain" value="''' + html.escape(d_list[22]) + '''">
                         <hr class="main_hr">
@@ -156,9 +156,9 @@ def main_setting_main(db_set):
                         <select name="encode">''' + encode_select + '''</select>
                         <hr class="main_hr">
                         
-                        <input type="checkbox" name="wiki_access_password_need" ''' + check_box_div[8] + '''> ''' + load_lang('set_wiki_access_password_need') + ''' (''' + load_lang('restart_required') + ''') (''' + load_lang('beta') + ''')
+                        <input type="checkbox" name="wiki_access_password_need" ''' + check_box_div[8] + '''> ''' + load_lang('set_wiki_access_password_need') + ''' (''' + load_lang('restart_required') + ''')
                         <hr class="main_hr">
-                        <span>''' + load_lang('set_wiki_access_password') + ''' (''' + load_lang('restart_required') + ''') (''' + load_lang('beta') + ''')</span>
+                        <span>''' + load_lang('set_wiki_access_password') + '''</span> (''' + load_lang('restart_required') + ''')
                         <hr class="main_hr">
                         <input type="password" name="wiki_access_password" value="''' + html.escape(d_list[32]) + '''">
 
@@ -197,7 +197,7 @@ def main_setting_main(db_set):
                         <input type="checkbox" name="ua_get" ''' + check_box_div[4] + '''> ''' + load_lang('ua_get_off') + '''
                         <hr class="main_hr">
                         
-                        <span>''' + load_lang('password_min_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('password_min_length') + '''</span> (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="password_min_length" value="''' + html.escape(d_list[30]) + '''">
                         
@@ -209,37 +209,32 @@ def main_setting_main(db_set):
 
                         <span ''' + sqlite_only + '''>
                             <h3>''' + load_lang('sqlite_only') + '''</h3>
-                            <span>
-                                ''' + load_lang('backup_interval') + ''' (''' + load_lang('hour') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''') ''' + \
-                                '''(''' + load_lang('restart_required') + ''')</span>
+                            <span>''' + load_lang('backup_interval') + '''</span> (''' + load_lang('hour') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''') (''' + load_lang('restart_required') + ''')
                             <hr class="main_hr">
                             <input name="back_up" value="''' + html.escape(d_list[9]) + '''">
                             <hr class="main_hr">
-
-                            <span>
-                                ''' + load_lang('backup_where') + ''' (''' + load_lang('default') + ''' : ''' + load_lang('empty') + ''') ''' + \
-                                '''(''' + load_lang('restart_required') + ''') (''' + load_lang('example') + ''' : ./data/backup.db)
-                            </span>
+                            
+                            <span>''' + load_lang('backup_where') + '''</span> (''' + load_lang('default') + ''' : ''' + load_lang('empty') + ''') (''' + load_lang('restart_required') + ''') (''' + load_lang('example') + ''' : ./data/backup.db)
                             <hr class="main_hr">
                             <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
                             <hr class="main_hr">
                         </span>
 
                         <h2>''' + load_lang('edit_set') + '''</h2>
-                        <span>''' + load_lang('slow_edit') + ''' (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('slow_edit') + '''</span> (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="slow_edit" value="''' + html.escape(d_list[19]) + '''">
                         <hr class="main_hr">
                         
-                        <input type="checkbox" name="edit_bottom_compulsion" ''' + check_box_div[7] + '''> ''' + load_lang('edit_bottom_compulsion') + ''' (''' + load_lang('beta') + ''')
+                        <input type="checkbox" name="edit_bottom_compulsion" ''' + check_box_div[7] + '''> ''' + load_lang('edit_bottom_compulsion') + '''
                         <hr class="main_hr">
                         
-                        <span>''' + load_lang('title_max_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('title_max_length') + '''</span> (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="title_max_length" value="''' + html.escape(d_list[28]) + '''">
                         <hr class="main_hr">
                         
-                        <span>''' + load_lang('title_topic_max_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('title_topic_max_length') + '''</span> (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="title_topic_max_length" value="''' + html.escape(d_list[29]) + '''">
                         <hr class="main_hr">
@@ -249,18 +244,18 @@ def main_setting_main(db_set):
                         <input name="upload" value="''' + html.escape(d_list[4]) + '''">
                         <hr class="main_hr">
                         
-                        <input type="checkbox" name="history_recording_off" ''' + check_box_div[9] + '''> ''' + load_lang('set_history_recording_off') + ''' (''' + load_lang('beta') + ''')
+                        <input type="checkbox" name="history_recording_off" ''' + check_box_div[9] + '''> ''' + load_lang('set_history_recording_off') + '''
                         <hr class="main_hr">
 
                         <input type="checkbox" name="move_with_redirect" ''' + check_box_div[13] + '''> ''' + load_lang('move_with_redirect') + ''' (''' + load_lang('not_working') + ''')
                         <hr class="main_hr">
 
-                        <span>''' + load_lang('slow_thread') + ''' (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('slow_thread') + '''</span> (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="slow_thread" value="''' + html.escape(d_list[38]) + '''">
                         <hr class="main_hr">
 
-                        <span>''' + load_lang('edit_timeout') + ''' (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''') (''' + load_lang('linux_only') + ''')</span>
+                        <span>''' + load_lang('edit_timeout') + '''</span> (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''') (''' + load_lang('linux_only') + ''')
                         <hr class="main_hr">
                         <input name="edit_timeout" value="''' + html.escape(d_list[39]) + '''">
                         <hr class="main_hr">

+ 4 - 0
route/main_setting_skin_set.py

@@ -121,6 +121,10 @@ def main_setting_skin_set():
                         <select name="main_css_math_scroll">
                             ''' + set_data["main_css_math_scroll"] + '''
                         </select>
+                        <h3>''' + load_lang("view_history") + '''</h3>
+                        <select name="main_css_view_history">
+                            ''' + set_data["main_css_view_history"] + '''
+                        </select>
                         <h2>''' + load_lang("edit") + '''</h2>
                         <h3>''' + load_lang("image_paste") + '''</h3>
                         <sup>''' + load_lang('only_korean') + '''</sup> <sup>''' + load_lang('unavailable_in_monaco') + '''</sup>

+ 10 - 9
route/main_tool_admin.py

@@ -25,15 +25,16 @@ def main_tool_admin():
                 </ul>
                 <h3>''' + load_lang('filter') + '''</h3>
                 <ul class="opennamu_ul">
-                    <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
-                    <li><a href="/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
-                    <li><a href="/edit_top">''' + load_lang('edit_tool_list') + '''</a></li>
-                    <li><a href="/image_license">''' + load_lang('image_license_list') + '''</a></li>
-                    <li><a href="/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
-                    <li><a href="/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
-                    <li><a href="/file_filter">''' + load_lang('file_filter_list') + '''</a></li>
-                    <li><a href="/extension_filter">''' + load_lang('extension_filter_list') + '''</a></li>
-                    <li><a href="/filter/document/list">''' + load_lang('document_filter_list') + ''' (''' + load_lang('beta') + ''')</a></li>
+                    <li><a href="/filter/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
+                    <li><a href="/filter/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
+                    <li><a href="/filter/edit_top">''' + load_lang('edit_tool_list') + '''</a></li>
+                    <li><a href="/filter/image_license">''' + load_lang('image_license_list') + '''</a></li>
+                    <li><a href="/filter/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
+                    <li><a href="/filter/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
+                    <li><a href="/filter/file_filter">''' + load_lang('file_filter_list') + '''</a></li>
+                    <li><a href="/filter/extension_filter">''' + load_lang('extension_filter_list') + '''</a></li>
+                    <li><a href="/filter/document">''' + load_lang('document_filter_list') + '''</a></li>
+                    <li><a href="/filter/outer_link">''' + load_lang('outer_link_filter_list') + '''</a> (''' + load_lang('beta') + ''')
                 </ul>
                 <h3>''' + load_lang('server') + '''</h2>
                 <ul class="opennamu_ul">

+ 2 - 2
route/main_tool_redirect.py

@@ -5,12 +5,12 @@ def main_tool_redirect(num = 1, add_2 = ''):
         title_list = {
             0 : [load_lang('document_name'), '/acl', load_lang('acl')],
             1 : [0, '/list/user/check', load_lang('check')],
-            2 : [load_lang('file_name'), '/file_filter/add', load_lang('file_filter_add')],
+            2 : [load_lang('file_name'), '/filter/file_filter/add', load_lang('file_filter_add')],
             3 : [0, '/auth/give', load_lang('authorize')],
             4 : [0, '/record', load_lang('edit_record')],
             5 : [0, '/record/topic', load_lang('discussion_record')],
             6 : [load_lang('name'), '/admin_plus', load_lang('add_admin_group')],
-            7 : [load_lang('name'), '/edit_filter/add', load_lang('edit_filter_add')],
+            7 : [load_lang('name'), '/filter/edit_filter/add', load_lang('edit_filter_add')],
             8 : [load_lang('document_name'), '/search', load_lang('search')],
             9 : [0, '/block_log/user', load_lang('blocked_user')],
             10 : [0, '/block_log/admin', load_lang('blocked_admin')],

+ 101 - 93
route/recent_change.py

@@ -15,72 +15,59 @@ def recent_change_send_render(data):
 
     return data
 
-def recent_change(name = None, tool = ''):
+def recent_change(name = '', tool = '', num = 1, set_type = 'normal'):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
+        ip = ip_check()
+        all_admin = admin_check('all', None, ip)
+        owner = admin_check(None, None, ip)
+
         if flask.request.method == 'POST':
-            return redirect(
-                '/diff' + 
-                '/' + flask.request.form.get('b', '1') +
-                '/' + flask.request.form.get('a', '1') +
-                '/' + url_pas(name)
-            )
+            return redirect('/diff/' + flask.request.form.get('b', '1') + '/' + flask.request.form.get('a', '1') + '/' + url_pas(name))
         else:
             ban = ''
             select = ''
             sub = ''
-            admin = admin_check()
+            admin = owner
             div = '''
                 <table id="main_table_set">
                     <tbody>
                         <tr id="main_table_top_tr">
             '''
 
-            num = int(number_check(flask.request.args.get('num', '1')))
             sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
-            if name:
-                if tool == 'history':
-                    sub += ' (' + load_lang('history') + ')'
-
-                    div += '''
-                        <td id="main_table_width">''' + load_lang('version') + '''</td>
-                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                        <td id="main_table_width">''' + load_lang('time') + '''</td>
-                    '''
+            if tool == 'history':
+                div += '''
+                    <td id="main_table_width">''' + load_lang('version') + '''</td>
+                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                    <td id="main_table_width">''' + load_lang('time') + '''</td>
+                '''
+                sub = '(' + load_lang('history') + ')'
 
-                    set_type = flask.request.args.get('set', 'normal')
-                    set_type = '' if set_type == 'edit' else set_type
+                set_type = '' if set_type == 'edit' else set_type
+                if set_type != 'normal':
+                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where title = ? and type = ? order by id + 0 desc limit ?, 50'), [name, set_type, sql_num])
+                else:
+                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where title = ? order by id + 0 desc limit ?, 50'), [name, sql_num])
 
-                    if set_type != 'normal':
-                        curs.execute(db_change('' + \
-                            'select id, title, date, ip, send, leng, hide from history ' + \
-                            'where title = ? and type = ? ' + \
-                            'order by id + 0 desc ' + \
-                            "limit ?, 50" + \
-                        ''), [name, set_type, sql_num])
-                    else:
-                        curs.execute(db_change('' + \
-                            'select id, title, date, ip, send, leng, hide from history ' + \
-                            'where title = ? ' + \
-                            'order by id + 0 desc ' + \
-                            "limit ?, 50" + \
-                        ''), [name, sql_num])
+                data_list = curs.fetchall()
+            elif tool == 'record':
+                div +=  '''
+                    <td id="main_table_width">''' + load_lang('document_name') + '''</td>
+                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                    <td id="main_table_width">''' + load_lang('time') + '''</td>
+                '''
+                sub = '(' + load_lang('edit_record') + ')'
+                set_type = '' if set_type == 'edit' else set_type
 
-                    data_list = curs.fetchall()
+                if set_type != 'normal':
+                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where ip = ? and type = ? order by date desc limit ?, 50'), [name, set_type, sql_num])
                 else:
-                    div +=  '''
-                        <td id="main_table_width">''' + load_lang('document_name') + '''</td>
-                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                        <td id="main_table_width">''' + load_lang('time') + '''</td>
-                    '''
-
-                    curs.execute(db_change('' + \
-                        'select id, title, date, ip, send, leng, hide from history ' + \
-                        "where ip = ? order by date desc limit ?, 50" + \
-                    ''), [name, sql_num])
-                    data_list = curs.fetchall()
+                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where ip = ? order by date desc limit ?, 50'), [name, sql_num])
+                
+                data_list = curs.fetchall()
             else:
                 div +=  '''
                     <td id="main_table_width">''' + load_lang('document_name') + '''</td>
@@ -88,14 +75,22 @@ def recent_change(name = None, tool = ''):
                     <td id="main_table_width">''' + load_lang('time') + '''</td>
                 '''
                 sub = ''
-                set_type = flask.request.args.get('set', 'normal')
                 set_type = '' if set_type == 'edit' else set_type
 
                 data_list = []
-                curs.execute(db_change('select title, id from rc where type = ? order by date desc limit 50'), [set_type])
-                for i in curs.fetchall():
-                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where title = ? and id = ?'), i)
-                    data_list += curs.fetchall()
+
+                if num == 1 or all_admin != 1:
+                    curs.execute(db_change('select title, id from rc where type = ? order by date desc limit 50'), [set_type])
+                    for for_a in curs.fetchall():
+                        curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where title = ? and id = ?'), for_a)
+                        data_list += curs.fetchall()
+                else:
+                    if set_type != 'normal':
+                        curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where type = ? order by date desc limit ?, 50'), [sql_num])
+                    else:
+                        curs.execute(db_change('select id, title, date, ip, send, leng, hide from history order by date desc limit ?, 50'), [sql_num])
+
+                    data_list = curs.fetchall()
 
             div += '</tr>'
 
@@ -155,57 +150,70 @@ def recent_change(name = None, tool = ''):
                 </table>
             '''
 
-            if name:
-                if tool == 'history':
-                    div = '' + \
-                        '<a href="?set=normal">(' + load_lang('normal') + ')</a> ' + \
-                        '<a href="?set=edit">(' + load_lang('edit') + ')</a> ' + \
-                        '<a href="?set=move">(' + load_lang('move') + ')</a> ' + \
-                        '<a href="?set=delete">(' + load_lang('delete') + ')</a> ' + \
-                        '<a href="?set=revert">(' + load_lang('revert') + ')</a>' + \
-                        '<hr class="main_hr">' + div + \
-                    ''
-                    menu = [['w/' + url_pas(name), load_lang('return')]]
-
-                    if set_type == 'normal':
-                        div = '''
-                            <form method="post">
-                                <select name="a">''' + select + '''</select> <select name="b">''' + select + '''</select>
-                                <button type="submit">''' + load_lang('compare') + '''</button>
-                            </form>
-                            <hr class="main_hr">
-                        ''' + div
-
-                        if admin == 1:
-                            menu += [
-                                ['history_add/' + url_pas(name), load_lang('history_add')],
-                                ['history_reset/' + url_pas(name), load_lang('history_reset')]
-                            ]
-
-                    title = name
-                    div += next_fix('/history/' + url_pas(name) + '?tool=' + set_type + '&num=', num, data_list)
-                else:
-                    title = load_lang('edit_record')
-                    menu = [
-                        ['other', load_lang('other')], 
-                        ['user', load_lang('user')],
-                        ['record/reset/' + url_pas(name), load_lang('record_reset')]
+            if tool == 'history':
+                div = '' + \
+                    '<a href="/history_page/1/normal/' + url_pas(name) + '">(' + load_lang('normal') + ')</a> ' + \
+                    '<a href="/history_page/1/edit/' + url_pas(name) + '">(' + load_lang('edit') + ')</a> ' + \
+                    '<a href="/history_page/1/move/' + url_pas(name) + '">(' + load_lang('move') + ')</a> ' + \
+                    '<a href="/history_page/1/delete/' + url_pas(name) + '">(' + load_lang('delete') + ')</a> ' + \
+                    '<a href="/history_page/1/revert/' + url_pas(name) + '">(' + load_lang('revert') + ')</a>' + \
+                    '<hr class="main_hr">' + div + \
+                ''
+                menu = [['w/' + url_pas(name), load_lang('return')]]
+
+                if set_type == 'normal':
+                    div = '''
+                        <form method="post">
+                            <select name="a">''' + select + '''</select> <select name="b">''' + select + '''</select>
+                            <button type="submit">''' + load_lang('compare') + '''</button>
+                        </form>
+                        <hr class="main_hr">
+                    ''' + div
+
+                if admin == 1:
+                    menu += [
+                        ['history_add/' + url_pas(name), load_lang('history_add')],
+                        ['history_reset/' + url_pas(name), load_lang('history_reset')]
                     ]
-                    div += next_fix('/record/' + url_pas(name) + '?num=', num, data_list)
+
+                title = name
+                div += get_next_page_bottom('/history_page/{}/' + set_type + '/' + url_pas(name), num, data_list)
+            elif tool == 'record':
+                div = '' + \
+                    '<a href="/record/1/normal/' + url_pas(name) + '">(' + load_lang('normal') + ')</a> ' + \
+                    '<a href="/record/1/edit/' + url_pas(name) + '">(' + load_lang('edit') + ')</a> ' + \
+                    '<a href="/record/1/move/' + url_pas(name) + '">(' + load_lang('move') + ')</a> ' + \
+                    '<a href="/record/1/delete/' + url_pas(name) + '">(' + load_lang('delete') + ')</a> ' + \
+                    '<a href="/record/1/revert/' + url_pas(name) + '">(' + load_lang('revert') + ')</a>' + \
+                    '<hr class="main_hr">' + div + \
+                ''
+
+                title = name
+                menu = [
+                    ['other', load_lang('other')], 
+                    ['user', load_lang('user')]
+                ]
+                if admin == 1:
+                    menu += [['record/reset/' + url_pas(name), load_lang('record_reset')]]
+
+                div += get_next_page_bottom('/record/{}/' + url_pas(name), num, data_list)
             else:
                 div = '' + \
-                    '<a href="?set=normal">(' + load_lang('normal') + ')</a> ' + \
-                    '<a href="?set=edit">(' + load_lang('edit') + ')</a> ' + \
-                    '<a href="?set=user">(' + load_lang('user_document') + ')</a> ' + \
-                    '<a href="?set=move">(' + load_lang('move') + ')</a> ' + \
-                    '<a href="?set=delete">(' + load_lang('delete') + ')</a> ' + \
-                    '<a href="?set=revert">(' + load_lang('revert') + ')</a>' + \
+                    '<a href="/recent_change/1/normal">(' + load_lang('normal') + ')</a> ' + \
+                    '<a href="/recent_change/1/edit">(' + load_lang('edit') + ')</a> ' + \
+                    '<a href="/recent_change/1/user">(' + load_lang('user_document') + ')</a> ' + \
+                    '<a href="/recent_change/1/move">(' + load_lang('move') + ')</a> ' + \
+                    '<a href="/recent_change/1/delete">(' + load_lang('delete') + ')</a> ' + \
+                    '<a href="/recent_change/1/revert">(' + load_lang('revert') + ')</a>' + \
                     '<hr class="main_hr">' + div + \
                 ''
 
                 menu = [['other', load_lang('return')]]
                 title = load_lang('recent_change')
 
+                if all_admin == 1:
+                    div += get_next_page_bottom('/recent_change/{}/' + set_type, num, data_list)
+
             if sub == '':
                 sub = 0
 

+ 19 - 9
route/tool/func.py

@@ -362,7 +362,7 @@ def update(ver_num, set_data):
         if ver_num < 3170002:
             curs.execute(db_change("select html from html_filter where kind = 'extension'"))
             if not curs.fetchall():
-                for i in ['jpg', 'jpeg', 'png', 'gif', 'webp']:
+                for i in ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg']:
                     curs.execute(db_change("insert into html_filter (html, kind) values (?, 'extension')"), [i])
 
         if ver_num < 3170400:
@@ -753,9 +753,12 @@ def leng_check(A, B):
     # A -> old
     return '0' if A == B else (('-' + str(A - B)) if A > B else ('+' + str(B - A)))
 
-def number_check(data):
+def number_check(data, f=False):
     try:
-        int(data)
+        if f:
+            float(data)
+        else:
+            int(data)
         return data
     except:
         return '1'
@@ -814,6 +817,7 @@ def load_domain(data_type = 'normal'):
         curs = conn.cursor()
         
         domain = ''
+        sys_host = flask.request.host
         
         if data_type == 'full':
             curs.execute(db_change("select data from other where name = 'http_select'"))
@@ -823,11 +827,11 @@ def load_domain(data_type = 'normal'):
 
             curs.execute(db_change("select data from other where name = 'domain'"))
             db_data = curs.fetchall()
-            domain += db_data[0][0] if db_data and db_data[0][0] != '' else flask.request.host
+            domain += db_data[0][0] if db_data and db_data[0][0] != '' else sys_host
         else:
             curs.execute(db_change("select data from other where name = 'domain'"))
             db_data = curs.fetchall()
-            domain += db_data[0][0] if db_data and db_data[0][0] != '' else flask.request.host
+            domain += db_data[0][0] if db_data and db_data[0][0] != '' else sys_host
 
         return domain
 
@@ -854,7 +858,7 @@ def edit_button(ob_name = 'opennamu_edit_textarea', monaco_ob_name = 'opennamu_m
         for insert_data in insert_list:
             data += '<a href="javascript:do_insert_data(\'' + ob_name + '\', \'' + get_tool_js_safe(insert_data[0]) + '\', \'' + monaco_ob_name + '\');">(' + html.escape(insert_data[1]) + ')</a> '
 
-        data += (' ' if data != '' else '') + '<a href="/edit_top">(' + load_lang('add') + ')</a>'
+        data += (' ' if data != '' else '') + '<a href="/filter/edit_top">(' + load_lang('add') + ')</a>'
         data += '<hr class="main_hr">'
         
         return data
@@ -1375,6 +1379,8 @@ def render_set(doc_name = '', doc_data = '', data_type = 'view', data_in = '', d
                         <style>
                             .opennamu_render_complete {
                                 font-size: 14.4px !important;
+
+                                line-height: 1.5;
                             }
 
                             .opennamu_render_complete td {
@@ -1645,6 +1651,10 @@ def do_user_name_check(user_name):
         # IP와 혼동 방지 
         if ip_or_user(user_name) == 1:
             return 1
+        
+        # 슬래시 불가능
+        if user_name.find('/') != -1:
+            return 1
 
         # ID 필터
         curs.execute(db_change('select html from html_filter where kind = "name"'))
@@ -2650,7 +2660,7 @@ def re_error(data):
             elif num == 8:
                 data = '' + \
                     load_lang('long_id_error') + '<br>' + \
-                    load_lang('id_char_error') + ' <a href="/name_filter">(' + load_lang('id_filter_list') + ')</a><br>' + \
+                    load_lang('id_char_error') + ' <a href="/filter/name_filter">(' + load_lang('id_filter_list') + ')</a><br>' + \
                     load_lang('same_id_exist_error') + \
                 ''
             elif num == 9:
@@ -2664,7 +2674,7 @@ def re_error(data):
             elif num == 13:
                 data = load_lang('recaptcha_error')
             elif num == 14:
-                data = load_lang('file_extension_error') + ' <a href="/extension_filter">(' + load_lang('extension_filter_list') + ')</a>'
+                data = load_lang('file_extension_error') + ' <a href="/filter/extension_filter">(' + load_lang('extension_filter_list') + ')</a>'
             elif num == 15:
                 data = load_lang('edit_record_error')
             elif num == 16:
@@ -2772,4 +2782,4 @@ def re_error(data):
                         '</ul>' + \
                     '',
                     menu = 0
-                )), 400
+                )), 400

+ 49 - 19
route/tool/func_render_namumark.py

@@ -1107,8 +1107,34 @@ class class_do_render_namumark:
                         link_sub = ''
                         link_sub_storage = link_main_org
 
-                    data_name = self.get_tool_data_storage('<a class="opennamu_link_out" target="_blank" title="' + link_title + '" href="' + link_main + '">' + link_sub_storage, '</a>', link_data_full)
+                    domain = ''
+                    try:
+                        domain = urllib.parse.urlparse(link_main).netloc
+                    except:
+                        pass
+
+                    link_inter_icon = ''
+                    link_class = 'opennamu_link_out'
+
+                    self.curs.execute(db_change("select html, plus_t from html_filter where kind = 'outer_link' and plus = ?"), [domain])
+                    db_data = self.curs.fetchall()
+                    if db_data:
+                        if db_data[0][1] != '':
+                            if re.search(r'<|>', db_data[0][1]):
+                                link_inter_icon = db_data[0][1]
+                                link_class = 'opennamu_link_inter'
+                            else:
+                                if self.get_tool_data_restore(link_sub).find('"' + db_data[0][1] + '"') != -1:
+                                    link_inter_icon = ''
+                                    link_class = 'opennamu_link_inter'
+                                else:
+                                    link_inter_icon = '<img src="' + db_data[0][1] + '">'
+                                    link_class = 'opennamu_link_inter'
+                        else:
+                            link_inter_icon = db_data[0][0] + ':'
+                            link_class = 'opennamu_link_inter'
 
+                    data_name = self.get_tool_data_storage('<a class="' + link_class + '" target="_blank" title="' + link_title + '" href="' + link_main + '">' + link_inter_icon + link_sub_storage, '</a>', link_data_full)
                     self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
                 # in link
                 else:
@@ -1172,7 +1198,6 @@ class class_do_render_namumark:
                         link_sub_storage = link_main_org
 
                     data_name = self.get_tool_data_storage('<a class="' + link_exist + ' ' + link_same + '" title="' + link_title + '" href="' + link_main + link_data_sharp + '">' + link_sub_storage, '</a>', link_data_full)
-
                     self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
 
             link_count_all -= 1
@@ -1684,9 +1709,6 @@ class class_do_render_namumark:
                     table_data_in = table_sub[3]
                     table_data_in = re.sub(r'^\n+', '', table_data_in)
 
-                    table_sub_parameter = do_render_table_parameter(table_sub[1], table_sub[2], table_data_in)
-                    table_parameter["tr"] += table_sub_parameter['tr']
-
                     if table_sub[0] != '' and table_tr_change == 1:
                         table_col_num = 0
                         table_data_end += '<tr style="' + table_parameter["tr"] + '">' + table_parameter["td"] + '</tr>'
@@ -1694,6 +1716,9 @@ class class_do_render_namumark:
                         table_parameter["tr"] = ""
                         table_parameter["td"] = ""
 
+                    table_sub_parameter = do_render_table_parameter(table_sub[1], table_sub[2], table_data_in)
+                    table_parameter["tr"] += table_sub_parameter['tr']
+
                     if not table_col_num in table_parameter['rowspan']:
                         table_parameter['rowspan'][table_col_num] = 0
                     else:
@@ -1858,13 +1883,28 @@ class class_do_render_namumark:
 
                         data_name = self.get_tool_data_storage('<pre id="syntax"><code class="' + wiki_data_syntax + '">' + wiki_data, '</code></pre>', middle_data_org)
                         syntax_count += 1
-                    elif middle_name in ('+5', '+4', '+3', '+2', '+1'):
+                    elif middle_name in ('#!dark', '#!white'):
                         if middle_slash:
                             middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+)(?:[^<>]+))>', '<temp_' + middle_slash + '>', middle_data_org)
                             self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                             continue
 
-                        wiki_data = re.sub(r'^\+[1-5]( |\n)', '', middle_data)
+                        wiki_data = re.sub(r'^#!(dark|white)( |\n)', '', middle_data)
+                        if middle_name == '#!dark' and self.darkmode == '1':
+                            middle_data_pass = wiki_data
+                        elif middle_name == '#!white' and self.darkmode == '0':
+                            middle_data_pass = wiki_data
+                        else:
+                            middle_data_pass = ''
+                        
+                        data_name = self.get_tool_data_storage('', '', middle_data_org)
+                    elif middle_name in ('+5', '+4', '+3', '+2', '+1', '-5', '-4', '-3', '-2', '-1'):
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+)(?:[^<>]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_data = re.sub(r'^(\+|\-)[1-5]( |\n)', '', middle_data)
                         if middle_name == '+5':
                             wiki_size = '200'
                         elif middle_name == '+4':
@@ -1873,19 +1913,9 @@ class class_do_render_namumark:
                             wiki_size = '160'
                         elif middle_name == '+2':
                             wiki_size = '140'
-                        else:
+                        elif middle_name == '+1':
                             wiki_size = '120'
-
-                        middle_data_pass = wiki_data
-                        data_name = self.get_tool_data_storage('<span style="font-size:' + wiki_size + '%">', '</span>', middle_data_org)
-                    elif middle_name in ('-5', '-4', '-3', '-2', '-1'):
-                        if middle_slash:
-                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+)(?:[^<>]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
-                            continue
-
-                        wiki_data = re.sub(r'^\-[1-5]( |\n)', '', middle_data)
-                        if middle_name == '-5':
+                        elif middle_name == '-5':
                             wiki_size = '50'
                         elif middle_name == '-4':
                             wiki_size = '60'

+ 2 - 2
route/user_setting_email.py

@@ -21,7 +21,7 @@ def user_setting_email_2():
                     for i in re_set_list:
                         flask.session.pop(i, None)
 
-                    return redirect('/email_filter')
+                    return redirect('/filter/email_filter')
             else:
                 for i in re_set_list:
                     flask.session.pop(i, None)
@@ -63,7 +63,7 @@ def user_setting_email_2():
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('email'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    <a href="/email_filter">(''' + load_lang('email_filter_list') + ''')</a>
+                    <a href="/filter/email_filter">(''' + load_lang('email_filter_list') + ''')</a>
                     <hr class="main_hr">
                     ''' + b_text + '''
                     <form method="post">

+ 9 - 0
route/user_setting_skin_set_main.py

@@ -84,6 +84,10 @@ def user_setting_skin_set_main_set_list():
             ['default', load_lang('default')],
             ['off', load_lang('off')],
             ['on', load_lang('use')]
+        ], 'main_css_view_history' : [
+            ['default', load_lang('default')],
+            ['off', load_lang('off')],
+            ['on', load_lang('use')]
         ]
     }
 
@@ -244,6 +248,11 @@ def user_setting_skin_set_main():
                         <select name="main_css_math_scroll">
                             ''' + set_data["main_css_math_scroll"] + '''
                         </select>
+                        <h3>''' + load_lang("view_history") + '''</h3>
+                        ''' + set_data_main["main_css_view_history"] + '''
+                        <select name="main_css_view_history">
+                            ''' + set_data["main_css_view_history"] + '''
+                        </select>
                         <h2>''' + load_lang("edit") + '''</h2>
                         <h3>''' + load_lang("image_paste") + '''</h3>
                         <sup>''' + load_lang('only_korean') + '''</sup> <sup>''' + load_lang('unavailable_in_monaco') + '''</sup>

+ 17 - 0
route/view_read.py

@@ -247,6 +247,23 @@ def view_read(name = 'Test', doc_rev = '', doc_from = '', do_type = ''):
                 flask.session['lastest_document'] = flask.session['lastest_document'][-9:] + [name]
             else:
                 flask.session['lastest_document'] += [name]
+            
+            flask.session['lastest_document'] = list(reversed(dict.fromkeys(reversed(flask.session['lastest_document']))))
+
+            view_history_on = get_main_skin_set(curs, flask.session, 'main_css_view_history', ip)
+            if view_history_on == 'on':
+                end_data = '' + \
+                    '<div id="redirect">' + \
+                        load_lang('trace') + ' : ' + \
+                        ' ➥ '.join(
+                            [
+                                '<a href="/w/' + url_pas(for_a) + '">' + html.escape(for_a) + '</a>'
+                                for for_a in flask.session['lastest_document']
+                            ]
+                        ) + \
+                    '</div>' + \
+                    '<hr class="main_hr">' + \
+                '' + end_data
 
             if uppage != 0:
                 menu += [['w/' + url_pas(uppage), load_lang('upper')]]

+ 1 - 1
version.json

@@ -1,6 +1,6 @@
 {
     "beta" : {
-        "r_ver" : "v3.4.6-RC5-dev24",
+        "r_ver" : "v3.4.6-RC5-dev28",
         "c_ver" : "3500373",
         "s_ver" : "3500112"
     }

+ 4 - 0
views/main_css/css/main.css

@@ -269,6 +269,10 @@ hr {
     display: inline;
 }
 
+.opennamu_render_complete img {
+    vertical-align: middle;
+}
+
 blockquote {
     padding: 15px 40px 15px 15px;
     margin: 0;