Explorar o código

Merge pull request #655 from 2du/master

아 이제 슬슬 새 버전
잉여강화기 (SPUP) %!s(int64=7) %!d(string=hai) anos
pai
achega
c75de3cbad
Modificáronse 80 ficheiros con 1023 adicións e 738 borrados
  1. 3 4
      .gitignore
  2. 123 131
      app.py
  3. 25 1
      language/en-US.json
  4. 30 6
      language/ko-KR.json
  5. 0 3
      route/alarm.py
  6. 1 1
      route/alarm_del.py
  7. 1 1
      route/api_skin_info.py
  8. 19 5
      route/api_topic_sub.py
  9. 1 1
      route/api_w.py
  10. 0 91
      route/block_log.py
  11. 8 0
      route/edit.py
  12. 1 1
      route/edit_delete.py
  13. 1 1
      route/edit_move.py
  14. 1 1
      route/edit_revert.py
  15. 1 1
      route/func_title_random.py
  16. 21 16
      route/func_upload.py
  17. 1 1
      route/give_acl.py
  18. 1 1
      route/give_admin.py
  19. 1 1
      route/give_admin_groups.py
  20. 1 1
      route/give_history_hidden.py
  21. 114 0
      route/give_user_ban.py
  22. 1 1
      route/give_user_check.py
  23. 8 1
      route/inter_wiki.py
  24. 3 1
      route/inter_wiki_del.py
  25. 43 17
      route/inter_wiki_plus.py
  26. 2 2
      route/list_acl.py
  27. 1 1
      route/list_admin.py
  28. 1 1
      route/list_admin_use.py
  29. 113 0
      route/list_block.py
  30. 1 1
      route/list_give.py
  31. 1 1
      route/list_not_close_topic.py
  32. 1 1
      route/list_please.py
  33. 1 1
      route/list_title_index.py
  34. 2 13
      route/list_user.py
  35. 1 1
      route/list_user_topic.py
  36. 1 1
      route/login_change_password.py
  37. 1 1
      route/login_check_key.py
  38. 1 1
      route/login_logout.py
  39. 1 1
      route/login_need_email.py
  40. 1 1
      route/login_register.py
  41. 1 1
      route/main_easter_egg.py
  42. 1 1
      route/main_error_404.py
  43. 1 1
      route/main_image_view.py
  44. 4 3
      route/main_manager.py
  45. 1 1
      route/main_other.py
  46. 20 0
      route/main_skin_set.py
  47. 1 1
      route/main_views.py
  48. 1 1
      route/search_deep.py
  49. 1 1
      route/search_goto.py
  50. 1 1
      route/server_indexing.py
  51. 25 20
      route/server_now_update.py
  52. 2 1
      route/server_restart.py
  53. 42 57
      route/setting.py
  54. 1 1
      route/setting_adsense.py
  55. 1 1
      route/setting_oauth.py
  56. 104 62
      route/tool/func.py
  57. 5 5
      route/tool/init.py
  58. 1 1
      route/tool/set_mark/namu.py
  59. 32 33
      route/topic.py
  60. 5 5
      route/topic_admin.py
  61. 1 1
      route/topic_close_list.py
  62. 53 44
      route/topic_stop.py
  63. 46 0
      route/topic_tool.py
  64. 0 82
      route/user_ban.py
  65. 1 1
      route/user_count_edit.py
  66. 1 1
      route/user_custom_head_view.py
  67. 41 42
      route/user_info.py
  68. 13 12
      route/user_tool.py
  69. 1 1
      route/view_diff_data.py
  70. 1 1
      route/view_down.py
  71. 1 1
      route/view_raw.py
  72. 1 1
      route/view_read.py
  73. 1 1
      route/view_xref.py
  74. 2 1
      views/main_css/css/main.css
  75. 3 0
      views/main_css/js/reload.js
  76. 10 0
      views/main_css/js/req_browser_alarm.js
  77. 23 26
      views/main_css/js/topic_load.js
  78. 4 4
      views/neo_yousoro/css/main.css
  79. 1 1
      views/neo_yousoro/info.json
  80. 31 6
      views/neo_yousoro/js/skin_set.js

+ 3 - 4
.gitignore

@@ -1,11 +1,10 @@
-set.json
-
 __pycache__
 /app_session
 .vscode
 
 *.db
 *.db-journal
+
 images
 robots.txt
 
@@ -14,5 +13,5 @@ views/yousoro
 views/super_lite
 views/buma
 views/before_namu
-views/acme/
-views/sl-open/
+views/acme
+views/sl-open

+ 123 - 131
app.py

@@ -8,7 +8,7 @@ for i_data in os.listdir("route"):
 
         exec("from route." + f_src + " import *")
 
-r_ver = 'v3.1.0-master-06'
+r_ver = 'v3.1.0-stable-99'
 c_ver = '400001'
 s_ver = '2'
 
@@ -183,7 +183,7 @@ if not os.path.exists('views'):
 
 import route.tool.init as server_init
 
-dislay_set_key = ['Host', 'Port', 'Language', 'Markup', 'Encrypt Method']
+dislay_set_key = ['Host', 'Port', 'Language', 'Markup', 'Encryption method']
 server_set_key = ['host', 'port', 'language', 'markup', 'encode']
 server_set = {}
 
@@ -217,6 +217,7 @@ try:
 
             curs.execute('insert into other (name, data) values ("robot", "User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/")')
         
+        print('----')
         print('Engine made robots.txt')
 except:
     pass
@@ -240,6 +241,7 @@ curs.execute('delete from other where name = "ver"')
 curs.execute('insert into other (name, data) values ("ver", ?)', [c_ver])
 
 def back_up():
+    print('----')
     try:
         shutil.copyfile(db_name + '.db', 'back_' + db_name + '.db')
         
@@ -257,6 +259,7 @@ try:
 except:
     back_time = 0
     
+print('----')
 if back_time != 0:
     print('Back up state : ' + str(back_time) + ' hours')
     
@@ -282,25 +285,25 @@ else:
 
 ## Func
 @app.route('/del_alarm')
-def del_alarm():
-    return del_alarm_2(conn)
+def alarm_del():
+    return alarm_del_2(conn)
 
 @app.route('/alarm')
 def alarm():
     return alarm_2(conn)
 
-@app.route('/<regex("inter_wiki|(?:edit|email|name)_filter"):tools>')
+@app.route('/<regex("inter_wiki|(?:edit|email|file|name)_filter"):tools>')
 def inter_wiki(tools = None):
     return inter_wiki_2(conn, tools)
 
-@app.route('/<regex("del_(?:inter_wiki|(?:edit|email|name)_filter)"):tools>/<name>')
-def del_inter(tools = None, name = None):
-    return del_inter_2(conn, tools, name)
+@app.route('/<regex("del_(?:inter_wiki|(?:edit|email|file|name)_filter)"):tools>/<name>')
+def inter_wiki_del(tools = None, name = None):
+    return inter_wiki_del_2(conn, tools, name)
 
-@app.route('/<regex("plus_(?:inter_wiki|(?:edit|email|name)_filter)"):tools>', methods=['POST', 'GET'])
+@app.route('/<regex("plus_(?:inter_wiki|(?:edit|email|file|name)_filter)"):tools>', methods=['POST', 'GET'])
 @app.route('/<regex("plus_edit_filter"):tools>/<name>', methods=['POST', 'GET'])
-def plus_inter(tools = None, name = None):
-    return plus_inter_2(conn, tools, name)
+def inter_wiki_plus(tools = None, name = None):
+    return inter_wiki_plus_2(conn, tools, name)
 
 @app.route('/setting')
 @app.route('/setting/<int:num>', methods=['POST', 'GET'])
@@ -308,68 +311,64 @@ def setting(num = 0):
     return setting_2(conn, num)
 
 @app.route('/not_close_topic')
-def not_close_topic():
-    return not_close_topic_2(conn)
-
-@app.route('/image/<name>')
-def image_view(name = None):
-    return image_view_2(conn, name, app_var)
+def list_not_close_topic():
+    return list_not_close_topic_2(conn)
 
 @app.route('/acl_list')
-def acl_list():
-    return acl_list_2(conn)
+def list_acl():
+    return list_acl_2(conn)
 
 @app.route('/admin_plus/<name>', methods=['POST', 'GET'])
-def admin_plus(name = None):
-    return admin_plus_2(conn, name)
+def give_admin_groups(name = None):
+    return give_admin_groups_2(conn, name)
         
 @app.route('/admin_list')
-def admin_list():
-    return admin_list_2(conn)
+def list_admin():
+    return list_admin_2(conn)
         
 @app.route('/hidden/<everything:name>')
-def history_hidden(name = None):
-    return history_hidden_2(name)
+def give_history_hidden(name = None):
+    return give_history_hidden_2(name)
         
 @app.route('/user_log')
-def user_log():
-    return user_log_2(conn)
+def list_user():
+    return list_user_2(conn)
 
 @app.route('/admin_log')
-def admin_log():
-    return admin_log_2(conn)
+def list_admin_use():
+    return list_admin_use_2(conn)
 
 @app.route('/give_log')
-def give_log():        
-    return give_log_2(conn)
+def list_give():
+    return list_give_2(conn)
 
 @app.route('/indexing', methods=['POST', 'GET'])
-def indexing():
-    return indexing_2(conn)       
+def server_indexing():
+    return server_indexing_2(conn)       
 
 @app.route('/restart', methods=['POST', 'GET'])
-def restart():
-    return restart_2(conn)
+def server_restart():
+    return server_restart_2(conn)
 
 @app.route('/update', methods=['GET', 'POST'])
-def now_update():
-    return now_update_2(conn)
+def server_now_update():
+    return server_now_update_2(conn)
 
 @app.route('/oauth_setting', methods=['GET', 'POST'])
-def oauth_setting():
-    return oauth_setting_2(conn)
+def setting_oauth():
+    return setting_oauth_2(conn)
 
 @app.route('/adsense_setting', methods=['GET', 'POST'])
-def adsense_setting():
-    return adsense_setting_2(conn)
+def setting_adsense():
+    return setting_adsense_2(conn)
         
 @app.route('/xref/<everything:name>')
-def xref(name = None):
-    return xref_2(conn, name)
+def view_xref(name = None):
+    return view_xref_2(conn, name)
 
 @app.route('/please')
-def please():
-    return please_2(conn)
+def list_please():
+    return list_please_2(conn)
         
 @app.route('/recent_discuss')
 def recent_discuss():
@@ -377,58 +376,54 @@ def recent_discuss():
 
 @app.route('/block_log')
 @app.route('/<regex("block_user|block_admin"):tool>/<name>')
-def block_log(name = None, tool = None):
-    return block_log_2(conn, name, tool)
+def list_block(name = None, tool = None):
+    return list_block_2(conn, name, tool)
             
 @app.route('/search', methods=['POST'])
 def search():
     return search_2(conn)
 
 @app.route('/goto', methods=['POST'])
-def goto():
-    return goto_2(conn)
+def search_goto():
+    return search_goto_2(conn)
 
 @app.route('/search/<everything:name>')
-def deep_search(name = ''):
-    return deep_search_2(conn, name)
+def search_deep(name = ''):
+    return search_deep_2(conn, name)
          
 @app.route('/raw/<everything:name>')
 @app.route('/topic/<everything:name>/sub/<sub_title>/raw/<int:num>')
-def raw_view(name = None, sub_title = None, num = None):
-    return raw_view_2(conn, name, sub_title, num)
+def view_raw(name = None, sub_title = None, num = None):
+    return view_raw_2(conn, name, sub_title, num)
         
 @app.route('/revert/<everything:name>', methods=['POST', 'GET'])
-def revert(name = None):    
-    return revert_2(conn, name)
+def edit_revert(name = None):
+    return edit_revert_2(conn, name)
 
 @app.route('/edit/<everything:name>', methods=['POST', 'GET'])
 def edit(name = None):
     return edit_2(conn, name)
-
-@app.route('/preview/<everything:name>', methods=['POST'])
-def preview(name = None):
-    return preview_2(conn, name)
         
 @app.route('/delete/<everything:name>', methods=['POST', 'GET'])
-def delete(name = None):
-    return delete_2(conn, name, app_var)        
+def edit_delete(name = None):
+    return edit_delete_2(conn, name, app_var)        
             
 @app.route('/move/<everything:name>', methods=['POST', 'GET'])
-def move(name = None):
-    return move_2(conn, name)
+def edit_move(name = None):
+    return edit_move_2(conn, name)
 
 @app.route('/other')
-def other():
-    return other_2(conn, r_ver)
+def main_other():
+    return main_other_2(conn, r_ver)
     
 @app.route('/manager', methods=['POST', 'GET'])
 @app.route('/manager/<int:num>', methods=['POST', 'GET'])
-def manager(num = 1):
-    return manager_2(conn, num)
+def main_manager(num = 1):
+    return main_manager_2(conn, num)
         
 @app.route('/title_index')
-def title_index():
-    return title_index_2(conn)
+def list_title_index():
+    return list_title_index_2(conn)
                 
 @app.route('/topic/<everything:name>/sub/<sub>/b/<int:num>')
 def topic_block(name = None, sub = None, num = 1):
@@ -438,10 +433,14 @@ def topic_block(name = None, sub = None, num = 1):
 def topic_top(name = None, sub = None, num = 1):
     return topic_top_2(conn, name, sub, num)
                 
-@app.route('/topic/<everything:name>/sub/<sub>/tool/<regex("close|stop|agree"):tool>')
+@app.route('/topic/<everything:name>/sub/<sub>/tool/<regex("close|stop|agree"):tool>', methods=['POST', 'GET'])
 def topic_stop(name = None, sub = None, tool = None):
     return topic_stop_2(conn, name, sub, tool)
 
