Просмотр исходного кода

Merge pull request #1320 from openNAMU/dev

Dev
잉여개발기 (SPDV) 4 лет назад
Родитель
Сommit
22f23f57e8
66 измененных файлов с 4382 добавлено и 2612 удалено
  1. 93 398
      app.py
  2. 89 107
      emergency_tool.py
  3. 2 0
      lang/en-US.json
  4. 5 3
      lang/ko-KR.json
  5. 2 2
      readme-en.md
  6. 1 1
      readme.md
  7. 1 3
      route/api_image_view.py
  8. 9 8
      route/api_markup.py
  9. 22 21
      route/api_raw.py
  10. 22 22
      route/api_recent_change.py
  11. 17 16
      route/api_recent_discuss.py
  12. 24 32
      route/api_search.py
  13. 3 5
      route/api_sha224.py
  14. 42 41
      route/api_sitemap.py
  15. 49 48
      route/api_skin_info.py
  16. 11 10
      route/api_title_index.py
  17. 60 48
      route/api_topic_sub.py
  18. 62 61
      route/api_user_info.py
  19. 13 12
      route/api_version.py
  20. 80 90
      route/api_w.py
  21. 41 0
      route/filter_document.py
  22. 62 0
      route/filter_document_add.py
  23. 13 0
      route/filter_document_del.py
  24. 85 0
      route/filter_inter_wiki.py
  25. 237 0
      route/filter_inter_wiki_add.py
  26. 7 6
      route/filter_inter_wiki_del.py
  27. 0 84
      route/inter_wiki.py
  28. 0 236
      route/inter_wiki_add.py
  29. 1 3
      route/main_error_404.py
  30. 1 3
      route/main_func_easter_egg.py
  31. 13 0
      route/main_func_random.py
  32. 760 0
      route/main_func_setting.py
  33. 18 0
      route/main_func_skin_set.py
  34. 154 0
      route/main_func_upload.py
  35. 0 755
      route/main_setting.py
  36. 0 20
      route/main_skin_set.py
  37. 1 3
      route/main_sys_restart.py
  38. 1 3
      route/main_sys_shutdown.py
  39. 63 0
      route/main_sys_update.py
  40. 0 15
      route/main_test_func.py
  41. 0 12
      route/main_title_random.py
  42. 14 15
      route/main_tool_admin.py
  43. 1 3
      route/main_tool_other.py
  44. 0 62
      route/main_update.py
  45. 0 153
      route/main_upload.py
  46. 3 5
      route/main_view.py
  47. 3 5
      route/main_view_file.py
  48. 3 5
      route/main_view_image.py
  49. 141 66
      route/tool/func.py
  50. 1820 0
      route/tool/func_new.py
  51. 1 0
      route/tool/func_tool.py
  52. 132 108
      route/topic.py
  53. 47 68
      route/topic_close_list.py
  54. 37 23
      route/user_alarm.py
  55. 7 6
      route/user_alarm_del.py
  56. 4 0
      route/user_setting_email.py
  57. 4 0
      route/user_setting_email_check.py
  58. 6 7
      route/user_watch_list.py
  59. 2 0
      route/user_watch_list_name.py
  60. 1 1
      version.json
  61. 5 6
      views/main_css/js/load_something.js
  62. 3 3
      views/main_css/js/load_topic.js
  63. 2 0
      views/main_css/js/render_onmark.js
  64. 4 2
      views/main_css/js/render_wiki.js
  65. 47 1
      views/ringo/css/main.css
  66. 31 5
      views/ringo/index.html

+ 93 - 398
app.py

@@ -129,7 +129,8 @@ if data_db_set['type'] == 'mysql':
         data_db_set['mysql_port'] = '3306'
 
 db_data_get(data_db_set['type'])
-load_db = get_db_connect(data_db_set)
+do_db_set(data_db_set)
+load_db = get_db_connect_old(data_db_set)
 
 conn = load_db.db_load()
 curs = conn.cursor()
@@ -346,256 +347,44 @@ if os.path.exists('custom.py'):
     
 # Func
 # Func-inter_wiki
-app.add_url_rule(
-    rule = '/inter_wiki',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'inter_wiki' 
-    }, 
-    view_func = inter_wiki
-)
-
-app.add_url_rule(
-    rule = '/inter_wiki/del/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'del_inter_wiki',
-        'name' : 'Test'
-    }, 
-    view_func = inter_wiki_del
-)
-
-app.add_url_rule(
-    rule = '/inter_wiki/add',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_inter_wiki',
-        'name' : None
-    }, 
-    methods = ['GET', 'POST'],
-    view_func = inter_wiki_add
-)
-
-app.add_url_rule(
-    rule = '/edit_top',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'edit_top'
-    }, 
-    view_func = inter_wiki
-)
-
-app.add_url_rule(
-    rule = '/edit_top/del/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'del_edit_top',
-        'name' : 'Test'
-    }, 
-    view_func = inter_wiki_del
-)
-
-app.add_url_rule(
-    rule = '/edit_top/add',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_edit_top',
-        'name' : None
-    }, 
-    methods = ['GET', 'POST'],
-    view_func = inter_wiki_add
-)
-
-app.add_url_rule(
-    rule = '/image_license',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'image_license'
-    }, 
-    view_func = inter_wiki
-)
-
-app.add_url_rule(
-    rule = '/image_license/del/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'del_image_license',
-        'name' : 'Test'
-    }, 
-    view_func = inter_wiki_del
-)
-
-app.add_url_rule(
-    rule = '/image_license/add',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_image_license',
-        'name' : None
-    }, 
-    methods = ['GET', 'POST'],
-    view_func = inter_wiki_add
-)
-
-app.add_url_rule(
-    rule = '/edit_filter',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'edit_filter'
-    }, 
-    view_func = inter_wiki
-)
-
-app.add_url_rule(
-    rule = '/edit_filter/del/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'del_edit_filter',
-        'name' : 'Test'
-    }, 
-    view_func = inter_wiki_del
-)
-
-# 이거 수정 필요 할 듯
-app.add_url_rule(
-    rule = '/edit_filter/add',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_edit_filter',
-        'name' : None
-    }, 
-    view_func = inter_wiki_add
-)
-
-app.add_url_rule(
-    rule = '/edit_filter/add/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_edit_filter',
-        'name' : 'Test'
-    }, 
-    methods = ['GET', 'POST'],
-    view_func = inter_wiki_add
-)
-
-app.add_url_rule(
-    rule = '/email_filter',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'email_filter'
-    }, 
-    view_func = inter_wiki
-)
-
-app.add_url_rule(
-    rule = '/email_filter/del/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'del_email_filter',
-        'name' : 'Test'
-    }, 
-    view_func = inter_wiki_del
-)
-
-app.add_url_rule(
-    rule = '/email_filter/add',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_email_filter',
-        'name' : None
-    }, 
-    methods = ['GET', 'POST'],
-    view_func = inter_wiki_add
-)
-
-app.add_url_rule(
-    rule = '/file_filter',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'file_filter'
-    }, 
-    view_func = inter_wiki
-)
+app.route('/inter_wiki', defaults = { 'tool' : 'inter_wiki' })(inter_wiki)
+app.route('/inter_wiki/del/<name>', defaults = { 'tool' : 'del_inter_wiki' })(inter_wiki_del)
+app.route('/inter_wiki/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_inter_wiki' })(inter_wiki_add)
+app.route('/inter_wiki/add/<name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_inter_wiki' })(inter_wiki_add)
 
-app.add_url_rule(
-    rule = '/file_filter/del/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'del_file_filter',
-        'name' : 'Test'
-    }, 
-    view_func = inter_wiki_del
-)
+app.route('/filter/document/list')(filter_document)
+app.route('/filter/document/add/<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_del)
 
-app.add_url_rule(
-    rule = '/file_filter/add',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_file_filter',
-        'name' : None
-    }, 
-    methods = ['GET', 'POST'],
-    view_func = inter_wiki_add
-)
+app.route('/edit_top', defaults = { 'tool' : 'edit_top' })(inter_wiki)
+app.route('/edit_top/del/<name>', defaults = { 'tool' : 'del_edit_top' })(inter_wiki_del)
+app.route('/edit_top/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_top' })(inter_wiki_add)
 
-app.add_url_rule(
-    rule = '/name_filter',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'name_filter'
-    }, 
-    view_func = inter_wiki
-)
+app.route('/image_license', defaults = { 'tool' : 'image_license' })(inter_wiki)
+app.route('/image_license/del/<name>', defaults = { 'tool' : 'del_image_license' })(inter_wiki_del)
+app.route('/image_license/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_image_license' })(inter_wiki_add)
 
-app.add_url_rule(
-    rule = '/name_filter/del/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'del_name_filter',
-        'name' : 'Test'
-    }, 
-    view_func = inter_wiki_del
-)
+app.route('/edit_filter', defaults = { 'tool' : 'edit_filter' })(inter_wiki)
+app.route('/edit_filter/del/<name>', defaults = { 'tool' : 'del_edit_filter' })(inter_wiki_del)
+app.route('/edit_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_filter' })(inter_wiki_add)
+app.route('/edit_filter/add/<name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_filter' })(inter_wiki_add)
 
-app.add_url_rule(
-    rule = '/name_filter/add',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_name_filter',
-        'name' : None
-    }, 
-    methods = ['GET', 'POST'],
-    view_func = inter_wiki_add
-)
+app.route('/email_filter', defaults = { 'tool' : 'email_filter' })(inter_wiki)
+app.route('/email_filter/del/<name>', defaults = { 'tool' : 'del_email_filter' })(inter_wiki_del)
+app.route('/email_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_email_filter' })(inter_wiki_add)
 
-app.add_url_rule(
-    rule = '/extension_filter',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'extension_filter'
-    }, 
-    view_func = inter_wiki
-)
+app.route('/file_filter', defaults = { 'tool' : 'file_filter' })(inter_wiki)
+app.route('/file_filter/del/<name>', defaults = { 'tool' : 'del_file_filter' })(inter_wiki_del)
+app.route('/file_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_file_filter' })(inter_wiki_add)
 
-app.add_url_rule(
-    rule = '/extension_filter/del/<name>',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'del_extension_filter',
-        'name' : 'Test'
-    }, 
-    view_func = inter_wiki_del
-)
+app.route('/name_filter', defaults = { 'tool' : 'name_filter' })(inter_wiki)
+app.route('/name_filter/del/<name>', defaults = { 'tool' : 'del_name_filter' })(inter_wiki_del)
+app.route('/name_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_name_filter' })(inter_wiki_add)
 
-app.add_url_rule(
-    rule = '/extension_filter/add',
-    defaults = { 
-        'conn' : load_db.db_get(), 
-        'tool' : 'plus_extension_filter',
-        'name' : None
-    }, 
-    methods = ['GET', 'POST'],
-    view_func = inter_wiki_add
-)
+app.route('/extension_filter', defaults = { 'tool' : 'extension_filter' })(inter_wiki)
+app.route('/extension_filter/del/<name>', defaults = { 'tool' : 'del_extension_filter' })(inter_wiki_del)
+app.route('/extension_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_extension_filter' })(inter_wiki_add)
 
 # Func-list
 # /list/document/old
@@ -715,19 +504,19 @@ def recent_record(name = None):
 def recent_history(name = None):
     return recent_change_2(load_db.db_get(), name, 'history')
 
-@app.route('/history/tool/<int(signed=True):rev>/<everything:name>')
+@app.route('/history/tool/<int(signed = True):rev>/<everything:name>')
 def recent_history_tool(name = 'Test', rev = 1):
     return recent_history_tool_2(load_db.db_get(), name, rev)
 
-@app.route('/history/delete/<int(signed=True):rev>/<everything:name>', methods = ['POST', 'GET'])
+@app.route('/history/delete/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])
 def recent_history_delete(name = 'Test', rev = 1):
     return recent_history_delete_2(load_db.db_get(), name, rev)
 
-@app.route('/history/hidden/<int(signed=True):rev>/<everything:name>')
+@app.route('/history/hidden/<int(signed = True):rev>/<everything:name>')
 def recent_history_hidden(name = 'Test', rev = 1):
     return recent_history_hidden_2(load_db.db_get(), name, rev)
 
-@app.route('/history/send/<int(signed=True):rev>/<everything:name>', methods = ['POST', 'GET'])
+@app.route('/history/send/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])
 def recent_history_send(name = 'Test', rev = 1):
     return recent_history_send_2(load_db.db_get(), name, rev)
 
@@ -780,7 +569,7 @@ def view_xref_this(name = 'Test'):
 def view_raw(name = None, topic_num = None, num = None):
     return view_raw_2(load_db.db_get(), name, topic_num, num)
 
-@app.route('/diff/<int:num_a>/<int:num_b>/<everything:name>')
+@app.route('/diff/<int(signed = True):num_a>/<int(signed = True):num_b>/<everything:name>')
 def view_diff(name = 'Test', num_a = 1, num_b = 1):
     return view_diff_2(load_db.db_get(), name, num_a, num_b)
 
@@ -788,7 +577,7 @@ def view_diff(name = 'Test', num_a = 1, num_b = 1):
 def view_down(name = None):
     return view_down_2(load_db.db_get(), name)
 
-@app.route('/w/<everything:name>/doc_rev/<int:doc_rev>')
+@app.route('/w/<everything:name>/doc_rev/<int(signed = True):doc_rev>')
 @app.route('/w/<everything:name>/doc_from/<everything:doc_from>')
 @app.route('/w/<everything:name>')
 def view_read(name = 'Test', doc_rev = 0, doc_from = ''):
@@ -869,13 +658,8 @@ def topic_change(topic_num = 1):
 def topic_admin(topic_num = 1, num = 1):
     return topic_admin_2(load_db.db_get(), topic_num, num)
 
-@app.route('/thread/<int:topic_num>', methods = ['POST', 'GET'])
-def topic(topic_num = 1):
-    return topic_2(load_db.db_get(), topic_num)
-
-@app.route('/topic/<everything:name>', methods = ['POST', 'GET'])
-def topic_close_list(name = 'test'):
-    return topic_close_list_2(load_db.db_get(), name)
+app.route('/thread/<int:topic_num>', methods = ['POST', 'GET'])(topic)
+app.route('/topic/<everything:name>', methods = ['POST', 'GET'])(topic_close_list)
 
 # Func-user
 @app.route('/change', methods = ['POST', 'GET'])
@@ -908,13 +692,8 @@ def user_info(name = ''):
 def user_count_edit(name = None):
     return user_count_edit_2(load_db.db_get(), name)
     
-@app.route('/alarm')
-def user_alarm():
-    return user_alarm_2(load_db.db_get())
-
-@app.route('/alarm/delete')
-def user_alarm_del():
-    return user_alarm_del_2(load_db.db_get())
+app.route('/alarm')(user_alarm)
+app.route('/alarm/delete')(user_alarm_del)
     
 @app.route('/watch_list')
 def user_watch_list():
@@ -947,12 +726,6 @@ def login_login():
 def login_login_2fa():
     return login_login_2fa_2(load_db.db_get())
 
-'''
-@app.route('/login/2fa/email', methods = ['POST', 'GET'])
-def login_2fa_email():
-    return login_login_2fa_email_2(load_db.db_get())
-'''
-
 @app.route('/register', methods = ['POST', 'GET'])
 def login_register():
     return login_register_2(load_db.db_get())
@@ -1011,138 +784,60 @@ def vote_add():
     return vote_add_2(load_db.db_get())
 
 # Func-api
-@app.route('/api/w/<everything:name>', methods = ['POST', 'GET'])
-def api_w(name = ''):
-    return api_w_2(load_db.db_get(), name)
-
-@app.route('/api/raw/<everything:name>')
-def api_raw(name = ''):
-    return api_raw_2(load_db.db_get(), name)
-
-@app.route('/api/version')
-def api_version():
-    return api_version_2(load_db.db_get(), version_list)
-
-@app.route('/api/skin_info')
-@app.route('/api/skin_info/<name>')
-def api_skin_info(name = ''):
-    return api_skin_info_2(load_db.db_get(), name)
-
-@app.route('/api/markup')
-def api_markup():
-    return api_markup_2(load_db.db_get())
-
-@app.route('/api/user_info/<name>')
-def api_user_info(name = ''):
-    return api_user_info_2(load_db.db_get(), name)
-
-@app.route('/api/thread/<topic_num>')
-def api_topic_sub(name = '', topic_num = 1):
-    return api_topic_sub_2(load_db.db_get(), topic_num)
-
-@app.route('/api/search/<name>')
-def api_search(name = ''):
-    return api_search_2(load_db.db_get(), name)
-
-@app.route('/api/recent_changes')
-def api_recent_change():
-    return api_recent_change_2(load_db.db_get())
-
-@app.route('/api/recent_discuss')
-@app.route('/api/recent_discuss/<int:num>')
-def api_recent_discuss(num = 10):
-    return api_recent_discuss_2(load_db.db_get(), num, 'normal')
-
-@app.route('/api/recent_discuss/stop')
-@app.route('/api/recent_discuss/<int:num>/stop')
-def api_recent_discuss_stop(num = 10):
-    return api_recent_discuss_2(load_db.db_get(), num, 'stop')
-
-@app.route('/api/recent_discuss/all')
-@app.route('/api/recent_discuss/<int:num>/all')
-def api_recent_discuss_all(num = 10):
-    return api_recent_discuss_2(load_db.db_get(), num, 'all')
-
-@app.route('/api/sha224/<everything:name>', methods = ['POST', 'GET'])
-def api_sha224(name = 'test'):
-    return api_sha224_2(load_db.db_get(), name)
-
-@app.route('/api/title_index')
-def api_title_index():
-    return api_title_index_2(load_db.db_get())
-
-@app.route('/api/image/<everything:name>', methods = ['POST', 'GET'])
-def api_image_view(name = ''):
-    return api_image_view_2(load_db.db_get(), name)
-
-@app.route('/api/sitemap.xml')
-def api_sitemap():
-    return api_sitemap_2(load_db.db_get())
+app.route('/api/w/<everything:name>/doc_tool/<tool>/doc_rev/<int(signed = True):rev>')(api_w)
+app.route('/api/w/<everything:name>/doc_tool/<tool>', methods = ['GET', 'POST'])(api_w)
+app.route('/api/w/<everything:name>', methods = ['GET', 'POST'])(api_w)
+app.route('/api/raw/<everything:name>')(api_raw)
+app.route('/api/version', defaults = { 'version_list' : version_list })(api_version)
+app.route('/api/skin_info')(api_skin_info)
+app.route('/api/skin_info/<name>')(api_skin_info)
+app.route('/api/markup')(api_markup)
+app.route('/api/user_info/<name>')(api_user_info)
+app.route('/api/thread/<int:topic_num>/<tool>/<int:num>')(api_topic_sub)
+app.route('/api/thread/<int:topic_num>/<tool>')(api_topic_sub)
+app.route('/api/thread/<int:topic_num>')(api_topic_sub)
+app.route('/api/search/<everything:name>/doc_num/<int:num>/<int:page>')(api_search)
+app.route('/api/search/<everything:name>')(api_search)
+app.route('/api/recent_change/<int:num>')(api_recent_change)
+app.route('/api/recent_change')(api_recent_change)
+# recent_changes -> recent_change
+app.route('/api/recent_changes')(api_recent_change)
+app.route('/api/recent_discuss/<get_type>/<int:num>')(api_recent_discuss)
+app.route('/api/recent_discuss/<int:num>')(api_recent_discuss)
+app.route('/api/recent_discuss')(api_recent_discuss)
+app.route('/api/sha224/<everything:data>', methods = ['POST', 'GET'])(api_sha224)
+app.route('/api/title_index')(api_title_index)
+app.route('/api/image/<everything:name>', methods = ['POST', 'GET'])(api_image_view)
+# 이건 API 영역이 아닌 것 같아서 고심 중
+app.route('/api/sitemap.xml')(api_sitemap)
 
 # Func-main
 # 여기도 전반적인 조정 시행 예정
-@app.route('/restart', methods = ['POST', 'GET'])
-def main_restart():
-    return main_restart_2(load_db.db_get())
-
-@app.route('/update', methods=['GET', 'POST'])
-def main_update():
-    return main_update_2(load_db.db_get())
-
-@app.route('/random')
-def main_title_random():
-    return main_title_random_2(load_db.db_get())
-
-@app.route('/upload', methods=['GET', 'POST'])
-def main_upload():
-    return main_upload_2(load_db.db_get())
-
-@app.route('/setting')
-@app.route('/setting/<int:num>', methods = ['POST', 'GET'])
-def setting(num = 0):
-    return main_setting_2(load_db.db_get(), num, data_db_set['type'])
-
-@app.route('/other')
-def main_other():
-    return main_other_2(load_db.db_get())
-
-@app.route('/manager', methods = ['POST', 'GET'])
-@app.route('/manager/<int:num>', methods = ['POST', 'GET'])
-def main_manager(num = 1):
-    return main_manager_2(load_db.db_get(), num)
-
-@app.route('/image/<everything:name>')
-def main_image_view(name = None):
-    return main_image_view_2(load_db.db_get(), name)
-
-@app.route('/skin_set')
-@app.route('/main_skin_set')
-def main_skin_set():
-    return main_skin_set_2(load_db.db_get())
-
-@app.route('/views/<everything:name>')
-def main_views(name = None):
-    return main_views_2(load_db.db_get(), name)
-
-@app.route('/test_func')
-def main_test_func():
-    return main_test_func_2(load_db.db_get())
-
-@app.route('/shutdown', methods = ['POST', 'GET'])
-def main_shutdown():
-    return main_shutdown_2(load_db.db_get())
-
-@app.route('/easter_egg.xml')
-def main_easter_egg():
-    return main_easter_egg_2(load_db.db_get())
-
-@app.route('/<regex("[^.]+\.(?:txt|xml)"):data>')
-def main_file(data = ''):
-    return main_file_2(load_db.db_get(), data)
-
-@app.errorhandler(404)
-def main_error_404(e):
-    return main_error_404_2(load_db.db_get())
+app.route('/other')(main_tool_other)
+app.route('/manager', methods = ['POST', 'GET'])(main_tool_admin)
+app.route('/manager/<int:num>', methods = ['POST', 'GET'])(main_tool_admin)
+app.route('/manager/<int:num>/<add_2>', methods = ['POST', 'GET'])(main_tool_admin)
+
+app.route('/random')(main_func_random)
+app.route('/upload', methods = ['POST', 'GET'])(main_func_upload)
+app.route('/setting', defaults = { 'db_set' : data_db_set['type'] })(main_func_setting)
+app.route('/setting/<int:num>', methods = ['POST', 'GET'], defaults = { 'db_set' : data_db_set['type'] })(main_func_setting)
+app.route('/skin_set')(main_func_skin_set)
+app.route('/main_skin_set')(main_func_skin_set)
+app.route('/easter_egg.xml')(main_func_easter_egg)
+
+# views -> view
+app.route('/view/<everything:name>')(main_view)
+app.route('/views/<everything:name>')(main_view)
+app.route('/image/<everything:name>')(main_view_image)
+# 조정 계획 중
+app.route('/<regex("[^.]+\.(?:txt|xml)"):data>')(main_view_file)
+
+app.route('/shutdown', methods = ['POST', 'GET'])(main_sys_shutdown)
+app.route('/restart', methods = ['POST', 'GET'])(main_sys_restart)
+app.route('/update', methods = ['POST', 'GET'])(main_sys_update)
+
+app.errorhandler(404)(main_error_404)
     
 if __name__ == "__main__":
     do_server = netius.servers.WSGIServer(app = app)

+ 89 - 107
emergency_tool.py

@@ -2,10 +2,9 @@
 import time
 from route.tool.func import *
 
-while 1:
-    print('Load DB (Y) [Y, N] : ', end = '')
-    data_db_load = input()
-    if data_db_load in ['Y', 'N']:
+while True:
+    data_db_load = input('Load DB (Y) [Y, N] : ')
+    if data_db_load in ('Y', 'N'):
         break
 
 if data_db_load == 'Y':
@@ -13,14 +12,14 @@ if data_db_load == 'Y':
     if os.path.exists(os.path.join('data', 'set.json')):
         db_set_list = ['db', 'db_type']
         set_data = json.loads(open(
-            os.path.join('data', 'set.json'), 
-            encoding = 'utf8'
+            os.path.join('data', 'set.json'),
+            encoding='utf8'
         ).read())
         for i in db_set_list:
-            if not i in set_data:
+            if i not in set_data:
                 print('Please delete set.json')
                 print('----')
-                raise
+                raise KeyError(i)
 
         print('DB name : ' + set_data['db'])
         print('DB type : ' + set_data['db_type'])
@@ -43,8 +42,7 @@ if data_db_load == 'Y':
         set_data = {}
         normal_db_type = ['sqlite', 'mysql']
 
-        print('DB type (' + normal_db_type[0] + ') [' + ', '.join(normal_db_type) + '] : ', end = '')
-        data_get = str(input())
+        data_get = input('DB type (' + normal_db_type[0] + ') [' + ', '.join(normal_db_type) + '] : ')
         if data_get == '' or not data_get in normal_db_type:
             set_data['db_type'] = 'sqlite'
         else:
@@ -57,57 +55,44 @@ if data_db_load == 'Y':
                 if f_src:
                     all_src += [f_src.group(1)]
 
-        print('DB name (data) [' + ', '.join(all_src) + '] : ', end = '')
-
-        data_get = str(input())
+        data_get = input('DB name (data) [' + ', '.join(all_src) + '] : ')
         if data_get == '':
             set_data['db'] = 'data'
         else:
             set_data['db'] = data_get
 
-        with open(os.path.join('data', 'set.json'), 'w', encoding = 'utf8') as f:
+        with open(os.path.join('data', 'set.json'), 'w', encoding='utf8') as f:
             f.write(json.dumps(set_data))
 
-    data_db_set = {}
-    data_db_set['name'] = set_data['db']
-    data_db_set['type'] = set_data['db_type']
+    data_db_set = {'name': set_data['db'], 'type': set_data['db_type']}
 
     if data_db_set['type'] == 'mysql':
-        if not os.path.exists(os.path.join('data', 'mysql.json')):
-            db_set_list = ['user', 'password', 'host', 'port']
-            set_data = json.loads(
-                open(
-                    os.path.join('data', 'mysql.json'),
-                    encoding = 'utf8'
-                ).read()
-            )
-            for i in db_set_list:
-                if not i in set_data:
+        if os.path.exists(os.path.join('data', 'mysql.json')):
+            with open(os.path.join('data', 'mysql.json'), encoding='utf8') as f:
+                set_data = json.loads(f.read())
+
+            for i in ('user', 'password', 'host', 'port'):
+                if i not in set_data:
                     print('Please delete mysql.json')
                     print('----')
-                    raise
+                    raise KeyError(i)
 
-            print('DB user ID : ', end = '')
-            set_data_mysql['user'] = str(input())
-
-            print('DB password : ', end = '')
-            set_data_mysql['password'] = str(input())
+            set_data_mysql = set_data
+        else:
+            set_data_mysql = {
+                'user': input('DB user ID : '),
+                'password': input('DB password : '),
+                'host': input('DB host (localhost) : '),
+                'port': input('DB port (3306) : '),
+            }
 
-            print('DB host (localhost) : ', end = '')
-            set_data_mysql['host'] = str(input())
             if set_data_mysql['host'] == '':
                 set_data_mysql['host'] = 'localhost'
 
-            print('DB port (3306) : ', end = '')
-            set_data_mysql['port'] = str(input())
             if set_data_mysql['port'] == '':
                 set_data_mysql['port'] = '3306'
 
-            with open(
-                os.path.join('data', 'mysql.json'), 
-                'w', 
-                encoding = 'utf8'
-            ) as f:
+            with open(os.path.join('data', 'mysql.json'), 'w', encoding='utf8') as f:
                 f.write(json.dumps(set_data_mysql))
 
         data_db_set['mysql_user'] = set_data_mysql['user']
@@ -123,7 +108,7 @@ if data_db_load == 'Y':
             data_db_set['mysql_port'] = '3306'
 
     db_data_get(data_db_set['type'])
-    load_db = get_db_connect(data_db_set)
+    load_db = get_db_connect_old(data_db_set)
 
     conn = load_db.db_load()
     curs = conn.cursor()
@@ -152,22 +137,19 @@ print('16. Delete 2FA password')
 print('17. Change markup')
 
 print('----')
-print('Select : ', end = '')
-what_i_do = input()
+what_i_do = input('Select : ')
 
 if what_i_do == '1':
     print('----')
-    print('All delete (Y) [Y, N] : ', end = '')
-    go_num = input()
+    go_num = input('All delete (Y) [Y, N] : ')
     if not go_num == 'N':
         curs.execute(db_change("delete from back"))
         conn.commit()
 
     print('----')
-    print('Count (100) : ', end = '')
     try:
-        go_num = int(input())
-    except:
+        go_num = int(input('Count (100) : '))
+    except ValueError:
         go_num = 100
 
     num = 0
@@ -175,12 +157,15 @@ if what_i_do == '1':
     print('----')
     print('Load...')
 
-    curs.execute(db_change("" + \
-        "select title from data d " + \
-        "where not exists (" + \
-            "select title from back where link = d.title limit 1" + \
-        ")" + \
-    ""))
+    curs.execute(
+        db_change(
+            "select title from data d "
+            "where not exists ("
+            "select title from back where link = d.title limit 1"
+            ")"
+            ""
+        )
+    )
     title = curs.fetchall()
 
     print('----')
@@ -199,7 +184,7 @@ if what_i_do == '1':
 
         curs.execute(db_change("select data from data where title = ?"), [name[0]])
         data = curs.fetchall()
-        
+
         get_class_render = class_do_render(conn)
         get_class_render.do_render(name[0], data[0][0], 'backlink', '')
 elif what_i_do == '2':
@@ -207,38 +192,37 @@ elif what_i_do == '2':
     curs.execute(db_change("delete from other where name = 'sec_re'"))
 elif what_i_do == '3':
     print('----')
-    print('IP or Name : ', end = '')
-    user_data = input()
-
-    curs.execute(db_change("" + \
-        "insert into rb (block, end, today, blocker, why, band) " + \
-        "values (?, ?, ?, ?, ?, ?)"
-    ), [
-        user_data,
-        'release',
-        get_time(),
-        'tool:emergency',
-        '',
-        ''
-    ])
+    user_data = input('IP or Name : ')
+
+    curs.execute(
+        db_change(
+            "insert into rb (block, end, today, blocker, why, band) "
+            "values (?, ?, ?, ?, ?, ?)"
+        ),
+        [
+            user_data,
+            'release',
+            get_time(),
+            'tool:emergency',
+            '',
+            '',
+        ]
+    )
 
     curs.execute(db_change("update rb set ongoing = '' where block = ?"), [user_data])
 elif what_i_do == '4':
     print('----')
-    print('Host : ', end = '')
-    host = input()
+    host = input('Host : ')
 
     curs.execute(db_change("update other set data = ? where name = 'host'"), [host])
 elif what_i_do == '5':
     print('----')
-    print('Port : ', end = '')
-    port = int(input())
+    port = int(input('Port : '))
 
     curs.execute(db_change("update other set data = ? where name = 'port'"), [port])
 elif what_i_do == '6':
     print('----')
-    print('Skin name : ', end = '')
-    skin = input()
+    skin = input('Skin name : ')
 
     curs.execute(db_change("update other set data = ? where name = 'skin'"), [skin])
 elif what_i_do == '7':
@@ -247,36 +231,34 @@ elif what_i_do == '7':
     print('2. sha3')
 
     print('----')
-    print('Select : ', end = '')
-    what_i_do = int(input())
+    what_i_do = input('Select : ')
 
     print('----')
-    print('User name : ', end = '')
-    user_name = input()
+    user_name = input('User name : ')
 
     print('----')
-    print('User password : ', end = '')
-    user_pw = input()
+    user_pw = input('User password : ')
 
     if what_i_do == '1':
         hashed = hashlib.sha256(bytes(user_pw, 'utf-8')).hexdigest()
-    else:
+    elif what_i_do == '2':
         if sys.version_info < (3, 6):
             hashed = sha3.sha3_256(bytes(user_pw, 'utf-8')).hexdigest()
         else:
             hashed = hashlib.sha3_256(bytes(user_pw, 'utf-8')).hexdigest()
+    else:
+        raise ValueError(what_i_do)
 
     curs.execute(db_change("update user_set set data = ? where id = ? and name = 'pw'"), [
-        hashed, 
+        hashed,
         user_name
     ])
 elif what_i_do == '8':
     print('----')
-    print('Insert version (0000000) : ', end = '')
-    new_ver = input()
-    
+    new_ver = input('Insert version (0000000) : ')
+
     if new_ver == '':
-        new_ver == '0000000'
+        new_ver = '0000000'
 
     curs.execute(db_change("update other set data = ? where name = 'ver'"), [new_ver])
 elif what_i_do == '9':
@@ -284,17 +266,15 @@ elif what_i_do == '9':
         os.remove(os.path.join('data', 'set.json'))
 elif what_i_do == '10':
     print('----')
-    print('User name : ', end = '')
-    user_name = input()
+    user_name = input('User name : ')
 
     print('----')
-    print('New name : ', end = '')
-    new_name = input()
+    new_name = input('New name : ')
 
-    curs.execute(db_change("update user_set set id = ? where id = ?"), [
-        new_name, 
-        user_name
-    ])
+    curs.execute(
+        db_change("update user_set set id = ? where id = ?"),
+        [new_name, user_name]
+    )
 elif what_i_do == '11':
     if os.path.exists(os.path.join('data', 'mysql.json')):
         os.remove(os.path.join('data', 'mysql.json'))
@@ -307,33 +287,35 @@ elif what_i_do == '12':
         count_data = 0
 
     curs.execute(db_change('delete from other where name = "count_all_title"'))
-    curs.execute(db_change('insert into other (name, data) values ("count_all_title", ?)'), [
-        str(count_data)
-    ])
+    curs.execute(
+        db_change(
+            'insert into other (name, data) values ("count_all_title", ?)'
+        ),
+        [str(count_data)]
+    )
 elif what_i_do == '13':
     curs.execute(db_change('delete from cache_data'))
 elif what_i_do == '14':
     curs.execute(db_change('delete from other where name = "head"'))
 elif what_i_do == '15':
     print('----')
-    print('User name : ', end = '')
-    user_name = input()
+    user_name = input('User name : ')
 
     curs.execute(db_change("update user_set set data = 'owner' where id = ? and name = 'acl'"), [user_name])
 elif what_i_do == '16':
     print('----')
-    print('User name : ', end = '')
-    user_name = input()
+    user_name = input('User name : ')
 
     curs.execute(db_change('select data from user_set where name = "2fa" and id = ?'), [user_name])
     if curs.fetchall():
         curs.execute(db_change("update user_set set data = '' where name = '2fa' and id = ?"), [user_name])
-else:
+elif what_i_do == '17':
     print('----')
-    print('Markup name : ', end = '')
-    markup = input()
+    markup = input('Markup name : ')
 
     curs.execute(db_change("update other set data = ? where name = 'markup'"), [markup])
+else:
+    raise ValueError(what_i_do)
 
 if data_db_load == 'Y':
     conn.commit()

+ 2 - 0
lang/en-US.json

@@ -225,6 +225,7 @@
                 "edit_tool_list" : "Edit tool(s) list",
                 "image_license_list" : "Image license(s) list",
                 "extension_filter_list" : "Extension filter(s) list",
+                "document_filter_list" : "Document filter(s) list",
             "_comment_2.1.2_" : "Add",
                 "interwiki_add" : "Add Interwiki",
                 "edit_filter_add" : "Add contents filter",
@@ -234,6 +235,7 @@
                 "edit_tool_add" : "Add edit tool",
                 "image_license_add" : "Add image license",
                 "extension_filter_add" : "Add extension filter",
+                "document_filter_add" : "Add document filter",
         "_comment_2.2_" : "Setting",
             "setting" : "Setting",
             "restart_required" : "Restart required",

+ 5 - 3
lang/ko-KR.json

@@ -406,6 +406,8 @@
     "record_reset": "사용자 편집 기록 초기화",
     "email_setting": "이메일 설정",
     "oauth_client_id": "OAuth 클라이언트 ID",
-    "today_doc" : "오늘의 문서",
-    "send_edit" : "편집 사유 수정"
-}
+    "today_doc": "오늘의 문서",
+    "send_edit": "편집 사유 수정",
+    "document_filter_list": "문서명 필터 목록",
+    "document_filter_add": "문서명 필터 추가"
+}

+ 2 - 2
readme-en.md

@@ -1,7 +1,7 @@
-[(en-US)](./readme-en.md) | [(ko-KR)](./readme.md)
+[(en-US)](./readme-en.md) | [(ko-KR)](./readme.md)
 
 # openNAMU
-[![Up to Python 3.6](https://img.shields.io/badge/python->=%203.6-blue.svg)](https://python.org)
+[![Up to Python 3.7](https://img.shields.io/badge/python->=%203.7-blue.svg)](https://python.org)
 [![LICENSE](https://img.shields.io/badge/license-BSD%203--Clause-lightgrey.svg)](./LICENSE)
 
 ![](https://raw.githubusercontent.com/openNAMU/openNAMU/beta/.github/logo.png)

+ 1 - 1
readme.md

@@ -1,7 +1,7 @@
 [(en-US)](./readme-en.md) | [(ko-KR)](./readme.md)
 
 # 오픈나무
-[![Python 3.6 이상](https://img.shields.io/badge/python->=%203.6-blue.svg)](https://python.org)
+[![Python 3.7 이상](https://img.shields.io/badge/python->=%203.7-blue.svg)](https://python.org)
 [![라이선스](https://img.shields.io/badge/license-BSD%203--Clause-lightgrey.svg)](./LICENSE)
 
 ![](https://raw.githubusercontent.com/openNAMU/openNAMU/beta/.github/logo.png)

+ 1 - 3
route/api_image_view.py

@@ -1,8 +1,6 @@
 from .tool.func import *
 
-def api_image_view_2(conn, name):
-    curs = conn.cursor()
-
+def api_image_view(name = 'Test'):
     if flask.request.method == 'POST':
         try:
             title_list = json.loads(flask.request.form.get('title_list', ''))

+ 9 - 8
route/api_markup.py

@@ -1,11 +1,12 @@
 from .tool.func import *
 
-def api_markup_2(conn):
-    curs = conn.cursor()
+def api_markup():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    curs.execute(db_change('select data from other where name = "markup"'))
-    rep_data = curs.fetchall()
-    if rep_data and rep_data[0][0] != '':
-        return flask.jsonify({ "markup" : rep_data[0][0] })
-    else:
-        return flask.jsonify({})
+        curs.execute(db_change('select data from other where name = "markup"'))
+        rep_data = curs.fetchall()
+        if rep_data and rep_data[0][0] != '':
+            return flask.jsonify({ "markup" : rep_data[0][0] })
+        else:
+            return flask.jsonify({})

+ 22 - 21
route/api_raw.py

@@ -1,25 +1,26 @@
 from .tool.func import *
 
-def api_raw_2(conn, name):
-    curs = conn.cursor()
+def api_raw(name = 'Test'):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    if acl_check(name, 'render') != 1:
-        rev = flask.request.args.get('num', '')
-        if rev != '':
-            curs.execute(db_change("select data from history where title = ? and id = ?"), [name, rev])
-        else:
-            curs.execute(db_change("select data from data where title = ?"), [name])
-        data = curs.fetchall()
-        if data:
-            json_data = {
-                "title" : name, 
-                "data" : render_set(
-                    doc_name = name, 
-                    doc_data = data[0][0],
-                    data_type = 'raw'
-                )
-            }
+        if acl_check(name, 'render') != 1:
+            rev = flask.request.args.get('num', '')
+            if rev != '':
+                curs.execute(db_change("select data from history where title = ? and id = ?"), [name, rev])
+            else:
+                curs.execute(db_change("select data from data where title = ?"), [name])
+            data = curs.fetchall()
+            if data:
+                json_data = {
+                    "title" : name, 
+                    "data" : render_set(
+                        doc_name = name, 
+                        doc_data = data[0][0],
+                        data_type = 'raw'
+                    )
+                }
 
-            return flask.jsonify(json_data)
-        
-    return flask.jsonify({})
+                return flask.jsonify(json_data)
+
+        return flask.jsonify({})

+ 22 - 22
route/api_recent_change.py

@@ -1,27 +1,27 @@
 from .tool.func import *
 
-def api_recent_change_2(conn):
-    curs = conn.cursor()
+def api_recent_change(num = 10):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    num = int(number_check(flask.request.args.get('num', '10')))
-    num = 50 if (1 if not num > 0 else num) > 50 else num
-    repeat_ok = flask.request.args.get('repeat', '1')
-    data_list = []
-    admin = admin_check(6)
-    get_title = ''
+        num = 50 if (1 if not num > 0 else num) > 50 else num
+        repeat_ok = flask.request.args.get('repeat', '1')
+        data_list = []
+        admin = admin_check(6)
+        get_title = ''
 
-    curs.execute(db_change('select id, title from rc where type = "" order by date desc'))
-    for i in curs.fetchall():
-        if repeat_ok == '1' or i[1] != get_title:
-            get_title = i[1]
-            curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where id = ? and title = ?'), i)
-            get_data = curs.fetchall()
-            if get_data:
-                if get_data[0][6] == '' or admin == 1:
-                    data_list += get_data
+        curs.execute(db_change('select id, title from rc where type = "" order by date desc'))
+        for i in curs.fetchall():
+            if repeat_ok == '1' or i[1] != get_title:
+                get_title = i[1]
+                curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where id = ? and title = ?'), i)
+                get_data = curs.fetchall()
+                if get_data:
+                    if get_data[0][6] == '' or admin == 1:
+                        data_list += get_data
+                    else:
+                        data_list += [['', '', '', '', '', '', get_data[0][6]]]
                 else:
-                    data_list += [['', '', '', '', '', '', get_data[0][6]]]
-            else:
-                data_list += [['', '', '', '', '', '', '']]
-        
-    return flask.jsonify(data_list if data_list else {}) 
+                    data_list += [['', '', '', '', '', '', '']]
+
+        return flask.jsonify(data_list if data_list else {}) 

+ 17 - 16
route/api_recent_discuss.py

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

+ 24 - 32
route/api_search.py

@@ -1,36 +1,28 @@
 from .tool.func import *
 
-def api_search_2(conn, name):
-    curs = conn.cursor()
+def api_search(name = 'Test', num = 10, page = 1):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    num = int(number_check(flask.request.args.get('num', '10')))
-    if not num > 0:
-        num = 1
+        num = 1 if num > 1000 else num
+        page = (page * (num - 1)) if page * num > 0 else 0
 
-    if num > 1000:
-        num = 1
-
-    page = int(number_check(flask.request.args.get('page', '1')))
-    if page * num > 0:
-        page = page * num - num
-    else:
-        page = 0
-
-    curs.execute(db_change('select data from other where name = "count_all_title"'))
-    if int(curs.fetchall()[0][0]) < 30000:
-        curs.execute(db_change("" + \
-            "select distinct title, case " + \
-            "when title like ? then 'title' else 'data' end from data " + \
-            "where (title like ? or data like ?) order by case " + \
-            "when title like ? then 1 else 2 end limit ?, ?"),
-            ['%' + name + '%', '%' + name + '%', '%' + name + '%', '%' + name + '%', page, num]
-        )
-    else:
-        curs.execute(db_change("select title from data where title like ? order by title limit ?, ?"),
-            ['%' + name + '%', page, num]
-        )
-    all_list = curs.fetchall()
-    if all_list:
-        return flask.jsonify(all_list)
-    else:
-        return flask.jsonify({})
+        curs.execute(db_change('select data from other where name = "count_all_title"'))
+        if int(curs.fetchall()[0][0]) < 30000:
+            curs.execute(db_change("" + \
+                "select distinct title, case " + \
+                "when title like ? then 'title' else 'data' end from data " + \
+                "where (title like ? or data like ?) order by case " + \
+                "when title like ? then 1 else 2 end limit ?, ?"),
+                ['%' + name + '%', '%' + name + '%', '%' + name + '%', '%' + name + '%', page, num]
+            )
+        else:
+            curs.execute(db_change("select title from data where title like ? order by title limit ?, ?"),
+                ['%' + name + '%', page, num]
+            )
+            
+        all_list = curs.fetchall()
+        if all_list:
+            return flask.jsonify(all_list)
+        else:
+            return flask.jsonify({})

+ 3 - 5
route/api_sha224.py

@@ -1,19 +1,17 @@
 from .tool.func import *
 
-def api_sha224_2(conn, data):
-    curs = conn.cursor()
-
+def api_sha224(data = 'Test'):
     if flask.request.method == 'POST':
         try:
             title_list = json.loads(flask.request.form.get('title_list', ''))
             title_list = list(set(title_list))
         except:
             title_list = []
-        
+
         data_list = {}
         for i in title_list:
             data_list[i] = sha224_replace(i)
-        
+
         return flask.jsonify(data_list)
     else:
         return flask.jsonify({ "data" : sha224_replace(data) })

+ 42 - 41
route/api_sitemap.py

@@ -1,55 +1,56 @@
 from .tool.func import *
 
-def api_sitemap_2(conn):
-    curs = conn.cursor()
+def api_sitemap():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    if admin_check(None, 'make sitemap') == 1:
-        data = '' + \
-            '<?xml version="1.0" encoding="UTF-8"?>\n' + \
-            '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + \
-        ''
-        domain = load_domain()
-
-        curs.execute(db_change("select title from data"))
-        all_data = curs.fetchall()
-
-        len_all_data = len(all_data)
-        count = int(len_all_data / 30000)
-        other_count = len_all_data % 30000
-
-        for i in range(count + 1):
-            data += '<sitemap><loc>' + domain + 'sitemap_' + str(i) + '.xml</loc></sitemap>\n'
-
-        data += '' + \
-            '</sitemapindex>' + \
-        ''
-
-        f = open("sitemap.xml", 'w')
-        f.write(data)
-        f.close()
-
-        e = 0
-        for i in range(count + 1):
+        if admin_check(None, 'make sitemap') == 1:
             data = '' + \
                 '<?xml version="1.0" encoding="UTF-8"?>\n' + \
-                '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + \
+                '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + \
             ''
+            domain = load_domain()
+
+            curs.execute(db_change("select title from data"))
+            all_data = curs.fetchall()
+
+            len_all_data = len(all_data)
+            count = int(len_all_data / 30000)
+            other_count = len_all_data % 30000
 
-            if count == i:
-                for x in all_data[30000 * i:]:
-                    data += '<url><loc>' + domain + 'w/' + url_pas(x[0]) + '</loc></url>\n'
-            else:
-                for x in all_data[30000 * i:30000 * (i + 1)]:
-                    data += '<url><loc>' + domain + 'w/' + url_pas(x[0]) + '</loc></url>\n'
+            for i in range(count + 1):
+                data += '<sitemap><loc>' + domain + 'sitemap_' + str(i) + '.xml</loc></sitemap>\n'
 
             data += '' + \
-                '</urlset>' + \
+                '</sitemapindex>' + \
             ''
 
-            f = open("sitemap_" + str(i) + ".xml", 'w')
+            f = open("sitemap.xml", 'w')
             f.write(data)
             f.close()
 
-        return redirect('/sitemap.xml')
-    else:
-        return re_error('/ban')
+            e = 0
+            for i in range(count + 1):
+                data = '' + \
+                    '<?xml version="1.0" encoding="UTF-8"?>\n' + \
+                    '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + \
+                ''
+
+                if count == i:
+                    for x in all_data[30000 * i:]:
+                        data += '<url><loc>' + domain + 'w/' + url_pas(x[0]) + '</loc></url>\n'
+                else:
+                    for x in all_data[30000 * i:30000 * (i + 1)]:
+                        data += '<url><loc>' + domain + 'w/' + url_pas(x[0]) + '</loc></url>\n'
+
+                data += '' + \
+                    '</urlset>' + \
+                ''
+
+                f = open("sitemap_" + str(i) + ".xml", 'w')
+                f.write(data)
+                f.close()
+
+            return redirect('/sitemap.xml')
+        else:
+            return re_error('/ban')

+ 49 - 48
route/api_skin_info.py

@@ -1,64 +1,65 @@
 from .tool.func import *
 
-def api_skin_info_2(conn, name):
-    curs = conn.cursor()
-    name = skin_check() if name == '' else './views/' + name + '/index.html'
-    
-    if not flask.request.args.get('all', None):
-        json_address = re.sub(r"(((?!\.|\/).)+)\.html$", "info.json", name)
-        try:
-            json_data = json.loads(open(json_address, encoding='utf8').read())
-        except:
-            json_data = None
+def api_skin_info(name = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+        name = skin_check() if name == '' else './views/' + name + '/index.html'
 
-        if json_data:
-            return flask.jsonify(json_data)
-        else:
-            return flask.jsonify({}), 404
-    else:
-        a_data = {}
-        d_link_data = {
-            "ACME" : "https://raw.githubusercontent.com/openNAMU/openNAMU-Skin-ACME/master/info.json",
-            "Liberty" : "https://raw.githubusercontent.com/openNAMU/openNAMU-Skin-Liberty/master/info.json",
-            "Before Namu" : "https://raw.githubusercontent.com/openNAMU/openNAMU-Skin-Before_Namu/master/info.json"
-        }
-
-        for i in load_skin(skin_check(1), 1):
-            json_address = re.sub(r"(((?!\.|\/).)+)\.html$", "info.json", './views/' + i + '/index.html')
+        if not flask.request.args.get('all', None):
+            json_address = re.sub(r"(((?!\.|\/).)+)\.html$", "info.json", name)
             try:
                 json_data = json.loads(open(json_address, encoding='utf8').read())
             except:
                 json_data = None
 
             if json_data:
-                if i == skin_check(1):
-                    json_data = {**json_data, **{ "main" : "true" }}
+                return flask.jsonify(json_data)
+            else:
+                return flask.jsonify({}), 404
+        else:
+            a_data = {}
+            d_link_data = {
+                "ACME" : "https://raw.githubusercontent.com/openNAMU/openNAMU-Skin-ACME/master/info.json",
+                "Liberty" : "https://raw.githubusercontent.com/openNAMU/openNAMU-Skin-Liberty/master/info.json",
+                "Before Namu" : "https://raw.githubusercontent.com/openNAMU/openNAMU-Skin-Before_Namu/master/info.json"
+            }
+
+            for i in load_skin(skin_check(1), 1):
+                json_address = re.sub(r"(((?!\.|\/).)+)\.html$", "info.json", './views/' + i + '/index.html')
+                try:
+                    json_data = json.loads(open(json_address, encoding='utf8').read())
+                except:
+                    json_data = None
 
-                if "info_link" in json_data:
-                    info_link = json_data["info_link"]
-                elif json_data["name"] in d_link_data:
-                    info_link = d_link_data[json_data["name"]]
-                else:
-                    info_link = 0
+                if json_data:
+                    if i == skin_check(1):
+                        json_data = {**json_data, **{ "main" : "true" }}
 
-                if info_link != 0:
-                    try:
-                        get_data = urllib.request.urlopen(info_link)
-                    except:
-                        get_data = None
+                    if "info_link" in json_data:
+                        info_link = json_data["info_link"]
+                    elif json_data["name"] in d_link_data:
+                        info_link = d_link_data[json_data["name"]]
+                    else:
+                        info_link = 0
 
-                    if get_data and get_data.getcode() == 200:
+                    if info_link != 0:
                         try:
-                            get_data = json.loads(get_data.read().decode())
+                            get_data = urllib.request.urlopen(info_link)
                         except:
-                            get_data = {}
-                        
-                        if "skin_ver" in get_data:
-                            json_data = {**json_data, **{ "lastest_version" : {
-                                "skin_ver" : get_data["skin_ver"]
-                            }}}
-                        
+                            get_data = None
+
+                        if get_data and get_data.getcode() == 200:
+                            try:
+                                get_data = json.loads(get_data.read().decode())
+                            except:
+                                get_data = {}
+
+                            if "skin_ver" in get_data:
+                                json_data = {**json_data, **{ "lastest_version" : {
+                                    "skin_ver" : get_data["skin_ver"]
+                                }}}
+
 
-                a_data = {**a_data, **{ i : json_data }}
+                    a_data = {**a_data, **{ i : json_data }}
 
-        return flask.jsonify(a_data)
+            return flask.jsonify(a_data)

+ 11 - 10
route/api_title_index.py

@@ -1,14 +1,15 @@
 from .tool.func import *
 
-def api_title_index_2(conn):
-    curs = conn.cursor()
+def api_title_index():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    if flask.request.args.get('count', '1') == '1':
-        curs.execute(db_change('select data from other where name = "count_all_title"'))
-        title_count = curs.fetchall()
-        if title_count:
-            return flask.jsonify({ 'count' : title_count[0][0] })
+        if flask.request.args.get('count', '1') == '1':
+            curs.execute(db_change('select data from other where name = "count_all_title"'))
+            title_count = curs.fetchall()
+            if title_count:
+                return flask.jsonify({ 'count' : title_count[0][0] })
+            else:
+                return flask.jsonify({ 'count' : '0' })
         else:
-            return flask.jsonify({ 'count' : '0' })
-    else:
-        return flask.jsonify({})
+            return flask.jsonify({})

+ 60 - 48
route/api_topic_sub.py

@@ -1,53 +1,65 @@
 from .tool.func import *
 
-def api_topic_sub_2(conn, topic_num):
-    curs = conn.cursor()
-
-    topic_num = str(topic_num)
-
-    if flask.request.args.get('num', None):
-        curs.execute(db_change("select id, data, date, ip, block, top from topic where code = ? and id + 0 = ? + 0 order by id + 0 asc"), [
-            topic_num,
-            flask.request.args.get('num', '')
-        ])
-    elif flask.request.args.get('top', None):
-        curs.execute(db_change("select id, data, date, ip, block, top from topic where code = ? and top = 'O' order by id + 0 asc"), [topic_num])
-    else:
-        curs.execute(db_change("select id, data, date, ip, block, top from topic where code = ? order by id + 0 asc"), [topic_num])
-
-    data = curs.fetchall()
-    if data:
-        data_a = {}
-        admin = admin_check(3)
-
-        curs.execute(db_change("select ip from topic where code = ? order by id + 0 asc limit 1"), [topic_num])
-        data_f = curs.fetchall()
-        data_f = data_f[0][0] if data_f else ''
-        data_a['data_main'] = {
-            "ip_first" : ip_pas(data_f, 1),
-            "admin" : str(admin)
-        }
-            
-        ip_a = ip_pas([i[3] for i in data])
-        ip_a_2 = ip_pas([i[3] for i in data], 1)
-        for i in data:
-            data_v = i[1] if i[4] != 'O' or admin == 1 else ''
+def api_topic_sub(topic_num = 1, tool = 'normal', num = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        topic_num = str(topic_num)
+
+        if tool == 'normal':
+            if num != '':
+                curs.execute(db_change(
+                    "select id, data, date, ip, block, top from topic where code = ? and id + 0 = ? + 0 order by id + 0 asc"
+                ), [
+                    topic_num,
+                    num
+                ])
+            else:
+                curs.execute(db_change(
+                    "select id, data, date, ip, block, top from topic where code = ? order by id + 0 asc"
+                ), [
+                    topic_num
+                ]) 
+        else:
+            curs.execute(db_change(
+                "select id, data, date, ip, block, top from topic where code = ? and top = 'O' order by id + 0 asc"
+            ), [
+                topic_num
+            ])
             
-            data_a[i[0]] = {
-                "data" : data_v,
-                "date" : i[2],
-                "ip" : ip_a_2[i[3]],
-                "blind" : i[4],
-                
-                "ip_pas" : ip_a[i[3]],
-                "data_pas" : render_set(
-                    doc_data = data_v, 
-                    data_type = 'api_view',
-                    data_in = 'topic_' + topic_num + '_' + i[0],
-                    doc_acl = 0
-                )
+        data = curs.fetchall()
+        if data:
+            data_a = {}
+            admin = admin_check(3)
+
+            curs.execute(db_change("select ip from topic where code = ? order by id + 0 asc limit 1"), [topic_num])
+            data_f = curs.fetchall()
+            data_f = data_f[0][0] if data_f else ''
+            data_a['data_main'] = {
+                "ip_first" : ip_pas(data_f, 1),
+                "admin" : str(admin)
             }
 
-        return flask.jsonify(data_a)
-    else:
-        return flask.jsonify({})
+            ip_a = ip_pas([i[3] for i in data])
+            ip_a_2 = ip_pas([i[3] for i in data], 1)
+            for i in data:
+                data_v = i[1] if i[4] != 'O' or admin == 1 else ''
+
+                data_a[i[0]] = {
+                    "data" : data_v,
+                    "date" : i[2],
+                    "ip" : ip_a_2[i[3]],
+                    "blind" : i[4],
+
+                    "ip_pas" : ip_a[i[3]],
+                    "data_pas" : render_set(
+                        doc_data = data_v, 
+                        data_type = 'api_view',
+                        data_in = 'topic_' + topic_num + '_' + i[0],
+                        doc_acl = 0
+                    )
+                }
+
+            return flask.jsonify(data_a)
+        else:
+            return flask.jsonify({})

+ 62 - 61
route/api_user_info.py

@@ -1,75 +1,76 @@
 from .tool.func import *
 
-def api_user_info_2(conn, name):
-    curs = conn.cursor()
+def api_user_info(name = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    if flask.request.args.get('render', None):
-        plus_d = ''
-        plus_t = []
+        if flask.request.args.get('render', None):
+            plus_d = ''
+            plus_t = []
 
-        curs.execute(db_change("update rb set ongoing = '' where end < ? and end != '' and ongoing = '1'"), [get_time()])
-        conn.commit()
+            curs.execute(db_change("update rb set ongoing = '' where end < ? and end != '' and ongoing = '1'"), [get_time()])
+            conn.commit()
 
-        plus_d = '''
-            <table class="user_info_table">
-                <tbody>
-                    <tr>
-                        <td>''' + load_lang('user_name') + '''</td>
-                        <td>{}</td>
-                    </tr>
-                    <tr>
-                        <td>''' + load_lang('authority') + '''</td>
-                        <td>{}</td>
-                    </tr>
-                    <tr>
-                        <td>''' + load_lang('state') + '''</td>
-                        <td>{}</td>
-                    </tr>
-                </tbody>
-            </table>
-        '''
+            plus_d = '''
+                <table class="user_info_table">
+                    <tbody>
+                        <tr>
+                            <td>''' + load_lang('user_name') + '''</td>
+                            <td>{}</td>
+                        </tr>
+                        <tr>
+                            <td>''' + load_lang('authority') + '''</td>
+                            <td>{}</td>
+                        </tr>
+                        <tr>
+                            <td>''' + load_lang('state') + '''</td>
+                            <td>{}</td>
+                        </tr>
+                    </tbody>
+                </table>
+            '''
 
-        curs.execute(db_change("select data from user_set where id = ? and name = 'acl'"), [name])
-        data = curs.fetchall()
-        if data:
-            if data[0][0] != 'user':
-                curs.execute(db_change("select name from alist where name = ?"), [data[0][0]])
-                if curs.fetchall():
-                    plus_t += [data[0][0]]
+            curs.execute(db_change("select data from user_set where id = ? and name = 'acl'"), [name])
+            data = curs.fetchall()
+            if data:
+                if data[0][0] != 'user':
+                    curs.execute(db_change("select name from alist where name = ?"), [data[0][0]])
+                    if curs.fetchall():
+                        plus_t += [data[0][0]]
+                    else:
+                        plus_t += [load_lang('member')]
                 else:
                     plus_t += [load_lang('member')]
             else:
-                plus_t += [load_lang('member')]
-        else:
-            plus_t += [load_lang('normal')]
+                plus_t += [load_lang('normal')]
 
-        if ban_check(name) == 0:
-            plus_t += [load_lang('normal')]
-        else:
-            plus_t += [load_lang('blocked') + '<br>']
-            regex_ban = 0
+            if ban_check(name) == 0:
+                plus_t += [load_lang('normal')]
+            else:
+                plus_t += [load_lang('blocked') + '<br>']
+                regex_ban = 0
 
-            curs.execute(db_change("select login, block, end, why from rb where band = 'regex' and ongoing = '1'"))
-            for test_r in curs.fetchall():
-                if re.compile(test_r[1]).search(name):
-                    plus_t[1] += load_lang('type') + ' : ' + load_lang('regex')
-                    plus_t[1] += '<br>' + load_lang('period') + ' : ' + (test_r[2] if test_r[2] != '' else load_lang('limitless'))
-                    plus_t[1] += ('<br>' + load_lang('login_able') if test_r[0] == 'O' else '')
-                    plus_t[1] += ('<br>' + load_lang('why') + ' : ' + test_r[3] if test_r[3] != '' else '')
-                    regex_ban = 1
+                curs.execute(db_change("select login, block, end, why from rb where band = 'regex' and ongoing = '1'"))
+                for test_r in curs.fetchall():
+                    if re.compile(test_r[1]).search(name):
+                        plus_t[1] += load_lang('type') + ' : ' + load_lang('regex')
+                        plus_t[1] += '<br>' + load_lang('period') + ' : ' + (test_r[2] if test_r[2] != '' else load_lang('limitless'))
+                        plus_t[1] += ('<br>' + load_lang('login_able') if test_r[0] == 'O' else '')
+                        plus_t[1] += ('<br>' + load_lang('why') + ' : ' + test_r[3] if test_r[3] != '' else '')
+                        regex_ban = 1
 
-            if regex_ban == 0:
-                curs.execute(db_change("select end, login, band, why from rb where block = ? and ongoing = '1'"), [name])
-                block_data = curs.fetchall()
-                if block_data:
-                    plus_t[1] += load_lang('type') + ' : ' + (load_lang('band_blocked') if block_data[0][2] == 'O' else load_lang('normal'))
-                    plus_t[1] += (' (' + load_lang('login_able') + ')' if block_data[0][1] != '' else '')
-                    plus_t[1] += '<br>' + load_lang('period') + ' : ' + (block_data[0][0] if block_data[0][0] != '' else load_lang('limitless'))
-                    plus_t[1] += ('<br>' + load_lang('band_blocked') if block_data[0][2] == 'O' else '')
-                    plus_t[1] += ('<br>' + load_lang('why') + ' : ' + block_data[0][3] if block_data[0][3] != '' else '')
+                if regex_ban == 0:
+                    curs.execute(db_change("select end, login, band, why from rb where block = ? and ongoing = '1'"), [name])
+                    block_data = curs.fetchall()
+                    if block_data:
+                        plus_t[1] += load_lang('type') + ' : ' + (load_lang('band_blocked') if block_data[0][2] == 'O' else load_lang('normal'))
+                        plus_t[1] += (' (' + load_lang('login_able') + ')' if block_data[0][1] != '' else '')
+                        plus_t[1] += '<br>' + load_lang('period') + ' : ' + (block_data[0][0] if block_data[0][0] != '' else load_lang('limitless'))
+                        plus_t[1] += ('<br>' + load_lang('band_blocked') if block_data[0][2] == 'O' else '')
+                        plus_t[1] += ('<br>' + load_lang('why') + ' : ' + block_data[0][3] if block_data[0][3] != '' else '')
 
-        plus_d = plus_d.format(ip_pas(name), plus_t[0], plus_t[1])
+            plus_d = plus_d.format(ip_pas(name), plus_t[0], plus_t[1])
 
-        return flask.jsonify({ "data" : plus_d })
-    else:
-        return flask.jsonify({})
+            return flask.jsonify({ "data" : plus_d })
+        else:
+            return flask.jsonify({})

+ 13 - 12
route/api_version.py

@@ -1,17 +1,18 @@
 from .tool.func import *
 
-def api_version_2(conn, version_list):
-    curs = conn.cursor()
+def api_version(version_list):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    curs.execute(db_change('select data from other where name = "update"'))
-    up_data = curs.fetchall()
-    up_data = up_data[0][0] if up_data and up_data[0][0] in ['stable', 'beta', 'dev'] else 'stable'
+        curs.execute(db_change('select data from other where name = "update"'))
+        up_data = curs.fetchall()
+        up_data = up_data[0][0] if up_data and up_data[0][0] in ['stable', 'beta', 'dev'] else 'stable'
 
-    json_data = {
-        "version" : version_list['beta']['r_ver'], 
-        "db_version" : version_list['beta']['c_ver'],
-        "skin_version" : version_list['beta']['s_ver'],
-        "build" : up_data
-    }
+        json_data = {
+            "version" : version_list['beta']['r_ver'], 
+            "db_version" : version_list['beta']['c_ver'],
+            "skin_version" : version_list['beta']['s_ver'],
+            "build" : up_data
+        }
 
-    return flask.jsonify(json_data)
+        return flask.jsonify(json_data)

+ 80 - 90
route/api_w.py

@@ -1,112 +1,102 @@
 from .tool.func import *
 
-def api_w_2(conn, name):
-    curs = conn.cursor()
-
-    data_arg_v = flask.request.args.get('v', '')
-    if flask.request.method == 'POST':
-        if data_arg_v == '' or data_arg_v == 'preview':
-            data_org = flask.request.form.get('data', '')
-            data_pas = render_set(
-                doc_name = name, 
-                doc_data = data_org, 
-                data_type = 'api_view',
-                data_in = 'preview'
-            )
-
-            return flask.jsonify({
-                "data" : data_pas[0], 
-                "js_data" : data_pas[1]
-            })
-        elif data_arg_v == 'include':
-            name_org = flask.request.args.get('name_org', '')
-            name_org = name if name_org == '' else name_org
-            
-            include_data = flask.request.args.get('include', '')
-                
-            try:
-                include_list = json.loads(flask.request.form.get('include_list', ''))
-            except:
-                include_list = []
-
-            curs.execute(db_change("select data from data where title = ?"), [name])
-            sql_data = curs.fetchall()
-            if not sql_data:
-                return flask.jsonify({})
-            else:
-                json_data = sql_data[0][0]
-
-                get_all_change_1 = []
-                find_replace_moment = re.findall(r'(@([^=@]+)=([^=@]+)@|@([^=@]+)@)', json_data)
-                for i in find_replace_moment:
-                    if i[1] != '':
-                        get_all_change_1 += [[i[1], i[2]]]
-
-                        json_data = json_data.replace(i[0], '@' + i[1] + '@', 1)
-                    else:
-                        json_data = json_data.replace(i[0], '@' + i[3] + '@', 1)
-
-                get_all_change_2 = include_list + get_all_change_1
-                for i in get_all_change_2:
-                    json_data = json_data.replace('@' + i[0] + '@', i[1])
+def api_w(name = 'Test', tool = '', rev = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
+        if flask.request.method == 'POST':
+            if tool == '' or tool == 'preview':
+                # data_in 말고 data_use_type이랑 data_use_num 추가 예정
+                data_org = flask.request.form.get('data', '')
                 data_pas = render_set(
-                    doc_name = name_org, 
-                    doc_data = json_data, 
+                    doc_name = name, 
+                    doc_data = data_org, 
                     data_type = 'api_view',
-                    data_in = include_data
+                    data_in = ''
                 )
 
                 return flask.jsonify({
                     "data" : data_pas[0], 
                     "js_data" : data_pas[1]
                 })
-        elif data_arg_v == 'exist':
-            try:
-                title_list = json.loads(flask.request.form.get('title_list', ''))
-                title_list = list(set(title_list))
-            except:
-                title_list = []
-            
-            data_exist = {}
-            for i in title_list:
-                curs.execute(db_change("select title from data where title = ?"), [i])
-                if curs.fetchall():
-                    data_exist[i] = '1'
-                    
-            return flask.jsonify(data_exist)
-        else:
-            return flask.jsonify({})
-    else:
-        data_arg_exist = flask.request.args.get('exist', '')
-        if data_arg_v == 'exist' or data_arg_exist != '':
-            curs.execute(db_change("select title from data where title = ?"), [name])
-            if curs.fetchall():
-                return flask.jsonify({ "exist" : "1" })
-            else:
-                return flask.jsonify({})
-        else:
-            data_arg_include = flask.request.args.get('include', '')
-            if acl_check(name, 'render') == 1:
-                return flask.jsonify({})
-            else:
-                data_arg_rev = flask.request.args.get('num', '')
-                if data_arg_rev != '':
-                    curs.execute(db_change("select data from history where title = ? and id = ?"), [name, rev])
-                else:
-                    curs.execute(db_change("select data from data where title = ?"), [name])
+            elif tool == 'include':
+                name_org = flask.request.form.get('name_org', '')
+                name_org = name if name_org == '' else name_org
 
+                include_data = flask.request.form.get('name_include', '')
+
+                try:
+                    include_list = json.loads(flask.request.form.get('include_list', ''))
+                except:
+                    include_list = []
+
+                curs.execute(db_change("select data from data where title = ?"), [name])
                 sql_data = curs.fetchall()
                 if not sql_data:
                     return flask.jsonify({})
                 else:
+                    json_data = sql_data[0][0]
+
+                    get_all_change_1 = []
+                    find_replace_moment = re.findall(r'(@([^=@]+)=([^=@]+)@|@([^=@]+)@)', json_data)
+                    for i in find_replace_moment:
+                        if i[1] != '':
+                            get_all_change_1 += [[i[1], i[2]]]
+
+                            json_data = json_data.replace(i[0], '@' + i[1] + '@', 1)
+                        else:
+                            json_data = json_data.replace(i[0], '@' + i[3] + '@', 1)
+
+                    get_all_change_2 = include_list + get_all_change_1
+                    for i in get_all_change_2:
+                        json_data = json_data.replace('@' + i[0] + '@', i[1])
+
                     data_pas = render_set(
-                        doc_name = name, 
-                        doc_data = sql_data[0][0], 
-                        data_type = 'api_view'
+                        doc_name = name_org, 
+                        doc_data = json_data, 
+                        data_type = 'api_view',
+                        data_in = include_data
                     )
 
                     return flask.jsonify({
                         "data" : data_pas[0], 
                         "js_data" : data_pas[1]
-                    })
+                    })
+            elif tool == 'exist':
+                try:
+                    title_list = json.loads(flask.request.form.get('title_list', ''))
+                    title_list = list(set(title_list))
+                except:
+                    title_list = []
+
+                data_exist = {}
+                for i in title_list:
+                    curs.execute(db_change("select title from data where title = ?"), [i])
+                    if curs.fetchall():
+                        data_exist[i] = '1'
+
+                return flask.jsonify(data_exist)
+
+            return flask.jsonify({})
+        else:
+            if tool == '' or tool == 'view':
+                if acl_check(name, 'render') != 1:
+                    if check_int(rev) == '':
+                        curs.execute(db_change("select data from data where title = ?"), [name])
+                    else:
+                        curs.execute(db_change("select data from history where title = ? and id = ?"), [name, rev])
+
+                    sql_data = curs.fetchall()
+                    if sql_data:
+                        data_pas = render_set(
+                            doc_name = name, 
+                            doc_data = sql_data[0][0], 
+                            data_type = 'api_view'
+                        )
+
+                        return flask.jsonify({
+                            "data" : data_pas[0], 
+                            "js_data" : data_pas[1]
+                        })
+
+            return flask.jsonify({})

+ 41 - 0
route/filter_document.py

@@ -0,0 +1,41 @@
+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')]]
+        ))

+ 62 - 0
route/filter_document_add.py

@@ -0,0 +1,62 @@
+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')]]
+            ))

+ 13 - 0
route/filter_document_del.py

@@ -0,0 +1,13 @@
+from .tool.func import *
+
+def filter_document_del(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')

+ 85 - 0
route/filter_inter_wiki.py

@@ -0,0 +1,85 @@
+from .tool.func import *
+
+def inter_wiki(tool):
+    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()
+
+        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 == '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'"))
+        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()
+        for data in db_data:
+            div += '<tr>'
+            div += '<td>'
+
+            div += html.escape(data[0])
+            if admin == 1:
+                div += ' <a href="/' + tool + '/add/' + url_pas(data[0]) + '">(' + load_lang('edit') + ')</a>'
+                div += ' <a href="/' + tool + '/del/' + url_pas(data[0]) + '">(' + load_lang('delete') + ')</a>'
+
+            div += '</td>'
+
+            if tool == 'inter_wiki':
+                div += '<td><a id="out_link" href="' + html.escape(data[1]) + '">' + html.escape(data[1]) + '</a></td>'
+            else:
+                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="/' + tool + '/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')]]
+        ))

+ 237 - 0
route/filter_inter_wiki_add.py

@@ -0,0 +1,237 @@
+from .tool.func import *
+
+def inter_wiki_add(tool, name = None):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if not name and tool == 'plus_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')
+
+                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
+                    ])
+                except:
+                    return re_error('/error/23')
+            else:
+                plus_d = ''
+
+                if tool == 'plus_name_filter':
+                    try:
+                        re.compile(flask.request.form.get('title', 'test'))
+                    except:
+                        return re_error('/error/23')
+
+                    admin_check(None, 'name_filter edit')
+
+                    type_d = 'name'
+                elif tool == 'plus_file_filter':
+                    try:
+                        re.compile(flask.request.form.get('title', 'test'))
+                    except:
+                        return re_error('/error/23')
+
+                    admin_check(None, 'file_filter edit')
+
+                    type_d = 'file'
+                elif tool == 'plus_email_filter':
+                    admin_check(None, 'email_filter edit')
+
+                    type_d = 'email'
+                elif tool == 'plus_image_license':
+                    admin_check(None, 'image_license edit')
+
+                    type_d = 'image_license'
+                elif tool == 'plus_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,
+                    ''
+                ])
+
+            conn.commit()
+
+            return redirect('/' + re.sub(r'^plus_', '', tool))
+        else:
+            get_sub = 0
+            stat = 'disabled' if admin_check() != 1 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])
+                    exist = curs.fetchall()
+                    if exist:
+                        value = exist[0]
+                    else:
+                        value = ['', '', '']
+                else:
+                    value = ['', '', '']
+
+                title = load_lang('interwiki_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') + '''
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(value[1]) + '''" type="text" name="link">
+                    <hr class="main_hr">
+                    ''' + load_lang('icon') + ''' (HTML)
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(value[2]) + '''" type="text" name="icon">
+                '''
+            elif tool == 'plus_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]
+                else:
+                    textarea = ''
+                    time_check = ''
+                    time_data = ''
+
+                insert_data = ''
+                if stat == '':
+                    t_data = [
+                        ['86400', load_lang('1_day')],
+                        ['432000‬', load_lang('5_day')],
+                        ['2592000', load_lang('30_day')],
+                        ['15552000', load_lang('180_day')],
+                        ['31104000‬', load_lang('360_day')],
+                        ['0', load_lang('limitless')]
+                    ]
+                    for i in t_data:
+                        insert_data += '<a href="javascript:insert_v(\'second\', \'' + i[0] + '\')">(' + i[1] + ')</a> '
+
+                title = load_lang('edit_filter_add')
+                form_data = '''
+                    <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''
+                    <hr class="main_hr">
+                    <input placeholder="''' + load_lang('second') + '''" id="second" name="second" type="text" value="''' + html.escape(time_data) + '''">
+                    <hr class="main_hr">
+                    <input placeholder="''' + load_lang('regex') + '''" name="content" value="''' + html.escape(textarea) + '''" type="text">
+                '''
+            elif tool == 'plus_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">' + \
+                ''
+            elif tool == 'plus_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">' + \
+                ''
+            elif tool == 'plus_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">' + \
+                ''
+            elif tool == 'plus_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">' + \
+                ''
+            elif tool == 'plus_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">' + \
+                ''
+            else:
+                title = load_lang('edit_tool_add')
+                if name:
+                    curs.execute(db_change("select plus from html_filter where html = ? and kind = 'edit_top'"), [name])
+                    exist = curs.fetchall()
+                    if exist:
+                        value = exist[0][0]
+                    else:
+                        value = ''
+                else:
+                    value = ''
+
+                form_data = '''
+                    ''' + load_lang('title') + '''
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(name if name else '') + '''" type="text" name="title">
+                    <hr class="main_hr">
+                    ''' + load_lang('markup') + '''
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(value) + '''" type="text" name="markup">
+                '''
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [title, wiki_set(), wiki_custom(), wiki_css([get_sub, 0])],
+                data =  '''
+                        <form method="post">
+                            ''' + form_data + '''
+                            <hr class="main_hr">
+                            <button ''' + stat + ''' type="submit">''' + load_lang('add') + '''</button>
+                        </form>
+                        ''',
+                menu = [[re.sub('^plus_', '', tool), load_lang('return')]]
+            ))

+ 7 - 6
route/inter_wiki_del.py → route/filter_inter_wiki_del.py

@@ -1,9 +1,12 @@
 from .tool.func import *
 
-def inter_wiki_del(conn, tool, name):
-    curs = conn.cursor()
+def inter_wiki_del(tool, name = 'Test'):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+        
+        if admin_check(None, tool) != 1:
+            return re_error('/error/3')
 
-    if admin_check(None, tool) == 1:
         if tool == 'del_inter_wiki':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'inter_wiki'"), [name])
         elif tool == 'del_edit_filter':
@@ -23,6 +26,4 @@ def inter_wiki_del(conn, tool, name):
 
         conn.commit()
 
-        return redirect('/' + re.sub(r'^del_', '', tool))
-    else:
-        return re_error('/error/3')
+        return redirect('/' + re.sub(r'^del_', '', tool))

+ 0 - 84
route/inter_wiki.py

@@ -1,84 +0,0 @@
-from .tool.func import *
-
-def inter_wiki(conn, tool):
-    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()
-
-    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 == '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'"))
-    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()
-    for data in db_data:
-        div += '<tr>'
-        div += '<td>'
-
-        div += data[0]
-        if admin == 1:
-            div += ' <a href="/' + tool + '/add/' + url_pas(data[0]) + '">(' + load_lang('edit') + ')</a>'
-            div += ' <a href="/' + tool + '/del/' + url_pas(data[0]) + '">(' + load_lang('delete') + ')</a>'
-        
-        div += '</td>'
-
-        if tool == 'inter_wiki':
-            div += '<td><a id="out_link" href="' + data[1] + '">' + html.escape(data[1]) + '</a></td>'
-        else:
-            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="/' + tool + '/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 - 236
route/inter_wiki_add.py

@@ -1,236 +0,0 @@
-from .tool.func import *
-
-def inter_wiki_add(conn, tool, name):
-    curs = conn.cursor()
-    
-    if not name:
-        if tool == 'plus_edit_filter':
-            return redirect('/manager/9')
-
-    if flask.request.method == 'POST':
-        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')
-
-            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
-                ])
-            except:
-                return re_error('/error/23')
-        else:
-            plus_d = ''
-
-            if tool == 'plus_name_filter':
-                try:
-                    re.compile(flask.request.form.get('title', 'test'))
-                except:
-                    return re_error('/error/23')
-
-                admin_check(None, 'name_filter edit')
-
-                type_d = 'name'
-            elif tool == 'plus_file_filter':
-                try:
-                    re.compile(flask.request.form.get('title', 'test'))
-                except:
-                    return re_error('/error/23')
-
-                admin_check(None, 'file_filter edit')
-
-                type_d = 'file'
-            elif tool == 'plus_email_filter':
-                admin_check(None, 'email_filter edit')
-
-                type_d = 'email'
-            elif tool == 'plus_image_license':
-                admin_check(None, 'image_license edit')
-
-                type_d = 'image_license'
-            elif tool == 'plus_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) values (?, ?, ?)'), [
-                flask.request.form.get('title', 'test'),
-                type_d,
-                plus_d
-            ])
-
-        conn.commit()
-
-        return redirect('/' + re.sub(r'^plus_', '', tool))
-    else:
-        get_sub = 0
-        if admin_check() != 1:
-            stat = 'disabled'
-        else:
-            stat = ''
-
-        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])
-                exist = curs.fetchall()
-                if exist:
-                    value = exist[0]
-                else:
-                    value = ['', '', '']
-            else:
-                value = ['', '', '']
-
-            title = load_lang('interwiki_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') + '''
-                <hr class="main_hr">
-                <input value="''' + html.escape(value[1]) + '''" type="text" name="link">
-                <hr class="main_hr">
-                ''' + load_lang('icon') + ''' (HTML)
-                <hr class="main_hr">
-                <input value="''' + html.escape(value[2]) + '''" type="text" name="icon">
-            '''
-        elif tool == 'plus_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]
-            else:
-                textarea = ''
-                time_check = ''
-                time_data = ''
-
-            insert_data = ''
-            if stat == '':
-                t_data = [
-                    ['86400', load_lang('1_day')],
-                    ['432000‬', load_lang('5_day')],
-                    ['2592000', load_lang('30_day')],
-                    ['15552000', load_lang('180_day')],
-                    ['31104000‬', load_lang('360_day')],
-                    ['0', load_lang('limitless')]
-                ]
-                for i in t_data:
-                    insert_data += '<a href="javascript:insert_v(\'second\', \'' + i[0] + '\')">(' + i[1] + ')</a> '
-
-            title = load_lang('edit_filter_add')
-            form_data = '''
-                <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''
-                <hr class="main_hr">
-                <input ''' + stat + ''' placeholder="''' + load_lang('second') + '''" id="second" name="second" type="text" value="''' + html.escape(time_data) + '''">
-                <hr class="main_hr">
-                <input ''' + stat + ''' placeholder="''' + load_lang('regex') + '''" name="content" value="''' + html.escape(textarea) + '''" type="text">
-            '''
-        elif tool == 'plus_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">' + \
-            ''
-        elif tool == 'plus_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">' + \
-            ''
-        elif tool == 'plus_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">' + \
-            ''
-        elif tool == 'plus_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">' + \
-            ''
-        elif tool == 'plus_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">' + \
-            ''
-        else:
-            title = load_lang('edit_tool_add')
-            if name:
-                curs.execute(db_change("select plus from html_filter where html = ? and kind = 'edit_top'"), [name])
-                exist = curs.fetchall()
-                if exist:
-                    value = exist[0][0]
-                else:
-                    value = ''
-            else:
-                value = ''
-
-            form_data = '''
-                ''' + load_lang('title') + '''
-                <hr class="main_hr">
-                <input value="''' + html.escape(name if name else '') + '''" type="text" name="title">
-                <hr class="main_hr">
-                ''' + load_lang('markup') + '''
-                <hr class="main_hr">
-                <input value="''' + html.escape(value) + '''" type="text" name="markup">
-            '''
-
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [title, wiki_set(), wiki_custom(), wiki_css([get_sub, 0])],
-            data =  '''
-                    <form method="post">
-                        ''' + form_data + '''
-                        <hr class="main_hr">
-                        <button ''' + stat + ''' type="submit">''' + load_lang('add') + '''</button>
-                    </form>
-                    ''',
-            menu = [[re.sub('^plus_', '', tool), load_lang('return')]]
-        ))