+@app.route('/topic/<everything:name>/sub/<sub>/tool')
+def topic_tool(name = None, sub = None):
+    return topic_tool_2(conn, name, sub)
+
 @app.route('/topic/<everything:name>/sub/<sub>/admin/<int:num>')
 def topic_admin(name = None, sub = None, num = 1):
     return topic_admin_2(conn, name, sub, num)
@@ -449,15 +448,15 @@ def topic_admin(name = None, sub = None, num = 1):
 @app.route('/topic/<everything:name>/sub/<sub>', methods=['POST', 'GET'])
 def topic(name = None, sub = None):
     return topic_2(conn, name, sub)
+        
+@app.route('/topic/<everything:name>', methods=['POST', 'GET'])
+@app.route('/topic/<everything:name>/<regex("close|agree"):tool>', methods=['GET'])
+def topic_close_list(name = None, tool = None):
+    return topic_close_list_2(conn, name, tool)
 
 @app.route('/tool/<name>')
 def user_tool(name = None):
     return user_tool_2(conn, name)
-        
-@app.route('/topic/<everything:name>', methods=['POST', 'GET'])
-@app.route('/topic/<everything:name>/<regex("close|agree"):tool>', methods=['GET'])
-def close_topic_list(name = None, tool = None):
-    return close_topic_list_2(conn, name, tool)
             
 @app.route('/login', methods=['POST', 'GET'])
 def login():
@@ -468,56 +467,57 @@ def login_oauth(platform = None, func = None):
     return login_oauth_2(conn, platform, func)
                 
 @app.route('/change', methods=['POST', 'GET'])
-def change_password():
-    return change_password_2(conn, server_init)
+def login_change_password():
+    return login_change_password_2(conn, server_init)
 
 @app.route('/check/<name>')
-def user_check(name = None):
-    return user_check_2(conn, name)
+def give_user_check(name = None):
+    return give_user_check_2(conn, name)
                 
 @app.route('/register', methods=['POST', 'GET'])
-def register():
-    return register_2(conn)
+def login_register():
+    return login_register_2(conn)
 
 @app.route('/<regex("need_email|pass_find"):tool>', methods=['POST', 'GET'])
-def need_email(tool = 'pass_find'):
-    return need_email_2(conn, tool)
+def login_need_email(tool = 'pass_find'):
+    return login_need_email_2(conn, tool)
 
 @app.route('/<regex("check_key|check_pass_key"):tool>', methods=['POST', 'GET'])
-def check_key(tool = 'check_pass_key'):
-    return check_key_2(conn, tool)
+def login_check_key(tool = 'check_pass_key'):
+    return login_check_key_2(conn, tool)
            
 @app.route('/logout')
-def logout():
-    return logout_2(conn)
+def login_logout():
+    return login_logout_2(conn)
     
+@app.route('/ban', methods=['POST', 'GET'])
 @app.route('/ban/<name>', methods=['POST', 'GET'])
-def user_ban(name = None):
-    return user_ban_2(conn, name)         
+def give_user_ban(name = None):
+    return give_user_ban_2(conn, name)         
                 
 @app.route('/acl/<everything:name>', methods=['POST', 'GET'])
-def acl(name = None):
-    return acl_2(conn, name)
+def give_acl(name = None):
+    return give_acl_2(conn, name)
             
 @app.route('/admin/<name>', methods=['POST', 'GET'])
-def user_admin(name = None):
-    return user_admin_2(conn, name)
+def give_admin(name = None):
+    return give_admin_2(conn, name)
     
 @app.route('/diff/<everything:name>')
-def diff_data(name = None):
-    return diff_data_2(conn, name)
+def view_diff_data(name = None):
+    return view_diff_data_2(conn, name)
         
 @app.route('/down/<everything:name>')
-def down(name = None):
-    return down_2(conn, name)   
+def view_down(name = None):
+    return view_down_2(conn, name)   
 
 @app.route('/w/<everything:name>')
-def read_view(name = None):
-    return read_view_2(conn, name)
+def view_read(name = None):
+    return view_read_2(conn, name)
 
 @app.route('/topic_record/<name>')
-def user_topic_list(name = None):
-    return user_topic_list_2(conn, name)
+def list_user_topic(name = None):
+    return list_user_topic_2(conn, name)
 
 @app.route('/recent_changes')
 @app.route('/<regex("record"):tool>/<name>')
@@ -526,8 +526,8 @@ def recent_changes(name = None, tool = 'record'):
     return recent_changes_2(conn, name, tool)
     
 @app.route('/upload', methods=['GET', 'POST'])
-def upload():
-    return upload_2(conn)
+def func_upload():
+    return func_upload_2(conn)
         
 @app.route('/user')
 def user_info():
@@ -542,35 +542,25 @@ def watch_list_name(name = None):
     return watch_list_name_2(conn, name)
 
 @app.route('/custom_head', methods=['GET', 'POST'])
-def custom_head_view():
-    return custom_head_view_2(conn)
+def user_custom_head_view():
+    return user_custom_head_view_2(conn)
 
 @app.route('/count')
 @app.route('/count/<name>')
-def count_edit(name = None):
-    return count_edit_2(conn, name)
+def user_count_edit(name = None):
+    return user_count_edit_2(conn, name)
         
 @app.route('/random')
-def title_random():
-    return title_random_2(conn)
+def func_title_random():
+    return func_title_random_2(conn)
 
-@app.route('/skin_set')
-def skin_set():
-    data = flask.make_response(re_error('/error/5'))
-
-    curs.execute("select data from other where name = 'language'")
-    main_data = curs.fetchall()
-
-    data.set_cookie('language', main_data[0][0])
-
-    curs.execute('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])
+@app.route('/image/<name>')
+def main_image_view(name = None):
+    return main_image_view_2(conn, name, app_var)
 
-    return data
+@app.route('/skin_set')
+def main_skin_set():
+    return main_skin_set_2(conn)
     
 # API
 @app.route('/api/w/<everything:name>', methods=['POST', 'GET'])
@@ -595,12 +585,12 @@ def api_topic_sub(name = '', sub = '', time = ''):
     
 ## File
 @app.route('/views/easter_egg.html')
-def easter_egg():
-    return easter_egg_2(conn)
+def main_easter_egg():
+    return main_easter_egg_2(conn)
 
 @app.route('/views/<everything:name>')
-def views(name = None):
-    return views_2(conn, name)
+def main_views(name = None):
+    return main_views_2(conn, name)
 
 @app.route('/<data>')
 def main_file(data = None):
@@ -608,11 +598,13 @@ def main_file(data = None):
 
 ## End
 @app.errorhandler(404)
-def error_404(e):
-    return error_404_2(conn)
+def main_error_404(e):
+    return main_error_404_2(conn)
 
 if __name__=="__main__":
     app.secret_key = rep_key
+
     http_server = tornado.httpserver.HTTPServer(tornado.wsgi.WSGIContainer(app))
     http_server.listen(server_set['port'], address=server_set['host'])
+    
     tornado.ioloop.IOLoop.instance().start()

+ 25 - 1
language/en-US.json

@@ -82,6 +82,11 @@
         "explanation" : "Explanation",
         "default" : "Default",
         "lastest" : "Lastest",
+        "type" : "Type",
+        "in_progress" : "In progress",
+        "start" : "Start",
+        "pass" : "Passing",
+        "file_name" : "File name",
         "_comment_1.1_" : "Time",
             "second" : "Second(s)",
             "hour" : "Hour(s)",
@@ -154,17 +159,31 @@
         "encryption_method" : "Encryption method",
         "check_key" : "Check Authentication Key",
         "reset_user_ok" : "Check Success",
+        "name_or_ip_or_regex" : "ID or IP or Regex",
+        "ban_period" : "Period to block",
+        "not_sure" : "Not sure",
+        "use_push_alarm" : "Enable Push Notification",
+        "topic_tool" : "Discussion tool",
+        "topic_state" : "Discussion status",
+        "topic_stop" : "Stop discussion",
+        "topic_close" : "Close discussion",
+        "topic_restart" : "Discussion restart",
+        "topic_open" : "Open discussion",
+        "topic_agreement" : "Discussion agreement",
+        "topic_destruction" : "Cancel discussion agreement",
         "_comment_2.1_" : "Filter",
             "_comment_2.1.1_" : "List",
                 "interwiki_list" : "Interwiki(s) list",
                 "email_filter_list" : "Email filter(s) list",
                 "id_filter_list" : "ID filter(s) list",
                 "edit_filter_list" : "Contents filter(s) list",
+                "file_filter_list" : "File name filter(s) list",
             "_comment_2.1.2_" : "Add",
                 "interwiki_add" : "Interwiki add",
                 "edit_filter_add" : "Contents filter add",
                 "id_filter_add" : "ID filter add",
                 "email_filter_add" : "Email filter add",
+                "file_filter_add" : "File name filter add",
         "_comment_2.2_" : "Setting",
             "setting" : "Setting",
             "restart_required" : "Restart required",
@@ -198,6 +217,7 @@
             "_comment_2.2.3_" : "Text",
                 "register_text" : "Terms of sign-up",
                 "non_login_alert" : "Non-login alert",
+                "edit_bottom_text" : "Editing textarea bottom notice",
             "_comment_2.2.4_" : "Google",
                 "recaptcha" : "reCAPTCHA",
                 "google_imap" : "Google IMAP",
@@ -235,6 +255,9 @@
         "user_head_warring" : "User[s] <head> will deleted if you close the browser or sign-in",
         "no_login_warring" : "Non-login status. IP is logged when working with non-login.",
         "user_reset_sign" : "Your account information has changed like this.",
+        "ban_explanation" : "If the blockout period is not set, it is an indefinite block.",
+        "update_warring" : "Manual updates are recommended if your version is 0.2 or lower than the latest version.",
+        "markup_enabled" : "Markup enabled",
         "_comment_3.1_" : "Error",
             "update_error" : "Auto update is not support.",
             "inter_error" : "Internal error.",
@@ -258,5 +281,6 @@
             "edit_filter_error" : "Censored by edit filter.",
             "file_name_error" : "Only alphabet, hangul, space, underscore, and minus signs are allowed for file names.",
             "topic_long_error" : "The discussion name must not exceed 256 characters.",
-            "email_error" : "No one has this email."
+            "email_error" : "No one has this email.",
+            "regex_error" : "There is an error in the regular expression."
 }

+ 30 - 6
language/ko-KR.json

@@ -46,8 +46,8 @@
         "upload" : "업로드",
         "version" : "버전",
         "stop" : "중지",
-        "close" : "닫",
-        "open" : "",
+        "close" : "닫",
+        "open" : "열기",
         "agreement" : "동의",
         "template" : "틀",
         "category" : "분류",
@@ -56,7 +56,7 @@
         "editor" : "에디터",
         "hide" : "숨김",
         "check" : "검사",
-        "destruction" : "삭제",
+        "destruction" : "취소",
         "tool" : "도구",
         "recent" : "최근",
         "password" : "비밀번호",
@@ -82,10 +82,15 @@
         "explanation" : "설명",
         "default" : "기본값",
         "lastest" : "최신",
+        "type" : "유형",
+        "in_progress" : "진행중",
+        "start" : "시작",
+        "pass" : "넘기기",
+        "file_name" : "파일명",
         "_comment_1.1_" : "시간",
             "second" : "초",
             "hour" : "시간",
-            "limitless" : "무제한",
+            "limitless" : "무한",
             "time" : "시간",
             "period" : "기간",
             "end" : "끝",
@@ -154,17 +159,31 @@
         "encryption_method" : "암호화 방식",
         "check_key" : "인증키 검사",
         "reset_user_ok" : "검사 성공",
+        "name_or_ip_or_regex" : "ID or IP or 정규식",
+        "ban_period" : "차단 기간",
+        "not_sure" : "확실하지 않음",
+        "use_push_alarm" : "푸쉬 알림 사용",
+        "topic_tool" : "토론 도구",
+        "topic_state" : "토론 상태",
+        "topic_stop" : "토론 중지",
+        "topic_close" : "토론 닫기",
+        "topic_restart" : "토론 중지 해제",
+        "topic_open" : "토론 열기",
+        "topic_agreement" : "토론 합의",
+        "topic_destruction" : "토론 합의 취소",
         "_comment_2.1_" : "필터",
             "_comment_2.1.1_" : "목록",
                 "interwiki_list" : "인터위키 목록",
                 "email_filter_list" : "이메일 필터 목록",
                 "id_filter_list" : "ID 필터 목록",
                 "edit_filter_list" : "편집 필터 목록",
+                "file_filter_list" : "파일명 필터 목록",
             "_comment_2.1.2_" : "추가",
                 "interwiki_add" : "인터위키 추가",
                 "edit_filter_add" : "편집 필터 추가",
                 "id_filter_add" : "ID 필터 추가",
                 "email_filter_add" : "이메일 필터 추가",
+                "file_filter_add" : "파일명 필터 추가",
         "_comment_2.2_" : "설정",
             "setting" : "설정",
             "restart_required" : "재시작 필요",
@@ -174,7 +193,7 @@
             "skin_setting" : "스킨 설정",
             "_comment_2.2.1_" : "목록",
                 "main_setting" : "메인 설정",
-                "text_setting" : "문 설정",
+                "text_setting" : "문 설정",
                 "main_head" : "전역 <head>",
                 "main_body" : "전역 <body>",
             "_comment_2.2.2_" : "메인",
@@ -198,6 +217,7 @@
             "_comment_2.2.3_" : "문자열",
                 "register_text" : "회원가입 정책",
                 "non_login_alert" : "비로그인 알림",
+                "edit_bottom_text" : "편집창 하단 문구",
             "_comment_2.2.4_" : "Google",
                 "recaptcha" : "reCAPTCHA",
                 "google_imap" : "Google IMAP",
@@ -235,6 +255,9 @@
         "user_head_warring" : "비로그인시 브라우저를 닫거나 로그인시 사용자의 <head>는 삭제됩니다.",
         "no_login_warring" : "비로그인 상태입니다. 편집시 지금 접속한 IP 명의로 기록됩니다.",
         "user_reset_sign" : "사용자의 계정 정보가 다음과 같이 변경 되었습니다.",
+        "ban_explanation" : "차단 기간이 정해지지 않으면 무기한 차단 입니다.",
+        "update_warring" : "최신 버전보다 0.2 버전 이상 낮은 경우 수동 업데이트를 권장 드립니다.",
+        "markup_enabled" : "문법 사용 가능",
         "_comment_3.1_" : "오류",
             "update_error" : "자동 업데이트가 지원되지 않습니다.",
             "inter_error" : "내부 오류.",
@@ -258,5 +281,6 @@
             "edit_filter_error" : "편집 필터에 의해 금지된 단어가 사용되었습니다.",
             "file_name_error" : "파일 이름에는 알파벳, 한글, 공백, 밑줄 과 빼기 기호만 사용할 수 있습니다.",
             "topic_long_error" : "토론 이름이 256자를 넘지 않아야 합니다.",
-            "email_error" : "이런 이메일을 가진 사용자가 없습니다."
+            "email_error" : "이런 이메일을 가진 사용자가 없습니다.",
+            "regex_error" : "정규표현식에 오류가 있습니다."
 }

+ 0 - 3
route/alarm.py

@@ -2,9 +2,6 @@ from .tool.func import *
 
 def alarm_2(conn):
     curs = conn.cursor()
-    
-    if custom()[2] == 0:
-        return redirect('/login')    
 
     data = '<ul>'    
     

+ 1 - 1
route/del_alarm.py → route/alarm_del.py

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

+ 1 - 1
route/api_skin_info.py

@@ -12,4 +12,4 @@ def api_skin_info_2(conn):
     if json_data:    
         return flask.jsonify(json_data)
     else:
-        return flask.jsonify({})
+        return flask.jsonify({}), 404

+ 19 - 5
route/api_topic_sub.py

@@ -3,19 +3,33 @@ from .tool.func import *
 def api_topic_sub_2(conn, name, sub, time):
     curs = conn.cursor()
 
-    if flask.request.args.get('time', None):
-        curs.execute("select id, data, ip from topic where title = ? and sub = ? and date >= ? order by id + 0 asc", [name, sub, flask.request.args.get('time', None)])
+    if flask.request.args.get('num', None):
+        if flask.request.args.get('over', '0') == '0':
+            curs.execute("select id, data, date, ip from topic where title = ? and sub = ? and id + 0 = ? + 0 order by id + 0 asc", [name, sub, flask.request.args.get('num', '')])
+        elif flask.request.args.get('over', '0') == '1':
+            curs.execute("select id, data, date, ip from topic where title = ? and sub = ? and id + 0 >= ? + 0 order by id + 0 asc", [name, sub, flask.request.args.get('num', '')])
+        else:
+            curs.execute("select id, data, date, ip from topic where title = ? and sub = ? and id + 0 <= ? + 0 order by id + 0 asc", [name, sub, flask.request.args.get('num', '')])
+    elif flask.request.args.get('time', None):
+        if flask.request.args.get('over', '0') == '0':
+            curs.execute("select id, data, date, ip from topic where title = ? and sub = ? and date = ? order by id + 0 asc", [name, sub, flask.request.args.get('time', '')])
+        if flask.request.args.get('over', '0') == '1':
+            curs.execute("select id, data, date, ip from topic where title = ? and sub = ? and date >= ? order by id + 0 asc", [name, sub, flask.request.args.get('time', '')])
+        else:
+            curs.execute("select id, data, date, ip from topic where title = ? and sub = ? and date <= ? order by id + 0 asc", [name, sub, flask.request.args.get('time', '')])
     else:
-        curs.execute("select id, data, ip from topic where title = ? and sub = ? order by id + 0 asc", [name, sub])
+        curs.execute("select id, data, date, ip from topic where title = ? and sub = ? order by id + 0 asc", [name, sub])
+
     data = curs.fetchall()
     if data:
         json_data = {}
         for i in data:
             json_data[i[0]] =   {
                 "data" : i[1],
-                "id" : i[2]
+                "date" : i[2],
+                "id" : i[3]
             }
 
         return flask.jsonify(json_data)
     else:
-        return flask.jsonify({})
+        return flask.jsonify({}), 404

+ 1 - 1
route/api_w.py

@@ -15,4 +15,4 @@ def api_w_2(conn, name):
         
             return flask.jsonify(json_data)
         else:
-            return flask.jsonify({})
+            return flask.jsonify({}), 404

+ 0 - 91
route/block_log.py

@@ -1,91 +0,0 @@
-from .tool.func import *
-
-def block_log_2(conn, name, tool):
-    curs = conn.cursor()
-
-    num = int(number_check(flask.request.args.get('num', '1')))
-    if num * 50 > 0:
-        sql_num = num * 50 - 50
-    else:
-        sql_num = 0
-    
-    div =   '''
-            <table id="main_table_set">
-                <tbody>
-                    <tr>
-                        <td id="main_table_width">''' + load_lang('blocked') + '''</td>
-                        <td id="main_table_width">''' + load_lang('admin') + '''</td>
-                        <td id="main_table_width">''' + load_lang('period') + '''</td>
-                    </tr>
-            '''
-    
-    data_list = ''
-    
-    if not name:
-        div =   '''
-                <a href="/manager/11">(''' + load_lang('blocked') + ''')</a> <a href="/manager/12">(''' + load_lang('admin') + ''')</a>
-                <hr class=\"main_hr\">
-                ''' + div
-        
-        sub = 0
-        menu = 0
-        
-        curs.execute("select why, block, blocker, end, today from rb order by today desc limit ?, '50'", [str(sql_num)])
-    else:
-        menu = [['block_log', load_lang('normal')]]
-        
-        if tool == 'block_user':
-            sub = ' (' + load_lang('blocked') + ')'
-            
-            curs.execute("select why, block, blocker, end, today from rb where block = ? order by today desc limit ?, '50'", [name, str(sql_num)])
-        else:
-            sub = ' (' + load_lang('admin') + ')'
-            
-            curs.execute("select why, block, blocker, end, today from rb where blocker = ? order by today desc limit ?, '50'", [name, str(sql_num)])
-
-    if data_list == '':
-        data_list = curs.fetchall()
-
-    for data in data_list:
-        why = html.escape(data[0])
-        if why == '':
-            why = '<br>'
-        
-        band = re.search("^([0-9]{1,3}\.[0-9]{1,3})$", data[1])
-        if band:
-            ip = data[1] + ' (' + load_lang('range') + ')'
-        else:
-            ip = ip_pas(data[1])
-
-        if data[3] != '':
-            end = data[3]
-        else:
-            end = load_lang('limitless') + ''
-            
-        div +=  '''
-            <tr>
-                <td>''' + ip + '''</td>
-                <td>''' + ip_pas(data[2]) + '''</td>
-                <td>
-                    start : ''' + data[4] + '''
-                    <br>
-                    end : ''' + end + '''
-                </td>
-            </tr>
-            <tr>
-                <td colspan="3">''' + why + '''</td>
-            </tr>
-        '''
-
-    div += '</tbody></table>'
-    
-    if not name:
-        div += next_fix('/block_log?num=', num, data_list)
-    else:
-        div += next_fix('/' + url_pas(tool) + '/' + url_pas(name) + '?num=', num, data_list)
-                
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = [load_lang('recent_ban'), wiki_set(), custom(), other2([sub, 0])],
-        data = div,
-        menu = menu
-    ))

+ 8 - 0
route/edit.py

@@ -92,6 +92,13 @@ def edit_2(conn, name):
                 data = get_data[0][0]
                 get_name = ''
 
+        curs.execute('select data from other where name = "edit_bottom_text"')
+        sql_d = curs.fetchall()
+        if sql_d and sql_d[0][0] != '':
+            b_text = '<hr class=\"main_hr\">' + sql_d[0][0]
+        else:
+            b_text = ''
+
         return easy_minify(flask.render_template(skin_check(), 
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('edit') + ')', 0])],
             data =  get_name + '''
@@ -106,6 +113,7 @@ def edit_2(conn, name):
                     <button id="save" type="submit">''' + load_lang('save') + '''</button>
                     <button id="preview" type="button" onclick="do_preview(\'''' + name + '\')">' + load_lang('preview') + '''</button>
                 </form>
+                ''' + b_text + '''
                 <hr class=\"main_hr\">
                 <div id="see_preview"></div>
             ''',

+ 1 - 1
route/delete.py → route/edit_delete.py

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

+ 1 - 1
route/move.py → route/edit_move.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def move_2(conn, name):
+def edit_move_2(conn, name):
     curs = conn.cursor()
 
     if acl_check(name) == 1:

+ 1 - 1
route/revert.py → route/edit_revert.py

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

+ 1 - 1
route/title_random.py → route/func_title_random.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def title_random_2(conn):
+def func_title_random_2(conn):
     curs = conn.cursor()
 
     curs.execute("select title from data order by random() limit 1")

+ 21 - 16
route/upload.py → route/func_upload.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def upload_2(conn):
+def func_upload_2(conn):
     curs = conn.cursor()
 
     if ban_check() == 1:
@@ -37,6 +37,13 @@ def upload_2(conn):
         curs.execute("select title from data where title = ?", ['file:' + name])
         if curs.fetchall():
             return re_error('/error/16')