+ 1 - 3
route/main_error_404.py

@@ -1,8 +1,6 @@
 from .tool.func import *
 
-def main_error_404_2(conn):
-    curs = conn.cursor()
-
+def main_error_404(e):
     if os.path.exists('404.html') and flask.request.path != '/':
         return open('404.html', encoding='utf8').read()
     else:

+ 1 - 3
route/main_easter_egg.py → route/main_func_easter_egg.py

@@ -1,8 +1,6 @@
 from .tool.func import *
 
-def main_easter_egg_2(conn):
-    curs = conn.cursor()
-
+def main_func_easter_egg(conn):
     return easy_minify(flask.render_template(skin_check(),
         imp = ['easter_egg.html', wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = open('./views/main_css/file/easter_egg.html', encoding='utf8').read(),

+ 13 - 0
route/main_func_random.py

@@ -0,0 +1,13 @@
+from .tool.func import *
+
+def main_func_random():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        curs.execute(db_change("" + \
+            "select title from data " + \
+            "where title not like 'user:%' and title not like 'category:%' and title not like 'file:%' " + \
+            "order by random() limit 1" + \
+        ""))
+        data = curs.fetchall()
+        return redirect('/w/' + url_pas(data[0][0])) if data else redirect()

+ 760 - 0
route/main_func_setting.py

@@ -0,0 +1,760 @@
+from .tool.func import *
+
+def main_func_setting(db_set, num = 0):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if not (num == 0 or num == 8) and admin_check() != 1:
+            return re_error('/ban')
+
+        if num == 0:
+            li_list = [
+                [1, load_lang('main_setting')],
+                [2, load_lang('text_setting')],
+                [5, 'robots.txt'],
+                [6, load_lang('ext_api_req_set')],
+                [3, load_lang('main_head')],
+                [4, load_lang('main_body')],
+                [7, load_lang('main_bottom_body')]
+            ]
+
+            li_data = ''.join(['<li><a href="/setting/' + str(li[0]) + '">' + li[1] + '</a></li>' for li in li_list])
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                data = '<h2>' + load_lang('list') + '</h2><ul class="inside_ul">' + li_data + '</ul>',
+                menu = [['manager', load_lang('return')]]
+            ))
+        elif num == 1:
+            i_list = {
+                0 : 'name',
+                2 : 'frontpage',
+                4 : 'upload',
+                5 : 'skin',
+                7 : 'reg',
+                8 : 'ip_view',
+                9 : 'back_up',
+                10 : 'port',
+                11 : 'key',
+                12 : 'update',
+                15 : 'encode',
+                16 : 'host',
+                19 : 'slow_edit',
+                20 : 'requires_approval',
+                21 : 'backup_where',
+                22 : 'domain',
+                23 : 'ua_get'
+            }
+            n_list = {
+                0 : 'Wiki',
+                2 : 'FrontPage',
+                4 : '2',
+                5 : '',
+                7 : '',
+                8 : '',
+                9 : '0',
+                10 : '3000',
+                11 : 'test',
+                12 : 'stable',
+                15 : 'sha3',
+                16 : '0.0.0.0',
+                19 : '0',
+                20 : '',
+                21 : '',
+                22 : flask.request.host_url,
+                23 : ''
+            }
+
+            if flask.request.method == 'POST':
+                for i in i_list:
+                    curs.execute(db_change("update other set data = ? where name = ?"), [
+                        flask.request.form.get(i_list[i], n_list[i]),
+                        i_list[i]
+                    ])
+
+                conn.commit()
+
+                admin_check(None, 'edit_set (' + str(num) + ')')
+
+                return redirect('/setting/1')
+            else:
+                d_list = {}
+
+                for i in i_list:
+                    curs.execute(db_change('select data from other where name = ?'), [i_list[i]])
+                    sql_d = curs.fetchall()
+                    if sql_d:
+                        d_list[i] = sql_d[0][0]
+                    else:
+                        curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i_list[i], n_list[i]])
+
+                        d_list[i] = n_list[i]
+
+                conn.commit()
+
+                acl_div = ['']
+                encode_data = ['sha256', 'sha3']
+                for acl_data in encode_data:
+                    if acl_data == d_list[15]:
+                        acl_div[0] = '<option value="' + acl_data + '">' + acl_data + '</option>' + acl_div[0]
+                    else:
+                        acl_div[0] += '<option value="' + acl_data + '">' + acl_data + '</option>'
+
+                check_box_div = ['', '', '', '', '']
+                for i in range(0, len(check_box_div)):
+                    if i == 0:
+                        acl_num = 7
+                    elif i == 1:
+                        acl_num = 8
+                    elif i == 3:
+                        acl_num = 20
+                    else:
+                        acl_num = 23
+
+                    if d_list[acl_num]:
+                        check_box_div[i] = 'checked="checked"'
+
+                branch_div = ''
+                branch_list = ['stable', 'dev', 'beta']
+                for i in branch_list:
+                    if d_list[12] == i:
+                        branch_div = '<option value="' + i + '">' + i + '</option>' + branch_div
+                    else:
+                        branch_div += '<option value="' + i + '">' + i + '</option>'
+
+                sqlite_only = 'style="display:none;"' if db_set != 'sqlite' else ''
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = [load_lang('main_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                    data = '''
+                        <form method="post" id="main_set_data">
+                            <h2>1. ''' + load_lang('basic_set') + '''</h2>
+                            <span>''' + load_lang('wiki_name') + '''</span>
+                            <hr class="main_hr">
+                            <input name="name" value="''' + html.escape(d_list[0]) + '''">
+                            <hr class="main_hr">
+
+                            <span><a href="/setting/9">(''' + load_lang('wiki_logo') + ''')</a></span>
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('main_page') + '''</span>
+                            <hr class="main_hr">
+                            <input name="frontpage" value="''' + html.escape(d_list[2]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('domain') + '''</span> (EX : http://2du.pythonanywhere.com/)
+                            <hr class="main_hr">
+                            <input name="''' + i_list[22] + '''" value="''' + html.escape(d_list[22]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('wiki_host') + '''</span>
+                            <hr class="main_hr">
+                            <input name="host" value="''' + html.escape(d_list[16]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('wiki_port') + '''</span>
+                            <hr class="main_hr">
+                            <input name="port" value="''' + html.escape(d_list[10]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('wiki_secret_key') + '''</span>
+                            <hr class="main_hr">
+                            <input type="password" name="key" value="''' + html.escape(d_list[11]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('encryption_method') + '''</span>
+                            <hr class="main_hr">
+                            <select name="encode">''' + acl_div[0] + '''</select>
+
+                            <h2>2. ''' + load_lang('design_set') + '''</h2>
+                            <span>''' + load_lang('wiki_skin') + '''</span>
+                            <hr class="main_hr">
+                            <select name="skin">''' + load_skin(d_list[5] if d_list[5] != '' else 'tenshi') + '''</select>
+
+                            <h2>3. ''' + load_lang('login_set') + '''</h2>
+                            <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
+                            <hr class="main_hr">
+
+                            <input type="checkbox" name="ip_view" ''' + check_box_div[1] + '''> ''' + load_lang('hide_ip') + '''
+                            <hr class="main_hr">
+
+                            <input type="checkbox" name="requires_approval" ''' + check_box_div[3] + '''> ''' + load_lang('requires_approval') + '''
+                            <hr class="main_hr">
+
+                            <input type="checkbox" name="ua_get" ''' + check_box_div[4] + '''> ''' + load_lang('ua_get_off') + '''
+
+                            <h2>4. ''' + load_lang('server_set') + '''</h2>
+                            <span>''' + load_lang('max_file_size') + ''' (MB)</span>
+                            <hr class="main_hr">
+                            <input name="upload" value="''' + html.escape(d_list[4]) + '''">
+                            <hr class="main_hr">
+
+                            <span ''' + sqlite_only + '''>
+                                <span>
+                                    ''' + load_lang('backup_interval') + ' (' + load_lang('hour') + ') (' + load_lang('off') + ' : 0) ' + \
+                                    '(' + load_lang('restart_required') + ''')</span>
+                                <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('empty') + ' : ' + load_lang('default') + ') ' + \
+                                    '(' + load_lang('restart_required') + ''') (EX : ./data/backup.db)
+                                </span>
+                                <hr class="main_hr">
+                                <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
+                                <hr class="main_hr">
+                            </span>
+
+                            <span>''' + load_lang('update_branch') + '''</span>
+                            <hr class="main_hr">
+                            <select name="update">''' + branch_div + '''</select>
+
+                            <h2>5. ''' + load_lang('edit_set') + '''</h2>
+                            <span><a href="/setting/8">(''' + load_lang('main_acl_setting') + ''')</a></span>
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('slow_edit') + ' (' + load_lang('second') + ') (' + load_lang('off') + ''' : 0)</span>
+                            <hr class="main_hr">
+                            <input name="''' + i_list[19] + '''" value="''' + html.escape(d_list[19]) + '''">
+
+                            <hr class="main_hr">
+                            <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        </form>
+                        <script>simple_render('main_set_data');</script>
+                    ''',
+                    menu = [['setting', load_lang('return')]]
+                ))
+        elif num == 2:
+            i_list = [
+                'contract',
+                'no_login_warning',
+                'edit_bottom_text',
+                'copyright_checkbox_text',
+                'check_key_text',
+                'email_title',
+                'email_text',
+                'email_insert_text',
+                'password_search_text',
+                'reset_user_text',
+                'error_401',
+                'error_404',
+                'approval_question',
+                'edit_help',
+                'upload_help',
+                'upload_default',
+                'license',
+                'topic_text'
+            ]
+            if flask.request.method == 'POST':
+                for i in i_list:
+                    curs.execute(db_change("update other set data = ? where name = ?"), [
+                        flask.request.form.get(i, ''),
+                        i
+                    ])
+
+                conn.commit()
+
+                admin_check(None, 'edit_set (' + str(num) + ')')
+
+                return redirect('/setting/2')
+            else:
+                d_list = []
+
+                for i in i_list:
+                    curs.execute(db_change('select data from other where name = ?'), [i])
+                    sql_d = curs.fetchall()
+                    if sql_d:
+                        d_list += [sql_d[0][0]]
+                    else:
+                        curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
+
+                        d_list += ['']
+
+                conn.commit()
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = [load_lang('text_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                    data = '''
+                        <form method="post" id="main_set_data">
+                            <h2>1. ''' + load_lang('register_text') + ''' (HTML)</h2>
+                            <textarea rows="3" name="''' + i_list[0] + '''">''' + html.escape(d_list[0]) + '''</textarea>
+
+                            <h2>2. ''' + load_lang('non_login_alert') + ''' (HTML)</h2>
+                            <textarea rows="3" name="''' + i_list[1] + '''">''' + html.escape(d_list[1]) + '''</textarea>
+
+                            <h2>3. ''' + load_lang('edit_bottom_text') + ''' (HTML)</h2>
+                            <textarea rows="3" name="''' + i_list[2] + '''">''' + html.escape(d_list[2]) + '''</textarea>
+
+                            <h2>4. ''' + load_lang('copyright_checkbox_text') + ''' (HTML)</h2>
+                            <textarea rows="3" name="''' + i_list[3] + '''">''' + html.escape(d_list[3]) + '''</textarea>
+
+                            <h2>5. ''' + load_lang('check_key_text') + ''' (HTML)</h2>
+                            <textarea rows="3" name="''' + i_list[4] + '''">''' + html.escape(d_list[4]) + '''</textarea>
+
+                            <h2>6. ''' + load_lang('email_title') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[5] + '''">''' + html.escape(d_list[5]) + '''</textarea>
+
+                            <h2>7. ''' + load_lang('email_text') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[6] + '''">''' + html.escape(d_list[6]) + '''</textarea>
+
+                            <h2>8. ''' + load_lang('email_insert_text') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[7] + '''">''' + html.escape(d_list[7]) + '''</textarea>
+
+                            <h2>9. ''' + load_lang('password_search_text') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[8] + '''">''' + html.escape(d_list[8]) + '''</textarea>
+
+                            <h2>10. ''' + load_lang('reset_user_text') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[9] + '''">''' + html.escape(d_list[9]) + '''</textarea>
+
+                            <h2>11. ''' + load_lang('error_401') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[10] + '''">''' + html.escape(d_list[10]) + '''</textarea>
+
+                            <h2>12. ''' + load_lang('error_404') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[11] + '''">''' + html.escape(d_list[11]) + '''</textarea>
+
+                            <h2>13. ''' + load_lang('approval_question') + '''</h2>
+                            <sup>(1)</sup>
+                            <hr class="main_hr">
+                            <textarea rows="3" name="''' + i_list[12] + '''">''' + html.escape(d_list[12]) + '''</textarea>
+
+                            <h2>14. ''' + load_lang('edit_help') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[13] + '''">''' + html.escape(d_list[13]) + '''</textarea>
+
+                            <h2>15. ''' + load_lang('upload_help') + ''' (HTML)</h2>
+                            <textarea rows="3" name="''' + i_list[14] + '''">''' + html.escape(d_list[14]) + '''</textarea>
+
+                            <h2>16. ''' + load_lang('upload_default') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[15] + '''">''' + html.escape(d_list[15]) + '''</textarea>
+
+                            <h2>17. ''' + load_lang('bottom_text') + ''' (HTML)</h2>
+                            <textarea rows="3" name="''' + i_list[16] + '''">''' + html.escape(d_list[16]) + '''</textarea>
+                            
+                            <h2>18. ''' + load_lang('topic_text') + '''</h2>
+                            <textarea rows="3" name="''' + i_list[17] + '''">''' + html.escape(d_list[17]) + '''</textarea>
+
+                            <hr class="main_hr">
+                            <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        </form>
+                        <ul id="footnote_data">
+                            <li><a href="#note_1" id="note_1_end">(1)</a> ''' + load_lang('approval_question_visible_only_when_approval_on') + '''</li>
+                        </ul>
+                        <script>simple_render('main_set_data');</script>
+                    ''',
+                    menu = [['setting', load_lang('return')]]
+                ))
+        elif num == 3 or num == 4 or num == 7:
+            if flask.request.method == 'POST':
+                if num == 4:
+                    info_d = 'body'
+                    end_r = '4'
+                    coverage = ''
+                elif num == 7:
+                    info_d = 'bottom_body'
+                    end_r = '7'
+                    coverage = ''
+                else:
+                    info_d = 'head'
+                    end_r = '3'
+                    if flask.request.args.get('skin', '') == '':
+                        coverage = ''
+                    else:
+                        coverage = flask.request.args.get('skin', '')
+
+                curs.execute(db_change("select name from other where name = ? and coverage = ?"), [info_d, coverage])
+                if curs.fetchall():
+                    curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [
+                        flask.request.form.get('content', ''),
+                        info_d,
+                        coverage
+                    ])
+                else:
+                    curs.execute(db_change("insert into other (name, data, coverage) values (?, ?, ?)"), [info_d, flask.request.form.get('content', ''), coverage])
+
+                conn.commit()
+
+                admin_check(None, 'edit_set (' + str(num) + ')')
+
+                return redirect('/setting/' + end_r + '?skin=' + flask.request.args.get('skin', ''))
+            else:
+                if num == 4:
+                    curs.execute(db_change("select data from other where name = 'body'"))
+                    title = '_body'
+                    start = ''
+                    plus = '''
+                        <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
+                        <hr class="main_hr">
+                        <div id="see_preview"></div>
+                    '''
+                elif num == 7:
+                    curs.execute(db_change("select data from other where name = 'bottom_body'"))
+                    title = '_bottom_body'
+                    start = ''
+                    plus = '''
+                        <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
+                        <hr class="main_hr">
+                        <div id="see_preview"></div>
+                    '''
+                else:
+                    curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [flask.request.args.get('skin', '')])
+                    title = '_head'
+                    start = '' + \
+                        '<a href="?">(' + load_lang('all') + ')</a> ' + \
+                        ' '.join(['<a href="?skin=' + i + '">(' + i + ')</a>' for i in load_skin('', 1)]) + '''
+                        <hr class="main_hr">
+                        <span>&lt;style&gt;CSS&lt;/style&gt;<br>&lt;script&gt;JS&lt;/script&gt;</span>
+                        <hr class="main_hr">
+                    '''
+                    plus = ''
+
+                head = curs.fetchall()
+                if head:
+                    data = head[0][0]
+                else:
+                    data = ''
+
+                if flask.request.args.get('skin', '') != '':
+                    sub_plus = ' (' + flask.request.args.get('skin', '') + ')'
+                else:
+                    sub_plus = ''
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = [load_lang(data = 'main' + title, safe = 1), wiki_set(), wiki_custom(), wiki_css(['(HTML)' + sub_plus, 0])],
+                    data = '''
+                        <form method="post">
+                            ''' + start + '''
+                            <textarea rows="25" placeholder="''' + load_lang('enter_html') + '''" name="content" id="content">''' + html.escape(data) + '''</textarea>
+                            <hr class="main_hr">
+                            <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                            ''' + plus + '''
+                        </form>
+                    ''',
+                    menu = [['setting', load_lang('return')]]
+                ))
+        elif num == 5:
+            if flask.request.method == 'POST':
+                curs.execute(db_change("select name from other where name = 'robot'"))
+                if curs.fetchall():
+                    curs.execute(db_change("update other set data = ? where name = 'robot'"), [flask.request.form.get('content', '')])
+                else:
+                    curs.execute(db_change("insert into other (name, data) values ('robot', ?)"), [flask.request.form.get('content', '')])
+
+                conn.commit()
+
+                fw = open('./robots.txt', 'w', encoding='utf8')
+                fw.write(re.sub('\r\n', '\n', flask.request.form.get('content', '')))
+                fw.close()
+
+                admin_check(None, 'edit_set (' + str(num) + ')')
+
+                return redirect('/setting/5')
+            else:
+                if not os.path.exists('robots.txt'):
+                    curs.execute(db_change('select data from other where name = "robot"'))
+                    robot_test = curs.fetchall()
+                    if robot_test:
+                        fw_test = open('./robots.txt', 'w', encoding='utf8')
+                        fw_test.write(re.sub('\r\n', '\n', robot_test[0][0]))
+                        fw_test.close()
+                    else:
+                        fw_test = open('./robots.txt', 'w', encoding='utf8')
+                        fw_test.write('User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/')
+                        fw_test.close()
+
+                        curs.execute(db_change('insert into other (name, data) values ("robot", "User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/")'))
+
+                curs.execute(db_change("select data from other where name = 'robot'"))
+                robot = curs.fetchall()
+                if robot:
+                    data = robot[0][0]
+                else:
+                    data = ''
+
+                f = open('./robots.txt', encoding='utf8')
+                lines = f.readlines()
+                f.close()
+
+                if not data or data == '':
+                    data = ''.join(lines)
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = ['robots.txt', wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                    data = '''
+                        <a href="/robots.txt">(''' + load_lang('view') + ''')</a>
+                        <hr class="main_hr">
+                        <form method="post">
+                            <textarea rows="25" name="content">''' + html.escape(data) + '''</textarea>
+                            <hr class="main_hr">
+                            <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        </form>
+                    ''',
+                    menu = [['setting', load_lang('return')]]
+                ))
+        elif num == 6:
+            i_list = [
+                'recaptcha',
+                'sec_re',
+                'smtp_server',
+                'smtp_port',
+                'smtp_security',
+                'smtp_email',
+                'smtp_pass',
+                'recaptcha_ver',
+                'oauth_client_id',
+                'email_have'
+            ]
+
+            if flask.request.method == 'POST':
+                for data in i_list:
+                    into_data = flask.request.form.get(data, '')
+
+                    curs.execute(db_change("update other set data = ? where name = ?"), [into_data, data])
+
+                conn.commit()
+
+                admin_check(None, 'edit_set (' + str(num) + ')')
+
+                return redirect('/setting/6')
+            else:
+                d_list = []
+
+                x = 0
+
+                for i in i_list:
+                    curs.execute(db_change('select data from other where name = ?'), [i])
+                    sql_d = curs.fetchall()
+                    if sql_d:
+                        d_list += [sql_d[0][0]]
+                    else:
+                        curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
+
+                        d_list += ['']
+
+                    x += 1
+
+                conn.commit()
+
+                security_radios = ''
+                for i in ['tls', 'starttls', 'plain']:
+                    security_radios += '<input name="smtp_security" type="radio" value="' + i + '" ' + ('checked' if d_list[4] == i else '') + '>' + i + '<hr class="main_hr">'
+
+                re_ver = ''
+                if d_list[7] == '':
+                    re_ver += '<option value="">v2</option><option value="v3">v3</option>'
+                else:
+                    re_ver += '<option value="v3">v3</option><option value="">v2</option>'
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = [load_lang('ext_api_req_set'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                    data = '''
+                        <form method="post" id="main_set_data">
+                            <h2>1. ''' + load_lang('recaptcha') + '''</h2>
+                            <a href="https://www.google.com/recaptcha/admin">(Google)</a>
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('public_key') + '''</span>
+                            <hr class="main_hr">
+                            <input name="recaptcha" value="''' + html.escape(d_list[0]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('secret_key') + '''</span>
+                            <hr class="main_hr">
+                            <input name="sec_re" value="''' + html.escape(d_list[1]) + '''">
+                            <hr class="main_hr">
+
+                            <select name="recaptcha_ver">
+                                ''' + re_ver + '''
+                            </select>
+
+                            <h2>2. ''' + load_lang('email_setting') + '''</h1>
+                            <input type="checkbox" name="email_have" ''' + ('checked' if d_list[9] != '' else '')  + '''> ''' + \
+                                 load_lang('email_required') + '''
+
+                            <h2>2.1. ''' + load_lang('smtp_setting') + '''</h1>
+                            <a href="https://support.google.com/mail/answer/7126229">(Google)</a>
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('smtp_server') + '''</span>
+                            <hr class="main_hr">
+                            <input name="smtp_server" value="''' + html.escape(d_list[2]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('smtp_port') + '''</span>
+                            <hr class="main_hr">
+                            <input name="smtp_port" value="''' + html.escape(d_list[3]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('smtp_security') + '''</span>
+                            <hr class="main_hr">
+                            ''' + security_radios + '''
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('smtp_username') + '''</span>
+                            <hr class="main_hr">
+                            <input name="smtp_email" value="''' + html.escape(d_list[5]) + '''">
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('smtp_password') + '''</span>
+                            <hr class="main_hr">
+                            <input type="password" name="smtp_pass" value="''' + html.escape(d_list[6]) + '''">
+
+                            <h2>3. ''' + load_lang('oauth') + '''</h2>
+                            <a href="https://developers.google.com/identity/protocols/oauth2">(Google)</a>
+                            <hr class="main_hr">
+
+                            <span>''' + load_lang('oauth_client_id') + '''</span>
+                            <hr class="main_hr">
+                            <input name="oauth_client_id" value="''' + html.escape(d_list[8]) + '''">
+                            <hr class="main_hr">
+
+                            <hr class="main_hr">
+                            <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        </form>
+                        <script>simple_render('main_set_data');</script>
+                    ''',
+                    menu = [['setting', load_lang('return')]]
+                ))
+        elif num == 8:
+            i_list = {
+                1 : 'edit',
+                2 : 'discussion',
+                3 : 'upload_acl',
+                4 : 'all_view_acl',
+                5 : 'many_upload_acl',
+                6 : 'vote_acl'
+            }
+
+            if flask.request.method == 'POST':
+                if admin_check(None, 'edit_set (' + str(num) + ')') != 1:
+                    return re_error('/ban')
+                else:
+                    for i in i_list:
+                        curs.execute(db_change("update other set data = ? where name = ?"), [
+                            flask.request.form.get(i_list[i], 'normal'),
+                            i_list[i]
+                        ])
+
+                    conn.commit()
+
+                    return redirect('/setting/8')
+            else:
+                d_list = {}
+
+                if admin_check() != 1:
+                    disable = 'disabled'
+                else:
+                    disable = ''
+
+                for i in i_list:
+                    curs.execute(db_change('select data from other where name = ?'), [i_list[i]])
+                    sql_d = curs.fetchall()
+                    if sql_d:
+                        d_list[i] = sql_d[0][0]
+                    else:
+                        curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i_list[i], 'normal'])
+
+                        d_list[i] = 'normal'
+
+                conn.commit()
+
+                acl_div = []
+                for i in range(0, len(i_list)):
+                    acl_div += ['']
+
+                acl_list = get_acl_list()
+                for i in range(0, len(i_list)):
+                    for data_list in acl_list:
+                        if data_list == d_list[i + 1]:
+                            check = 'selected="selected"'
+                        else:
+                            check = ''
+
+                        acl_div[i] += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = [load_lang('main_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                    data = '''
+                        <form method="post">
+                            <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
+                            <hr class="main_hr">
+                            <span>''' + load_lang('document_acl') + '''</span> 
+                            <hr class="main_hr">
+                            <select ''' + disable + ''' name="edit">''' + acl_div[0] + '''</select>
+                            <hr class="main_hr">
+                            <span>''' + load_lang('discussion_acl') + '''</span>
+                            <hr class="main_hr">
+                            <select ''' + disable + ''' name="discussion">''' + acl_div[1] + '''</select>
+                            <hr class="main_hr">
+                            <span>''' + load_lang('upload_acl') + '''</span>
+                            <hr class="main_hr">
+                            <select ''' + disable + ''' name="upload_acl">''' + acl_div[2] + '''</select>
+                            <hr class="main_hr">
+                            <span>''' + load_lang('view_acl') + '''</span>
+                            <hr class="main_hr">
+                            <select ''' + disable + ''' name="all_view_acl">''' + acl_div[3] + '''</select>
+                            <hr class="main_hr">
+                            <span>''' + load_lang('many_upload_acl') + '''</span>
+                            <hr class="main_hr">
+                            <select ''' + disable + ''' name="many_upload_acl">''' + acl_div[4] + '''</select>
+                            <hr class="main_hr">
+                            <span>''' + load_lang('vote_acl') + '''</span>
+                            <hr class="main_hr">
+                            <select ''' + disable + ''' name="vote_acl">''' + acl_div[5] + '''</select>
+                            <hr class="main_hr">
+                            <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        </form>
+                    ''',
+                    menu = [['setting', load_lang('return')]]
+                ))
+        elif num == 9:
+            skin_list = [0] + load_skin('', 1)
+            i_list = []
+            for i in skin_list:
+                i_list += [['logo', '' if i == 0 else i]]
+
+            if flask.request.method == 'POST':
+                for i in i_list:
+                    curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [
+                        flask.request.form.get(('main_css' if i[1] == '' else i[1]), ''),
+                        i[0], 
+                        i[1]
+                    ])
+
+                conn.commit()
+
+                admin_check(None, 'edit_set (' + str(num) + ')')
+
+                return redirect('/setting/9')
+            else:
+                d_list = []
+                for i in i_list:
+                    curs.execute(db_change('select data from other where name = ? and coverage = ?'), [i[0], i[1]])
+                    sql_d = curs.fetchall()
+                    if sql_d:
+                        d_list += [sql_d[0][0]]
+                    else:
+                        curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, ?)'), [i[0], '', i[1]])
+
+                        d_list += ['']
+
+                end_data = ''
+                for i in range(0, len(skin_list)):
+                    end_data += '' + \
+                        '<span>' + load_lang('wiki_logo') + ' ' + ('(' + skin_list[i] + ')' if skin_list[i] != 0 else '') + ' (HTML)' + \
+                        '<hr class="main_hr">' + \
+                        '<input name="' + (skin_list[i] if skin_list[i] != 0 else 'main_css') + '" value="' + html.escape(d_list[i]) + '">' + \
+                        '<hr class="main_hr">' + \
+                    ''
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = [load_lang('wiki_logo'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                    data = '''
+                        <form method="post">
+                            ''' + end_data + '''
+                            <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        </form>
+                    ''',
+                    menu = [['setting', load_lang('return')]]
+                ))
+        else:
+            return redirect()

+ 18 - 0
route/main_func_skin_set.py

@@ -0,0 +1,18 @@
+from .tool.func import *
+
+def main_func_skin_set(conn):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        data = flask.make_response(re_error('/error/5'))
+
+        curs.execute(db_change("select data from other where name = 'language'"))
+        main_data = curs.fetchall()
+
+        data.set_cookie('language', main_data[0][0])
+
+        curs.execute(db_change('select data from user_set where name = "lang" and id = ?'), [ip_check()])
+        user_data = curs.fetchall()
+        data.set_cookie('user_language', user_data[0][0] if user_data else main_data[0][0])
+
+        return data

+ 154 - 0
route/main_func_upload.py

@@ -0,0 +1,154 @@
+from .tool.func import *
+
+def main_func_upload():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if acl_check(None, 'upload') == 1:
+            return re_error('/ban')
+
+        if flask.request.method == 'POST':
+            if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
+                return re_error('/error/13')
+            else:
+                captcha_post('', 0)
+
+            file_data = flask.request.files.getlist("f_data[]", None)
+            if not file_data:
+                return re_error('/error/9')
+
+            file_len = len(file_data)
+
+            if (int(wiki_set(3)) * 1000 * 1000 * file_len) < flask.request.content_length:
+                return re_error('/error/17')
+
+            if file_len == 1:    
+                file_num = None
+            else:
+                if acl_check(None, 'many_upload') == 1:
+                    return re_error('/ban')
+
+                file_num = 1
+
+            for data in file_data:
+                value = os.path.splitext(data.filename)[1]
+
+                curs.execute(db_change("select html from html_filter where kind = 'extension'"))
+                extension = [i[0].lower() for i in curs.fetchall()]
+                if not re.sub(r'^\.', '', value).lower() in extension:
+                    return re_error('/error/14')
+
+                if flask.request.form.get('f_name', None):
+                    name = flask.request.form.get('f_name', None) + (' ' + str(file_num) if file_num else '') + value
+                else:
+                    name = data.filename
+
+                piece = os.path.splitext(name)
+                if re.search(r'[^ㄱ-힣0-9a-zA-Z_\- ]', piece[0]):
+                    return re_error('/error/22')
+
+                e_data = sha224_replace(piece[0]) + piece[1]
+
+                curs.execute(db_change("select title from data where title = ?"), ['file:' + name])
+                if curs.fetchall():
+                    return re_error('/error/16')
+
+                curs.execute(db_change("select html from html_filter where kind = 'file'"))
+                db_data = curs.fetchall()
+                for i in db_data:
+                    t_re = re.compile(i[0])
+                    if t_re.search(name):
+                        return redirect('/file_filter')
+
+                data_url_image = load_image_url()
+                if os.path.exists(os.path.join(data_url_image, e_data)):
+                    return re_error('/error/16')
+                else:
+                    data.save(os.path.join(data_url_image, e_data))
+
+                ip = ip_check()
+                g_lice = flask.request.form.get('f_lice', '')
+                file_size = os.stat(os.path.join(data_url_image, e_data)).st_size
+                file_size = str(round(file_size / 1000, 1))
+
+                curs.execute(db_change("select data from other where name = 'markup'"))
+                db_data = curs.fetchall()
+                if db_data and db_data[0][0] == 'namumark':
+                    file_d = '' + \
+                        flask.request.form.get('f_lice_sel', 'direct_input') + '\n' + \
+                        '[[category:' + re.sub(r'\]', '_', flask.request.form.get('f_lice_sel', '')) + ']]\n' + \
+                        (g_lice if g_lice != '' else '') + \
+                    ''
+                else:
+                    file_d = '' + \
+                        flask.request.form.get('f_lice_sel', 'direct_input') + '\n' + \
+                        (g_lice if g_lice != '' else '') + \
+                    ''
+
+                curs.execute(db_change("insert into data (title, data) values (?, ?)"), ['file:' + name, file_d])
+                curs.execute(db_change("insert into acl (title, data, type) values (?, 'admin', 'decu')"), ['file:' + name])
+
+                render_set(
+                    doc_name = 'file:' + name,
+                    doc_data = file_d,
+                    data_type = 'backlink'
+                )
+
+                history_plus(
+                    'file:' + name,
+                    file_d,
+                    get_time(),
+                    ip,
+                    '',
+                    '0',
+                    t_check = 'upload',
+                    mode = 'upload'
+                )
+
+                if file_num:
+                    file_num += 1
+
+            conn.commit()
+
+            return redirect('/w/file:' + name)
+        else:
+            license_list = '<option value="direct_input">' + load_lang('direct_input') + '</option>'
+            file_name = flask.request.args.get('name', '')
+
+            curs.execute(db_change("select html from html_filter where kind = 'image_license'"))
+            db_data = curs.fetchall()
+            license_list += ''.join(['<option value="' + i[0] + '">' + i[0] + '</option>' for i in db_data])
+
+            curs.execute(db_change("select data from other where name = 'upload_help'"))
+            db_data = curs.fetchall()
+            upload_help = ('<hr class="main_hr">' + db_data[0][0]) if db_data and db_data[0][0] != '' else ''
+
+            curs.execute(db_change("select data from other where name = 'upload_default'"))
+            db_data = curs.fetchall()
+            upload_default = html.escape(db_data[0][0]) if db_data and db_data[0][0] != '' else ''
+
+            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>
+                    ''' + upload_help + '''
+                    <hr class="main_hr">
+                    ''' + load_lang('max_file_size') + ''' : ''' + wiki_set(3) + '''MB
+                    <hr class="main_hr">
+                    <form method="post" enctype="multipart/form-data" accept-charset="utf8">
+                        <input multiple="multiple" type="file" name="f_data[]">
+                        <hr class="main_hr">
+                        <input placeholder="''' + load_lang('file_name') + '''" name="f_name" value="''' + file_name + '''">
+                        <hr class="main_hr">
+                        <select name="f_lice_sel">
+                            ''' + license_list + '''
+                        </select>
+                        <hr class="main_hr">
+                        <textarea rows="10" placeholder="''' + load_lang('other') + '''" name="f_lice">''' + upload_default + '''</textarea>
+                        <hr class="main_hr">
+                        ''' + captcha_get() + '''
+                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
+                menu = [['other', load_lang('return')]]
+            ))

+ 0 - 755
route/main_setting.py

@@ -1,755 +0,0 @@
-from .tool.func import *
-
-def main_setting_2(conn, num, db_set):
-    curs = conn.cursor()
-
-    if not (num == 0 or num == 8) and admin_check() != 1:
-        return re_error('/ban')
-
-    if num == 0:
-        li_list = [
-            [1, load_lang('main_setting')],
-            [2, load_lang('text_setting')],
-            [5, 'robots.txt'],
-            [6, load_lang('ext_api_req_set')],
-            [3, load_lang('main_head')],
-            [4, load_lang('main_body')],
-            [7, load_lang('main_bottom_body')]
-        ]
-
-        li_data = ''.join(['<li><a href="/setting/' + str(li[0]) + '">' + li[1] + '</a></li>' for li in li_list])
-        
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = '<h2>' + load_lang('list') + '</h2><ul class="inside_ul">' + li_data + '</ul>',
-            menu = [['manager', load_lang('return')]]
-        ))
-    elif num == 1:
-        i_list = {
-            0 : 'name',
-            2 : 'frontpage',
-            4 : 'upload',
-            5 : 'skin',
-            7 : 'reg',
-            8 : 'ip_view',
-            9 : 'back_up',
-            10 : 'port',
-            11 : 'key',
-            12 : 'update',
-            15 : 'encode',
-            16 : 'host',
-            19 : 'slow_edit',
-            20 : 'requires_approval',
-            21 : 'backup_where',
-            22 : 'domain',
-            23 : 'ua_get'
-        }
-        n_list = {
-            0 : 'Wiki',
-            2 : 'FrontPage',
-            4 : '2',
-            5 : '',
-            7 : '',
-            8 : '',
-            9 : '0',
-            10 : '3000',
-            11 : 'test',
-            12 : 'stable',
-            15 : 'sha3',
-            16 : '0.0.0.0',
-            19 : '0',
-            20 : '',
-            21 : '',
-            22 : flask.request.host_url,
-            23 : ''
-        }
-
-        if flask.request.method == 'POST':
-            for i in i_list:
-                curs.execute(db_change("update other set data = ? where name = ?"), [
-                    flask.request.form.get(i_list[i], n_list[i]),
-                    i_list[i]
-                ])
-
-            conn.commit()
-
-            admin_check(None, 'edit_set (' + str(num) + ')')
-
-            return redirect('/setting/1')
-        else:
-            d_list = {}
-
-            for i in i_list:
-                curs.execute(db_change('select data from other where name = ?'), [i_list[i]])
-                sql_d = curs.fetchall()
-                if sql_d:
-                    d_list[i] = sql_d[0][0]
-                else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i_list[i], n_list[i]])
-
-                    d_list[i] = n_list[i]
-
-            conn.commit()
-
-            acl_div = ['']
-            encode_data = ['sha256', 'sha3']
-            for acl_data in encode_data:
-                if acl_data == d_list[15]:
-                    acl_div[0] = '<option value="' + acl_data + '">' + acl_data + '</option>' + acl_div[0]
-                else:
-                    acl_div[0] += '<option value="' + acl_data + '">' + acl_data + '</option>'
-
-            check_box_div = ['', '', '', '', '']
-            for i in range(0, len(check_box_div)):
-                if i == 0:
-                    acl_num = 7
-                elif i == 1:
-                    acl_num = 8
-                elif i == 3:
-                    acl_num = 20
-                else:
-                    acl_num = 23
-
-                if d_list[acl_num]:
-                    check_box_div[i] = 'checked="checked"'
-
-            branch_div = ''
-            branch_list = ['stable', 'dev', 'beta']
-            for i in branch_list:
-                if d_list[12] == i:
-                    branch_div = '<option value="' + i + '">' + i + '</option>' + branch_div
-                else:
-                    branch_div += '<option value="' + i + '">' + i + '</option>'
-
-            sqlite_only = 'style="display:none;"' if db_set != 'sqlite' else ''
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('main_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post" id="main_set_data">
-                        <h2>1. ''' + load_lang('basic_set') + '''</h2>
-                        <span>''' + load_lang('wiki_name') + '''</span>
-                        <hr class="main_hr">
-                        <input name="name" value="''' + html.escape(d_list[0]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span><a href="/setting/9">(''' + load_lang('wiki_logo') + ''')</a></span>
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('main_page') + '''</span>
-                        <hr class="main_hr">
-                        <input name="frontpage" value="''' + html.escape(d_list[2]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('domain') + '''</span> (EX : http://2du.pythonanywhere.com/)
-                        <hr class="main_hr">
-                        <input name="''' + i_list[22] + '''" value="''' + html.escape(d_list[22]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('wiki_host') + '''</span>
-                        <hr class="main_hr">
-                        <input name="host" value="''' + html.escape(d_list[16]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('wiki_port') + '''</span>
-                        <hr class="main_hr">
-                        <input name="port" value="''' + html.escape(d_list[10]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('wiki_secret_key') + '''</span>
-                        <hr class="main_hr">
-                        <input type="password" name="key" value="''' + html.escape(d_list[11]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('encryption_method') + '''</span>
-                        <hr class="main_hr">
-                        <select name="encode">''' + acl_div[0] + '''</select>
-                        
-                        <h2>2. ''' + load_lang('design_set') + '''</h2>
-                        <span>''' + load_lang('wiki_skin') + '''</span>
-                        <hr class="main_hr">
-                        <select name="skin">''' + load_skin(d_list[5] if d_list[5] != '' else 'tenshi') + '''</select>
-                        
-                        <h2>3. ''' + load_lang('login_set') + '''</h2>
-                        <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
-                        <hr class="main_hr">
-                        
-                        <input type="checkbox" name="ip_view" ''' + check_box_div[1] + '''> ''' + load_lang('hide_ip') + '''
-                        <hr class="main_hr">
-                        
-                        <input type="checkbox" name="requires_approval" ''' + check_box_div[3] + '''> ''' + load_lang('requires_approval') + '''
-                        <hr class="main_hr">
-                        
-                        <input type="checkbox" name="ua_get" ''' + check_box_div[4] + '''> ''' + load_lang('ua_get_off') + '''
-                        
-                        <h2>4. ''' + load_lang('server_set') + '''</h2>
-                        <span>''' + load_lang('max_file_size') + ''' (MB)</span>
-                        <hr class="main_hr">
-                        <input name="upload" value="''' + html.escape(d_list[4]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span ''' + sqlite_only + '''>
-                            <span>
-                                ''' + load_lang('backup_interval') + ' (' + load_lang('hour') + ') (' + load_lang('off') + ' : 0) ' + \
-                                '(' + load_lang('restart_required') + ''')</span>
-                            <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('empty') + ' : ' + load_lang('default') + ') ' + \
-                                '(' + load_lang('restart_required') + ''') (EX : ./data/backup.db)
-                            </span>
-                            <hr class="main_hr">
-                            <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
-                            <hr class="main_hr">
-                        </span>
-                        
-                        <span>''' + load_lang('update_branch') + '''</span>
-                        <hr class="main_hr">
-                        <select name="update">''' + branch_div + '''</select>
-                        
-                        <h2>5. ''' + load_lang('edit_set') + '''</h2>
-                        <span><a href="/setting/8">(''' + load_lang('main_acl_setting') + ''')</a></span>
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('slow_edit') + ' (' + load_lang('second') + ') (' + load_lang('off') + ''' : 0)</span>
-                        <hr class="main_hr">
-                        <input name="''' + i_list[19] + '''" value="''' + html.escape(d_list[19]) + '''">
-                        
-                        <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                    <script>simple_render('main_set_data');</script>
-                ''',
-                menu = [['setting', load_lang('return')]]
-            ))
-    elif num == 2:
-        i_list = [
-            'contract',
-            'no_login_warning',
-            'edit_bottom_text',
-            'copyright_checkbox_text',
-            'check_key_text',
-            'email_title',
-            'email_text',
-            'email_insert_text',
-            'password_search_text',
-            'reset_user_text',
-            'error_401',
-            'error_404',
-            'approval_question',
-            'edit_help',
-            'upload_help',
-            'upload_default',
-            'license'
-        ]
-        if flask.request.method == 'POST':
-            for i in i_list:
-                curs.execute(db_change("update other set data = ? where name = ?"), [
-                    flask.request.form.get(i, ''),
-                    i
-                ])
-
-            conn.commit()
-
-            admin_check(None, 'edit_set (' + str(num) + ')')
-
-            return redirect('/setting/2')
-        else:
-            d_list = []
-
-            for i in i_list:
-                curs.execute(db_change('select data from other where name = ?'), [i])
-                sql_d = curs.fetchall()
-                if sql_d:
-                    d_list += [sql_d[0][0]]
-                else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
-
-                    d_list += ['']
-
-            conn.commit()
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('text_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post" id="main_set_data">
-                        <h2>1. ''' + load_lang('register_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[0] + '''">''' + html.escape(d_list[0]) + '''</textarea>
-                        
-                        <h2>2. ''' + load_lang('non_login_alert') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[1] + '''">''' + html.escape(d_list[1]) + '''</textarea>
-                        
-                        <h2>3. ''' + load_lang('edit_bottom_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[2] + '''">''' + html.escape(d_list[2]) + '''</textarea>
-                        
-                        <h2>4. ''' + load_lang('copyright_checkbox_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[3] + '''">''' + html.escape(d_list[3]) + '''</textarea>
-                        
-                        <h2>5. ''' + load_lang('check_key_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[4] + '''">''' + html.escape(d_list[4]) + '''</textarea>
-                        
-                        <h2>6. ''' + load_lang('email_title') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[5] + '''">''' + html.escape(d_list[5]) + '''</textarea>
-                        
-                        <h2>7. ''' + load_lang('email_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[6] + '''">''' + html.escape(d_list[6]) + '''</textarea>
-                        
-                        <h2>8. ''' + load_lang('email_insert_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[7] + '''">''' + html.escape(d_list[7]) + '''</textarea>
-                        
-                        <h2>9. ''' + load_lang('password_search_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[8] + '''">''' + html.escape(d_list[8]) + '''</textarea>
-                        
-                        <h2>10. ''' + load_lang('reset_user_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[9] + '''">''' + html.escape(d_list[9]) + '''</textarea>
-                        
-                        <h2>11. ''' + load_lang('error_401') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[10] + '''">''' + html.escape(d_list[10]) + '''</textarea>
-                        
-                        <h2>12. ''' + load_lang('error_404') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[11] + '''">''' + html.escape(d_list[11]) + '''</textarea>
-                        
-                        <h2>13. ''' + load_lang('approval_question') + '''</h2>
-                        <sup>(1)</sup>
-                        <hr class="main_hr">
-                        <textarea rows="3" name="''' + i_list[12] + '''">''' + html.escape(d_list[12]) + '''</textarea>
-                        
-                        <h2>14. ''' + load_lang('edit_help') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[13] + '''">''' + html.escape(d_list[13]) + '''</textarea>
-                        
-                        <h2>15. ''' + load_lang('upload_help') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[14] + '''">''' + html.escape(d_list[14]) + '''</textarea>
-                        
-                        <h2>16. ''' + load_lang('upload_default') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[15] + '''">''' + html.escape(d_list[15]) + '''</textarea>
-                        
-                        <h2>17. ''' + load_lang('bottom_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[16] + '''">''' + html.escape(d_list[16]) + '''</textarea>
-                        
-                        <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                    <ul id="footnote_data">
-                        <li><a href="#note_1" id="note_1_end">(1)</a> ''' + load_lang('approval_question_visible_only_when_approval_on') + '''</li>
-                    </ul>
-                    <script>simple_render('main_set_data');</script>
-                ''',
-                menu = [['setting', load_lang('return')]]
-            ))
-    elif num == 3 or num == 4 or num == 7:
-        if flask.request.method == 'POST':
-            if num == 4:
-                info_d = 'body'
-                end_r = '4'
-                coverage = ''
-            elif num == 7:
-                info_d = 'bottom_body'
-                end_r = '7'
-                coverage = ''
-            else:
-                info_d = 'head'
-                end_r = '3'
-                if flask.request.args.get('skin', '') == '':
-                    coverage = ''
-                else:
-                    coverage = flask.request.args.get('skin', '')
-
-            curs.execute(db_change("select name from other where name = ? and coverage = ?"), [info_d, coverage])
-            if curs.fetchall():
-                curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [
-                    flask.request.form.get('content', ''),
-                    info_d,
-                    coverage
-                ])
-            else:
-                curs.execute(db_change("insert into other (name, data, coverage) values (?, ?, ?)"), [info_d, flask.request.form.get('content', ''), coverage])
-
-            conn.commit()
-
-            admin_check(None, 'edit_set (' + str(num) + ')')
-
-            return redirect('/setting/' + end_r + '?skin=' + flask.request.args.get('skin', ''))
-        else:
-            if num == 4:
-                curs.execute(db_change("select data from other where name = 'body'"))
-                title = '_body'
-                start = ''
-                plus = '''
-                    <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
-                    <hr class="main_hr">
-                    <div id="see_preview"></div>
-                '''
-            elif num == 7:
-                curs.execute(db_change("select data from other where name = 'bottom_body'"))
-                title = '_bottom_body'
-                start = ''
-                plus = '''
-                    <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
-                    <hr class="main_hr">
-                    <div id="see_preview"></div>
-                '''
-            else:
-                curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [flask.request.args.get('skin', '')])
-                title = '_head'
-                start = '' + \
-                    '<a href="?">(' + load_lang('all') + ')</a> ' + \
-                    ' '.join(['<a href="?skin=' + i + '">(' + i + ')</a>' for i in load_skin('', 1)]) + '''
-                    <hr class="main_hr">
-                    <span>&lt;style&gt;CSS&lt;/style&gt;<br>&lt;script&gt;JS&lt;/script&gt;</span>
-                    <hr class="main_hr">
-                '''
-                plus = ''
-
-            head = curs.fetchall()
-            if head:
-                data = head[0][0]
-            else:
-                data = ''
-
-            if flask.request.args.get('skin', '') != '':
-                sub_plus = ' (' + flask.request.args.get('skin', '') + ')'
-            else:
-                sub_plus = ''
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang(data = 'main' + title, safe = 1), wiki_set(), wiki_custom(), wiki_css(['(HTML)' + sub_plus, 0])],
-                data = '''
-                    <form method="post">
-                        ''' + start + '''
-                        <textarea rows="25" placeholder="''' + load_lang('enter_html') + '''" name="content" id="content">''' + html.escape(data) + '''</textarea>
-                        <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                        ''' + plus + '''
-                    </form>
-                ''',
-                menu = [['setting', load_lang('return')]]
-            ))
-    elif num == 5:
-        if flask.request.method == 'POST':
-            curs.execute(db_change("select name from other where name = 'robot'"))
-            if curs.fetchall():
-                curs.execute(db_change("update other set data = ? where name = 'robot'"), [flask.request.form.get('content', '')])
-            else:
-                curs.execute(db_change("insert into other (name, data) values ('robot', ?)"), [flask.request.form.get('content', '')])
-
-            conn.commit()
-
-            fw = open('./robots.txt', 'w', encoding='utf8')
-            fw.write(re.sub('\r\n', '\n', flask.request.form.get('content', '')))
-            fw.close()
-
-            admin_check(None, 'edit_set (' + str(num) + ')')
-
-            return redirect('/setting/5')
-        else:
-            if not os.path.exists('robots.txt'):
-                curs.execute(db_change('select data from other where name = "robot"'))
-                robot_test = curs.fetchall()
-                if robot_test:
-                    fw_test = open('./robots.txt', 'w', encoding='utf8')
-                    fw_test.write(re.sub('\r\n', '\n', robot_test[0][0]))
-                    fw_test.close()
-                else:
-                    fw_test = open('./robots.txt', 'w', encoding='utf8')
-                    fw_test.write('User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/')
-                    fw_test.close()
-
-                    curs.execute(db_change('insert into other (name, data) values ("robot", "User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/")'))
-
-            curs.execute(db_change("select data from other where name = 'robot'"))
-            robot = curs.fetchall()
-            if robot:
-                data = robot[0][0]
-            else:
-                data = ''
-
-            f = open('./robots.txt', encoding='utf8')
-            lines = f.readlines()
-            f.close()
-
-            if not data or data == '':
-                data = ''.join(lines)
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = ['robots.txt', wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <a href="/robots.txt">(''' + load_lang('view') + ''')</a>
-                    <hr class="main_hr">
-                    <form method="post">
-                        <textarea rows="25" name="content">''' + html.escape(data) + '''</textarea>
-                        <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                ''',
-                menu = [['setting', load_lang('return')]]
-            ))
-    elif num == 6:
-        i_list = [
-            'recaptcha',
-            'sec_re',
-            'smtp_server',
-            'smtp_port',
-            'smtp_security',
-            'smtp_email',
-            'smtp_pass',
-            'recaptcha_ver',
-            'oauth_client_id',
-            'email_have'
-        ]
-
-        if flask.request.method == 'POST':
-            for data in i_list:
-                into_data = flask.request.form.get(data, '')
-
-                curs.execute(db_change("update other set data = ? where name = ?"), [into_data, data])
-
-            conn.commit()
-
-            admin_check(None, 'edit_set (' + str(num) + ')')
-
-            return redirect('/setting/6')
-        else:
-            d_list = []
-
-            x = 0
-
-            for i in i_list:
-                curs.execute(db_change('select data from other where name = ?'), [i])
-                sql_d = curs.fetchall()
-                if sql_d:
-                    d_list += [sql_d[0][0]]
-                else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
-
-                    d_list += ['']
-
-                x += 1
-
-            conn.commit()
-
-            security_radios = ''
-            for i in ['tls', 'starttls', 'plain']:
-                security_radios += '<input name="smtp_security" type="radio" value="' + i + '" ' + ('checked' if d_list[4] == i else '') + '>' + i + '<hr class="main_hr">'
-
-            re_ver = ''
-            if d_list[7] == '':
-                re_ver += '<option value="">v2</option><option value="v3">v3</option>'
-            else:
-                re_ver += '<option value="v3">v3</option><option value="">v2</option>'
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('ext_api_req_set'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post" id="main_set_data">
-                        <h2>1. ''' + load_lang('recaptcha') + '''</h2>
-                        <a href="https://www.google.com/recaptcha/admin">(Google)</a>
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('public_key') + '''</span>
-                        <hr class="main_hr">
-                        <input name="recaptcha" value="''' + html.escape(d_list[0]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('secret_key') + '''</span>
-                        <hr class="main_hr">
-                        <input name="sec_re" value="''' + html.escape(d_list[1]) + '''">
-                        <hr class="main_hr">
-                        
-                        <select name="recaptcha_ver">
-                            ''' + re_ver + '''
-                        </select>
-                        
-                        <h2>2. ''' + load_lang('email_setting') + '''</h1>
-                        <input type="checkbox" name="email_have" ''' + ('checked' if d_list[9] != '' else '')  + '''> ''' + \
-                             load_lang('email_required') + '''
-                        
-                        <h2>2.1. ''' + load_lang('smtp_setting') + '''</h1>
-                        <a href="https://support.google.com/mail/answer/7126229">(Google)</a>
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('smtp_server') + '''</span>
-                        <hr class="main_hr">
-                        <input name="smtp_server" value="''' + html.escape(d_list[2]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('smtp_port') + '''</span>
-                        <hr class="main_hr">
-                        <input name="smtp_port" value="''' + html.escape(d_list[3]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('smtp_security') + '''</span>
-                        <hr class="main_hr">
-                        ''' + security_radios + '''
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('smtp_username') + '''</span>
-                        <hr class="main_hr">
-                        <input name="smtp_email" value="''' + html.escape(d_list[5]) + '''">
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('smtp_password') + '''</span>
-                        <hr class="main_hr">
-                        <input type="password" name="smtp_pass" value="''' + html.escape(d_list[6]) + '''">
-                        
-                        <h2>3. ''' + load_lang('oauth') + '''</h2>
-                        <a href="https://developers.google.com/identity/protocols/oauth2">(Google)</a>
-                        <hr class="main_hr">
-                        
-                        <span>''' + load_lang('oauth_client_id') + '''</span>
-                        <hr class="main_hr">
-                        <input name="oauth_client_id" value="''' + html.escape(d_list[8]) + '''">
-                        <hr class="main_hr">
-                        
-                        <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                    <script>simple_render('main_set_data');</script>
-                ''',
-                menu = [['setting', load_lang('return')]]
-            ))
-    elif num == 8:
-        i_list = {
-            1 : 'edit',
-            2 : 'discussion',
-            3 : 'upload_acl',
-            4 : 'all_view_acl',
-            5 : 'many_upload_acl',
-            6 : 'vote_acl'
-        }
-
-        if flask.request.method == 'POST':
-            if admin_check(None, 'edit_set (' + str(num) + ')') != 1:
-                return re_error('/ban')
-            else:
-                for i in i_list:
-                    curs.execute(db_change("update other set data = ? where name = ?"), [
-                        flask.request.form.get(i_list[i], 'normal'),
-                        i_list[i]
-                    ])
-
-                conn.commit()
-
-                return redirect('/setting/8')
-        else:
-            d_list = {}
-
-            if admin_check() != 1:
-                disable = 'disabled'
-            else:
-                disable = ''
-
-            for i in i_list:
-                curs.execute(db_change('select data from other where name = ?'), [i_list[i]])
-                sql_d = curs.fetchall()
-                if sql_d:
-                    d_list[i] = sql_d[0][0]
-                else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i_list[i], 'normal'])
-
-                    d_list[i] = 'normal'
-
-            conn.commit()
-
-            acl_div = []
-            for i in range(0, len(i_list)):
-                acl_div += ['']
-
-            acl_list = get_acl_list()
-            for i in range(0, len(i_list)):
-                for data_list in acl_list:
-                    if data_list == d_list[i + 1]:
-                        check = 'selected="selected"'
-                    else:
-                        check = ''
-                    
-                    acl_div[i] += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('main_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post">
-                        <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('document_acl') + '''</span> 
-                        <hr class="main_hr">
-                        <select ''' + disable + ''' name="edit">''' + acl_div[0] + '''</select>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('discussion_acl') + '''</span>
-                        <hr class="main_hr">
-                        <select ''' + disable + ''' name="discussion">''' + acl_div[1] + '''</select>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('upload_acl') + '''</span>
-                        <hr class="main_hr">
-                        <select ''' + disable + ''' name="upload_acl">''' + acl_div[2] + '''</select>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('view_acl') + '''</span>
-                        <hr class="main_hr">
-                        <select ''' + disable + ''' name="all_view_acl">''' + acl_div[3] + '''</select>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('many_upload_acl') + '''</span>
-                        <hr class="main_hr">
-                        <select ''' + disable + ''' name="many_upload_acl">''' + acl_div[4] + '''</select>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('vote_acl') + '''</span>
-                        <hr class="main_hr">
-                        <select ''' + disable + ''' name="vote_acl">''' + acl_div[5] + '''</select>
-                        <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                ''',
-                menu = [['setting', load_lang('return')]]
-            ))
-    elif num == 9:
-        skin_list = [0] + load_skin('', 1)
-        i_list = []
-        for i in skin_list:
-            i_list += [['logo', '' if i == 0 else i]]
-        
-        if flask.request.method == 'POST':
-            for i in i_list:
-                curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [
-                    flask.request.form.get(('main_css' if i[1] == '' else i[1]), ''),
-                    i[0], 
-                    i[1]
-                ])
-
-            conn.commit()
-
-            admin_check(None, 'edit_set (' + str(num) + ')')
-
-            return redirect('/setting/9')
-        else:
-            d_list = []
-            for i in i_list:
-                curs.execute(db_change('select data from other where name = ? and coverage = ?'), [i[0], i[1]])
-                sql_d = curs.fetchall()
-                if sql_d:
-                    d_list += [sql_d[0][0]]
-                else:
-                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, ?)'), [i[0], '', i[1]])
-
-                    d_list += ['']
-            
-            end_data = ''
-            for i in range(0, len(skin_list)):
-                end_data += '' + \
-                    '<span>' + load_lang('wiki_logo') + ' ' + ('(' + skin_list[i] + ')' if skin_list[i] != 0 else '') + ' (HTML)' + \
-                    '<hr class="main_hr">' + \
-                    '<input name="' + (skin_list[i] if skin_list[i] != 0 else 'main_css') + '" value="' + html.escape(d_list[i]) + '">' + \
-                    '<hr class="main_hr">' + \
-                ''
-            
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('wiki_logo'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post">
-                        ''' + end_data + '''
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                ''',
-                menu = [['setting', load_lang('return')]]
-            ))
-    else:
-        return redirect()

+ 0 - 20
route/main_skin_set.py

@@ -1,20 +0,0 @@
-from .tool.func import *
-
-def main_skin_set_2(conn):
-    curs = conn.cursor()
-
-    data = flask.make_response(re_error('/error/5'))
-
-    curs.execute(db_change("select data from other where name = 'language'"))
-    main_data = curs.fetchall()
-
-    data.set_cookie('language', main_data[0][0])
-
-    curs.execute(db_change('select data from user_set where name = "lang" and id = ?'), [ip_check()])
-    user_data = curs.fetchall()
-    if user_data:
-        data.set_cookie('user_language', user_data[0][0])
-    else:
-        data.set_cookie('user_language', main_data[0][0])
-
-    return data

+ 1 - 3
route/main_restart.py → route/main_sys_restart.py

@@ -1,8 +1,6 @@
 from .tool.func import *
 
-def main_restart_2(conn):
-    curs = conn.cursor()
-
+def main_sys_restart():
     if admin_check() != 1:
         return re_error('/error/3')
 

+ 1 - 3
route/main_shutdown.py → route/main_sys_shutdown.py

@@ -1,8 +1,6 @@
 from .tool.func import *
 
-def main_shutdown_2(conn):
-    curs = conn.cursor()
-    
+def main_sys_shutdown():
     if admin_check() != 1:
         return re_error('/error/3')
 

+ 63 - 0
route/main_sys_update.py

@@ -0,0 +1,63 @@
+from .tool.func import *
+
+def main_sys_update():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if admin_check() != 1:
+            return re_error('/error/3')
+
+        if flask.request.method == 'POST':
+            admin_check(None, 'update')
+
+            curs.execute(db_change('select data from other where name = "update"'))
+            up_data = curs.fetchall()
+            up_data = up_data[0][0] if up_data and up_data[0][0] in ['stable', 'beta', 'dev'] else 'stable'
+
+            print('----')
+            print('Update')
+            print('----')
+            if platform.system() == 'Linux':
+                ok = []
+
+                ok += [os.system('git remote rm origin')]
+                ok += [os.system('git remote add origin https://github.com/opennamu/opennamu.git')]
+                ok += [os.system('git fetch origin ' + up_data)]
+                ok += [os.system('git reset --hard origin/' + up_data)]
+                if (ok[0] and ok[1] and ok[2] and ok[3]) == 0:
+                    return redirect('/restart')
+                else:
+                    print('Error : update failed')
+            elif platform.system() == 'Windows':
+                os.system('rd /s /q route')
+                urllib.request.urlretrieve('https://github.com/opennamu/opennamu/archive/' + up_data + '.zip', 'update.zip')
+                zipfile.ZipFile('update.zip').extractall('')
+                ok = os.system('xcopy /y /s /r opennamu-' + up_data + ' .')
+                if ok == 0:
+                    os.system('rd /s /q opennamu-' + up_data)
+                    os.system('del update.zip')
+
+                    return redirect('/restart')
+                else:
+                    print('Error : update failed')
+
+            return re_error('/error/34')
+        else:
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('update'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                data = load_lang('update_warning') + '''
+                    <hr class=\"main_hr\">
+                    <ul class="inside_ul">
+                        <li>''' + load_lang('version') + ''' : <span id="ver_send_2"></span></li>
+                        <li id="ver_send" style="display: none;">''' + load_lang('lastest') + ''' : </li>
+                    </ul>
+                    <a href="https://github.com/openNAMU/openNAMU">(Beta)</a> <a href="https://github.com/openNAMU/openNAMU/tree/stable">(Stable)</a>
+                    <hr class=\"main_hr\">
+                    <form method="post">
+                        <button type="submit">''' + load_lang('update') + '''</button>
+                    </form>
+                    <script>load_ver();</script>
+                ''',
+                menu = [['manager', load_lang('return')]]
+            ))
+

+ 0 - 15
route/main_test_func.py

@@ -1,15 +0,0 @@
-import time
-from .tool.func import *
-
-def main_test_func_2(conn):
-    if admin_check() != 1:
-        return re_error('/error/3')
-    
-    test_start = time.time()
-
-    for _ in range(0, 10000):
-        load_lang('edit')
-        
-    end_time = "time :" + str(time.time() - test_start) + '\n'
-
-    return end_time

+ 0 - 12
route/main_title_random.py

@@ -1,12 +0,0 @@
-from .tool.func import *
-
-def main_title_random_2(conn):
-    curs = conn.cursor()
-
-    curs.execute(db_change("" + \
-        "select title from data " + \
-        "where title not like 'user:%' and title not like 'category:%' and title not like 'file:%' " + \
-        "order by random() limit 1" + \
-    ""))
-    data = curs.fetchall()
-    return redirect('/w/' + url_pas(data[0][0])) if data else redirect()

+ 14 - 15
route/main_manager.py → route/main_tool_admin.py

@@ -1,8 +1,6 @@
 from .tool.func import *
 
-def main_manager_2(conn, num):
-    curs = conn.cursor()
-
+def main_tool_admin(num = 1, add_2 = ''):
     title_list = {
         0 : [load_lang('document_name'), 'acl', load_lang('acl')],
         1 : [0, 'check', load_lang('check')],
@@ -54,7 +52,7 @@ def main_manager_2(conn, num):
                         <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="/doc_filter">''' + load_lang('doc_filter_list') + '''</a></li>
+                        <li><a href="/filter/document/list">''' + load_lang('doc_filter_list') + '''</a></li>
                     </ul>
                     <h3>2.2. ''' + load_lang('server') + '''</h2>
                     <ul class="inside_ul">
@@ -78,31 +76,32 @@ def main_manager_2(conn, num):
             menu = [['other', load_lang('return')]]
         ))
     elif not num - 1 > len(title_list):
+        num -= 2
+        
+        add_1 = flask.request.form.get('name', 'test')
         if flask.request.method == 'POST':
-            if flask.request.args.get('plus', None):
-                return redirect(
-                    '/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.args.get('plus', 'test')) + '?plus=' + url_pas(flask.request.form.get('name', 'test'))
-                )
-            elif flask.request.form.get('regex', None):
-                return redirect('/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.form.get('name', 'test')) + '?type=regex')
+            if add_2 != '':
+                return redirect('/' + title_list[num][1] + '/' + url_pas(add_2) + '?plus=' + url_pas(add_1))
+            elif flask.request.form.get('regex', '') != '':
+                return redirect('/' + title_list[num][1] + '/' + url_pas(add_1) + '?type=regex')
             else:
-                return redirect('/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.form.get('name', 'test')))
+                return redirect('/' + title_list[num][1] + '/' + url_pas(add_1))
         else:
             if title_list[(num - 2)][0] == 0:
                 placeholder = load_lang('user_name')
             else:
-                placeholder = title_list[(num - 2)][0]
+                placeholder = title_list[num][0]
 
             plus = ''
-            if num - 2 == 15:
+            if num == 15:
                 plus = '<input type="checkbox" name="regex"> ' + load_lang('regex') + '<hr class="main_hr">'
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [title_list[(num - 2)][2], wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                imp = [title_list[num][2], wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <form method="post">
                         <input placeholder="''' + placeholder + '''" name="name" type="text">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         ''' + plus + '''
                         <button type="submit">''' + load_lang('go') + '''</button>
                     </form>

+ 1 - 3
route/main_other.py → route/main_tool_other.py

@@ -1,8 +1,6 @@
 from .tool.func import *
 
-def main_other_2(conn):
-    curs = conn.cursor()
-
+def main_tool_other():
     return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('other_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = '''

+ 0 - 62
route/main_update.py

@@ -1,62 +0,0 @@
-from .tool.func import *
-
-def main_update_2(conn):
-    curs = conn.cursor()
-
-    if admin_check() != 1:
-        return re_error('/error/3')
-
-    if flask.request.method == 'POST':
-        admin_check(None, 'update')
-
-        curs.execute(db_change('select data from other where name = "update"'))
-        up_data = curs.fetchall()
-        up_data = up_data[0][0] if up_data and up_data[0][0] in ['stable', 'beta', 'dev'] else 'stable'
-
-        print('----')
-        print('Update')
-        print('----')
-        if platform.system() == 'Linux':
-            ok = []
-
-            ok += [os.system('git remote rm origin')]
-            ok += [os.system('git remote add origin https://github.com/opennamu/opennamu.git')]
-            ok += [os.system('git fetch origin ' + up_data)]
-            ok += [os.system('git reset --hard origin/' + up_data)]
-            if (ok[0] and ok[1] and ok[2] and ok[3]) == 0:
-                return redirect('/restart')
-            else:
-                print('Error : update failed')
-        elif platform.system() == 'Windows':
-            os.system('rd /s /q route')
-            urllib.request.urlretrieve('https://github.com/opennamu/opennamu/archive/' + up_data + '.zip', 'update.zip')
-            zipfile.ZipFile('update.zip').extractall('')
-            ok = os.system('xcopy /y /s /r opennamu-' + up_data + ' .')
-            if ok == 0:
-                os.system('rd /s /q opennamu-' + up_data)
-                os.system('del update.zip')
-
-                return redirect('/restart')
-            else:
-                print('Error : update failed')
-
-        return re_error('/error/34')
-    else:
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('update'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = load_lang('update_warning') + '''
-                <hr class=\"main_hr\">
-                <ul class="inside_ul">
-                    <li>''' + load_lang('version') + ''' : <span id="ver_send_2"></span></li>
-                    <li id="ver_send" style="display: none;">''' + load_lang('lastest') + ''' : </li>
-                </ul>
-                <a href="https://github.com/openNAMU/openNAMU">(Beta)</a> <a href="https://github.com/openNAMU/openNAMU/tree/stable">(Stable)</a>
-                <hr class=\"main_hr\">
-                <form method="post">
-                    <button type="submit">''' + load_lang('update') + '''</button>
-                </form>
-                <script>load_ver();</script>
-            ''',
-            menu = [['manager', load_lang('return')]]
-        ))
-

+ 0 - 153
route/main_upload.py

@@ -1,153 +0,0 @@
-from .tool.func import *
-
-def main_upload_2(conn):
-    curs = conn.cursor()
-
-    if acl_check(None, 'upload') == 1:
-        return re_error('/ban')
-
-    if flask.request.method == 'POST':
-        if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
-            return re_error('/error/13')
-        else:
-            captcha_post('', 0)
-
-        file_data = flask.request.files.getlist("f_data[]", None)
-        if not file_data:
-            return re_error('/error/9')
-
-        file_len = len(file_data)
-
-        if (int(wiki_set(3)) * 1000 * 1000 * file_len) < flask.request.content_length:
-            return re_error('/error/17')
-
-        if file_len == 1:    
-            file_num = None
-        else:
-            if acl_check(None, 'many_upload') == 1:
-                return re_error('/ban')
-
-            file_num = 1
-
-        for data in file_data:
-            value = os.path.splitext(data.filename)[1]
-            
-            curs.execute(db_change("select html from html_filter where kind = 'extension'"))
-            extension = [i[0].lower() for i in curs.fetchall()]
-            if not re.sub(r'^\.', '', value).lower() in extension:
-                return re_error('/error/14')
-
-            if flask.request.form.get('f_name', None):
-                name = flask.request.form.get('f_name', None) + (' ' + str(file_num) if file_num else '') + value
-            else:
-                name = data.filename
-
-            piece = os.path.splitext(name)
-            if re.search(r'[^ㄱ-힣0-9a-zA-Z_\- ]', piece[0]):
-                return re_error('/error/22')
-
-            e_data = sha224_replace(piece[0]) + piece[1]
-
-            curs.execute(db_change("select title from data where title = ?"), ['file:' + name])
-            if curs.fetchall():
-                return re_error('/error/16')
-
-            curs.execute(db_change("select html from html_filter where kind = 'file'"))
-            db_data = curs.fetchall()
-            for i in db_data:
-                t_re = re.compile(i[0])
-                if t_re.search(name):
-                    return redirect('/file_filter')
-
-            data_url_image = load_image_url()
-            if os.path.exists(os.path.join(data_url_image, e_data)):
-                return re_error('/error/16')
-            else:
-                data.save(os.path.join(data_url_image, e_data))
-
-            ip = ip_check()
-            g_lice = flask.request.form.get('f_lice', '')
-            file_size = os.stat(os.path.join(data_url_image, e_data)).st_size
-            file_size = str(round(file_size / 1000, 1))
-
-            curs.execute(db_change("select data from other where name = 'markup'"))
-            db_data = curs.fetchall()
-            if db_data and db_data[0][0] == 'namumark':
-                file_d = '' + \
-                    flask.request.form.get('f_lice_sel', 'direct_input') + '\n' + \
-                    '[[category:' + re.sub(r'\]', '_', flask.request.form.get('f_lice_sel', '')) + ']]\n' + \
-                    (g_lice if g_lice != '' else '') + \
-                ''
-            else:
-                file_d = '' + \
-                    flask.request.form.get('f_lice_sel', 'direct_input') + '\n' + \
-                    (g_lice if g_lice != '' else '') + \
-                ''
-
-            curs.execute(db_change("insert into data (title, data) values (?, ?)"), ['file:' + name, file_d])
-            curs.execute(db_change("insert into acl (title, data, type) values (?, 'admin', 'decu')"), ['file:' + name])
-
-            render_set(
-                doc_name = 'file:' + name,
-                doc_data = file_d,
-                data_type = 'backlink'
-            )
-
-            history_plus(
-                'file:' + name,
-                file_d,
-                get_time(),
-                ip,
-                '',
-                '0',
-                t_check = 'upload',
-                mode = 'upload'
-            )
-
-            if file_num:
-                file_num += 1
-
-        conn.commit()
-
-        return redirect('/w/file:' + name)
-    else:
-        license_list = '<option value="direct_input">' + load_lang('direct_input') + '</option>'
-        file_name = flask.request.args.get('name', '')
-
-        curs.execute(db_change("select html from html_filter where kind = 'image_license'"))
-        db_data = curs.fetchall()
-        license_list += ''.join(['<option value="' + i[0] + '">' + i[0] + '</option>' for i in db_data])
-
-        curs.execute(db_change("select data from other where name = 'upload_help'"))
-        db_data = curs.fetchall()
-        upload_help = ('<hr class="main_hr">' + db_data[0][0]) if db_data and db_data[0][0] != '' else ''
-
-        curs.execute(db_change("select data from other where name = 'upload_default'"))
-        db_data = curs.fetchall()
-        upload_default = html.escape(db_data[0][0]) if db_data and db_data[0][0] != '' else ''
-
-        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>
-                ''' + upload_help + '''
-                <hr class="main_hr">
-                ''' + load_lang('max_file_size') + ''' : ''' + wiki_set(3) + '''MB
-                <hr class="main_hr">
-                <form method="post" enctype="multipart/form-data" accept-charset="utf8">
-                    <input multiple="multiple" type="file" name="f_data[]">
-                    <hr class="main_hr">
-                    <input placeholder="''' + load_lang('file_name') + '''" name="f_name" value="''' + file_name + '''">
-                    <hr class="main_hr">
-                    <select name="f_lice_sel">
-                        ''' + license_list + '''
-                    </select>
-                    <hr class="main_hr">
-                    <textarea rows="10" placeholder="''' + load_lang('other') + '''" name="f_lice">''' + upload_default + '''</textarea>
-                    <hr class="main_hr">
-                    ''' + captcha_get() + '''
-                    <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                </form>
-            ''',
-            menu = [['other', load_lang('return')]]
-        ))  

+ 3 - 5
route/main_views.py → route/main_view.py

@@ -1,12 +1,10 @@
 from .tool.func import *
-from . import main_error_404
-
-def main_views_2(conn, name):
-    curs = conn.cursor()
+from .main_error_404 import main_error_404
 
+def main_view(name = ''):
     file_name = re.search(r'([^/]+)$', name)
     if not file_name:
-        return main_error_404.main_error_404_2(conn)
+        return main_error_404(conn)
     else:
         file_name = file_name.group(1)
         dir_name = './views/' + re.sub(r'\.{2,}', '', re.sub(r'([^/]+)$', '', name))

+ 3 - 5
route/main_file.py → route/main_view_file.py

@@ -1,9 +1,7 @@
 from .tool.func import *
-from . import main_error_404
-
-def main_file_2(conn, data):
-    curs = conn.cursor()
+from .main_error_404 import main_error_404
 
+def main_view_file(data = ''):
     if data == 'robots.txt' and not os.path.exists('robots.txt'):
         return flask.Response('User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/', mimetype = 'text/plain')
     elif os.path.exists(data):
@@ -12,4 +10,4 @@ def main_file_2(conn, data):
         else:
             return flask.send_from_directory('./', data, mimetype = 'text/xml')
 
-    return main_error_404.main_error_404_2(conn)
+    return main_error_404()

+ 3 - 5
route/main_image_view.py → route/main_view_image.py

@@ -1,9 +1,7 @@
 from .tool.func import *
-from . import main_error_404
-
-def main_image_view_2(conn, name):
-    curs = conn.cursor()
+from .main_error_404 import main_error_404
 
+def main_view_image(name = ''):
     mime_type = re.search(r'([^.]+)$', name)
     if mime_type:
         mime_type = mime_type.group(1).lower()
@@ -15,4 +13,4 @@ def main_image_view_2(conn, name):
             mimetype = 'image/' + mime_type
         )
     else:
-        return main_error_404.main_error_404_2(conn)
+        return main_error_404()

+ 141 - 66
route/tool/func.py

@@ -84,7 +84,7 @@ global_wiki_set = {}
 
 global_db_set = ''
 
-data_css_ver = '118'
+data_css_ver = '119'
 data_css = ''
 
 conn = ''
@@ -96,15 +96,20 @@ def load_conn(data):
 
     conn = data
     
+def do_db_set(db_set):
+    global global_db_set
+    
+    global_db_set = db_set
+    
 # Func-init
-class get_db_connect:
+class get_db_connect_old:
     def __init__(self, db_set):
         self.db_set = db_set
         self.conn = ''
         
     def db_load(self):
         if self.db_set['type'] == 'sqlite':
-            self.conn = sqlite3.connect(self.db_set['name'] + '.db')
+            self.conn = sqlite3.connect(self.db_set['name'] + '.db', check_same_thread = False)
         else:
             self.conn = pymysql.connect(
                 host = self.db_set['mysql_host'],
@@ -128,12 +133,57 @@ class get_db_connect:
         load_conn(self.conn)
 
         return self.conn
-    
+
     def db_get(self):
         # if self.db_set['type'] != 'sqlite':
         #     self.conn.ping(reconnect = True)
             
         return self.conn
+    
+class get_db_connect:
+    # 임시 DB 커넥션 동작 구조
+    # Init 파트
+    # DB 커넥트(get_db_connect_old) -> func.py로 conn 넘겨줌
+    # route 파트
+    # DB 새로 커넥트 -> func.py에서 쓰던 conn은 conn_sub로 보관 ->
+    # func.py로 conn 넘겨줌 -> 모든 라우터 과정이 끝나면 conn_sub를 다시 func.py에 conn으로 넘겨줌 ->
+    # DB 커넥트 종료
+    def __init__(self):
+        global global_db_set
+        global conn
+        
+        self.conn_sub = conn
+        self.db_set = global_db_set
+        
+    def __enter__(self):
+        if self.db_set['type'] == 'sqlite':
+            self.conn = sqlite3.connect(self.db_set['name'] + '.db')
+        else:
+            self.conn = pymysql.connect(
+                host = self.db_set['mysql_host'],
+                user = self.db_set['mysql_user'],
+                password = self.db_set['mysql_pw'],
+                charset = 'utf8mb4',
+                port = int(self.db_set['mysql_port']),
+            )
+            curs = self.conn.cursor()
+
+            try:
+                curs.execute(db_change(
+                    'create database ' + self.db_set['name'] + ' ' + \
+                    'default character set utf8mb4;'
+                ))
+            except:
+                pass
+
+            self.conn.select_db(self.db_set['name'])
+
+        load_conn(self.conn)
+        return self.conn
+    
+    def __exit__(self, exc_type, exc_value, traceback):
+        load_conn(self.conn_sub)
+        self.conn.close()
 
 def update(ver_num, set_data):
     curs = conn.cursor()
@@ -467,7 +517,14 @@ def number_check(data):
         return data
     except:
         return '1'
-
+    
+def check_int(data):
+    try:
+        int(data)
+        return data
+    except:
+        return ''
+    
 def redirect(data = '/'):
     return flask.redirect(flask.request.host_url[:-1] + data)
     
@@ -1096,44 +1153,42 @@ def acl_check(name = 'test', tool = '', topic_num = '1'):
 
     ip = ip_check()
     get_ban = ban_check()
-    acl_c = re.search(r"^user:((?:(?!\/).)*)", name) if name else None
-    if tool == '' and acl_c:
-        acl_n = acl_c.groups()
-
-        if get_ban == 1:
+    
+    if tool == '' and name:
+        if tool == '' and acl_check(name, 'render') == 1:
             return 1
-
-        if admin_check(5) == 1:
-            return 0
-
-        curs.execute(db_change(
-            "select data from acl where title = ? and type = 'decu'"
-        ), ['user:' + acl_n[0]])
-        acl_data = curs.fetchall()
-        if acl_data:
-            if acl_data[0][0] == 'all':
-                return 0
-            elif acl_data[0][0] == 'user' and not ip_or_user(ip) == 1:
-                return 0
-            elif ip == acl_n[0] and not ip_or_user(ip) == 1:
+        
+        user_page = re.search(r"^user:((?:(?!\/).)*)", name)
+        if user_page:
+            user_page = user_page.group(1)
+            if admin_check(5) == 1:
                 return 0
-        else:
-            if ip == acl_n[0] and not ip_or_user(ip) == 1 and not ip_or_user(acl_n[0]) == 1:
+                
+            if get_ban == 1:
+                return 1
+                
+            curs.execute(db_change(
+                "select data from acl where title = ? and type = 'decu'"
+            ), [name])
+            acl_data = curs.fetchall()
+            if acl_data:
+                if acl_data[0][0] == 'all':
+                    return 0
+                elif acl_data[0][0] == 'user' and not ip_or_user(ip) == 1:
+                    return 0
+            
+            if ip == user_page and not ip_or_user(ip) == 1:
                 return 0
-
-        return 1
-
-    if tool == 'topic':
-        if not name:
-            curs.execute(db_change("select title from rd where code = ?"), [topic_num])
-            name = curs.fetchall()
-            name = name[0][0] if name else 'test'
-        
-        end = 3
-    elif tool == 'render' or tool == '' or tool == 'vote':
-        if tool == '' and acl_check(name, 'render') == 1:
+    
             return 1
+    elif tool == 'topic':
+        curs.execute(db_change("select title from rd where code = ?"), [topic_num])
+        name = curs.fetchall()
+        name = name[0][0] if name else 'test'
 
+    if tool in ['topic']:
+        end = 3
+    elif tool in ['render', 'vote', '']:
         end = 2
     else:
         end = 1
@@ -1144,27 +1199,43 @@ def acl_check(name = 'test', tool = '', topic_num = '1'):
                 curs.execute(db_change(
                     "select data from acl where title = ? and type = 'decu'"
                 ), [name])
+                '''
+            elif i == 1:
+                curs.execute(db_change(
+                    "select plus from html_filter where kind = 'document'"
+                ))
+                '''
             else:
-                curs.execute(db_change('select data from other where name = "edit"'))
+                curs.execute(db_change(
+                    'select data from other where name = "edit"'
+                ))
 
             num = 5
         elif tool == 'topic':
-            if i == 0 and topic_num:
-                curs.execute(db_change("select acl from rd where code = ?"), [topic_num])
+            if i == 0:
+                curs.execute(db_change(
+                    "select acl from rd where code = ?"
+                ), [topic_num])
             elif i == 1:
                 curs.execute(db_change(
                     "select data from acl where title = ? and type = 'dis'"
                 ), [name])
             else:
-                curs.execute(db_change('select data from other where name = "discussion"'))
+                curs.execute(db_change(
+                    'select data from other where name = "discussion"'
+                ))
 
             num = 3
         elif tool == 'upload':
-            curs.execute(db_change("select data from other where name = 'upload_acl'"))
+            curs.execute(db_change(
+                "select data from other where name = 'upload_acl'"
+            ))
 
             num = 5
         elif tool == 'many_upload':
-            curs.execute(db_change("select data from other where name = 'many_upload_acl'"))
+            curs.execute(db_change(
+                "select data from other where name = 'many_upload_acl'"
+            ))
 
             num = 5
         elif tool == 'vote':
@@ -1173,7 +1244,9 @@ def acl_check(name = 'test', tool = '', topic_num = '1'):
                     'select acl from vote where id = ? and user = ""'
                 ), [topic_num])
             else:
-                curs.execute(db_change('select data from other where name = "vote_acl"'))
+                curs.execute(db_change(
+                    'select data from other where name = "vote_acl"'
+                ))
 
             num = None
         else:
@@ -1188,18 +1261,16 @@ def acl_check(name = 'test', tool = '', topic_num = '1'):
             num = 5
 
         acl_data = curs.fetchall()
-        if  (
-                i == (end - 1) and \
-                (not acl_data or acl_data[0][0] == '' or acl_data[0][0] == 'normal')
-            ) and \
-            get_ban == 1 and \
-            tool != 'render':
-            return 1
-        elif acl_data and acl_data[0][0] != 'normal' and acl_data[0][0] != '':
-            if acl_data[0][0] != 'ban' and get_ban == 1 and tool != 'render':
+        if not acl_data:
+            acl_data = [['normal']]
+        elif acl_data and acl_data[0][0] == '':
+            acl_data = [['normal']]
+
+        if acl_data[0][0] != 'normal':
+            if not acl_data[0][0] in ['ban', 'ban_admin'] and get_ban == 1 and tool != 'render':
                 return 1
 
-            if acl_data[0][0] == 'all' or acl_data[0][0] == 'ban':
+            if acl_data[0][0] in ['all', 'ban']:
                 return 0
             elif acl_data[0][0] == 'user':
                 if ip_or_user(ip) != 1:
@@ -1265,23 +1336,27 @@ def acl_check(name = 'test', tool = '', topic_num = '1'):
                 if admin_check() == 1:
                     return 0
             elif acl_data[0][0] == 'ban_admin':
-                if admin_check(1) == 1 or ban_check() == 1:
+                if admin_check(1) == 1 or get_ban == 1:
                     return 0
 
             return 1
-        else:
-            if i == (end - 1):
-                if tool == 'topic' and topic_num:
-                    curs.execute(db_change(
-                        "select title from rd where code = ? and stop != ''"
-                    ), [topic_num])
-                    if curs.fetchall():
-                        if admin_check(3, 'topic (code ' + topic_num + ')') == 1:
-                            return 0
-                    else:
+        elif i == (end - 1):
+            if get_ban == 1 and tool != 'render':
+                return 1
+            
+            if tool == 'topic':
+                curs.execute(db_change(
+                    "select title from rd where code = ? and stop != ''"
+                ), [topic_num])
+                if curs.fetchall():
+                    if admin_check(3, 'topic (code ' + topic_num + ')') == 1:
                         return 0
+                    else:
+                        return 1
                 else:
                     return 0
+            else:
+                return 0
 
     return 1
 

+ 1820 - 0
route/tool/func_new.py

@@ -0,0 +1,1820 @@
+# Init
+import os
+import sys
+import platform
+import json
+import smtplib
+import zipfile
+import shutil
+import logging
+import random
+
+import email.mime.text
+import email.utils
+import email.header
+
+import urllib.request
+
+# Init-Version
+version_list = json.loads(open('version.json', encoding = 'utf8').read())
+
+print('Version : ' + version_list['beta']['r_ver'])
+print('DB set version : ' + version_list['beta']['c_ver'])
+print('Skin set version : ' + version_list['beta']['s_ver'])
+print('----')
+
+# Init-PIP_Install
+data_up_date = 1
+if os.path.exists(os.path.join('data', 'version.json')):
+    data_load_ver = open(os.path.join('data', 'version.json'), encoding = 'utf8').read()
+    if data_load_ver == version_list['beta']['r_ver']:
+        data_up_date = 0
+
+if data_up_date == 1:
+    with open(os.path.join('data', 'version.json'), 'w', encoding = 'utf8') as f:
+        f.write(version_list['beta']['r_ver'])
+    
+    if platform.system() in ('Linux', 'Windows'):
+        os.system(
+            'python' + ('3' if platform.system() != 'Windows' else '') + ' ' + \
+            '-m pip install --upgrade --user -r requirements.txt'
+        )
+        
+        print('----')
+        try:
+            os.execl(sys.executable, sys.executable, *sys.argv)
+        except:
+            pass
+
+        try:
+            os.execl(sys.executable, '"' + sys.executable + '"', *sys.argv)
+        except:
+            print('Error : restart failed')
+            raise
+    else:
+        print('Error : automatic installation is not supported.')
+        print('Help : try "python3 -m pip install -r requirements.txt"')
+else:
+    print('PIP check pass')
+    
+print('----')
+
+# Init-Load
+from .func_mark import *
+
+from diff_match_patch import diff_match_patch
+
+import netius.servers
+
+import werkzeug.routing
+import werkzeug.debug
+
+import flask
+
+import requests
+
+import pymysql
+
+if sys.version_info < (3, 6):
+    import sha3
+   
+# Init-Global
+global_lang = {}
+global_wiki_set = {}
+
+global_db_set = ''
+
+data_css_ver = '118'
+data_css = ''
+
+conn = ''
+
+# Func
+# Func-main
+def load_conn(data):
+    global conn
+
+    conn = data
+    
+def do_db_set(db_set):
+    global global_db_set
+    
+    global_db_set = db_set
+    
+# Func-init
+class get_db_connect_old:
+    def __init__(self, db_set):
+        self.db_set = db_set
+        self.conn = ''
+        
+    def db_load(self):
+        if self.db_set['type'] == 'sqlite':
+            self.conn = sqlite3.connect(self.db_set['name'] + '.db')
+        else:
+            self.conn = pymysql.connect(
+                host = self.db_set['mysql_host'],
+                user = self.db_set['mysql_user'],
+                password = self.db_set['mysql_pw'],
+                charset = 'utf8mb4',
+                port = int(self.db_set['mysql_port']),
+            )
+            curs = self.conn.cursor()
+
+            try:
+                curs.execute(db_change(
+                    'create database ' + self.db_set['name'] + ' ' + \
+                    'default character set utf8mb4;'
+                ))
+            except:
+                pass
+
+            self.conn.select_db(self.db_set['name'])
+
+        load_conn(self.conn)
+
+        return self.conn
+    
+    def db_get(self):
+        # if self.db_set['type'] != 'sqlite':
+        #     self.conn.ping(reconnect = True)
+            
+        return self.conn
+    
+class get_db_connect:
+    def __init__(self):
+        global global_db_set
+        
+        self.db_set = global_db_set
+        
+    def __enter__(self):
+        if self.db_set['type'] == 'sqlite':
+            self.conn = sqlite3.connect(self.db_set['name'] + '.db')
+        else:
+            self.conn = pymysql.connect(
+                host = self.db_set['mysql_host'],
+                user = self.db_set['mysql_user'],
+                password = self.db_set['mysql_pw'],
+                charset = 'utf8mb4',
+                port = int(self.db_set['mysql_port']),
+            )
+            curs = self.conn.cursor()
+
+            try:
+                curs.execute(db_change(
+                    'create database ' + self.db_set['name'] + ' ' + \
+                    'default character set utf8mb4;'
+                ))
+            except:
+                pass
+
+            self.conn.select_db(self.db_set['name'])
+
+        return self.conn
+    
+    def __exit__(self, exc_type, exc_value, traceback):
+        self.conn.close()
+
+def update(ver_num, set_data):
+    curs = conn.cursor()
+
+    print('----')
+    # 업데이트 하위 호환 유지 함수
+
+    if ver_num < 3160027:
+        print('Add init set')
+        set_init()
+
+    if ver_num < 3170002:
+        curs.execute(db_change("select html from html_filter where kind = 'extension'"))
+        if not curs.fetchall():
+            for i in ['jpg', 'jpeg', 'png', 'gif', 'webp']:
+                curs.execute(db_change(
+                    "insert into html_filter (html, kind) values (?, 'extension')"
+                ), [i])
+
+    if ver_num < 3170400:
+        curs.execute(db_change("select title, sub, code from topic where id = '1'"))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "update topic set code = ? where title = ? and sub = ?"
+            ), [
+                i[2], 
+                i[0], 
+                i[1]
+            ])
+            curs.execute(db_change(
+                "update rd set code = ? where title = ? and sub = ?"
+            ), [
+                i[2], 
+                i[0], 
+                i[1]
+            ])
+
+    if ver_num < 3171800:
+        curs.execute(db_change("select data from other where name = 'recaptcha'"))
+        change_rec = curs.fetchall()
+        if change_rec and change_rec[0][0] != '':
+            new_rec = re.search(r'data-sitekey="([^"]+)"', change_rec[0][0])
+            if new_rec:
+                curs.execute(db_change(
+                    "update other set data = ? where name = 'recaptcha'"
+                ), [new_rec.group(1)])
+            else:
+                curs.execute(db_change("update other set data = '' where name = 'recaptcha'"))
+                curs.execute(db_change("update other set data = '' where name = 'sec_re'"))
+    
+    if  ver_num < 3172800 and \
+        set_data['db_type'] == 'mysql':
+        get_data_mysql = json.loads(open('data/mysql.json', encoding = 'utf8').read())
+        
+        with open('data/mysql.json', 'w') as f:
+            f.write('{ "user" : "' + get_data_mysql['user'] + '", "password" : "' + get_data_mysql['password'] + '", "host" : "localhost" }')
+
+    if ver_num < 3183603:
+        curs.execute(db_change("select block from ban where band = 'O'"))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "update ban set block = ?, band = 'regex' where block = ? and band = 'O'"
+            ), [
+                '^' + i[0].replace('.', '\\.'),
+                i[0]
+            ])
+
+        curs.execute(db_change("select block from rb where band = 'O'"))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "update rb set block = ?, band = 'regex' where block = ? and band = 'O'"
+            ), [
+                '^' + i[0].replace('.', '\\.'),
+                i[0]
+            ])
+
+    if ver_num < 3190201:
+        today_time = get_time()
+
+        curs.execute(db_change("select block, end, why, band, login from ban"))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "insert into rb (block, end, today, why, band, login, ongoing) " + \
+                "values (?, ?, ?, ?, ?, ?, ?)"
+            ), [
+                i[0],
+                i[1],
+                today_time,
+                i[2],
+                i[3],
+                i[4],
+                '1'
+            ])
+
+    if ver_num < 3191301:
+        curs.execute(db_change('' + \
+            'select id, title, date from history ' + \
+            'where not title like "user:%" ' + \
+            'order by date desc ' + \
+            'limit 50' + \
+        ''))
+        data_list = curs.fetchall()
+        for get_data in data_list:
+            curs.execute(db_change(
+                "insert into rc (id, title, date, type) values (?, ?, ?, 'normal')"
+            ), [
+                get_data[0], 
+                get_data[1],
+                get_data[2]
+            ])
+
+    if ver_num < 3202400:
+        curs.execute(db_change("select data from other where name = 'update'"))
+        get_data = curs.fetchall()
+        if get_data and get_data[0][0] == 'master':
+            curs.execute(db_change("update other set data = 'beta' where name = 'update'"), [])
+
+    if ver_num < 3202600:
+        curs.execute(db_change("select name, regex, sub from filter"))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "insert into html_filter (html, kind, plus, plus_t) " + \
+                "values (?, 'regex_filter', ?, ?)"
+            ), [
+                i[0], 
+                i[1],
+                i[2]
+            ])
+
+        curs.execute(db_change("select title, link, icon from inter"))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "insert into html_filter (html, kind, plus, plus_t) " + \
+                "values (?, 'inter_wiki', ?, ?)"), [
+                i[0], 
+                i[1],
+                i[2]
+            ])
+
+    if ver_num < 3203400:
+        curs.execute(db_change("select user, css from custom"))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "insert into user_set (name, id, data) values ('custom_css', ?, ?)"
+            ), [
+                re.sub(r' \(head\)$', '', i[0]), 
+                i[1]
+            ])
+
+    if ver_num < 3205500:
+        curs.execute(db_change("select title, decu, dis, view, why from acl"))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "insert into acl (title, data, type) values (?, ?, ?)"
+            ), [i[0], i[1], 'decu'])
+            curs.execute(db_change(
+                "insert into acl (title, data, type) values (?, ?, ?)"
+            ), [i[0], i[2], 'dis'])
+            curs.execute(db_change(
+                "insert into acl (title, data, type) values (?, ?, ?)"
+            ), [i[0], i[3], 'view'])
+            curs.execute(db_change(
+                "insert into acl (title, data, type) values (?, ?, ?)"
+            ), [i[0], i[4], 'why'])
+
+    if ver_num < 3300101:
+        # 캐시 초기화
+        curs.execute(db_change('delete from cache_data'))
+    
+    if ver_num < 3300301:
+        # regex_filter 오류 해결
+        curs.execute(db_change(
+            'delete from html_filter where kind = "regex_filter" and html is null'
+        ))
+        
+    if ver_num < 3302302:
+        # user이랑 user_set 테이블의 통합
+        curs.execute(db_change('select id, pw, acl, date, encode from user'))
+        for i in curs.fetchall():
+            curs.execute(db_change(
+                "insert into user_set (name, id, data) values (?, ?, ?)"
+            ), ['pw', i[0], i[1]])
+            curs.execute(db_change(
+                "insert into user_set (name, id, data) values (?, ?, ?)"
+            ), ['acl', i[0], i[2]])
+            curs.execute(db_change(
+                "insert into user_set (name, id, data) values (?, ?, ?)"
+            ), ['date', i[0], i[3]])
+            curs.execute(db_change(
+                "insert into user_set (name, id, data) values (?, ?, ?)"
+            ), ['encode', i[0], i[4]])
+            
+    if ver_num < 3400101:
+        # user_set이랑 user_application 테이블의 통합
+        curs.execute(db_change('' + \
+            'select id, pw, date, encode, question, answer, ip, ua, email ' + \
+            'from user_application' + \
+        ''))
+        for i in curs.fetchall():
+            sql_data = {}
+            sql_data['id'] = i[0]
+            sql_data['pw'] = i[1]
+            sql_data['date'] = i[2]
+            sql_data['encode'] = i[3]
+            sql_data['question'] = i[4]
+            sql_data['answer'] = i[5]
+            sql_data['ip'] = i[6]
+            sql_data['ua'] = i[7]
+            sql_data['email'] = i[8]
+            
+            curs.execute(db_change(
+                "insert into user_set (name, id, data) values (?, ?, ?)"
+            ), ['application', i[0], json.dumps(sql_data)])
+    
+    conn.commit()
+
+    print('Update completed')
+
+def set_init_always(ver_num):
+    curs = conn.cursor()
+
+    curs.execute(db_change('delete from other where name = "ver"'))
+    curs.execute(db_change('insert into other (name, data) values ("ver", ?)'), [ver_num])
+    
+    curs.execute(db_change('delete from alist where name = "owner"'))
+    curs.execute(db_change('insert into alist (name, acl) values ("owner", "owner")'))
+
+    if not os.path.exists(load_image_url()):
+        os.makedirs(load_image_url())
+    
+    conn.commit()
+    
+def set_init():
+    curs = conn.cursor()
+
+    # 초기값 설정 함수    
+    curs.execute(db_change("select html from html_filter where kind = 'email'"))
+    if not curs.fetchall():
+        for i in ['naver.com', 'gmail.com', 'daum.net', 'kakao.com']:
+            curs.execute(db_change(
+                "insert into html_filter (html, kind, plus, plus_t) values (?, 'email', '', '')"
+            ), [i])
+
+    curs.execute(db_change("select html from html_filter where kind = 'extension'"))
+    if not curs.fetchall():
+        for i in ['jpg', 'jpeg', 'png', 'gif', 'webp']:
+            curs.execute(db_change(
+                "insert into html_filter (html, kind, plus, plus_t) values (?, 'extension', '', '')"
+            ), [i])
+
+    curs.execute(db_change(
+        'select data from other ' + \
+        'where name = "smtp_server" or name = "smtp_port" or name = "smtp_security"'
+    ))
+    if not curs.fetchall():
+        for i in [
+            ['smtp_server', 'smtp.gmail.com'],
+            ['smtp_port', '587'], 
+            ['smtp_security', 'starttls']
+        ]:
+            curs.execute(db_change(
+                "insert into other (name, data) values (?, ?)"
+            ), [i[0], i[1]])
+            
+    curs.execute(db_change('select data from other where name = "key"'))
+    rep_data = curs.fetchall()
+    if not rep_data:
+        curs.execute(db_change('insert into other (name, data) values ("key", ?)'), [load_random_key()])
+
+    curs.execute(db_change('select data from other where name = "count_all_title"'))
+    if not curs.fetchall():
+        curs.execute(db_change('insert into other (name, data) values ("count_all_title", "0")'))
+        
+    conn.commit()
+
+# Func-simple
+## Func-simple-without_DB
+def get_default_admin_group():
+    return ['owner', 'ban']
+
+def load_random_key(long = 64):
+    return ''.join(
+        random.choice(
+            "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+        ) for i in range(long)
+    )
+
+def http_warning():
+    return '''
+        <div id="http_warning_text"></div>
+        <script>
+            if(window.location.protocol !== 'https:') {
+                document.getElementById('http_warning_text').innerHTML = "''' + \
+                    load_lang('http_warning') + \
+                '''";
+                document.getElementById('http_warning_text').style.margin = "10px 0px 0px 0px";
+            }
+        </script>
+    '''
+
+def next_fix(link, num, page, end = 50):
+    list_data = ''
+
+    if num == 1:
+        if len(page) == end:
+            list_data += '' + \
+                '<hr class="main_hr">' + \
+                '<a href="' + link + str(num + 1) + '">(' + load_lang('next') + ')</a>' + \
+            ''
+    elif len(page) != end:
+        list_data += '' + \
+            '<hr class="main_hr">' + \
+            '<a href="' + link + str(num - 1) + '">(' + load_lang('previous') + ')</a>' + \
+        ''
+    else:
+        list_data += '' + \
+            '<hr class="main_hr">' + \
+            '<a href="' + link + str(num - 1) + '">(' + load_lang('previous') + ')</a> <a href="' + link + str(num + 1) + '">(' + load_lang('next') + ')</a>' + \
+        ''
+
+    return list_data
+
+def leng_check(A, B):
+    # B -> new
+    # A -> old
+    return '0' if A == B else (('-' + str(A - B)) if A > B else ('+' + str(B - A)))
+
+def number_check(data):
+    try:
+        int(data)
+        return data
+    except:
+        return '1'
+    
+def check_int(data):
+    try:
+        int(data)
+        return data
+    except:
+        return ''
+    
+def redirect(data = '/'):
+    return flask.redirect(flask.request.host_url[:-1] + data)
+    
+def get_acl_list(type_d = 'normal'):
+    if type_d == 'user':
+        return ['', 'user', 'all']
+    else:
+        return ['', 'all', 'user', 'admin', 'owner', '50_edit', 'email', 'ban', 'before', '30_day', 'ban_admin']
+
+## Func-simple-with_DB
+def load_image_url():
+    curs = conn.cursor()
+
+    curs.execute(db_change('select data from other where name = "image_where"'))
+    image_where = curs.fetchall()
+    image_where = image_where[0][0] if image_where else os.path.join('data', 'images')
+    
+    return image_where
+
+def load_domain():
+    curs = conn.cursor()
+
+    curs.execute(db_change("select data from other where name = 'domain'"))
+    domain = curs.fetchall()
+    domain = domain[0][0] if domain and domain[0][0] != '' else flask.request.host_url
+
+    return domain
+
+def edit_button(editor_display = '0'):
+    curs = conn.cursor()
+
+    insert_list = []
+
+    curs.execute(db_change("select html, plus from html_filter where kind = 'edit_top'"))
+    db_data = curs.fetchall()
+    for get_data in db_data:
+        insert_list += [[get_data[1], get_data[0]]]
+
+    data = ''
+    for insert_data in insert_list:
+        data += '' + \
+            '<a href="' + \
+                'javascript:do_insert_data(\'textarea_edit_view\', \'' + insert_data[0] + '\', ' + editor_display + ')' + \
+            '">(' + insert_data[1] + ')</a> ' + \
+        ''
+
+    data += (' ' if data != '' else '') + '<a href="/edit_top">(' + load_lang('add') + ')</a>'
+    data += '<hr class="main_hr">'
+    
+    return data
+
+def ip_warning():
+    curs = conn.cursor()
+
+    if ip_or_user() != 0:
+        curs.execute(db_change('select data from other where name = "no_login_warning"'))
+        data = curs.fetchall()
+        if data and data[0][0] != '':
+            text_data = '' + \
+                '<span>' + data[0][0] + '</span>' + \
+                '<hr class="main_hr">' + \
+            ''
+        else:
+            text_data = '' + \
+                '<span>' + load_lang('no_login_warning') + '</span>' + \
+                '<hr class="main_hr">' + \
+            ''
+    else:
+        text_data = ''
+
+    return text_data
+    
+# Func-login    
+def pw_encode(data, type_d = ''):
+    curs = conn.cursor()
+
+    if type_d == '':
+        curs.execute(db_change('select data from other where name = "encode"'))
+        set_data = curs.fetchall()
+
+        type_d = set_data[0][0]
+
+    if type_d == 'sha256':
+        return hashlib.sha256(bytes(data, 'utf-8')).hexdigest()
+    else:
+        if sys.version_info < (3, 6):
+            return sha3.sha3_256(bytes(data, 'utf-8')).hexdigest()
+        else:
+            return hashlib.sha3_256(bytes(data, 'utf-8')).hexdigest()
+
+def pw_check(data, data2, type_d = 'no', id_d = ''):
+    curs = conn.cursor()
+
+    curs.execute(db_change('select data from other where name = "encode"'))
+    db_data = curs.fetchall()
+
+    if type_d != 'no':
+        if type_d == '':
+            set_data = 'sha3'
+        else:
+            set_data = type_d
+    else:
+        set_data = db_data[0][0]
+
+    re_data = 1 if pw_encode(data, set_data) == data2 else 0
+    if db_data[0][0] != set_data and re_data == 1 and id_d != '':
+        curs.execute(db_change("update user_set set data = ? where id = ? and name = 'pw'"), [
+            pw_encode(data), 
+            id_d
+        ])
+        curs.execute(db_change("update user_set set data = ? where id = ? and name = 'encode'"), [
+            db_data[0][0], 
+            id_d
+        ])
+
+    return re_data
+        
+# Func-skin
+def easy_minify(data, tool = None):
+    # without_DB
+
+    return data
+
+def load_lang(data, safe = 0):
+    curs = conn.cursor()
+
+    global global_lang
+
+    ip = ip_check()
+    if ip_or_user(ip) == 0:
+        curs.execute(db_change('select data from user_set where name = "lang" and id = ?'), [ip])
+        rep_data = curs.fetchall()                    
+    elif 'lang' in flask.session:
+        rep_data = [[flask.session['lang']]]
+    else:
+        curs.execute(db_change("select data from other where name = 'language'"))
+        rep_data = curs.fetchall()
+
+    if not rep_data or rep_data[0][0] in ('', 'default'):
+        curs.execute(db_change("select data from other where name = 'language'"))
+        rep_data = curs.fetchall()
+
+    if rep_data:
+        lang_name = rep_data[0][0]
+    else:
+        lang_name = 'en-US'
+        
+    if lang_name in global_lang:
+        lang = global_lang[lang_name]
+    else:
+        lang_list = os.listdir('lang')
+        if (lang_name + '.json') in lang_list:
+            lang = json.loads(open(
+                os.path.join('lang', lang_name + '.json'), 
+                encoding = 'utf8'
+            ).read())
+            global_lang[lang_name] = lang
+        else:
+            lang = {}
+
+    if data in lang:
+        if safe == 1:
+            return lang[data] 
+        else:
+            return html.escape(lang[data])
+
+    return html.escape(data + ' (' + lang_name + ')')
+
+def skin_check(set_n = 0):
+    curs = conn.cursor()
+
+    # 개편 필요?
+    skin_list = load_skin('tenshi', 1)
+    skin = skin_list[0]
+    ip = ip_check()
+    
+    user_need_skin = ''
+    if ip_or_user(ip) == 0:
+        curs.execute(db_change('select data from user_set where name = "skin" and id = ?'), [ip])
+        skin_exist = curs.fetchall()
+        if skin_exist:
+            user_need_skin = skin_exist[0][0]            
+    else:
+        if 'skin' in flask.session:
+            user_need_skin = flask.session['skin']
+
+    if user_need_skin == '':
+        curs.execute(db_change('select data from other where name = "skin"'))
+        skin_exist = curs.fetchall()
+        if skin_exist:
+            user_need_skin = skin_exist[0][0]
+    
+    if user_need_skin != '' and user_need_skin in skin_list:
+        skin = user_need_skin
+
+    if set_n == 0:
+        return './views/' + skin + '/index.html'
+    else:
+        return skin
+    
+def wiki_css(data):
+    # without_DB
+
+    global data_css
+    global data_css_ver
+
+    data += ['' for _ in range(0, 3 - len(data))]
+
+    if data_css == '':
+        for i_data in os.listdir(os.path.join("views", "main_css", "css")):
+            if i_data != 'sub':
+                data_css += '<link rel="stylesheet" href="/views/main_css/css/' + i_data + '?ver=' + data_css_ver + '">'
+
+        for i_data in os.listdir(os.path.join("views", "main_css", "js")):
+            if i_data != 'sub':
+                data_css += '<script src="/views/main_css/js/' + i_data + '?ver=' + data_css_ver + '"></script>'
+                
+    data = data[0:2] + ['', '''
+        <link   rel="stylesheet"
+                href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.2.0/build/styles/default.min.css">
+        <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.2.0/build/highlight.min.js"></script>
+        <link   defer rel="stylesheet"
+                href="https://cdn.jsdelivr.net/npm/katex@0.13.2/dist/katex.min.css"
+                integrity="sha384-Cqd8ihRLum0CCg8rz0hYKPoLZ3uw+gES2rXQXycqnL5pgVQIflxAUDS7ZSjITLb5"
+                crossorigin="anonymous">
+        <script src="https://cdn.jsdelivr.net/npm/katex@0.13.2/dist/katex.min.js"
+                integrity="sha384-1Or6BdeNQb0ezrmtGeqQHFpppNd7a/gw29xeiSikBbsb44xu3uAo8c7FwbF5jhbd"
+                crossorigin="anonymous"></script>
+    ''' + data_css + '<script>window.addEventListener(\'DOMContentLoaded\', main_css_skin_load);</script>'] + data[2:]
+
+    return data
+
+def cut_100(data):
+    # without_DB
+
+    data = re.search(r'<pre style="display: none;" id="render_content_load">([^<>]+)<\/pre>', data)
+    if data:
+        data = data.group(1)
+        if len(data) > 100:
+            return data[0:100] + '...'
+        else:
+            return data[0:len(data)]
+    else:
+        return ''
+
+def wiki_set(num = 1):
+    curs = conn.cursor()
+
+    if num == 1:
+        skin_name = skin_check(1)
+        data_list = []
+
+        curs.execute(db_change('select data from other where name = ?'), ['name'])
+        db_data = curs.fetchall()
+        data_list += [db_data[0][0]] if db_data and db_data[0][0] != '' else ['Wiki']
+
+        curs.execute(db_change('select data from other where name = "license"'))
+        db_data = curs.fetchall()
+        data_list += [db_data[0][0]] if db_data and db_data[0][0] != '' else ['ARR']
+
+        data_list += ['', '']
+
+        curs.execute(db_change('select data from other where name = "logo" and coverage = ?'), [skin_name])
+        db_data = curs.fetchall()
+        if db_data and db_data[0][0] != '':
+            data_list += [db_data[0][0]]
+        else:
+            curs.execute(db_change('select data from other where name = "logo" and coverage = ""'))
+            db_data = curs.fetchall()
+            data_list += [db_data[0][0]] if db_data and db_data[0][0] != '' else [data_list[0]]
+
+        head_data = ''
+
+        curs.execute(db_change("select data from other where name = 'head' and coverage = ''"))
+        db_data = curs.fetchall()
+        head_data += db_data[0][0] if db_data and db_data[0][0] != '' else ''
+
+        curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [skin_name])
+        db_data = curs.fetchall()
+        head_data += db_data[0][0] if db_data and db_data[0][0] != '' else ''
+            
+        data_list += [head_data]
+    elif num == 2:
+        curs.execute(db_change('select data from other where name = "frontpage"'))
+        db_data = curs.fetchall()
+        data_list = db_data[0][0] if db_data and db_data[0][0] != '' else 'FrontPage'
+    elif num == 3:
+        curs.execute(db_change('select data from other where name = "upload"'))
+        db_data = curs.fetchall()
+        data_list = db_data[0][0] if db_data and db_data[0][0] != '' else '2'
+    else:
+        data_list = ''
+
+    return data_list
+
+def wiki_custom():
+    curs = conn.cursor()
+
+    ip = ip_check()
+    if ip_or_user(ip) == 0:
+        user_icon = 1
+        user_name = ip
+
+        curs.execute(db_change("select data from user_set where id = ? and name = 'custom_css'"), [ip])
+        user_head = curs.fetchall()
+        user_head = user_head[0][0] if user_head else ''
+        
+        curs.execute(db_change('select data from user_set where name = "email" and id = ?'), [ip])
+        email = curs.fetchall()
+        email = email[0][0] if email else ''
+
+        if admin_check('all') == 1:
+            user_admin = '1'
+            user_acl_list = []
+
+            curs.execute(db_change("select data from user_set where id = ? and name = 'acl'"), [ip])
+            curs.execute(db_change('select acl from alist where name = ?'), [curs.fetchall()[0][0]])
+            user_acl = curs.fetchall()
+            for i in user_acl:
+                user_acl_list += [i[0]]
+
+            user_acl_list = user_acl_list if user_acl != [] else '0'
+        else:
+            user_admin = '0'
+            user_acl_list = '0'
+
+        curs.execute(db_change("select count(*) from alarm where name = ?"), [ip])
+        count = curs.fetchall()
+        user_notice = str(count[0][0]) if count else '0'
+    else:
+        user_icon = 0
+        user_name = load_lang('user')
+        email = ''
+        user_admin = '0'
+        user_acl_list = '0'
+        user_notice = '0'
+        user_head = flask.session['head'] if 'head' in flask.session else ''
+
+    curs.execute(db_change("select title from rd where title = ? and stop = ''"), ['user:' + ip])
+    user_topic = '1' if curs.fetchall() else '0'
+    
+    split_path = flask.request.path.split('/')
+    if len(split_path) > 1:
+        split_path = split_path[1]
+    else:
+        split_path = 0
+
+    return [
+        '',
+        '',
+        user_icon,
+        user_head,
+        email,
+        user_name,
+        user_admin,
+        str(ban_check()),
+        user_notice,
+        user_acl_list,
+        ip,
+        user_topic,
+        split_path
+    ]
+
+def load_skin(data = '', set_n = 0, default = 0):
+    # without_DB
+
+    # data -> 가장 앞에 있을 스킨 이름
+    # set_n == 0 -> 스트링으로 반환
+    # set_n == 1 -> 리스트로 반환
+    # default == 0 -> 디폴트 미포함
+    # default == 1 -> 디폴트 포함
+
+    if set_n == 0:
+        skin_return_data = ''
+    else:
+        skin_return_data = []
+
+    skin_list_get = os.listdir('views')
+    if default == 1:
+        skin_list_get = ['default'] + skin_list_get
+
+    for skin_data in skin_list_get:
+        if skin_data != 'default':
+            see_data = skin_data
+        else:
+            see_data = load_lang('default')
+
+        if skin_data != 'main_css':
+            if set_n == 0:
+                if skin_data == data:
+                    skin_return_data = '' + \
+                        '<option value="' + skin_data + '">' + \
+                            see_data + \
+                        '</option>' + \
+                    '' + skin_return_data
+                else:
+                    skin_return_data += '' + \
+                        '<option value="' + skin_data + '">' + \
+                            see_data + \
+                        '</option>' + \
+                    ''
+            else:
+                if skin_data == data:
+                    skin_return_data = [skin_data] + skin_return_data
+                else:
+                    skin_return_data += [skin_data]                    
+
+    return skin_return_data
+
+# Func-markup
+def render_set(doc_name = '', doc_data = '', data_type = 'view', data_in = '', doc_acl = ''):
+    # without_DB
+
+    # data_type in ['view', 'raw', 'api_view', 'backlink']
+    doc_acl = acl_check(doc_name, 'render') if doc_acl == '' else doc_acl
+    doc_data = 0 if doc_data == None else doc_data
+        
+    if doc_acl == 1:
+        return 'HTTP Request 401.3'
+    else:
+        if data_type == 'raw':
+            return doc_data
+        else:
+            if doc_data != 0:
+                get_class_render = class_do_render(conn)
+                return get_class_render.do_render(doc_name, doc_data, data_type, data_in)
+            else:
+                return 'HTTP Request 404'
+
+# Func-request
+def send_email(who, title, data):
+    curs = conn.cursor()
+
+    try:
+        curs.execute(db_change('' + \
+            'select name, data from other ' + \
+            'where name = "smtp_email" or name = "smtp_pass" or name = "smtp_server" or name = "smtp_port" or name = "smtp_security"' + \
+        ''))
+        rep_data = curs.fetchall()
+
+        smtp_email = ''
+        smtp_pass = ''
+        smtp_server = ''
+        smtp_security = ''
+        smtp_port = ''
+        smtp = ''
+
+        for i in rep_data:
+            if i[0] == 'smtp_email':
+                smtp_email = i[1]
+            elif i[0] == 'smtp_pass':
+                smtp_pass = i[1]
+            elif i[0] == 'smtp_server':
+                smtp_server = i[1]
+            elif i[0] == 'smtp_security':
+                smtp_security = i[1]
+            elif i[0] == 'smtp_port':
+                smtp_port = i[1]
+        
+        smtp_port = int(smtp_port)
+        if smtp_security == 'plain':
+            smtp = smtplib.SMTP(smtp_server, smtp_port)
+        elif smtp_security == 'starttls':
+            smtp = smtplib.SMTP(smtp_server, smtp_port)
+            smtp.starttls()
+        else:
+            # if smtp_security == 'tls':
+            smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
+        
+        smtp.login(smtp_email, smtp_pass)
+
+        domain = load_domain()
+        wiki_name = wiki_set()[0]
+        
+        msg = email.mime.text.MIMEText(data)
+        msg['Subject'] = title
+        msg['From'] = 'openNAMU <noreply@' + domain + '>'
+        msg['To'] = who
+        
+        smtp.sendmail('openNAMU@' + domain, who, msg.as_string())
+        smtp.quit()
+
+        return 1
+    except Exception as e:
+        print('----')
+        print('Error : email send error')
+        print(e)
+
+        return 0
+
+def captcha_get():
+    curs = conn.cursor()
+
+    data = ''
+    
+    if ip_or_user() != 0:
+        curs.execute(db_change('select data from other where name = "recaptcha"'))
+        recaptcha = curs.fetchall()
+        
+        curs.execute(db_change('select data from other where name = "sec_re"'))
+        sec_re = curs.fetchall()
+        
+        curs.execute(db_change('select data from other where name = "recaptcha_ver"'))
+        rec_ver = curs.fetchall()
+        if  recaptcha and recaptcha[0][0] != '' and \
+            sec_re and sec_re[0][0] != '':
+            if not rec_ver or rec_ver[0][0] == '':
+                data += '' + \
+                    '<script src="https://www.google.com/recaptcha/api.js" async defer></script>' + \
+                    '<div class="g-recaptcha" data-sitekey="' + recaptcha[0][0] + '"></div>' + \
+                    '<hr class="main_hr">' + \
+                ''
+            else:
+                data += '' + \
+                    '<script src="https://www.google.com/recaptcha/api.js?render=' + recaptcha[0][0] + '"></script>' + \
+                    '<input type="hidden" id="g-recaptcha" name="g-recaptcha">' + \
+                    '<script type="text/javascript">' + \
+                        'grecaptcha.ready(function() {' + \
+                            'grecaptcha.execute(\'' + recaptcha[0][0] + '\', {action: \'homepage\'}).then(function(token) {' + \
+                                'document.getElementById(\'g-recaptcha\').value = token;' + \
+                            '});' + \
+                        '});' + \
+                    '</script>' + \
+                ''
+
+    return data
+
+def captcha_post(re_data, num = 1):
+    curs = conn.cursor()
+
+    if num == 1:
+        curs.execute(db_change('select data from other where name = "sec_re"'))
+        sec_re = curs.fetchall()
+        if  sec_re and sec_re[0][0] != '' and \
+            ip_or_user() != 0 and captcha_get() != '':
+            data = requests.get(
+                'https://www.google.com/recaptcha/api/siteverify' + \
+                '?secret=' + sec_re[0][0] + '&response=' + re_data
+            )
+            if data.status_code == 200:
+                json_data = json.loads(data.text)
+                if json_data['success'] != True:
+                    return 1
+
+        return 0
+
+# Func-user
+def ip_or_user(data = ''):
+    # without_DB
+
+    # 1 == ip
+    # 0 == reg
+    
+    if data == '':
+        data = ip_check()
+
+    if re.search(r'(\.|:)', data):
+        return 1
+    else:
+        return 0
+
+def admin_check(num = None, what = None, name = ''):
+    curs = conn.cursor()
+
+    ip = ip_check() if name == '' else name
+    time_data = get_time()
+    pass_ok = 0
+
+    if ip_or_user(ip) == 0:
+        curs.execute(db_change(
+            "select data from user_set where id = ? and name = 'acl'"
+        ), [ip])
+        user_auth = curs.fetchall()
+        if user_auth:
+            user_auth = user_auth[0][0]
+            
+            check = {
+                0 : 'owner',
+                1 : 'ban',
+                2 : 'nothing',
+                3 : 'toron',
+                4 : 'check',
+                5 : 'acl',
+                6 : 'hidel',
+                7 : 'give'
+            }
+            if not num:
+                check = check[0]
+            elif num == 'all':
+                check = [check[i] for i in check]
+            else:
+                check = check[num]
+
+            curs.execute(db_change(
+                'select name from alist where name = ? and acl = "owner"'
+            ), [user_auth])
+            if curs.fetchall():
+                pass_ok = 1
+            else:
+                if num == 'all':                    
+                    curs.execute(db_change(
+                        'select name from alist where name = ?'
+                    ), [user_auth])
+                else:
+                    curs.execute(db_change(
+                        'select name from alist where name = ? and acl = ?'
+                    ), [user_auth, check])
+                    
+                if curs.fetchall():
+                    pass_ok = 1
+
+                
+            if pass_ok == 1:
+                if what:
+                    curs.execute(db_change(
+                        "insert into re_admin (who, what, time) values (?, ?, ?)"
+                    ), [ip, what, time_data])
+                    conn.commit()
+
+                return 1
+
+    return 0
+
+def acl_check(name = 'test', tool = '', topic_num = '1'):
+    curs = conn.cursor()
+
+    ip = ip_check()
+    get_ban = ban_check()
+    acl_c = re.search(r"^user:((?:(?!\/).)*)", name) if name else None
+    if tool == '' and acl_c:
+        acl_n = acl_c.groups()
+
+        if get_ban == 1:
+            return 1
+
+        if admin_check(5) == 1:
+            return 0
+
+        curs.execute(db_change(
+            "select data from acl where title = ? and type = 'decu'"
+        ), ['user:' + acl_n[0]])
+        acl_data = curs.fetchall()
+        if acl_data:
+            if acl_data[0][0] == 'all':
+                return 0
+            elif acl_data[0][0] == 'user' and not ip_or_user(ip) == 1:
+                return 0
+            elif ip == acl_n[0] and not ip_or_user(ip) == 1:
+                return 0
+        else:
+            if ip == acl_n[0] and not ip_or_user(ip) == 1 and not ip_or_user(acl_n[0]) == 1:
+                return 0
+
+        return 1
+
+    if tool == 'topic':
+        if not name:
+            curs.execute(db_change("select title from rd where code = ?"), [topic_num])
+            name = curs.fetchall()
+            name = name[0][0] if name else 'test'
+        
+        end = 3
+    elif tool == 'render' or tool == '' or tool == 'vote':
+        if tool == '' and acl_check(name, 'render') == 1:
+            return 1
+
+        end = 2
+    else:
+        end = 1
+
+    for i in range(0, end):
+        if tool == '':
+            if i == 0:
+                curs.execute(db_change(
+                    "select data from acl where title = ? and type = 'decu'"
+                ), [name])
+            else:
+                curs.execute(db_change('select data from other where name = "edit"'))
+
+            num = 5
+        elif tool == 'topic':
+            if i == 0 and topic_num:
+                curs.execute(db_change("select acl from rd where code = ?"), [topic_num])
+            elif i == 1:
+                curs.execute(db_change(
+                    "select data from acl where title = ? and type = 'dis'"
+                ), [name])
+            else:
+                curs.execute(db_change('select data from other where name = "discussion"'))
+
+            num = 3
+        elif tool == 'upload':
+            curs.execute(db_change("select data from other where name = 'upload_acl'"))
+
+            num = 5
+        elif tool == 'many_upload':
+            curs.execute(db_change("select data from other where name = 'many_upload_acl'"))
+
+            num = 5
+        elif tool == 'vote':
+            if i == 0:
+                curs.execute(db_change(
+                    'select acl from vote where id = ? and user = ""'
+                ), [topic_num])
+            else:
+                curs.execute(db_change('select data from other where name = "vote_acl"'))
+
+            num = None
+        else:
+            # tool == 'render'
+            if i == 0:
+                curs.execute(db_change(
+                    "select data from acl where title = ? and type = 'view'"
+                ), [name])
+            else:
+                curs.execute(db_change("select data from other where name = 'all_view_acl'"))
+
+            num = 5
+
+        acl_data = curs.fetchall()
+        if  (
+                i == (end - 1) and \
+                (not acl_data or acl_data[0][0] == '' or acl_data[0][0] == 'normal')
+            ) and \
+            get_ban == 1 and \
+            tool != 'render':
+            return 1
+        elif acl_data and acl_data[0][0] != 'normal' and acl_data[0][0] != '':
+            if acl_data[0][0] != 'ban' and get_ban == 1 and tool != 'render':
+                return 1
+
+            if acl_data[0][0] == 'all' or acl_data[0][0] == 'ban':
+                return 0
+            elif acl_data[0][0] == 'user':
+                if ip_or_user(ip) != 1:
+                    return 0
+            elif acl_data[0][0] == 'admin':
+                if ip_or_user(ip) != 1:
+                    if admin_check(num) == 1:
+                        return 0
+            elif acl_data[0][0] == '50_edit':
+                if ip_or_user(ip) != 1:
+                    if admin_check(num) == 1:
+                        return 0
+                    else:
+                        curs.execute(db_change(
+                            "select count(*) from history where ip = ?"
+                        ), [ip])
+                        count = curs.fetchall()
+                        count = count[0][0] if count else 0
+                        if count >= 50:
+                            return 0
+            elif acl_data[0][0] == 'before':
+                if ip_or_user(ip) != 1:
+                    if admin_check(num) == 1:
+                        return 0
+                
+                curs.execute(db_change(
+                    "select ip from history where title = ? and ip = ?"
+                ), [name, ip])
+                if curs.fetchall():
+                    return 0
+            elif acl_data[0][0] == '30_day':
+                if ip_or_user(ip) != 1:
+                    if admin_check(num) == 1:
+                        return 0
+                    else:
+                        curs.execute(db_change(
+                            "select data from user_set where id = ? and name = 'date'"
+                        ), [ip])
+                        user_date = curs.fetchall()[0][0]
+                        
+                        time_1 = datetime.datetime.strptime(
+                            user_date, 
+                            '%Y-%m-%d %H:%M:%S'
+                        ) + datetime.timedelta(days = 30)
+                        time_2 = datetime.datetime.strptime(
+                            get_time(), 
+                            '%Y-%m-%d %H:%M:%S'
+                        )
+                        
+                        if time_2 > time_1:
+                            return 0
+            elif acl_data[0][0] == 'email':
+                if ip_or_user(ip) != 1:
+                    if admin_check(num) == 1:
+                        return 0
+                    else:
+                        curs.execute(db_change(
+                            "select data from user_set where id = ? and name = 'email'"
+                        ), [ip])
+                        if curs.fetchall():
+                            return 0
+            elif acl_data[0][0] == 'owner':
+                if admin_check() == 1:
+                    return 0
+            elif acl_data[0][0] == 'ban_admin':
+                if admin_check(1) == 1 or ban_check() == 1:
+                    return 0
+
+            return 1
+        else:
+            if i == (end - 1):
+                if tool == 'topic' and topic_num:
+                    curs.execute(db_change(
+                        "select title from rd where code = ? and stop != ''"
+                    ), [topic_num])
+                    if curs.fetchall():
+                        if admin_check(3, 'topic (code ' + topic_num + ')') == 1:
+                            return 0
+                    else:
+                        return 0
+                else:
+                    return 0
+
+    return 1
+
+def ban_check(ip = None, tool = ''):
+    curs = conn.cursor()
+
+    ip = ip_check() if not ip else ip
+    tool = '' if not tool else tool
+
+    if admin_check(None, None, ip) == 1:
+        return 0
+
+    curs.execute(db_change(
+        "update rb set ongoing = '' " + \
+        "where end < ? and end != '' and ongoing = '1'"
+    ), [get_time()])
+    conn.commit()
+
+    curs.execute(db_change("" + \
+        "select login, block from rb " + \
+        "where band = 'regex' and ongoing = '1'" + \
+    ""))
+    regex_d = curs.fetchall()
+    for test_r in regex_d:
+        g_regex = re.compile(test_r[1])
+        if g_regex.search(ip):
+            if tool == 'login':
+                if test_r[0] != 'O':
+                    return 1
+            else:
+                return 1
+
+    curs.execute(db_change("" + \
+        "select login from rb " + \
+        "where block = ? and band = '' and ongoing = '1'" + \
+        "" + \
+    ""), [ip])
+    ban_d = curs.fetchall()
+    if ban_d:
+        if tool == 'login':
+            if ban_d[0][0] != 'O':
+                return 1
+        else:
+            return 1
+
+    return 0
+
+def ip_pas(raw_ip, type_d = 0):
+    curs = conn.cursor()
+
+    hide = 0
+    end_ip = {}
+    i = 0
+
+    return_data = 0
+    if type(raw_ip) != type([]):
+        get_ip = [raw_ip]
+        
+        return_data = 1
+    else:
+        get_ip = raw_ip
+
+    curs.execute(db_change("select data from other where name = 'ip_view'"))
+    ip_view = curs.fetchall()
+    ip_view = ip_view[0][0] if ip_view else ''
+    ip_view = '' if admin_check(1) == 1 else ip_view
+    
+    get_ip = list(set(get_ip))
+    
+    for raw_ip in get_ip:
+        change_ip = 0
+        is_this_ip = ip_or_user(raw_ip)
+        if is_this_ip != 0 and ip_view != '':
+            ip = re.sub(r'\.([^.]*)\.([^.]*)$', '.*.*', raw_ip)
+            ip = re.sub(r':([^:]*):([^:]*)$', ':*:*', ip)
+                
+            change_ip = 1
+        else:     
+            ip = raw_ip
+            
+        if type_d == 0:
+            if is_this_ip == 0:
+                ip = '<a href="/w/' + url_pas('user:' + raw_ip) + '">' + raw_ip + '</a>'
+                
+            if change_ip == 0:
+                ip += ' <a href="/user/' + url_pas(raw_ip) + '">(' + load_lang('tool') + ')</a>'
+
+        end_ip[raw_ip] = ip
+    
+    if return_data == 1:
+        return end_ip[raw_ip]
+    else:
+        return end_ip
+        
+# Func-edit
+def slow_edit_check():
+    curs = conn.cursor()
+
+    curs.execute(db_change("select data from other where name = 'slow_edit'"))
+    slow_edit = curs.fetchall()
+    if slow_edit and slow_edit != '0' and admin_check(5) != 1:
+        slow_edit = slow_edit[0][0]
+
+        curs.execute(db_change(
+            "select date from history where ip = ? order by date desc limit 1"
+        ), [ip_check()])
+        last_edit_data = curs.fetchall()
+        if last_edit_data:
+            last_edit_data = int(re.sub(' |:|-', '', last_edit_data[0][0]))
+            now_edit_data = int(
+                (datetime.datetime.now() - datetime.timedelta(
+                    seconds = int(slow_edit))
+                ).strftime("%Y%m%d%H%M%S")
+            )
+
+            if last_edit_data > now_edit_data:
+                return 1
+
+    return 0
+
+def edit_filter_do(data):
+    curs = conn.cursor()
+
+    if admin_check(1) != 1:
+        curs.execute(db_change(
+            "select plus, plus_t from html_filter where kind = 'regex_filter' and plus != ''"
+        ))
+        for data_list in curs.fetchall():
+            match = re.compile(data_list[0], re.I)
+            if match.search(data):
+                ban_insert(
+                    ip_check(),
+                    '0' if data_list[1] == 'X' else data_list[1],
+                    'edit filter',
+                    None,
+                    'tool:edit filter'
+                )
+
+                return 1
+
+    return 0
+
+# Func-insert
+def add_alarm(who, context):
+    curs = conn.cursor()
+
+    curs.execute(db_change(
+        'insert into alarm (name, data, date) values (?, ?, ?)'
+    ), [who, context, get_time()])
+    conn.commit()
+    
+def add_user(user_name, user_pw, user_email = '', user_encode = ''):
+    curs = conn.cursor()
+
+    if user_encode == '':
+        user_pw_hash = pw_encode(user_pw)
+
+        curs.execute(db_change('select data from other where name = "encode"'))
+        data_encode = curs.fetchall()
+        data_encode = data_encode[0][0]
+    else:
+        user_pw_hash = user_pw
+        data_encode = user_encode
+
+    curs.execute(db_change("select id from user_set limit 1"))
+    if not curs.fetchall():
+        user_auth = 'owner'
+    else:
+        user_auth = 'user'
+
+    curs.execute(db_change("insert into user_set (id, name, data) values (?, 'pw', ?)"), [
+        user_name,
+        user_pw_hash
+    ])
+    curs.execute(db_change("insert into user_set (id, name, data) values (?, 'acl', ?)"), [
+        user_name,
+        user_auth
+    ])
+    curs.execute(db_change("insert into user_set (id, name, data) values (?, 'date', ?)"), [
+        user_name,
+        get_time()
+    ])
+    curs.execute(db_change("insert into user_set (id, name, data) values (?, 'encode', ?)"), [
+        user_name,
+        data_encode
+    ])
+    
+    if user_email != '':
+        curs.execute(db_change("insert into user_set (name, id, data) values ('email', ?, ?)"), [
+            user_name,
+            user_email
+        ])
+        
+    conn.commit()
+    
+def ua_plus(u_id, u_ip, u_agent, time):
+    curs = conn.cursor()
+
+    curs.execute(db_change("select data from other where name = 'ua_get'"))
+    rep_data = curs.fetchall()
+    if rep_data and rep_data[0][0] != '':
+        pass
+    else:
+        curs.execute(db_change(
+            "insert into ua_d (name, ip, ua, today, sub) values (?, ?, ?, ?, '')"
+        ), [
+            u_id, 
+            u_ip, 
+            u_agent, 
+            time
+        ])
+        conn.commit()
+
+def ban_insert(name, end, why, login, blocker, type_d = None):
+    curs = conn.cursor()
+
+    now_time = get_time()
+    band = type_d if type_d else ''
+
+    curs.execute(db_change(
+        "update rb set ongoing = '' where end < ? and end != '' and ongoing = '1'"
+    ), [now_time])
+    curs.execute(db_change("" + \
+        "select block from rb " + \
+        "where ((end > ? and end != '') or end = '') and block = ? and " + \
+            "band = ? and ongoing = '1'" + \
+    ""), [now_time, name, band])
+    if curs.fetchall():
+        curs.execute(db_change(
+            "insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)"
+        ), [
+            name,
+            'release',
+            now_time,
+            blocker,
+            '',
+            band
+        ])
+        curs.execute(db_change(
+            "update rb set ongoing = '' where block = ? and band = ? and ongoing = '1'"
+        ), [name, band])
+    else:
+        login = 'O' if login != '' else ''
+
+        if end != '0':
+            end = int(number_check(end))
+            time = datetime.datetime.now()
+            plus = datetime.timedelta(seconds = end)
+            r_time = (time + plus).strftime("%Y-%m-%d %H:%M:%S")
+        else:
+            r_time = ''
+
+        curs.execute(db_change(
+            "insert into rb (block, end, today, blocker, why, band, ongoing, login) " + \
+            "values (?, ?, ?, ?, ?, ?, '1', ?)"
+        ), [
+            name, 
+            r_time, 
+            now_time, 
+            blocker, 
+            why, 
+            band,
+            login
+        ])
+
+    conn.commit()
+
+def rd_plus(topic_num, date, name = None, sub = None):
+    curs = conn.cursor()
+
+    curs.execute(db_change("select code from rd where code = ?"), [topic_num])
+    if curs.fetchall():
+        curs.execute(db_change("update rd set date = ? where code = ?"), [date, topic_num])
+    else:
+        curs.execute(db_change(
+            "insert into rd (title, sub, code, date) values (?, ?, ?, ?)"
+        ), [name, sub, topic_num, date])
+
+    conn.commit()
+
+def history_plus(title, data, date, ip, send, leng, t_check = '', mode = ''):
+    curs = conn.cursor()
+
+    if mode == 'add':
+        curs.execute(db_change(
+            "select id from history where title = ? order by id + 0 asc limit 1"
+        ), [title])
+        id_data = curs.fetchall()
+        id_data = str(int(id_data[0][0]) - 1) if id_data else '0'
+    else:
+        curs.execute(db_change(
+            "select id from history where title = ? order by id + 0 desc limit 1"
+        ), [title])
+        id_data = curs.fetchall()
+        id_data = str(int(id_data[0][0]) + 1) if id_data else '1'
+        
+        mode = mode if not re.search('^user:', title) else 'user'
+
+    send = re.sub(r'\(|\)|<|>', '', send)
+    send = send[:128] if len(send) > 128 else send
+    send = send + ' (' + t_check + ')' if t_check != '' else send
+
+    if mode != 'add' and mode != 'user':
+        curs.execute(db_change("select count(*) from rc where type = 'normal'"))
+        if curs.fetchall()[0][0] >= 200:
+            curs.execute(db_change(
+                "select id, title from rc where type = 'normal' order by date asc limit 1"
+            ))
+            rc_data = curs.fetchall()
+            if rc_data:
+                curs.execute(db_change(
+                    'delete from rc where id = ? and title = ? and type = "normal"'
+                ), [
+                    rc_data[0][0],
+                    rc_data[0][1]
+                ])
+    
+        curs.execute(db_change(
+            "insert into rc (id, title, date, type) values (?, ?, ?, 'normal')"
+        ), [
+            id_data,
+            title,
+            date
+        ])
+    
+    if mode != 'add':
+        curs.execute(db_change("select count(*) from rc where type = ?"), [mode])
+        if curs.fetchall()[0][0] >= 200:
+            curs.execute(db_change(
+                "select id, title from rc where type = ? order by date asc limit 1"
+            ), [mode])
+            rc_data = curs.fetchall()
+            if rc_data:
+                curs.execute(db_change(
+                    'delete from rc where id = ? and title = ? and type = ?'
+                ), [
+                    rc_data[0][0],
+                    rc_data[0][1],
+                    mode
+                ])
+    
+        curs.execute(db_change(
+            "insert into rc (id, title, date, type) values (?, ?, ?, ?)"
+        ), [
+            id_data,
+            title,
+            date,
+            mode
+        ])
+            
+    curs.execute(db_change(
+        "insert into history (id, title, data, date, ip, send, leng, hide, type) " + \
+        "values (?, ?, ?, ?, ?, ?, ?, '', ?)"
+    ), [
+        id_data,
+        title,
+        data,
+        date,
+        ip,
+        send,
+        leng,
+        mode
+    ])
+
+# Func-error
+def re_error(data):
+    curs = conn.cursor()
+
+    conn.commit()
+
+    if data == '/ban':
+        if ban_check() == 1:
+            end = '<div id="get_user_info"></div><script>load_user_info("' + ip_check() + '");</script>'
+        else:
+            end = '<ul class="inside_ul"><li>' + load_lang('authority_error') + '</li></ul>'
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('error'), wiki_set(1), wiki_custom(), wiki_css([0, 0])],
+            data = '<h2>' + load_lang('error') + '</h2>' + end,
+            menu = 0
+        )), 401
+    else:
+        num = int(number_check(data.replace('/error/', '')))
+        if num == 1:
+            data = load_lang('no_login_error')
+        elif num == 2:
+            data = load_lang('no_exist_user_error')
+        elif num == 3:
+            data = load_lang('authority_error')
+        elif num == 4:
+            data = load_lang('no_admin_block_error')
+        elif num == 5:
+            data = load_lang('skin_error')
+        elif num == 6:
+            data = load_lang('same_id_exist_error')
+        elif num == 7:
+            data = load_lang('long_id_error')
+        elif num == 8:
+            data = load_lang('id_char_error') + ' <a href="/name_filter">(' + load_lang('id_filter_list') + ')</a>'
+        elif num == 9:
+            data = load_lang('file_exist_error')
+        elif num == 10:
+            data = load_lang('password_error')
+        elif num == 11:
+            data = load_lang('topic_long_error')
+        elif num == 12:
+            data = load_lang('email_error')
+        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>'
+        elif num == 15:
+            data = load_lang('edit_record_error')
+        elif num == 16:
+            data = load_lang('same_file_error')
+        elif num == 17:
+            data = load_lang('file_capacity_error') + wiki_set(3)
+        elif num == 18:
+            data = load_lang('email_send_error')
+        elif num == 19:
+            data = load_lang('decument_exist_error')
+        elif num == 20:
+            data = load_lang('password_diffrent_error')
+        elif num == 21:
+            data = load_lang('edit_filter_error')
+        elif num == 22:
+            data = load_lang('file_name_error')
+        elif num == 23:
+            data = load_lang('regex_error')
+        elif num == 24:
+            curs.execute(db_change("select data from other where name = 'slow_edit'"))
+            slow_edit = curs.fetchall()
+            slow_edit = '' if not slow_edit else slow_edit[0][0]
+            data = load_lang('fast_edit_error') + slow_edit
+        elif num == 25:
+            data = load_lang('too_many_dec_error')
+        elif num == 26:
+            data = load_lang('application_not_found')
+        elif num == 27:
+            data = load_lang("invalid_password_error")
+        elif num == 28:
+            data = load_lang('watchlist_overflow_error')
+        elif num == 29:
+            data = load_lang('copyright_disagreed')
+        elif num == 30:
+            data = load_lang('ie_wrong_callback')
+        elif num == 33:
+            data = load_lang('restart_fail_error')
+        elif num == 34:
+            data = load_lang("update_error") + ' <a href="https://github.com/opennamu/opennamu">(Github)</a>'
+        elif num == 35:
+            data = load_lang('same_email_error')
+        elif num == 36:
+            data = load_lang('input_email_error')
+        else:
+            data = '???'
+
+        if num == 5:
+            if flask.request.path != '/main_skin_set':
+                title = load_lang('skin_set')
+                tool = [['main_skin_set', load_lang('main_skin_set')]]
+                load_skin_set = ''
+            else:
+                title = load_lang('main_skin_set')
+                tool = [['skin_set', load_lang('skin_set')]]
+                load_skin_set = '<script>main_css_skin_set();</script>'
+        
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [title, wiki_set(1), wiki_custom(), wiki_css([0, 0])],
+                data = '' + \
+                    '<div id="main_skin_set">' + \
+                        '<h2>' + load_lang('error') + '</h2>' + \
+                        '<ul class="inside_ul">' + \
+                            '<li>' + data + ' <a href="/main_skin_set">(' + load_lang('main_skin_set') + ')</a></li>' + \
+                        '</ul>' + \
+                    '</div>' + \
+                    load_skin_set,
+                menu = tool
+            ))
+        else:
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('error'), wiki_set(1), wiki_custom(), wiki_css([0, 0])],
+                data = '' + \
+                     '<h2>' + load_lang('error') + '</h2>' + \
+                     '<ul class="inside_ul">' + \
+                         '<li>' + data + '</li>' + \
+                     '</ul>' + \
+                '',
+                menu = 0
+            )), 400

+ 1 - 0
route/tool/func_tool.py

@@ -17,6 +17,7 @@ def get_time():
 
 def db_data_get(data):
     global set_data
+    
     set_data = data
 
 def db_change(data):

+ 132 - 108
route/topic.py

@@ -1,121 +1,145 @@
 from .tool.func import *
 
-def topic_2(conn, topic_num):
-    curs = conn.cursor()
-    topic_num = str(topic_num)
-
-    if flask.request.method == 'POST':
-        name = flask.request.form.get('topic', 'test')
-        sub = flask.request.form.get('title', 'test')
-    else:
-        curs.execute(db_change("select title, sub from rd where code = ?"), [topic_num])
-        name = curs.fetchall()
-        if name:
-            sub = name[0][1]
-            name = name[0][0]
+def topic(topic_num = 0):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+        topic_num = str(topic_num)
+
+        if flask.request.method == 'POST':
+            name = flask.request.form.get('topic', 'Test')
+            sub = flask.request.form.get('title', 'Test')
+            
+            if topic_num == '0':
+                curs.execute(db_change("select code from topic order by code + 0 desc limit 1"))
+                t_data = curs.fetchall()
+                topic_num = str(int(t_data[0][0]) + 1) if t_data else '1'
         else:
-            return redirect('/')
+            if topic_num == '0':
+                name = load_lang('make_new_topic')
+                sub = load_lang('make_new_topic')
+            else:
+                curs.execute(db_change("select title, sub from rd where code = ?"), [topic_num])
+                name = curs.fetchall()
+                if name:
+                    sub = name[0][1]
+                    name = name[0][0]
+                else:
+                    return redirect('/')
 
-    ban = acl_check(name, 'topic', topic_num)
+        ban = acl_check(name, 'topic', topic_num)
 
-    if flask.request.method == 'POST':
-        if flask.request.form.get('content', 'Test') == '':
-            return redirect('/thread/' + topic_num)
+        if flask.request.method == 'POST':
+            if flask.request.form.get('content', 'Test') == '':
+                return redirect('/thread/' + topic_num)
 
-        if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
-            return re_error('/error/13')
-        else:
-            captcha_post('', 0)
-
-        ip = ip_check()
-        today = get_time()
-
-        if ban == 1:
-            return re_error('/ban')
-
-        curs.execute(db_change("select id from topic where code = ? order by id + 0 desc limit 1"), [topic_num])
-        old_num = curs.fetchall()
-        num = str((int(old_num[0][0]) + 1) if old_num else 1)
-
-        match = re.search(r'^user:([^/]+)', name)
-        if match:
-            match = match.group(1)
-            y_check = 0
-            if ip_or_user(match) == 1:
-                curs.execute(db_change("select ip from history where ip = ? limit 1"), [match])
-                u_data = curs.fetchall()
-                if u_data:
-                    y_check = 1
+            if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
+                return re_error('/error/13')
+            else:
+                captcha_post('', 0)
+
+            ip = ip_check()
+            today = get_time()
+
+            if ban == 1:
+                return re_error('/ban')
+
+            curs.execute(db_change("select id from topic where code = ? order by id + 0 desc limit 1"), [topic_num])
+            old_num = curs.fetchall()
+            num = str((int(old_num[0][0]) + 1) if old_num else 1)
+
+            match = re.search(r'^user:([^/]+)', name)
+            if match:
+                match = match.group(1)
+                y_check = 0
+                if ip_or_user(match) == 1:
+                    curs.execute(db_change("select ip from history where ip = ? limit 1"), [match])
+                    u_data = curs.fetchall()
+                    if u_data:
+                        y_check = 1
+                    else:
+                        curs.execute(db_change("select ip from topic where ip = ? limit 1"), [match])
+                        u_data = curs.fetchall()
+                        if u_data:
+                            y_check = 1
                 else:
-                    curs.execute(db_change("select ip from topic where ip = ? limit 1"), [match])
+                    curs.execute(db_change("select id from user_set where id = ?"), [match])
                     u_data = curs.fetchall()
                     if u_data:
                         y_check = 1
-            else:
-                curs.execute(db_change("select id from user_set where id = ?"), [match])
-                u_data = curs.fetchall()
-                if u_data:
-                    y_check = 1
-
-            if y_check == 1:
-                add_alarm(match, ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
-
-        cate_re = re.compile(r'\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
-        data = cate_re.sub('[br]', flask.request.form.get('content', 'Test').replace('\r', ''))
-
-        for rd_data in re.findall(r"(?: |\n|^)(#(?:[0-9]+))(?: |\n|$)", data):
-            curs.execute(db_change("select ip from topic where code = ? and id = ?"), [topic_num, rd_data])
-            ip_data = curs.fetchall()
-            if ip_data and ip_or_user(ip_data[0][0]) == 0:
-                add_alarm(ip_data[0][0], ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
-
-        for rd_data in re.findall(r"(?: |\n|^)@((?:[^ ]+))(?: |\n|$)", data):
-            curs.execute(db_change("select ip from history where ip = ? limit 1"), [rd_data])
-            ip_data = curs.fetchall()
-            if not ip_data:
-                curs.execute(db_change("select ip from topic where ip = ? limit 1"), [rd_data])
+
+                if y_check == 1:
+                    add_alarm(match, ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
+
+            cate_re = re.compile(r'\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
+            data = cate_re.sub('[br]', flask.request.form.get('content', 'Test').replace('\r', ''))
+
+            for rd_data in re.findall(r"(?: |\n|^)(#(?:[0-9]+))(?: |\n|$)", data):
+                curs.execute(db_change("select ip from topic where code = ? and id = ?"), [topic_num, rd_data])
                 ip_data = curs.fetchall()
+                if ip_data and ip_or_user(ip_data[0][0]) == 0:
+                    add_alarm(ip_data[0][0], ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
 
-            if ip_data and ip_or_user(ip_data[0][0]) == 0:
-                add_alarm(ip_data[0][0], ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
-
-        data = re.sub(r"( |\n|^)(#(?:[0-9]+))( |\n|$)", '\g<1><topic_a>\g<2></topic_a>\g<3>', data)
-        data = re.sub(r"( |\n|^)(@(?:[^ ]+))( |\n|$)", '\g<1><topic_call>\g<2></topic_call>\g<3>', data)
-
-        rd_plus(topic_num, today, name, sub)
-        curs.execute(db_change("insert into topic (id, data, date, ip, code) values (?, ?, ?, ?, ?)"), [
-            num,
-            data,
-            today,
-            ip,
-            topic_num
-        ])
-        conn.commit()
-
-        return redirect('/thread/' + topic_num + '#' + num)
-    else:
-        display = 'display: none;' if ban == 1 else ''
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('discussion') + ')', 0])],
-            data = '''
-                <h2 id="topic_top_title">''' + html.escape(sub) + '''</h2>
-                <div id="top_topic"></div>
-                <div id="main_topic"></div>
-                <div id="plus_topic"></div>
-                <script>new_topic_load("''' + topic_num + '''");</script>
-                <a href="/thread/''' + topic_num + '/tool">(' + load_lang('topic_tool') + ''')</a>
-                <hr class="main_hr">
-                <form style="''' + display + '''" method="post">
-                    <textarea id="textarea_edit_view" class="topic_content" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
+            for rd_data in re.findall(r"(?: |\n|^)@((?:[^ ]+))(?: |\n|$)", data):
+                curs.execute(db_change("select ip from history where ip = ? limit 1"), [rd_data])
+                ip_data = curs.fetchall()
+                if not ip_data:
+                    curs.execute(db_change("select ip from topic where ip = ? limit 1"), [rd_data])
+                    ip_data = curs.fetchall()
+
+                if ip_data and ip_or_user(ip_data[0][0]) == 0:
+                    add_alarm(ip_data[0][0], ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
+
+            data = re.sub(r"( |\n|^)(#(?:[0-9]+))( |\n|$)", '\g<1><topic_a>\g<2></topic_a>\g<3>', data)
+            data = re.sub(r"( |\n|^)(@(?:[^ ]+))( |\n|$)", '\g<1><topic_call>\g<2></topic_call>\g<3>', data)
+
+            rd_plus(topic_num, today, name, sub)
+            curs.execute(db_change("insert into topic (id, data, date, ip, code) values (?, ?, ?, ?, ?)"), [
+                num,
+                data,
+                today,
+                ip,
+                topic_num
+            ])
+            conn.commit()
+
+            return redirect('/thread/' + topic_num + '#' + num)
+        else:
+            display = 'display: none;' if ban == 1 else ''
+            data_input_topic_name = ''
+            if topic_num == '0':
+                data_input_topic_name = '' + \
+                    '<input placeholder="' + load_lang('discussion_name') + '" name="title">' + \
+                    '<hr class="main_hr">' + \
+                    '<input placeholder="' + load_lang('document_name') + '" name="topic">' + \
+                    '<hr class="main_hr">' + \
+                ''
+                
+            curs.execute(db_change('select data from other where name = "topic_text"'))
+            sql_d = curs.fetchall()
+            topic_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('content')
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('discussion') + ')', 0])],
+                data = '''
+                    <h2 id="topic_top_title">''' + html.escape(sub) + '''</h2>
+                    <div id="top_topic"></div>
+                    <div id="main_topic"></div>
+                    <div id="plus_topic"></div>
+                    <script>new_topic_load("''' + topic_num + '''");</script>
+                    <a href="/thread/''' + topic_num + '/tool">(' + load_lang('topic_tool') + ''')</a>
+                    <hr class="main_hr">
+                    <form style="''' + display + '''" method="post">
+                        ''' + data_input_topic_name + '''
+                        <textarea id="textarea_edit_view" class="topic_content" placeholder="''' + topic_text + '''" name="content"></textarea>
+                        <hr class="main_hr">
+                        ''' + captcha_get() + (ip_warning() if display == '' else '') + '''
+                        <input style="display: none;" name="topic" value="''' + name + '''">
+                        <input style="display: none;" name="title" value="''' + sub + '''">
+                        <button id="save" type="submit">''' + load_lang('send') + '''</button>
+                        <button id="preview" type="button" onclick="load_preview(\'\')">''' + load_lang('preview') + '''</button>
+                    </form>
                     <hr class="main_hr">
-                    ''' + captcha_get() + (ip_warning() if display == '' else '') + '''
-                    <input style="display: none;" name="topic" value="''' + name + '''">
-                    <input style="display: none;" name="title" value="''' + sub + '''">
-                    <button id="save" type="submit">''' + load_lang('send') + '''</button>
-                    <button id="preview" type="button" onclick="load_preview(\'\')">''' + load_lang('preview') + '''</button>
-                </form>
-                <hr class="main_hr">
-                <div id="see_preview"></div>
-            ''',
-            menu = [['topic/' + url_pas(name), load_lang('list')]]
-        ))
+                    <div id="see_preview"></div>
+                ''',
+                menu = [['topic/' + url_pas(name), load_lang('list')]]
+            ))

+ 47 - 68
route/topic_close_list.py

@@ -1,78 +1,57 @@
 from .tool.func import *
 
-def topic_close_list_2(conn, name):
-    curs = conn.cursor()
+def topic_close_list(name = 'Test'):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
-    div = ''
-    tool = flask.request.args.get('tool', '')
+        div = ''
+        tool = flask.request.args.get('tool', '')
 
-    plus = ''
-    menu = [['topic/' + url_pas(name), load_lang('return')]]
+        plus = ''
+        menu = [['topic/' + url_pas(name), load_lang('return')]]
 
-    if tool == 'close':
-        curs.execute(db_change("select code, sub from rd where title = ? and stop = 'O' order by sub asc"), [name])
+        if tool == 'close':
+            curs.execute(db_change("select code, sub from rd where title = ? and stop = 'O' order by sub asc"), [name])
 
-        sub = load_lang('closed_discussion')
-    elif tool == 'agree':
-        curs.execute(db_change("select code, sub from rd where title = ? and agree = 'O' order by sub asc"), [name])
+            sub = load_lang('closed_discussion')
+        elif tool == 'agree':
+            curs.execute(db_change("select code, sub from rd where title = ? and agree = 'O' order by sub asc"), [name])
 
-        sub = load_lang('agreed_discussion')
-    else:
-        sub = load_lang('discussion_list')
-        menu = [['w/' + url_pas(name), load_lang('document')]]
-
-        if acl_check(name, 'topic', None) == 1:
-            display = 'display: none;'
-        else:
-            display = ''
-
-        curs.execute(db_change("select code from topic order by code + 0 desc limit 1"))
-        t_data = curs.fetchall()
-        if t_data:
-            topic_num = str(int(t_data[0][0]) + 1)
+            sub = load_lang('agreed_discussion')
         else:
-            topic_num = '1'
+            sub = load_lang('discussion_list')
+            menu = [['w/' + url_pas(name), load_lang('document')]]
 
-        plus = '''
-            <a href="/topic/''' + url_pas(name) + '?tool=close">(' + load_lang('closed_discussion') + ')</a> <a href="/topic/' + url_pas(name) + '?tool=agree">(' + load_lang('agreed_discussion') + ''')</a>
-            <hr class="main_hr">
-            <form style="''' + display + '" method="post" action="/thread/' + topic_num + '''">
-                <input placeholder="''' + load_lang('discussion_name') + '''" name="title">
+            plus = '''
+                <a href="/topic/''' + url_pas(name) + '?tool=close">(' + load_lang('closed_discussion') + ''')</a>
+                <a href="/topic/''' + url_pas(name) + '?tool=agree">(' + load_lang('agreed_discussion') + ''')</a>
                 <hr class="main_hr">
-                <textarea rows="10" id="textarea_edit_view" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
-                <hr class="main_hr">
-                ''' + captcha_get() + (ip_warning() if display == '' else '') + '''
-                <input style="display: none;" name="topic" value="''' + name + '''">
-                <button type="submit">''' + load_lang('send') + '''</button>
-                <button id="preview" type="button" onclick="load_preview(\'''' + url_pas(name) + '\')">' + load_lang('preview') + '''</button>
-            </form>
-            <hr class="main_hr">
-            <div id="see_preview"></div>
-        '''
-
-        curs.execute(db_change("select code, sub from rd where title = ? and stop != 'O' order by date desc"), [name])
-
-    for data in curs.fetchall():
-        curs.execute(db_change("select id from topic where code = ? order by id + 0 desc limit 1"), [data[0]])
-        t_data = curs.fetchall()
-
-        div += '''
-            <h2><a href="/thread/''' + data[0] + '">' + data[0] + '. ' + data[1] + '''</a></h2>
-            <div id="topic_pre_''' + data[0] + '''"></div>
-            <div id="topic_back_pre_''' + data[0] + '''"></div>
-            <script>
-                new_topic_load(''' + data[0] + ', "list", "?num=1", "topic_pre_' + data[0] + '''");
-                if(''' + t_data[0][0] + ''' !== 1) {
-                    new_topic_load(''' + data[0] + ', "list", "?num=' + t_data[0][0] + '", "topic_back_pre_' + data[0] + '''");
-                }
-            </script>
-        '''
-
-    if div == '':
-        plus = re.sub(r'^<br>', '', plus)
-
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + sub + ')', 0])],
-        data = div + plus,
-        menu = menu
-    ))
+                <a href="/thread/0">(''' + load_lang('make_new_topic') + ''')</a>
+            '''
+
+            curs.execute(db_change("select code, sub from rd where title = ? and stop != 'O' order by date desc"), [name])
+
+        for data in curs.fetchall():
+            curs.execute(db_change("select id from topic where code = ? order by id + 0 desc limit 1"), [data[0]])
+            t_data = curs.fetchall()
+
+            div += '''
+                <h2><a href="/thread/''' + data[0] + '">' + data[0] + '. ' + data[1] + '''</a></h2>
+                <div id="topic_pre_''' + data[0] + '''"></div>
+                <div id="topic_back_pre_''' + data[0] + '''"></div>
+                <script>
+                    new_topic_load(''' + data[0] + ', "list", "/normal/1", "topic_pre_' + data[0] + '''");
+                    if(''' + t_data[0][0] + ''' !== 1) {
+                        new_topic_load(''' + data[0] + ', "list", "/normal/' + t_data[0][0] + '", "topic_back_pre_' + data[0] + '''");
+                    }
+                </script>
+            '''
+
+        if div == '':
+            plus = re.sub(r'^<br>', '', plus)
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + sub + ')', 0])],
+            data = div + plus,
+            menu = menu
+        ))

+ 37 - 23
route/user_alarm.py

@@ -1,25 +1,39 @@
 from .tool.func import *
 
-def user_alarm_2(conn):
-    curs = conn.cursor()
-
-    num = int(number_check(flask.request.args.get('num', '1')))
-    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
-
-    data = '<ul class="inside_ul">'
-
-    curs.execute(db_change("select data, date from alarm where name = ? order by date desc limit ?, 50"), [ip_check(), sql_num])
-    data_list = curs.fetchall()
-    if data_list:
-        data = '<a href="/alarm/delete">(' + load_lang('delete') + ')</a><hr class=\"main_hr\">' + data
-
-        for data_one in data_list:
-            data += '<li>' + html.escape(data_one[0]) + ' (' + data_one[1] + ')</li>'
-
-    data += '</ul>' + next_fix('/alarm?num=', num, data_list)
-
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('notice'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-        data = data,
-        menu = [['user', load_lang('return')]]
-    ))
+def user_alarm():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+    
+        num = int(number_check(flask.request.args.get('num', '1')))
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
+    
+        data = '<ul class="inside_ul">'
+    
+        curs.execute(db_change("select data, date from alarm where name = ? order by date desc limit ?, 50"), [ip_check(), sql_num])
+        data_list = curs.fetchall()
+        if data_list:
+            data = '' + \
+                '<a href="/alarm/delete">(' + load_lang('delete') + ')</a>' + \
+                '<hr class="main_hr">' + \
+                data + \
+            ''
+    
+            for data_one in data_list:
+                data += '' + \
+                    '<li>' + \
+                        '<span class="send_content">' + html.escape(data_one[0]) + '</span> ' + \
+                        '(' + data_one[1] + ')' + \
+                    '</li>' + \
+                ''
+    
+        data += '' + \
+            '</ul>' + \
+            '<script>send_render();</script>' + \
+            next_fix('/alarm?num=', num, data_list) + \
+        ''
+    
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('notice'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = data,
+            menu = [['user', load_lang('return')]]
+        ))

+ 7 - 6
route/user_alarm_del.py

@@ -1,9 +1,10 @@
 from .tool.func import *
 
-def user_alarm_del_2(conn):
-    curs = conn.cursor()
+def user_alarm_del():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+    
+        curs.execute(db_change("delete from alarm where name = ?"), [ip_check()])
+        conn.commit()
 
-    curs.execute(db_change("delete from alarm where name = ?"), [ip_check()])
-    conn.commit()
-
-    return redirect('/alarm')
+        return redirect('/alarm')

+ 4 - 0
route/user_setting_email.py

@@ -3,6 +3,10 @@ from .tool.func import *
 def user_setting_email_2(conn):
     curs = conn.cursor()
     
+    ip = ip_check()
+    if ip_or_user(ip) != 0:
+        return redirect('/login')
+    
     if flask.request.method == 'POST':
         # c_key 같은 이름 대신 한 기능에 고유 명칭 부여 필요
         re_set_list = ['c_key']

+ 4 - 0
route/user_setting_email_check.py

@@ -2,6 +2,10 @@ from .tool.func import *
 
 def user_setting_email_check_2(conn):
     curs = conn.cursor()
+    
+    ip = ip_check()
+    if ip_or_user(ip) != 0:
+        return redirect('/login')
 
     re_set_list = ['c_key', 'c_email']
     if  not 'c_key' in flask.session or \

+ 6 - 7
route/user_watch_list.py

@@ -4,7 +4,7 @@ def user_watch_list_2(conn, tool):
     curs = conn.cursor()
 
     if tool == 'watch_list':
-        div = load_lang("msg_whatchlist_lmt") + ' : 10 <hr class=\"main_hr\">'
+        div = load_lang("msg_whatchlist_lmt") + ' : 10 <hr class="main_hr">'
     else:
         div = ''
 
@@ -13,10 +13,6 @@ def user_watch_list_2(conn, tool):
     if ip_or_user(ip) != 0:
         return redirect('/login')
 
-
-    curs.execute(db_change("delete from scan where user = ? and title = ''"), [ip])
-    conn.commit()
-
     if tool == 'watch_list':
         curs.execute(db_change("select title from scan where type = '' and user = ?"), [ip])
 
@@ -40,14 +36,17 @@ def user_watch_list_2(conn, tool):
 
         div += '' + \
             '<li>' + \
-                '<a href="/w/' + url_pas(data_list[0]) + '">' + data_list[0] + '</a> ' + \
+                '<a href="/w/' + url_pas(data_list[0]) + '">' + html.escape(data_list[0]) + '</a> ' + \
                 plus + \
                 '<a href="/' + ('star_doc' if tool == 'star_doc' else 'watch_list') + '/' + url_pas(data_list[0]) + '">(' + load_lang('delete') + ')</a>' + \
             '</li>' + \
         ''
 
     if data:
-        div = '<ul class="inside_ul">' + div + '</ul><hr class=\"main_hr\">'
+        div = '' + \
+            '<ul class="inside_ul">' + div + '</ul>' + \
+            '<hr class="main_hr">' + \
+        ''
 
     div += '<a href="/manager/' + ('13' if tool == 'watch_list' else '16') + '">(' + load_lang('add') + ')</a>'
 

+ 2 - 0
route/user_watch_list_name.py

@@ -2,6 +2,8 @@ from .tool.func import *
 
 def user_watch_list_name_2(conn, tool, name):
     curs = conn.cursor()
+    
+    print(tool, name)
 
     ip = ip_check()
     if ip_or_user(ip) != 0:

+ 1 - 1
version.json

@@ -1,6 +1,6 @@
 {
     "beta" : {
-        "r_ver" : "v3.4.2-stable (stable1) (beta12) (dev18)",
+        "r_ver" : "v3.5.0 (stable1) (beta12) (dev24)",
         "c_ver" : "3500101",
         "s_ver" : "3500110"
     }

+ 5 - 6
views/main_css/js/load_something.js

@@ -69,19 +69,18 @@ function do_twofa_check(init = 0) {
 }
 
 function send_render(i = 0) {
-    var get_class = document.getElementsByClassName('send_content')[i];
+    let get_class = document.getElementsByClassName('send_content')[i];
     if(get_class) {
         send_render(i + 1);
         
-        var data = get_class.innerHTML;
-        
+        let data = get_class.innerHTML;
         if(data === '&lt;br&gt;') {
             document.getElementsByClassName('send_content')[i].innerHTML = '<br>';
         } else {
             data = data.replace(/javascript:/i, '');
-            
-            data = data.replace(/&lt;a&gt;((?:(?!&lt;\/a&gt;).)+)&lt;\/a&gt;/g, function(x, x_1) {
-                return '<a href="/w/' + encodeURIComponent(x_1) + '">' + x_1 + '</a>';
+            data = data.replace(/&lt;a(?:(?:(?!&gt;).)+)&gt;((?:(?!&lt;\/a&gt;).)+)&lt;\/a&gt;/g, function(x, x_1) {
+                x_1_org = x_1.replace('&lt;', '<').replace('&gt;', '>');
+                return '<a href="/w/' + encodeURIComponent(x_1_org) + '">' + x_1 + '</a>';
             });
             
             document.getElementsByClassName('send_content')[i].innerHTML = data;

+ 3 - 3
views/main_css/js/load_topic.js

@@ -1,6 +1,6 @@
 function new_topic_load(topic_num, type_do = 'top', some = '', where = 'top_topic') {
     if(type_do === 'top') {
-        var url = "/api/thread/" + topic_num + "?top=1";
+        var url = "/api/thread/" + topic_num + "/top";
     } else if(type_do === 'main') {
         var url = "/api/thread/" + topic_num;
     } else {
@@ -15,7 +15,7 @@ function new_topic_load(topic_num, type_do = 'top', some = '', where = 'top_topi
         if(this.readyState === 4 && this.status === 200) {
             var data_t = JSON.parse(this.responseText);
             var start = 0;
-            var key_v = '?num=1';
+            var key_v = '/normal/1';
             
             for(var key in data_t) {
                 var data_a = '';
@@ -30,7 +30,7 @@ function new_topic_load(topic_num, type_do = 'top', some = '', where = 'top_topi
                     continue;
                 }
                 
-                key_v = '?num=' + String(Number(key) + 1);
+                key_v = '/normal/' + String(Number(key) + 1);
                 
                 var color_b = '';
                 var color_t = '';

+ 2 - 0
views/main_css/js/render_onmark.js

@@ -1249,9 +1249,11 @@ function do_onmark_redirect_render(data, data_js, name_doc) {
         var link_main = link_data_var[0];
         var link_sub = link_data_var[1];
         
+        // 임시 조치
         if(
             name_include == '' &&
             window.location.search === '' &&
+            window.location.pathname.match(/\/w\//) &&
             !window.location.pathname.match(/\/doc_from\//)
         ) {
             window.location.href = '/w/' + do_url_change(link_main) + '/doc_from/' + do_url_change(name_doc) + link_sub;

+ 4 - 2
views/main_css/js/render_wiki.js

@@ -35,7 +35,7 @@ function get_link_state(data) {
     data_form.append('title_list', JSON.stringify(link_list));
     
     var xhr = new XMLHttpRequest();
-    xhr.open("POST", "/api/w/test?v=exist");
+    xhr.open("POST", "/api/w/test/doc_tool/exist");
     xhr.send(data_form);
 
     xhr.onreadystatechange = function() {
@@ -239,9 +239,11 @@ function get_file_state(data, i = 0) {
 function load_include(name_doc, name_ob, data_include, name_org = '') {
     var data_form = new FormData();
     data_form.append('include_list', JSON.stringify(data_include));
+    data_form.append('name_include', name_ob);
+    data_form.append('name_org', name_org);
     
     var xhr = new XMLHttpRequest();
-    xhr.open("POST", "/api/w/" + encodeURI(name_doc) + "?v=include&include=" + name_ob + "&name_org=" + name_org);
+    xhr.open("POST", "/api/w/" + encodeURI(name_doc) + "/doc_tool/include");
     xhr.send(data_form);
 
     document.getElementsByClassName(name_ob)[0].href = "/w/" + do_url_change(name_doc);

+ 47 - 1
views/ringo/css/main.css

@@ -3,6 +3,7 @@ body {
 }
 
 html {
+    font-family: "나눔바른고딕", "나눔고딕", "맑은고딕", "Sans-Serif";
     background: #eee;
 }
 
@@ -35,6 +36,19 @@ header#main form.not_mobile {
     display: inline-block;
 }
 
+div#menu {
+    margin-top: 10px;
+}
+
+.menu_item {
+    border: 0;
+    background-color: white;
+    
+    padding: 10px;
+    
+    display: inline-block;
+}
+
 input.search {
     height: 35px;
     
@@ -101,6 +115,30 @@ aside button {
     width: 25%;
 }
 
+aside .side_button {
+    border: 0;
+    background-color: white;
+    
+    padding: 10px;
+}
+
+aside .side_button:hover {
+    background-color: #eee;
+}
+
+#side_button_2 {
+    border-left: 0;
+    border-right: 0;
+}
+
+#side_button_3 {
+    border-right: 0;
+}
+
+#side_content {
+    margin-top: 20px;
+}
+
 section {
     width: calc(100% - (250px + 40px));
     
@@ -129,7 +167,7 @@ article.main {
     margin: auto;
 }
 
-article.main#content {
+article.main#main_data {
     padding-top: 20px;
     
     min-height: 400px;
@@ -183,4 +221,12 @@ footer {
 
 footer.only_mobile {
     margin-top: 0px;
+}
+
+#main_data input, #main_data textarea, #main_data button, #main_data select {
+    border: 1px solid #aaa;
+    
+    padding: 10px;
+    
+    background-color: white;
 }

+ 31 - 5
views/ringo/index.html

@@ -77,9 +77,32 @@
             <header id="section">
                 <article class="main" id="title">
                     <h1><span class="change_space">{{imp[0]}}</span></h1>
+                    {% if menu != 0 %}
+                        <div id="menu">
+                            {% for menu_data in menu %}<!--
+                             --><div class="menu_item">
+                                    {% if menu[0] == 1 %}
+                                        {% set menu_data_2 = menu_data[0] %}
+                                    {% else %}
+                                        {% set menu_data_2 = '/' + menu_data[0] %}
+                                    {% endif %}
+                                    
+                                    {% if menu_data|length > 2 and menu_data[2] == 1 %}
+                                        {% set menu_topic = 'topic_color' %}
+                                    {% else %}
+                                        {% set menu_topic = '' %}
+                                    {% endif %}
+                                    
+                                    <a class="menu_item_link" href="{{menu_data_2}}" id="{{menu_topic}}">
+                                        {{menu_data[1]}}
+                                    </a>
+                                </div><!--
+                         -->{% endfor %}
+                        </div>
+                    {% endif %}
                 </article>
             </header>
-            <article class="main" id="content">
+            <article class="main" id="main_data">
                 {{data|safe}}
             </article>
             <footer class="not_mobile">
@@ -92,10 +115,13 @@
             </footer>
         </section>
         <aside>
-            <button class="side_button selected">A</button><!--
-         --><button class="side_button">B</button><!--
-         --><button class="side_button">C</button><!--
-         --><button class="side_button">D</button>
+            <button id="side_button_1" class="side_button selected">변경</button><!--
+         --><button id="side_button_2" class="side_button">토론</button><!--
+         --><button id="side_button_3" class="side_button">목차</button><!--
+         --><button id="side_button_4" class="side_button">각주</button>
+            <div id="side_content">
+                Loading...
+            </div>
         </aside>
         <footer class="only_mobile">
             {{imp[1][1]|safe}}