+
+        curs.execute("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')
             
         ip = ip_check()
 
@@ -54,10 +61,6 @@ def upload_2(conn):
             data.save(os.path.join(app_var['path_data_image'], e_data))
         else:
             data.save(os.path.join(app_var['path_data_image'], e_data))
-            
-        curs.execute("select title from data where title = ?", ['file:' + name])
-        if curs.fetchall(): 
-            curs.execute("delete from data where title = ?", ['file:' + name])
         
         curs.execute("insert into data (title, data) values (?, ?)", ['file:' + name, '[[file:' + name + ']][br][br]{{{[[file:' + name + ']]}}}[br][br]' + lice])
         curs.execute("insert into acl (title, dec, dis, why, view) values (?, 'admin', '', '', '')", ['file:' + name])
@@ -77,16 +80,18 @@ def upload_2(conn):
         return easy_minify(flask.render_template(skin_check(), 
             imp = [load_lang('upload'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
-                    <form method="post" enctype="multipart/form-data" accept-charset="utf8">
-                        <input type="file" name="f_data">
-                        <hr class=\"main_hr\">
-                        <input placeholder="''' + load_lang('name') + '''" name="f_name" type="text">
-                        <hr class=\"main_hr\">
-                        <input placeholder="''' + load_lang('license') + '''" name="f_lice" type="text">
-                        <hr class=\"main_hr\">
-                        ''' + captcha_get() + '''
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                    ''',
+                <a href="/file_filter">(''' + load_lang('file_filter_list') + ''')</a>
+                <hr class=\"main_hr\">
+                <form method="post" enctype="multipart/form-data" accept-charset="utf8">
+                    <input type="file" name="f_data">
+                    <hr class=\"main_hr\">
+                    <input placeholder="''' + load_lang('file_name') + '''" name="f_name" type="text">
+                    <hr class=\"main_hr\">
+                    <input placeholder="''' + load_lang('license') + '''" name="f_lice" type="text">
+                    <hr class=\"main_hr\">
+                    ''' + captcha_get() + '''
+                    <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                </form>
+            ''',
             menu = [['other', load_lang('return')]]
         ))  

+ 1 - 1
route/acl.py → route/give_acl.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def acl_2(conn, name):
+def give_acl_2(conn, name):
     curs = conn.cursor()
 
     check_ok = ''

+ 1 - 1
route/user_admin.py → route/give_admin.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def user_admin_2(conn, name):
+def give_admin_2(conn, name):
     curs = conn.cursor()
 
     owner = admin_check()

+ 1 - 1
route/admin_plus.py → route/give_admin_groups.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def admin_plus_2(conn, name):
+def give_admin_groups_2(conn, name):
     curs = conn.cursor()
     
     if flask.request.method == 'POST':

+ 1 - 1
route/history_hidden.py → route/give_history_hidden.py

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

+ 114 - 0
route/give_user_ban.py

@@ -0,0 +1,114 @@
+from .tool.func import *
+
+def give_user_ban_2(conn, name):
+    curs = conn.cursor()
+
+    if name and ip_or_user(name) == 0:
+        curs.execute("select acl from user where id = ?", [name])
+        user = curs.fetchall()
+        if not user:
+            return re_error('/error/2')
+
+        if user and user[0][0] != 'user':
+            if admin_check() != 1:
+                return re_error('/error/4')
+
+    if ban_check(ip = ip_check(), tool = 'login') == 1:
+        return re_error('/ban')
+                
+    if flask.request.method == 'POST':
+        name = name if name else flask.request.form.get('name', 'test')
+
+        if admin_check(1, 'ban' + ((' (' + name + ')') if name else '')) != 1:
+            return re_error('/error/3')
+
+        end = flask.request.form.get('second', '0')
+        end = end if end else '0'
+
+        if flask.request.form.get('regex', None):
+            type_d = 'regex'
+
+            try:
+                re.compile(name)
+            except:
+                return re_error('/error/23')
+        else:
+            type_d = None
+
+        ban_insert(
+            name, 
+            end, 
+            flask.request.form.get('why', ''), 
+            flask.request.form.get('login', ''), 
+            ip_check(),
+            type_d
+        )
+
+        return redirect('/block_log')     
+    else:
+        if admin_check(1) != 1:
+            return re_error('/error/3')
+
+        curs.execute("select end, why from ban where block = ?", [name])
+        end = curs.fetchall()
+        if end:
+            now = load_lang('release')
+
+            if end[0][0] == '':
+                data = '<ul><li>' + load_lang('limitless') + '</li>'
+            else:
+                data = '<ul><li>' + load_lang('period') + ' : ' + end[0][0] + '</li>'
+                
+            curs.execute("select block from ban where block = ? and login = 'O'", [name])
+            if curs.fetchall():
+                data += '<li>' + load_lang('login_able') + '</li>'
+
+            if end[0][1] != '':
+                data += '<li>' + load_lang('why') + ' : ' + end[0][1] + '</li></ul><hr class=\"main_hr\">'
+            else:
+                data += '</ul><hr class=\"main_hr\">'
+        else:
+            if name:
+                if name and re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name):
+                    b_now = load_lang('band_ban')
+                else:
+                    b_now = load_lang('ban')
+
+                now = ' (' + b_now + ')'
+                    
+                if name and ip_or_user(name) == 1:
+                    plus = '<input type="checkbox" name="login"> ' + load_lang('login_able') + '<hr class=\"main_hr\">'
+                else:
+                    plus = ''
+
+                name += '<hr class=\"main_hr\">'
+                regex = ''
+            else:
+                name = '<input placeholder="' + load_lang('name_or_ip_or_regex') + '" name="name" type="text"><hr class=\"main_hr\">'
+                regex = '<input type="checkbox" name="regex"> ' + load_lang('regex') + '<hr class=\"main_hr\">'
+                plus = '<input type="checkbox" name="login"> ' + load_lang('login_able') + '<hr class=\"main_hr\">'
+                now = 0
+                b_now = load_lang('ban')
+
+            data = name + '''
+                <input placeholder="''' + load_lang('ban_period') + ''' (''' + load_lang('second') + ''')" name="second" type="text">
+                <hr class=\"main_hr\">
+                ''' + regex + '''
+                <input placeholder="''' + load_lang('why') + '''" name="why" type="text">
+                <hr class=\"main_hr\">
+            ''' + plus
+
+        return easy_minify(flask.render_template(skin_check(), 
+            imp = [load_lang('ban'), wiki_set(), custom(), other2([now, 0])],
+            data = '''
+                <form method="post">
+                    ''' + data + '''
+                    <button type="submit">''' + b_now + '''</button>
+                </form>
+                <h2>''' + load_lang('explanation') + '''</h2>
+                <ul>
+                    <li>''' + load_lang('ban_explanation') + '''</li>
+                </ul>
+            ''',
+            menu = [['manager', load_lang('return')]]
+        ))   

+ 1 - 1
route/user_check.py → route/give_user_check.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def user_check_2(conn, name):
+def give_user_check_2(conn, name):
     curs = conn.cursor()
 
     curs.execute("select acl from user where id = ? or id = ?", [name, flask.request.args.get('plus', '-')])

+ 8 - 1
route/inter_wiki.py

@@ -35,13 +35,20 @@ def inter_wiki_2(conn, tools):
         div = ''
 
         curs.execute("select html from html_filter where kind = 'name'")
-    else:
+    elif tools == 'edit_filter':
         del_link = 'del_edit_filter'
         plus_link = 'manager/9'
         title = load_lang('edit_filter_list')
         div = ''
 
         curs.execute("select name from filter")
+    else:
+        del_link = 'del_file_filter'
+        plus_link = 'plus_file_filter'
+        title = load_lang('file_filter_list')
+        div = ''
+
+        curs.execute("select html from html_filter where kind = 'file'")
 
     db_data = curs.fetchall()
     if db_data:

+ 3 - 1
route/del_inter.py → route/inter_wiki_del.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def del_inter_2(conn, tools, name):
+def inter_wiki_del_2(conn, tools, name):
     curs = conn.cursor()
     
     if admin_check(None, tools) == 1:
@@ -10,6 +10,8 @@ def del_inter_2(conn, tools, name):
             curs.execute("delete from filter where name = ?", [name])
         elif tools == 'del_name_filter':
             curs.execute("delete from html_filter where html = ? and kind = 'name'", [name])
+        elif tools == 'del_file_filter':
+            curs.execute("delete from html_filter where html = ? and kind = 'file'", [name])
         else:
             curs.execute("delete from html_filter where html = ? and kind = 'email'", [name])
         

+ 43 - 17
route/plus_inter.py → route/inter_wiki_plus.py

@@ -1,11 +1,12 @@
 from .tool.func import *
 
-def plus_inter_2(conn, tools, name):
+def inter_wiki_plus_2(conn, tools, name):
     curs = conn.cursor()
     
     if flask.request.method == 'POST':
         if tools == 'plus_inter_wiki':
             curs.execute('insert into inter (title, link) values (?, ?)', [flask.request.form.get('title', None), flask.request.form.get('link', None)])
+            
             admin_check(None, 'inter_wiki_plus')
         elif tools == 'plus_edit_filter':
             if admin_check(1, 'edit_filter edit') != 1:
@@ -16,17 +17,38 @@ def plus_inter_2(conn, tools, name):
             else:
                 end = flask.request.form.get('second', 'X')
 
-            curs.execute("select name from filter where name = ?", [name])
-            if curs.fetchall():
-                curs.execute("update filter set regex = ?, sub = ? where name = ?", [flask.request.form.get('content', 'test'), end, name])
-            else:
-                curs.execute("insert into filter (name, regex, sub) values (?, ?, ?)", [name, flask.request.form.get('content', 'test'), end])
+            try:
+                re.compile(flask.request.form.get('content', 'test'))
+
+                curs.execute("select name from filter where name = ?", [name])
+                if curs.fetchall():
+                    curs.execute("update filter set regex = ?, sub = ? where name = ?", [flask.request.form.get('content', 'test'), end, name])
+                else:
+                    curs.execute("insert into filter (name, regex, sub) values (?, ?, ?)", [name, flask.request.form.get('content', 'test'), end])
+            except:
+                return re_error('/error/23')                
         else:
             if tools == '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 tools == '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'
             else:
                 admin_check(None, 'email_filter edit')
+                
                 type_d = 'email'
             
             curs.execute('insert into html_filter (html, kind) values (?, ?)', [flask.request.form.get('title', 'test'), type_d])
@@ -43,10 +65,10 @@ def plus_inter_2(conn, tools, name):
         if tools == 'plus_inter_wiki':
             title = load_lang('interwiki_add')
             form_data = '''
-                        <input placeholder="''' + load_lang('name') + '''" type="text" name="title">
-                        <hr class=\"main_hr\">
-                        <input placeholder="link" type="text" name="link">
-                        '''
+                <input placeholder="''' + load_lang('name') + '''" type="text" name="title">
+                <hr class=\"main_hr\">
+                <input placeholder="link" type="text" name="link">
+            '''
         elif tools == 'plus_edit_filter':
             curs.execute("select regex, sub from filter where name = ?", [name])
             exist = curs.fetchall()
@@ -66,19 +88,23 @@ def plus_inter_2(conn, tools, name):
 
             title = load_lang('edit_filter_add')
             form_data = '''
-                        <input placeholder="''' + load_lang('second') + '''" name="second" type="text" value="''' + html.escape(time_data) + '''">
-                        <hr class=\"main_hr\">
-                        <input ''' + stat + ''' type="checkbox" ''' + time_check + ''' name="limitless"> ''' + load_lang('limitless') + '''
-                        <hr class=\"main_hr\">
-                        <input ''' + stat + ''' placeholder="''' + load_lang('regex') + '''" name="content" value="''' + html.escape(textarea) + '''" type="text">
-                        '''
+                <input placeholder="''' + load_lang('second') + '''" name="second" type="text" value="''' + html.escape(time_data) + '''">
+                <hr class=\"main_hr\">
+                <input ''' + stat + ''' type="checkbox" ''' + time_check + ''' name="limitless"> ''' + load_lang('limitless') + '''
+                <hr class=\"main_hr\">
+                <input ''' + stat + ''' placeholder="''' + load_lang('regex') + '''" name="content" value="''' + html.escape(textarea) + '''" type="text">
+            '''
         elif tools == 'plus_name_filter':
             title = load_lang('id_filter_add')
-            form_data = '<input placeholder="' + load_lang('id') + ' ' + load_lang('regex') + '" type="text" name="title">'
+            form_data = '<input placeholder="' + load_lang('regex') + '" type="text" name="title">'
+        elif tools == 'plus_file_filter':
+            title = load_lang('file_filter_add')
+            form_data = '<input placeholder="' + load_lang('regex') + '" type="text" name="title">'
         else:
             title = load_lang('email_filter_add')
             form_data = '<input placeholder="email" type="text" name="title">'
 
+
         return easy_minify(flask.render_template(skin_check(), 
             imp = [title, wiki_set(), custom(), other2([0, 0])],
             data =  '''

+ 2 - 2
route/acl_list.py → route/list_acl.py

@@ -1,9 +1,9 @@
 from .tool.func import *
 
-def acl_list_2(conn):
+def list_acl_2(conn):
     curs = conn.cursor()
     
-    div =   '''
+    div = '''
         <table id="main_table_set">
             <tbody>
                 <tr>

+ 1 - 1
route/admin_list.py → route/list_admin.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def admin_list_2(conn):
+def list_admin_2(conn):
     curs = conn.cursor()
 
     div = '<ul>'

+ 1 - 1
route/admin_log.py → route/list_admin_use.py

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

+ 113 - 0
route/list_block.py

@@ -0,0 +1,113 @@
+from .tool.func import *
+
+def list_block_2(conn, name, tool):
+    curs = conn.cursor()
+
+    num = int(number_check(flask.request.args.get('num', '1')))
+    if num * 50 > 0:
+        sql_num = num * 50 - 50
+    else:
+        sql_num = 0
+    
+    div = '''
+        <table id="main_table_set">
+            <tbody>
+                <tr>
+                    <td id="main_table_width">''' + load_lang('blocked') + '''</td>
+                    <td id="main_table_width">''' + load_lang('admin') + '''</td>
+                    <td id="main_table_width">''' + load_lang('period') + '''</td>
+                </tr>
+    '''
+    
+    data_list = ''
+
+    curs.execute("delete from ban where (end < ? and end like '2%')", [get_time()])
+    conn.commit()
+    
+    if not name:        
+        if flask.request.args.get('type', '') == 'ongoing':
+            sub = ' (' + load_lang('in_progress') + ')'
+            menu = [['block_log', load_lang('normal')]]
+
+            curs.execute("select why, block, '', end, '', band from ban where ((end > ? and end like '2%') or end = '') order by end desc limit ?, '50'", [get_time(), str(sql_num)])
+        else:
+            sub = 0
+            menu = 0
+
+            div = '''
+                <a href="/manager/11">(''' + load_lang('blocked') + ''')</a> <a href="/manager/12">(''' + load_lang('admin') + ''')</a> <a href="?type=ongoing">(''' + load_lang('in_progress') + ''')</a>
+                <hr class=\"main_hr\">
+            ''' + div
+            
+            curs.execute("select why, block, blocker, end, today, band from rb order by today desc limit ?, '50'", [str(sql_num)])
+    else:
+        menu = [['block_log', load_lang('normal')]]
+        
+        if tool == 'block_user':
+            sub = ' (' + load_lang('blocked') + ')'
+            
+            curs.execute("select why, block, blocker, end, today, band from rb where block = ? order by today desc limit ?, '50'", [name, str(sql_num)])
+        else:
+            sub = ' (' + load_lang('admin') + ')'
+            
+            curs.execute("select why, block, blocker, end, today, band from rb where blocker = ? order by today desc limit ?, '50'", [name, str(sql_num)])
+
+    if data_list == '':
+        data_list = curs.fetchall()
+
+    for data in data_list:
+        why = html.escape(data[0])
+        if why == '':
+            why = '<br>'
+        
+        if data[5] == 'O':
+            ip = data[1] + ' (' + load_lang('range') + ')'
+        elif data[5] == 'regex':
+            ip = data[1] + ' (' + load_lang('regex') + ')'
+        else:
+            ip = ip_pas(data[1])
+
+        if data[3] == '':
+            end = load_lang('limitless')
+        elif data[3] == 'release':
+            end = load_lang('release')
+        else:
+            end = data[3]
+
+        if data[2] == '':
+            admin = ''
+        else:
+            admin = ip_pas(data[2])
+
+        if data[4] == '':
+            start = ''
+        else:
+            start = load_lang('start') + ' : ' + data[4]
+            
+        div += '''
+            <tr>
+                <td>''' + ip + '''</td>
+                <td>''' + admin + '''</td>
+                <td>
+                    ''' + start + '''
+                    <br>
+                    ''' + load_lang('end') + ' : ' + end + '''
+                </td>
+            </tr>
+            <tr>
+                <td colspan="3">''' + why + '''</td>
+            </tr>
+        '''
+
+    div += '</tbody></table>'
+    
+    if not name:
+        div += next_fix('/block_log?num=', num, data_list)
+    else:
+        div += next_fix('/' + url_pas(tool) + '/' + url_pas(name) + '?num=', num, data_list)
+                
+    return easy_minify(flask.render_template(skin_check(), 
+        imp = [load_lang('recent_ban'), wiki_set(), custom(), other2([sub, 0])],
+        data = div,
+        menu = menu
+    ))

+ 1 - 1
route/give_log.py → route/list_give.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def give_log_2(conn):
+def list_give_2(conn):
     curs = conn.cursor()
 
     list_data = '<ul>'

+ 1 - 1
route/not_close_topic.py → route/list_not_close_topic.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def not_close_topic_2(conn):
+def list_not_close_topic_2(conn):
     curs = conn.cursor()
 
     div = '<ul>'

+ 1 - 1
route/please.py → route/list_please.py

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

+ 1 - 1
route/title_index.py → route/list_title_index.py

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

+ 2 - 13
route/user_log.py → route/list_user.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def user_log_2(conn):
+def list_user_2(conn):
     curs = conn.cursor()
 
     num = int(number_check(flask.request.args.get('num', '1')))
@@ -33,18 +33,7 @@ def user_log_2(conn):
         list_data += '</li>'
 
     if num == 1:
-        curs.execute("select count(id) from user")
-        user_count = curs.fetchall()
-        if user_count:
-            count = user_count[0][0]
-        else:
-            count = 0
-
-        list_data +=    '''
-            </ul>
-            <hr class=\"main_hr\">
-            <ul>
-                <li>all : ''' + str(count) + '''</li>
+        list_data += '''
             </ul>
         '''
 

+ 1 - 1
route/user_topic_list.py → route/list_user_topic.py

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

+ 1 - 1
route/change_password.py → route/login_change_password.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def change_password_2(conn, server_init):
+def login_change_password_2(conn, server_init):
     curs = conn.cursor()
 
     support_language = server_init.server_set_var['language']['list']

+ 1 - 1
route/check_key.py → route/login_check_key.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def check_key_2(conn, tool):
+def login_check_key_2(conn, tool):
     curs = conn.cursor()
 
     if flask.request.method == 'POST':

+ 1 - 1
route/logout.py → route/login_logout.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def logout_2(conn):
+def login_logout_2(conn):
     curs = conn.cursor()
 
     flask.session.pop('state', None)

+ 1 - 1
route/need_email.py → route/login_need_email.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def need_email_2(conn, tool):
+def login_need_email_2(conn, tool):
     curs = conn.cursor()
 
     if flask.request.method == 'POST':

+ 1 - 1
route/register.py → route/login_register.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def register_2(conn):
+def login_register_2(conn):
     curs = conn.cursor()
 
     if ban_check() == 1:

+ 1 - 1
route/easter_egg.py → route/main_easter_egg.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def easter_egg_2(conn):
+def main_easter_egg_2(conn):
     curs = conn.cursor()
 
     return easy_minify(flask.render_template(skin_check(), 

+ 1 - 1
route/error_404.py → route/main_error_404.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def error_404_2(conn):
+def main_error_404_2(conn):
     curs = conn.cursor()
 
     return redirect('/w/' + url_pas(wiki_set(2)))

+ 1 - 1
route/image_view.py → route/main_image_view.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def image_view_2(conn, name, app_var):
+def main_image_view_2(conn, name, app_var):
     curs = conn.cursor()
     
     if os.path.exists(os.path.join(app_var['path_data_image'], name)):

+ 4 - 3
route/manager.py → route/main_manager.py

@@ -1,12 +1,12 @@
 from .tool.func import *
 
-def manager_2(conn, num):
+def main_manager_2(conn, num):
     curs = conn.cursor()
     
     title_list = {
         0 : [load_lang('document_name'), 'acl'], 
         1 : [0, 'check'], 
-        2 : [0, 'ban'], 
+        2 : [load_lang('file_name'), 'plus_file_filter'],
         3 : [0, 'admin'], 
         4 : [0, 'record'], 
         5 : [0, 'topic_record'], 
@@ -27,7 +27,7 @@ def manager_2(conn, num):
                     <h2>''' + load_lang('admin') + '''</h2>
                     <ul>
                         <li><a href="/manager/3">''' + load_lang('check_user') + '''</a></li>
-                        <li><a href="/manager/4">''' + load_lang('ban') + '''</a></li>
+                        <li><a href="/ban">''' + load_lang('ban') + '''</a></li>
                         <li><a href="/manager/5">''' + load_lang('authorize') + '''</a></li>
                         <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
                         <li><a href="/give_log">''' + load_lang('admin_group_list') + '''</a></li>
@@ -43,6 +43,7 @@ def manager_2(conn, num):
                         <li><a href="/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
                         <li><a href="/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
                         <li><a href="/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
+                        <li><a href="/file_filter">''' + load_lang('file_filter_list') + '''</a></li>
                     </ul>
                     <br>
                     <h2>''' + load_lang('server') + '''</h2>

+ 1 - 1
route/other.py → route/main_other.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def other_2(conn, r_ver):
+def main_other_2(conn, r_ver):
     curs = conn.cursor()
     
     return easy_minify(flask.render_template(skin_check(), 

+ 20 - 0
route/main_skin_set.py

@@ -0,0 +1,20 @@
+from .tool.func import *
+
+def main_skin_set_2(conn):
+    curs = conn.cursor()
+    
+    data = flask.make_response(re_error('/error/5'))
+
+    curs.execute("select data from other where name = 'language'")
+    main_data = curs.fetchall()
+
+    data.set_cookie('language', main_data[0][0])
+
+    curs.execute('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 - 1
route/views.py → route/main_views.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def views_2(conn, name):
+def main_views_2(conn, name):
     curs = conn.cursor()
 
     if re.search('\/', name):

+ 1 - 1
route/deep_search.py → route/search_deep.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def deep_search_2(conn, name):
+def search_deep_2(conn, name):
     curs = conn.cursor()
 
     if name == '':

+ 1 - 1
route/goto.py → route/search_goto.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def goto_2(conn):
+def search_goto_2(conn):
     curs = conn.cursor()
 
     curs.execute("select title from data where title = ?", [flask.request.form.get('search', 'test')])

+ 1 - 1
route/indexing.py → route/server_indexing.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def indexing_2(conn):
+def server_indexing_2(conn):
     curs = conn.cursor()
 
     if admin_check() != 1:

+ 25 - 20
route/now_update.py → route/server_now_update.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def now_update_2(conn):
+def server_now_update_2(conn):
     curs = conn.cursor()
 
     if admin_check() != 1:
@@ -16,9 +16,10 @@ def now_update_2(conn):
         else:
             up_data = 'stable'
 
-        if platform.system() == 'Linux':
-            print('Update')
+        print('----')
+        print('Update')
 
+        if platform.system() == 'Linux':
             ok = []
 
             ok += [os.system('git remote rm origin')]
@@ -27,19 +28,19 @@ def now_update_2(conn):
             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:
-            if platform.system() == 'Windows':
-                print('Update')
+            else:
+                print('Update error')
+        elif platform.system() == 'Windows':
+            urllib.request.urlretrieve('https://github.com/2DU/opennamu/archive/' + up_data + '.zip', 'update.zip')
+            zipfile.ZipFile('update.zip').extractall('')
+            ok = os.system('xcopy /y /r opennamu-' + up_data + ' .')
+            if ok == 0:
+                os.system('rd /s /q opennamu-' + up_data)
+                os.system('del update.zip')
 
-                urllib.request.urlretrieve('https://github.com/2DU/opennamu/archive/' + up_data + '.zip', 'update.zip')
-                zipfile.ZipFile('update.zip').extractall('')
-                ok = os.system('xcopy /y /r opennamu-' + up_data + ' .')
-                if ok == 0:
-                    print('Remove')
-                    os.system('rd /s /q opennamu-' + up_data)
-                    os.system('del update.zip')
-
-                    return redirect('/restart')
+                return redirect('/restart')
+            else:
+                print('Update error')
 
         return easy_minify(flask.render_template(skin_check(), 
             imp = [load_lang('update'), wiki_set(), custom(), other2([0, 0])],
@@ -49,11 +50,15 @@ def now_update_2(conn):
     else:
         return easy_minify(flask.render_template(skin_check(), 
             imp = [load_lang('update'), wiki_set(), custom(), other2([0, 0])],
-            data =  '''
-                    <form method="post">
-                        <button type="submit">''' + load_lang('update') + '''</button>
-                    </form>
-                    ''',
+            data = '''
+                ''' + load_lang('update_warring') + '''
+                <hr class=\"main_hr\">
+                <a href="https://github.com/2du/openNAMU/blob/master/app.py">(Master)</a> <a href="https://github.com/2du/openNAMU/blob/stable/app.py">(Stable)</a>
+                <hr class=\"main_hr\">
+                <form method="post">
+                    <button type="submit">''' + load_lang('update') + '''</button>
+                </form>
+            ''',
             menu = [['manager', load_lang('return')]]
         ))
 

+ 2 - 1
route/restart.py → route/server_restart.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def restart_2(conn):
+def server_restart_2(conn):
     curs = conn.cursor()
 
     if admin_check() != 1:
@@ -9,6 +9,7 @@ def restart_2(conn):
     if flask.request.method == 'POST':
         admin_check(None, 'restart')
 
+        print('----')
         print('Restart')
 
         os.execl(sys.executable, sys.executable, *sys.argv)

+ 42 - 57
route/setting.py

@@ -114,48 +114,39 @@ def setting_2(conn, num):
                 data =  '''
                         <form method="post">
                             <span>''' + load_lang('wiki_name') + '''</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('wiki_name') + '''" type="text" name="name" value="''' + html.escape(d_list[0]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="text" name="name" value="''' + html.escape(d_list[0]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('wiki_logo') + ''' (HTML)</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('wiki_logo') + '''" type="text" name="logo" value="''' + html.escape(d_list[1]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="text" name="logo" value="''' + html.escape(d_list[1]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('main_page') + '''</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('main_page') + '''" type="text" name="frontpage" value="''' + html.escape(d_list[2]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="text" name="frontpage" value="''' + html.escape(d_list[2]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('bottom_text') + ''' (HTML)</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('bottom_text') + '''" type="text" name="license" value="''' + html.escape(d_list[3]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="text" name="license" value="''' + html.escape(d_list[3]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('max_file_size') + ''' [MB]</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('max_file_size') + '''" type="text" name="upload" value="''' + html.escape(d_list[4]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="text" name="upload" value="''' + html.escape(d_list[4]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('backup_interval') + ' [' + load_lang('hour') + '''] (off : 0) {restart}</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('backup_interval') + '''" type="text" name="back_up" value="''' + html.escape(d_list[9]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="text" name="back_up" value="''' + html.escape(d_list[9]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('wiki_skin') + '''</span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <select name="skin">''' + div2 + '''</select>
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('default_acl') + '''</span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <select name="edit">''' + div + '''</select>
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('default_discussion_acl') + '''</span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <select name="discussion">''' + div4 + '''</select>
                             <hr class=\"main_hr\">
                             <input type="checkbox" name="reg" ''' + ch_1 + '''> ''' + load_lang('no_register') + '''
@@ -165,28 +156,23 @@ def setting_2(conn, num):
                             <input type="checkbox" name="email_have" ''' + ch_3 + '''> ''' + load_lang('email_required') + ''' {<a href="/setting/5">''' + load_lang('google_imap_required') + '''</a>}
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('wiki_host') + '''</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('wiki_host') + '''" type="text" name="host" value="''' + html.escape(d_list[16]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="text" name="host" value="''' + html.escape(d_list[16]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('wiki_port') + '''</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('wiki_port') + '''" type="text" name="port" value="''' + html.escape(d_list[10]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="text" name="port" value="''' + html.escape(d_list[10]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('wiki_secret_key') + '''</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('wiki_secret_key') + '''" type="password" name="key" value="''' + html.escape(d_list[11]) + '''">
+                            <hr class=\"main_hr\">
+                            <input type="password" name="key" value="''' + html.escape(d_list[11]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('update_branch') + '''</span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <select name="update">''' + div3 + '''</select>
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('encryption_method') + '''</span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <select name="encode">''' + div5 + '''</select>
                             <hr class=\"main_hr\">
                             <button id="save" type="submit">''' + load_lang('save') + '''</button>
@@ -195,17 +181,18 @@ def setting_2(conn, num):
                 menu = [['setting', load_lang('return')]]
             ))
     elif num == 2:
+        i_list = ['contract', 'no_login_warring', 'edit_bottom_text']
         if flask.request.method == 'POST':
-            curs.execute("update other set data = ? where name = ?", [flask.request.form.get('contract', ''), 'contract'])
-            curs.execute("update other set data = ? where name = ?", [flask.request.form.get('no_login_warring', ''), 'no_login_warring'])
+            for i in i_list:
+                curs.execute("update other set data = ? where name = ?", [flask.request.form.get(i, ''), i])
+
             conn.commit()
             
             admin_check(None, 'edit_set')
 
             return redirect('/setting/2')
         else:
-            i_list = ['contract', 'no_login_warring']
-            n_list = ['', '']
+            n_list = ['', '', '']
             d_list = []
             
             x = 0
@@ -228,15 +215,17 @@ def setting_2(conn, num):
                 imp = [load_lang('text_setting'), wiki_set(), custom(), other2([0, 0])],
                 data =  '''
                         <form method="post">
-                            <span>''' + load_lang('register_text') + '''</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('register_text') + '''" type="text" name="contract" value="''' + html.escape(d_list[0]) + '''">
+                            <span>''' + load_lang('register_text') + ''' (HTML)</span>
+                            <hr class=\"main_hr\">
+                            <input type="text" name="contract" value="''' + html.escape(d_list[0]) + '''">
+                            <hr class=\"main_hr\">
+                            <span>''' + load_lang('non_login_alert') + ''' (HTML)</span>
                             <hr class=\"main_hr\">
-                            <span>''' + load_lang('non_login_alert') + '''</span>
-                            <br>
-                            <br>
-                            <input placeholder="''' + load_lang('non_login_alert') + '''" type="text" name="no_login_warring" value="''' + html.escape(d_list[1]) + '''">
+                            <input type="text" name="no_login_warring" value="''' + html.escape(d_list[1]) + '''">
+                            <hr class=\"main_hr\">
+                            <span>''' + load_lang('edit_bottom_text') + ''' (HTML)</span>
+                            <hr class=\"main_hr\">
+                            <input type="text" name="edit_bottom_text" value="''' + html.escape(d_list[2]) + '''">
                             <hr class=\"main_hr\">
                             <button id="save" type="submit">''' + load_lang('save') + '''</button>
                         </form>
@@ -393,24 +382,20 @@ def setting_2(conn, num):
                         <form method="post">
                             <h2><a href="https://www.google.com/recaptcha/admin">recaptcha</a></h2>
                             <span>''' + load_lang('recaptcha') + ''' (HTML)</span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <input placeholder="''' + load_lang('recaptcha') + ''' (HTML)" type="text" name="recaptcha" value="''' + html.escape(d_list[0]) + '''">
                             <hr class=\"main_hr\">
                             <span>''' + load_lang('recaptcha') + ' (' + load_lang('secret_key') + ''')</span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <input placeholder="''' + load_lang('recaptcha') + ' (' + load_lang('secret_key') + ''')" type="text" name="sec_re" value="''' + html.escape(d_list[1]) + '''">
                             <hr class=\"main_hr\">
                             <h2><a href="https://support.google.com/mail/answer/7126229">''' + load_lang('google_imap') + '</a> {' + load_lang('restart_required') + '''}</h1>
                             <span>''' + load_lang('google_email') + '''</span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <input placeholder="''' + load_lang('google_email') + '''" type="text" name="g_email" value="''' + html.escape(d_list[2]) + '''">
                             <hr class=\"main_hr\">
                             <span><a href="https://security.google.com/settings/security/apppasswords">''' + load_lang('google_app_password') + '''</a></span>
-                            <br>
-                            <br>
+                            <hr class=\"main_hr\">
                             <input placeholder="''' + load_lang('google_app_password') + '''" type="password" name="g_pass" value="''' + html.escape(d_list[3]) + '''">
                             <hr class=\"main_hr\">
                             <button id="save" type="submit">''' + load_lang('save') + '''</button>

+ 1 - 1
route/adsense_setting.py → route/setting_adsense.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def adsense_setting_2(conn):
+def setting_adsense_setting_2(conn):
     curs = conn.cursor()
 
     if admin_check(None, 'adsense setting') != 1:

+ 1 - 1
route/oauth_setting.py → route/setting_oauth.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def oauth_setting_2(conn):
+def setting_oauth_setting_2(conn):
     curs = conn.cursor()
 
     if admin_check(None, 'oauth setting') != 1:

+ 104 - 62
route/tool/func.py

@@ -41,21 +41,23 @@ for i in range(0, 2):
     except ImportError as e:
         if i == 0:
             if platform.system() == 'Linux':
-                ok = os.system('python3 -m pip install -r requirements.txt')
+                ok = os.system('python3 -m pip install --user -r requirements.txt')
                 if ok == 0:
                     os.execl(sys.executable, sys.executable, *sys.argv)
                 else:
                     raise
             elif platform.system() == 'Windows':
-                ok = os.system('python -m pip install -r requirements.txt')
+                ok = os.system('python -m pip install --user -r requirements.txt')
                 if ok == 0:
                     os.execl(sys.executable, sys.executable, *sys.argv)
                 else:
                     raise
             else:
+                print('----')
                 print(e)
                 raise
         else:
+            print('----')
             print(e)
             raise
 
@@ -93,7 +95,8 @@ def send_email(who, title, data):
 
         smtp.quit()
     except:
-        print('Error : Email login error')
+        print('----')
+        print('Error : Email send error')
 
 def last_change(data):
     json_address = re.sub("(((?!\.|\/).)+)\.html$", "set.json", skin_check())
@@ -413,25 +416,24 @@ def next_fix(link, num, page, end = 50):
     return list_data
 
 def other2(data):
+    req_list = ''
+    for i_data in os.listdir(os.path.join("views", "main_css", "css")):
+        req_list += '<link rel="stylesheet" href="/views/main_css/css/' + i_data + '">'
+    
+    for i_data in os.listdir(os.path.join("views", "main_css", "js")):
+        req_list += '<script src="/views/main_css/js/' + i_data + '"></script>'
+
     data += ['', '''
-        <link rel="stylesheet" href="/views/main_css/css/main.css">
-        <link rel="stylesheet" href="/views/main_css/css/oauth.css">
         <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
         <link   rel="stylesheet"
                 href="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.css"
                 integrity="sha384-dbVIfZGuN1Yq7/1Ocstc1lUEm+AT+/rCkibIcC/OmWo5f0EA48Vf8CytHzGrSwbQ"
                 crossorigin="anonymous">
-        <script src="/views/main_css/js/open_foot.js"></script>
-        <script src="/views/main_css/js/folding.js"></script>
-        <script src="/views/main_css/js/topic_load.js"></script>
-        <script src="/views/main_css/js/do_preview.js"></script>
-        <script src="/views/main_css/js/load_ver.js"></script>
-        <script src="/views/main_css/js/insert_data.js"></script>
         <script src="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.js"
                 integrity="sha384-2BKqo+exmr9su6dir+qCw08N2ZKRucY4PrGQPPWU1A7FtlCGjmEGFqXCv5nyM5Ij"
                 crossorigin="anonymous"></script>
         <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
-    ''']
+    ''' + req_list]
 
     return data
 
@@ -617,8 +619,9 @@ def custom():
     else:
         user_head = ''
 
-    if 'state' in flask.session and flask.session['state'] == 1:
-        curs.execute('select name from alarm where name = ? limit 1', [ip_check()])
+    ip = ip_check()
+    if ip_or_user(ip) == 0:
+        curs.execute('select name from alarm where name = ? limit 1', [ip])
         if curs.fetchall():
             user_icon = 2
         else:
@@ -627,7 +630,7 @@ def custom():
         user_icon = 0
 
     if user_icon != 0:
-        curs.execute('select data from user_set where name = "email" and id = ?', [ip_check()])
+        curs.execute('select data from user_set where name = "email" and id = ?', [ip])
         data = curs.fetchall()
         if data:
             email = data[0][0]
@@ -637,7 +640,7 @@ def custom():
         email = ''
 
     if user_icon != 0:
-        user_name = ip_check()
+        user_name = ip
     else:
         user_name = load_lang('user')
 
@@ -828,20 +831,38 @@ def ban_check(ip = None, tool = None):
         band_it = band.groups()[0]
     else:
         band_it = '-'
+
+    curs.execute("delete from ban where (end < ? and end like '2%')", [get_time()])
+    conn.commit()
+
+    curs.execute("select login, block from ban where ((end > ? and end like '2%') or end = '') and band = 'regex'", [get_time()])
+    regex_d = curs.fetchall()
+    for test_r in regex_d:
+        g_regex = re.compile(test_r[1])
+        if g_regex.search(ip):
+            if tool and tool == 'login':
+                if test_r[0] != 'O':
+                    return 1
+            else:
+                return 1
     
-    curs.execute("select end, login from ban where block = ?", [band_it])
+    curs.execute("select login from ban where ((end > ? and end like '2%') or end = '') and block = ? and band = 'O'", [get_time(), band_it])
     band_d = curs.fetchall()
-    
-    curs.execute("select end, login from ban where block = ?", [ip])
+    if band_d:
+        if tool and tool == 'login':
+            if data[0][0] != 'O':
+                return 1
+        else:
+            return 1
+
+    curs.execute("select login from ban where ((end > ? and end like '2%') or end = '') and block = ? and band = ''", [get_time(), ip])
     ban_d = curs.fetchall()
-    
-    data = band_d or ban_d
-    if data and (data[0][0] == '' or data[0][0] > get_time()):
-        if tool and tool == 'login':                    
-            if data[0][1] == 'O':
-                return 0
-                
-        return 1
+    if ban_d:
+        if tool and tool == 'login':
+            if data[0][0] != 'O':
+                return 1
+        else:
+            return 1
 
     return 0
         
@@ -901,25 +922,30 @@ def topic_check(name, sub):
 
     return 0
 
-def ban_insert(name, end, why, login, blocker):
+def ban_insert(name, end, why, login, blocker, type_d = None):
     now_time = get_time()
 
-    if re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name):
-        band = 'O'
+    if type_d:
+        band = type_d
     else:
-        band = ''
+        if re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name):
+            band = 'O'
+        else:
+            band = ''
 
-    curs.execute("select block from ban where block = ?", [name])
+    curs.execute("delete from ban where (end < ? and end like '2%')", [get_time()])
+
+    curs.execute("select block from ban where ((end > ? and end like '2%') or end = '') and block = ? and band = ?", [name, band])
     if curs.fetchall():
         curs.execute("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)", [
             name, 
-            load_lang('release', 1),
+            'release',
             now_time, 
             blocker, 
             '', 
             band
         ])
-        curs.execute("delete from ban where block = ?", [name])
+        curs.execute("delete from ban where block = ? and band = ?", [name, band])
     else:
         if login != '':
             login = 'O'
@@ -1018,35 +1044,49 @@ def re_error(data):
         end = '<li>' + load_lang('why') + ' : ' + load_lang('authority_error') + '</li>'
 
         if ban_check() == 1:
-            curs.execute("select end, why from ban where block = ?", [ip])
-            end_data = curs.fetchall()
-            if not end_data:
-                match = re.search("^([0-9]{1,3}\.[0-9]{1,3})", ip)
-                if match:
-                    curs.execute("select end, why from ban where block = ?", [match.groups()[0]])
-                    end_data = curs.fetchall()
-            
-            if end_data:
-                end = '<li>' + load_lang('state') + ' : ' + load_lang('ban') + '</li><li>'
+            end = '<li>' + load_lang('state') + ' : ' + load_lang('ban') + '</li>'
+            ok_sign = 1
 
-                if end_data[0][0]:
-                    now = int(re.sub('(\-| |:)', '', get_time()))
-                    day = int(re.sub('(\-| |:)', '', end_data[0][0]))
-                    
-                    if now >= day:
-                        curs.execute("delete from ban where block = ?", [ip])
-                        conn.commit()
-
-                        end += '<script>location.reload();</script>'
-                    else:
-                        end += 'end : ' + end_data[0][0]
-                else:
-                    end += load_lang('limitless')
-                
-                end += '</li>'
-
-                if end_data[0][1] != '':
-                    end += '<li>' + load_lang('why') + ' : ' + end_data[0][1] + '</li>'
+            band = re.search("^([0-9]{1,3}\.[0-9]{1,3})", ip)
+            if band:
+                band_it = band.groups()[0]
+            else:
+                band_it = '-'
+
+            curs.execute("delete from ban where (end < ? and end like '2%')", [get_time()])
+            conn.commit()
+
+            curs.execute("select login, block, end from ban where ((end > ? and end like '2%') or end = '') and band = 'regex'", [get_time()])
+            regex_d = curs.fetchall()
+            for test_r in regex_d:
+                g_regex = re.compile(test_r[1])
+                if g_regex.search(ip):
+                    end += '<li>' + load_lang('type') + ' : regex ban</li>'
+                    end += '<li>' + load_lang('end') + ' : ' + test_r[2] + '</li>'
+                    if test_r[0] != 'O':
+                        end += '<li>' + load_lang('login_able') + ' (' + load_lang('not_sure') + ')</li>'
+
+                    end += '<hr class=\"main_hr\">'
+            
+            curs.execute("select login, end from ban where ((end > ? and end like '2%') or end = '') and block = ?", [get_time(), band_it])
+            band_d = curs.fetchall()
+            if band_d:
+                end += '<li>' + load_lang('type') + ' : band ban</li>'
+                end += '<li>' + load_lang('end') + ' : ' + band_d[0][1] + '</li>'
+                if data[0][0] != 'O':
+                    end += '<li>' + load_lang('login_able') + ' (' + load_lang('not_sure') + ')</li>'
+
+                end += '<hr class=\"main_hr\">'
+
+            curs.execute("select login, end from ban where ((end > ? and end like '2%') or end = '') and block = ?", [get_time(), ip])
+            ban_d = curs.fetchall()
+            if ban_d:
+                end += '<li>' + load_lang('type') + ' : ban</li>'
+                end += '<li>' + load_lang('end') + ' : ' + ban_d[0][1] + '</li>'
+                if data[0][0] != 'O':
+                    end += '<li>' + load_lang('login_able') + ' (' + load_lang('not_sure') + ')</li>'
+
+                end += '<hr class=\"main_hr\">'
 
         return easy_minify(flask.render_template(skin_check(), 
             imp = [load_lang('error'), wiki_set(1), custom(), other2([0, 0])],
@@ -1097,6 +1137,8 @@ def re_error(data):
                 data = load_lang('edit_filter_error')
             elif num == 22:
                 data = load_lang('file_name_error')
+            elif num == 23:
+                data = load_lang('regex_error')
             else:
                 data = '???'
 

+ 5 - 5
route/tool/init.py

@@ -1,11 +1,11 @@
 import os
 
 env_dict = {
-    'host'      : os.getenv('NAMU_HOST'),
-    'port'      : os.getenv('NAMU_PORT'),
-    'language'  : os.getenv('NAMU_LANG'),
-    'markup'    : os.getenv('NAMU_MARKUP'),
-    'encode'    : os.getenv('NAMU_ENCRYPT')
+    'host' : os.getenv('NAMU_HOST'),
+    'port' : os.getenv('NAMU_PORT'),
+    'language' : os.getenv('NAMU_LANG'),
+    'markup' : os.getenv('NAMU_MARKUP'),
+    'encode' : os.getenv('NAMU_ENCRYPT')
 }
 
 server_set_var = {

+ 1 - 1
route/tool/set_mark/namu.py

@@ -552,7 +552,7 @@ def namu(conn, data, title, main_num):
     toc_top_stack = 6
     toc_stack = [0, 0, 0, 0, 0, 0]
     edit_number = 0
-    toc_data = '<div id="toc"><span style="font-size: 18px;">toc</span>\n\n'
+    toc_data = '<div id="toc"><span id="toc_title">TOC</span>\n\n'
     while 1:
         toc = re.search('\n(={1,6}) ?((?:(?!\n).)+) ?\n', data)
         if toc:

+ 32 - 33
route/topic.py

@@ -32,7 +32,29 @@ def topic_2(conn, name, sub):
 
         match = re.search('^user:([^/]+)', name)
         if match:
-            curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [match.groups()[0], ip + ' - <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '">' + load_lang('user_discussion', 1) + '</a>', today])
+            y_check = 0
+            if ip_or_user(match.groups()[0]) == 1:
+                curs.execute("select ip from history where ip = ? limit 1", [match.groups()[0]])
+                u_data = curs.fetchall()
+                if u_data:
+                    y_check = 1
+                else:
+                    curs.execute("select ip from topic where ip = ? limit 1", [match.groups()[0]])
+                    u_data = curs.fetchall()
+                    if u_data:
+                        y_check = 1
+            else:
+                curs.execute("select id from user where id = ?", [match.groups()[0]])
+                u_data = curs.fetchall()
+                if u_data:
+                    y_check = 1
+
+            if y_check == 1:
+                curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [
+                    match.groups()[0], 
+                    ip + ' - <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '">' + load_lang('user_discussion', 1) + '</a>', 
+                    today
+                ])
         
         cate_re = re.compile('\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
         data = cate_re.sub('[br]', flask.request.form.get('content', 'Test'))
@@ -65,25 +87,6 @@ def topic_2(conn, name, sub):
         data = ''
         number = 1
         
-        if admin == 1 and topic_exist:
-            if close_data:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/close">(' + load_lang('open') + ')</a> '
-            else:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/close">(' + load_lang('close') + ')</a> '
-            
-            if stop_data:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/stop">(' + load_lang('restart') + ')</a> '
-            else:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/stop">(' + load_lang('stop') + ')</a> '
-
-            curs.execute("select title from rd where title = ? and sub = ? and agree = 'O'", [name, sub])
-            if curs.fetchall():
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/agree">(' + load_lang('destruction') + ')</a>'
-            else:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/agree">(' + load_lang('agreement') + ')</a>'
-            
-            all_data += '<hr class=\"main_hr\">'
-        
         if (close_data or stop_data) and admin != 1:
             display = 'display: none;'
         
@@ -114,7 +117,7 @@ def topic_2(conn, name, sub):
                         </tr>
                     </tbody>
                 </table>
-                <br>
+                <hr class=\"main_hr\">
             '''    
 
         for topic_data in topic:
@@ -174,25 +177,21 @@ def topic_2(conn, name, sub):
                         </tr>
                     </tbody>
                 </table>
-                <br>
+                <hr class=\"main_hr\">
             '''
+
             number += 1
 
         if ban != 1 or admin == 1:
             data += '''
                 <div id="plus"></div>
-                <script>topic_load("''' + name + '''", "''' + sub + '''");</script>
-                <a id="reload" href="javascript:void(0);" onclick="location.href.endsWith(\'#reload\')? location.reload(true):location.href=\'#reload\'">(''' + load_lang('reload') + ''')</a>
-                <form style="''' + display + '''" method="post">
-                <br>
-                <textarea style="height: 100px;" name="content"></textarea>
+                <script>topic_load("''' + name + '''", "''' + sub + '''", "''' + str(number) + '''");</script>
+                <a id="reload" href="javascript:void(0);" onclick="reload();">(''' + load_lang('reload') + ''')</a> <a href="/topic/''' + url_pas(name) + '''/sub/''' + url_pas(sub) + '''/tool">(''' + load_lang('topic_tool') + ''')</a>
                 <hr class=\"main_hr\">
-            ''' + captcha_get()
-            
-            if display == '':
-                data += ip_warring()
-
-            data += '''
+                <form style="''' + display + '''" method="post">
+                    <textarea style="height: 100px;" name="content"></textarea>
+                    <hr class=\"main_hr\">
+                    ''' + captcha_get() + (ip_warring() if display == '' else '') + '''
                     <button type="submit">''' + load_lang('send') + '''</button>
                 </form>
             '''

+ 5 - 5
route/topic_admin.py

@@ -12,11 +12,11 @@ def topic_admin_2(conn, name, sub, num):
 
     if admin_check(3) == 1:
         ban +=  '''
-                </ul>
-                <br>
-                <h2>''' + load_lang('admin_tool') + '''</h2>
-                <ul>
-                '''
+            </ul>
+            <br>
+            <h2>''' + load_lang('admin_tool') + '''</h2>
+            <ul>
+        '''
         is_ban = '<li><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/b/' + str(num) + '">'
 
         if data[0][0] == 'O':

+ 1 - 1
route/close_topic_list.py → route/topic_close_list.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def close_topic_list_2(conn, name, tool):
+def topic_close_list_2(conn, name, tool):
     curs = conn.cursor()
     
     div = ''

+ 53 - 44
route/topic_stop.py

@@ -3,53 +3,62 @@ from .tool.func import *
 def topic_stop_2(conn, name, sub, tool):
     curs = conn.cursor()
 
-    if tool == 'close':
-        set_list = [
-            'O', 
-            'S', 
-            load_lang('close', 1), 
-            load_lang('open', 1)
-        ]
-    elif tool == 'stop':
-        set_list = [
-            '', 
-            'O', 
-            load_lang('stop', 1), 
-            load_lang('restart', 1)
-        ]
-    elif tool == 'agree':
-        pass
-    else:
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))
-
     if admin_check(3, 'topic ' + tool + ' (' + name + ' - ' + sub + ')') != 1:
         return re_error('/error/3')
 
     ip = ip_check()
     time = get_time()
-    
-    curs.execute("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1", [name, sub])
-    topic_check = curs.fetchall()
-    if topic_check:
-        if tool == 'agree':
-            curs.execute("select title from rd where title = ? and sub = ? and agree = 'O'", [name, sub])
-            if curs.fetchall():
-                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, '" + load_lang('agreement', 1) + " X', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip])
-                curs.execute("update rd set agree = '' where title = ? and sub = ?", [name, sub])
-            else:
-                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, '" + load_lang('agreement', 1) + " O', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip])
-                curs.execute("update rd set agree = 'O' where title = ? and sub = ?", [name, sub])
-        else:
-            curs.execute("select title from rd where title = ? and sub = ? and stop = ?", [name, sub, set_list[0]])
-            if curs.fetchall():
-                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[3], time, ip])
-                curs.execute("update rd set stop = '' where title = ? and sub = ?", [name, sub])
+
+    if flask.request.method == 'POST' or tool == 'agree' or tool == 'stop':
+        curs.execute("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1", [name, sub])
+        topic_check = curs.fetchall()
+        if topic_check:
+            if tool == 'agree':
+                curs.execute("select title from rd where title = ? and sub = ? and agree = 'O'", [name, sub])
+                if curs.fetchall():
+                    curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, 'ok', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip])
+                    curs.execute("update rd set agree = '' where title = ? and sub = ?", [name, sub])
+                else:
+                    curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, 'break', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip])
+                    curs.execute("update rd set agree = 'O' where title = ? and sub = ?", [name, sub])
             else:
-                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[2], time, ip])
-                curs.execute("update rd set stop = ? where title = ? and sub = ?", [set_list[0], name, sub])
-        
-        rd_plus(name, sub, time)
-        
-        conn.commit()
-        
-    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))    
+                if tool == 'close':
+                    why = flask.request.form.get('why', '')
+                    set_list = [
+                        'O', 
+                        'S', 
+                        'close' + (('[br][br]why : ' + why) if why else ''), 
+                        'open' + (('[br][br]why : ' + why) if why else '')
+                    ]
+                elif tool == 'stop':
+                    set_list = ['', 'O', 'stop', 'restart']
+                else:
+                    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))
+
+                curs.execute("select title from rd where title = ? and sub = ? and stop = ?", [name, sub, set_list[0]])
+                if curs.fetchall():
+                    curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[3], time, ip])
+                    curs.execute("update rd set stop = '' where title = ? and sub = ?", [name, sub])
+                else:
+                    curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[2], time, ip])
+                    curs.execute("update rd set stop = ? where title = ? and sub = ?", [set_list[0], name, sub])
+            
+            rd_plus(name, sub, time)
+            
+            conn.commit()
+
+        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))    
+    else:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [name, wiki_set(), custom(), other2([' (' + tool + ')', 0])],
+            data = '''
+                <span>''' + load_lang('markup_enabled') + '''</span>
+                <hr class=\"main_hr\">
+                <form method="post">
+                    <input placeholder="''' + load_lang('why') + '''" name="why" type="text">
+                    <hr class=\"main_hr\">
+                    <button type="submit">''' + load_lang('save') + '''</button>
+                </form>
+            ''',
+            menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub), load_lang('return')]]
+        ))

+ 46 - 0
route/topic_tool.py

@@ -0,0 +1,46 @@
+from .tool.func import *
+
+def topic_tool_2(conn, name, sub):
+    curs = conn.cursor()
+    
+    curs.execute("select id from topic where title = ? and sub = ? limit 1", [name, sub])
+    topic_exist = curs.fetchall()
+    if not topic_exist:
+        return re_error('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))
+
+    all_data = ''
+
+    if admin_check(3) == 1:
+        all_data = '<h2>' + load_lang('topic_state') + '</h2><ul><li><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/close">'
+
+        curs.execute("select title from rd where title = ? and sub = ? and stop = 'O'", [name, sub])
+        if curs.fetchall():
+            all_data += load_lang('topic_open')
+        else:
+            all_data += load_lang('topic_close')
+        
+        all_data += '</a></li><li><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/stop">'
+
+        curs.execute("select title from rd where title = ? and sub = ? and stop = 'S'", [name, sub])
+        if curs.fetchall():
+            all_data += load_lang('topic_restart')
+        else:
+            all_data += load_lang('topic_stop')
+            
+        all_data += '</a></li><li><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/agree">'
+        
+        curs.execute("select title from rd where title = ? and sub = ? and agree = 'O'", [name, sub])
+        if curs.fetchall():
+            all_data += load_lang('topic_destruction')
+        else:
+            all_data += load_lang('topic_agreement')
+        
+        all_data += '</a></li></ul>'
+
+    all_data += '<h2>' + load_lang('tool') + '</h2><ul><li><a id="reload" href="javascript:void(0);" onclick="req_alarm();">' + load_lang('use_push_alarm') + '</a></li></ul>'
+
+    return easy_minify(flask.render_template(skin_check(), 
+        imp = [name, wiki_set(), custom(), other2([' (' + load_lang('topic_tool') + ')', 0])],
+        data = all_data,
+        menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub), load_lang('return')]]
+    ))

+ 0 - 82
route/user_ban.py

@@ -1,82 +0,0 @@
-from .tool.func import *
-
-def user_ban_2(conn, name):
-    curs = conn.cursor()
-
-    if ip_or_user(name) == 0:
-        curs.execute("select acl from user where id = ?", [name])
-        user = curs.fetchall()
-        if not user:
-            return re_error('/error/2')
-
-        if user and user[0][0] != 'user':
-            if admin_check() != 1:
-                return re_error('/error/4')
-
-    if ban_check(ip = ip_check(), tool = 'login') == 1:
-        return re_error('/ban')
-                
-    if flask.request.method == 'POST':
-        if admin_check(1, 'ban (' + name + ')') != 1:
-            return re_error('/error/3')
-
-        if flask.request.form.get('limitless', '') == '':
-            end = flask.request.form.get('second', '0')
-        else:
-            end = '0'
-
-        ban_insert(name, end, flask.request.form.get('why', ''), flask.request.form.get('login', ''), ip_check())
-
-        return redirect('/ban/' + url_pas(name))     
-    else:
-        if admin_check(1) != 1:
-            return re_error('/error/3')
-
-        curs.execute("select end, why from ban where block = ?", [name])
-        end = curs.fetchall()
-        if end:
-            now = load_lang('release')
-
-            if end[0][0] == '':
-                data = '<ul><li>' + load_lang('limitless') + '</li>'
-            else:
-                data = '<ul><li>' + load_lang('period') + ' : ' + end[0][0] + '</li>'
-                
-            curs.execute("select block from ban where block = ? and login = 'O'", [name])
-            if curs.fetchall():
-                data += '<li>' + load_lang('login_able') + '</li>'
-
-            if end[0][1] != '':
-                data += '<li>' + load_lang('why') + ' : ' + end[0][1] + '</li></ul><hr class=\"main_hr\">'
-            else:
-                data += '</ul><hr class=\"main_hr\">'
-        else:
-            if re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name):
-                now = load_lang('band_ban')
-            else:
-                now = load_lang('ban')
-                
-            if ip_or_user(name) == 1:
-                plus = '<input type="checkbox" name="login"> ' + load_lang('login_able') + '<hr class=\"main_hr\">'
-            else:
-                plus = ''
-
-            data =  '''
-                    <input placeholder="''' + load_lang('second') + '''" name="second" type="text">
-                    <hr class=\"main_hr\">
-                    <input type="checkbox" name="limitless"> ''' + load_lang('limitless') + '''
-                    <hr class=\"main_hr\">
-                    <input placeholder="''' + load_lang('why') + '''" name="why" type="text">
-                    <hr class=\"main_hr\">
-                    ''' + plus
-
-        return easy_minify(flask.render_template(skin_check(), 
-            imp = [name, wiki_set(), custom(), other2([' (' + now + ')', 0])],
-            data =  '''
-                    <form method="post">
-                        ''' + data + '''
-                        <button type="submit">''' + now + '''</button>
-                    </form>
-                    ''',
-            menu = [['manager', load_lang('return')]]
-        ))   

+ 1 - 1
route/count_edit.py → route/user_count_edit.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def count_edit_2(conn, name):
+def user_count_edit_2(conn, name):
     curs = conn.cursor()
 
     if name == None:

+ 1 - 1
route/custom_head_view.py → route/user_custom_head_view.py

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

+ 41 - 42
route/user_info.py

@@ -37,31 +37,30 @@ def user_info_2(conn):
 
             if block_data[0][2] == 'O':
                 acl += ' (' + load_lang('band_blocked') + ')'
-            
+
+    curs.execute('select name from alarm where name = ? limit 1', [ip_check()])
+    if curs.fetchall():
+        plus2 = '<li><a href="/alarm">' + load_lang('alarm') + ' (O)</a></li>'
+    else:
+        plus2 = '<li><a href="/alarm">' + load_lang('alarm') + '</a></li>'
+
     if custom()[2] != 0:
         ip_user = '<a href="/w/user:' + ip + '">' + ip + '</a>'
         
-        plus =  '''
-                <li><a href="/logout">''' + load_lang('logout') + '''</a></li>
-                <li><a href="/change">''' + load_lang('user_setting') + '''</a></li>
-                '''
-        
-        curs.execute('select name from alarm where name = ? limit 1', [ip_check()])
-        if curs.fetchall():
-            plus2 = '<li><a href="/alarm">' + load_lang('alarm') + ' (O)</a></li>'
-        else:
-            plus2 = '<li><a href="/alarm">' + load_lang('alarm') + '</a></li>'
+        plus = '''
+            <li><a href="/logout">''' + load_lang('logout') + '''</a></li>
+            <li><a href="/change">''' + load_lang('user_setting') + '''</a></li>
+        '''
 
         plus2 += '<li><a href="/watch_list">' + load_lang('watchlist') + '</a></li>'
         plus3 = '<li><a href="/acl/user:' + url_pas(ip) + '">' + load_lang('user_document_acl') + '</a></li>'
     else:
         ip_user = ip
         
-        plus =  '''
-                <li><a href="/login">''' + load_lang('login') + '''</a></li>
-                <li><a href="/register">''' + load_lang('register') + '''</a></li>
-                '''
-        plus2 = ''
+        plus = '''
+            <li><a href="/login">''' + load_lang('login') + '''</a></li>
+            <li><a href="/register">''' + load_lang('register') + '''</a></li>
+        '''
         plus3 = ''
 
         curs.execute("select data from other where name = 'email_have'")
@@ -71,31 +70,31 @@ def user_info_2(conn):
 
     return easy_minify(flask.render_template(skin_check(), 
         imp = [load_lang('user') + ' ' + load_lang('tool'), wiki_set(), custom(), other2([0, 0])],
-        data =  '''
-                <h2>''' + load_lang('state') + '''</h2>
-                <ul>
-                    <li>''' + ip_user + ''' <a href="/record/''' + url_pas(ip) + '''">(''' + load_lang('record') + ''')</a></li>
-                    <li>''' + load_lang('state') + ''' : ''' + acl + '''</li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('login') + '''</h2>
-                <ul>
-                    ''' + plus + '''
-                </ul>
-                <br>
-                <h2>''' + load_lang('tool') + '''</h2>
-                <ul>
-                    ''' + plus3 + '''
-                    <li><a href="/custom_head">''' + load_lang('user_head') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('other') + '''</h2>
-                <ul>
-                ''' + plus2 + '''
-                <li>
-                    <a href="/count">''' + load_lang('count') + '''</a>
-                </li>
-                </ul>
-                ''',
+        data = '''
+            <h2>''' + load_lang('state') + '''</h2>
+            <ul>
+                <li>''' + ip_user + ''' <a href="/record/''' + url_pas(ip) + '''">(''' + load_lang('record') + ''')</a></li>
+                <li>''' + load_lang('state') + ''' : ''' + acl + '''</li>
+            </ul>
+            <br>
+            <h2>''' + load_lang('login') + '''</h2>
+            <ul>
+                ''' + plus + '''
+            </ul>
+            <br>
+            <h2>''' + load_lang('tool') + '''</h2>
+            <ul>
+                ''' + plus3 + '''
+                <li><a href="/custom_head">''' + load_lang('user_head') + '''</a></li>
+            </ul>
+            <br>
+            <h2>''' + load_lang('other') + '''</h2>
+            <ul>
+            ''' + plus2 + '''
+            <li>
+                <a href="/count">''' + load_lang('count') + '''</a>
+            </li>
+            </ul>
+        ''',
         menu = 0
     ))

+ 13 - 12
route/user_tool.py

@@ -3,12 +3,13 @@ from .tool.func import *
 def user_tool_2(conn, name):
     curs = conn.cursor()
     
-    data =  '''
-            <h2>''' + load_lang('tool') + '''</h2>
-            <ul>
-                <li><a href="/record/''' + url_pas(name) + '''">''' + load_lang('record') + '''</a></li>
-            </ul>
-            '''
+    data = '''
+        <h2>''' + load_lang('tool') + '''</h2>
+        <ul>
+            <li><a href="/record/''' + url_pas(name) + '''">''' + load_lang('record') + '''</a></li>
+            <li><a href="/topic/user:''' + url_pas(name) + '''">''' + load_lang('user_discussion') + '''</a></li>
+        </ul>
+    '''
             
     if admin_check(1) == 1:
         curs.execute("select block from ban where block = ?", [name])
@@ -18,12 +19,12 @@ def user_tool_2(conn, name):
             ban_name = load_lang('ban')
     
         data += '''
-                <h2>''' + load_lang('admin') + '''</h2>
-                <ul>
-                    <li><a href="/ban/''' + url_pas(name) + '''">''' + ban_name + '''</a></li>
-                    <li><a href="/check/''' + url_pas(name) + '''">''' + load_lang('check') + '''</a></li>
-                </ul>
-                '''
+            <h2>''' + load_lang('admin') + '''</h2>
+            <ul>
+                <li><a href="/ban/''' + url_pas(name) + '''">''' + ban_name + '''</a></li>
+                <li><a href="/check/''' + url_pas(name) + '''">''' + load_lang('check') + '''</a></li>
+            </ul>
+        '''
 
     return easy_minify(flask.render_template(skin_check(), 
         imp = [name, wiki_set(), custom(), other2([' (' + load_lang('tool') + ')', 0])],

+ 1 - 1
route/diff_data.py → route/view_diff_data.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def diff_data_2(conn, name):
+def view_diff_data_2(conn, name):
     curs = conn.cursor()
 
     first = flask.request.args.get('first', '1')

+ 1 - 1
route/down.py → route/view_down.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def down_2(conn, name):
+def view_down_2(conn, name):
     curs = conn.cursor()
 
     div = '<ul>'

+ 1 - 1
route/raw_view.py → route/view_raw.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def raw_view_2(conn, name, sub_title, num):
+def view_raw_2(conn, name, sub_title, num):
     curs = conn.cursor()
 
     v_name = name

+ 1 - 1
route/read_view.py → route/view_read.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def read_view_2(conn, name):
+def view_read_2(conn, name):
     curs = conn.cursor()
 
     data_none = 0

+ 1 - 1
route/xref.py → route/view_xref.py

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

+ 2 - 1
views/main_css/css/main.css

@@ -34,4 +34,5 @@ s:hover, strike:hover, del:hover { color: gray; background-color: gainsboro; tex
 body { word-break: break-all; overflow: auto; }
 hr.main_hr { border: none; }
 #include_link { display: none; }
-.foot_plus { background: gainsboro; }
+.foot_plus { background: gainsboro; }
+#toc_title { font-size: 18px; }

+ 3 - 0
views/main_css/js/reload.js

@@ -0,0 +1,3 @@
+function reload() {
+    location.href.endsWith('#reload') ? location.reload(true) : location.href = '#reload';
+}

+ 10 - 0
views/main_css/js/req_browser_alarm.js

@@ -0,0 +1,10 @@
+// https://programmingsummaries.tistory.com/379
+function req_alarm() {
+    Notification.requestPermission(function (result) {
+        if(result === 'denied') {
+            document.cookie = 'topic_req=false;';
+        } else {
+            document.cookie = 'topic_req=false;';
+        }
+    });
+}

+ 23 - 26
views/main_css/js/topic_load.js

@@ -1,34 +1,31 @@
-function topic_load(name, sub) {
-    function addZero(i) {
-        if(i < 10) {
-            i = "0" + i;
-        }
-        
-        return i;
-    }
-
-    setTimeout(function() {
-        var test = setInterval(function() {
-            var d = new Date();
-            d.setSeconds(d.getSeconds() - 3);
-            
-            var date = d.getFullYear() + '-' + addZero(d.getMonth() + 1) + '-' + addZero(d.getDate());
-            date += ' ' + addZero(d.getHours()) + ':' + addZero(d.getMinutes()) + ':' + addZero(d.getSeconds());
+function topic_load(name, sub, num) {
+    var test = setInterval(function() {
+        var url = "/api/topic/" + name + "/sub/" + sub + "?num=" + num;
+        var doc_data = document.getElementById("plus");
 
-            var url = "/api/topic/" + name + "/sub/" + sub + "?time=" + date;
-            var xhr = new XMLHttpRequest();
-            var doc_data = document.getElementById("plus");
+        var xhr = new XMLHttpRequest();
+        xhr.open("GET", url, true);
+        xhr.send(null);
 
-            xhr.open("GET", url, true);
-            xhr.send(null);
+        xhr.onreadystatechange = function() {
+            if(this.readyState === 4 && this.status === 200) {
+                if(this.responseText) {
+                    doc_data.innerHTML += '<hr class="main_hr">(New)<hr class="main_hr">';
 
-            xhr.onreadystatechange = function() {
-                if(this.readyState === 4 && this.status === 200 && this.responseText !== "{}\n") {
-                    doc_data.innerText += '(New)\n\n';
+                    // https://programmingsummaries.tistory.com/379
+                    var options = {
+                        body: 'New topic'
+                    }
+                   
+                    var notification = new Notification("openNAMU", options);
+                    
+                    setTimeout(function () {
+                        notification.close();
+                    }, 5000);
 
                     clearInterval(test);
                 }
             }
-        }, 1000)
-    }, 4000);
+        }
+    }, 2000);
 }

+ 4 - 4
views/neo_yousoro/css/main.css

@@ -339,14 +339,14 @@ input {
 #go_toc {
     display: inline-block;
     padding: 10px;
-    border-left: 2px solid gainsboro;
+    border-left: 2px solid skyblue;
     width: 25px;
 }
 
 #go_top {
     display: inline-block;
     padding: 10px;
-    border-right: 2px solid gainsboro;
+    border-right: 2px solid skyblue;
     width: 25px;
 }
 
@@ -362,8 +362,8 @@ input {
     position: fixed;
     bottom: 0;
     right: 0;
-    border: 2px solid gainsboro;
-    background: skyblue;
+    border: 2px solid skyblue;
+    background: white;
     text-align: center;
 }
 

+ 1 - 1
views/neo_yousoro/info.json

@@ -1,5 +1,5 @@
 {
     "name" : "Neo_Yousoro",
-    "skin_ver" : "v1.0.1",
+    "skin_ver" : "v1.0.2",
     "require_ver" : "2"
 }

+ 31 - 6
views/neo_yousoro/js/skin_set.js

@@ -19,9 +19,16 @@ function get_post() {
 
     check = document.getElementById('include');
     if(check.checked === true) {
-        document.cookie = 'include_link=true;';
+        document.cookie = 'include_link=1;';
     } else {
-        document.cookie = 'include_link=false;';
+        document.cookie = 'include_link=0;';
+    }
+
+    check = document.getElementById('invert');
+    if(check.checked === true) {
+        document.cookie = 'invert=1;';
+    } else {
+        document.cookie = 'invert=0;';
     }
 
     history.go(0);
@@ -55,10 +62,17 @@ function main_load() {
 
     if(
         cookies.match(regex_data('include_link')) &&
-        cookies.match(regex_data('include_link'))[1] === 'true'
+        cookies.match(regex_data('include_link'))[1] === '1'
     ) {
         head_data.innerHTML += '<style>#include_link { display: inline; }</style>';
     }
+
+    if(
+        cookies.match(regex_data('invert')) &&
+        cookies.match(regex_data('invert'))[1] === '1'
+    ) {
+        head_data.innerHTML += '<style>body { -webkit-filter: invert(100%); filter: invert(100%); background: black; }</style>';
+    }
 }
 
 main_load();
@@ -75,7 +89,8 @@ window.onload = function () {
                 "save" : "Save",
                 "strike" : "Strike",
                 "bold" : "Bold",
-                "other" : "Other"
+                "other" : "Other",
+                "invert" : "Reversal of color"
             }, "ko-KR" : {
                 "default" : "기본값",
                 "change_to_normal" : "일반 텍스트로 변경",
@@ -85,7 +100,8 @@ window.onload = function () {
                 "save" : "저장",
                 "strike" : "취소선",
                 "bold" : "볼드체",
-                "other" : "기타"
+                "other" : "기타",
+                "invert" : "색 반전"
             }
         }
 
@@ -163,11 +179,18 @@ window.onload = function () {
         
         if(
             cookies.match(regex_data('include_link')) &&
-            cookies.match(regex_data('include_link'))[1] === 'true'
+            cookies.match(regex_data('include_link'))[1] === '1'
         ) {
             set_data["include"] = "checked";
         }
 
+        if(
+            cookies.match(regex_data('invert')) &&
+            cookies.match(regex_data('invert'))[1] === '1'
+        ) {
+            set_data["invert"] = "checked";
+        }
+
         data.innerHTML = ' \
             <h2>' + set_language[language]['strike'] + '</h2> \
             <hr class="main_hr"> \
@@ -181,6 +204,8 @@ window.onload = function () {
             <h2>' + set_language[language]['other'] + '</h2> \
             <input ' + set_data["include"] + ' type="checkbox" id="include" name="include" value="include"> ' + set_language[language]['include_link'] + ' \
             <hr class="main_hr"> \
+            <input ' + set_data["invert"] + ' type="checkbox" id="invert" name="invert" value="invert"> ' + set_language[language]['invert'] + ' \
+            <hr class="main_hr"> \
             <button onclick="get_post();">' + set_language[language]['save'] + '</button> \
         ';
     }