Browse Source

Merge pull request #812 from 2du/master

3.1.5
잉여개발기 (SPDV) 6 năm trước cách đây
mục cha
commit
0e8d2b3219
100 tập tin đã thay đổi với 2585 bổ sung1925 xóa
  1. 158 160
      app.py
  2. 37 32
      emergency_tool.py
  3. 66 51
      language/en-US.json
  4. 59 45
      language/ko-KR.json
  5. 4 3
      readme-en.md
  6. 3 2
      readme.md
  7. 12 6
      route/alarm.py
  8. 1 1
      route/alarm_del.py
  9. 1 1
      route/api_raw.py
  10. 1 1
      route/api_recent_change.py
  11. 13 7
      route/api_search.py
  12. 6 0
      route/api_sha224.py
  13. 36 28
      route/api_topic_sub.py
  14. 26 18
      route/api_user_info.py
  15. 1 1
      route/api_version.py
  16. 3 3
      route/api_w.py
  17. 46 30
      route/edit.py
  18. 18 12
      route/edit_delete.py
  19. 62 0
      route/edit_many_delete.py
  20. 24 21
      route/edit_move.py
  21. 163 0
      route/edit_req.py
  22. 15 12
      route/edit_revert.py
  23. 17 17
      route/func_upload.py
  24. 25 25
      route/give_acl.py
  25. 8 8
      route/give_admin.py
  26. 9 9
      route/give_admin_groups.py
  27. 65 0
      route/give_history_add.py
  28. 2 2
      route/give_history_hidden.py
  29. 12 12
      route/give_user_ban.py
  30. 11 11
      route/give_user_check.py
  31. 14 14
      route/inter_wiki.py
  32. 3 3
      route/inter_wiki_del.py
  33. 95 35
      route/inter_wiki_plus.py
  34. 23 28
      route/list_acl.py
  35. 5 5
      route/list_admin.py
  36. 3 3
      route/list_admin_use.py
  37. 14 14
      route/list_block.py
  38. 3 3
      route/list_give.py
  39. 6 5
      route/list_not_close_topic.py
  40. 7 3
      route/list_old_page.py
  41. 10 6
      route/list_please.py
  42. 6 7
      route/list_title_index.py
  43. 5 5
      route/list_user.py
  44. 11 10
      route/list_user_topic.py
  45. 14 14
      route/login.py
  46. 22 22
      route/login_check_key.py
  47. 8 8
      route/login_need_email.py
  48. 30 30
      route/login_oauth.py
  49. 5 5
      route/login_pw_change.py
  50. 11 11
      route/login_register.py
  51. 0 10
      route/main_easter_egg.py
  52. 15 3
      route/main_file.py
  53. 1 1
      route/main_image_view.py
  54. 19 19
      route/main_manager.py
  55. 2 2
      route/main_other.py
  56. 1 1
      route/main_skin_set.py
  57. 1 1
      route/main_views.py
  58. 104 93
      route/recent_changes.py
  59. 16 9
      route/recent_discuss.py
  60. 1 1
      route/recent_history_delete.py
  61. 3 3
      route/recent_history_tool.py
  62. 29 20
      route/search_deep.py
  63. 0 63
      route/server_indexing.py
  64. 2 2
      route/server_now_update.py
  65. 1 1
      route/server_restart.py
  66. 212 137
      route/setting.py
  67. 5 5
      route/setting_adsense.py
  68. 11 11
      route/setting_oauth.py
  69. 206 200
      route/tool/func.py
  70. 1 1
      route/tool/init.py
  71. 16 10
      route/tool/mark.py
  72. 2 2
      route/tool/set_mark/markdown.py
  73. 389 273
      route/tool/set_mark/namumark.py
  74. 0 0
      route/tool/set_mark/namumark_backlink.py
  75. 18 28
      route/tool/set_mark/tool.py
  76. 40 24
      route/topic.py
  77. 12 8
      route/topic_admin.py
  78. 9 5
      route/topic_block.py
  79. 84 77
      route/topic_close_list.py
  80. 29 0
      route/topic_delete.py
  81. 14 10
      route/topic_stop.py
  82. 21 5
      route/topic_tool.py
  83. 8 4
      route/topic_top.py
  84. 1 1
      route/user_count_edit.py
  85. 3 3
      route/user_custom_head_view.py
  86. 8 7
      route/user_info.py
  87. 5 5
      route/user_setting.py
  88. 4 4
      route/user_tool.py
  89. 7 10
      route/view_diff_data.py
  90. 3 3
      route/view_down.py
  91. 16 10
      route/view_raw.py
  92. 29 30
      route/view_read.py
  93. 9 9
      route/view_xref.py
  94. 2 2
      route/watch_list.py
  95. 2 2
      route/watch_list_name.py
  96. 3 3
      version.json
  97. 0 53
      views/easter_egg.html
  98. 5 2
      views/main_css/css/main.css
  99. 14 0
      views/main_css/file/easter_egg.html
  100. 3 3
      views/main_css/js/do_insert_data.js

+ 158 - 160
app.py

@@ -32,13 +32,13 @@ while 1:
             break
     except:
         if os.getenv('NAMU_DB') != None or os.getenv('NAMU_DB_TYPE') != None:
-            set_data = { 
-                "db" : os.getenv('NAMU_DB') if os.getenv('NAMU_DB') else 'data', 
+            set_data = {
+                "db" : os.getenv('NAMU_DB') if os.getenv('NAMU_DB') else 'data',
                 "db_type" : os.getenv('NAMU_DB_TYPE') if os.getenv('NAMU_DB_TYPE') else 'sqlite'
             }
 
             break
-        else:        
+        else:
             new_json = ['', '']
             normal_db_type = ['sqlite', 'mysql']
 
@@ -61,14 +61,14 @@ while 1:
             new_json[1] = str(input())
             if new_json[1] == '':
                 new_json[1] = 'data'
-                
+
             with open('data/set.json', 'w') as f:
                 f.write('{ "db" : "' + new_json[1] + '", "db_type" : "' + new_json[0] + '" }')
-                
+
             set_data = json.loads(open('data/set.json').read())
-            
+
             break
-        
+
 print('DB name : ' + set_data['db'])
 print('DB type : ' + set_data['db_type'])
 
@@ -94,12 +94,12 @@ if set_data['db_type'] == 'mysql':
 
         with open('data/mysql.json', 'w') as f:
             f.write('{ "user" : "' + new_json[0] + '", "password" : "' + new_json[1] + '" }')
-                
+
         set_data_mysql = json.loads(open('data/mysql.json').read())
 
     conn = pymysql.connect(
-        host = 'localhost', 
-        user = set_data_mysql['user'], 
+        host = 'localhost',
+        user = set_data_mysql['user'],
         password = set_data_mysql['password'],
         charset = 'utf8mb4'
     )
@@ -114,7 +114,7 @@ if set_data['db_type'] == 'mysql':
 else:
     conn = sqlite3.connect(set_data['db'] + '.db', check_same_thread = False)
     curs = conn.cursor()
-            
+
 if os.path.exists(set_data['db'] + '.db'):
     setup_tool = 0
 else:
@@ -138,34 +138,33 @@ class EverythingConverter(werkzeug.routing.PathConverter):
 app.jinja_env.filters['md5_replace'] = md5_replace
 app.jinja_env.filters['load_lang'] = load_lang
 app.jinja_env.filters['cut_100'] = cut_100
-app.jinja_env.filters['change_space'] = change_space
 
 app.url_map.converters['everything'] = EverythingConverter
 
 create_data = {}
 create_data['all_data'] = [
-    'data', 
-    'cache_data', 
-    'history', 
-    'rd', 
+    'data',
+    'cache_data',
+    'history',
+    'rd',
     'user',
     'user_set',
-    'ban', 
-    'topic', 
-    'rb', 
-    'back', 
-    'custom', 
-    'other', 
-    'alist', 
-    're_admin', 
-    'alarm', 
-    'ua_d', 
-    'filter', 
-    'scan', 
-    'acl', 
-    'inter', 
+    'ban',
+    'topic',
+    'rb',
+    'back',
+    'custom',
+    'other',
+    'alist',
+    're_admin',
+    'alarm',
+    'ua_d',
+    'filter',
+    'scan',
+    'acl',
+    'inter',
     'html_filter',
-    'oauth_conn'
+    'oauth_conn',
 ]
 for i in create_data['all_data']:
     try:
@@ -193,7 +192,7 @@ if setup_tool != 0:
     create_data['user'] = ['id', 'pw', 'acl', 'date', 'encode']
     create_data['user_set'] = ['name', 'id', 'data']
     create_data['ban'] = ['block', 'end', 'why', 'band', 'login']
-    create_data['topic'] = ['id', 'title', 'sub', 'data', 'date', 'ip', 'block', 'top']
+    create_data['topic'] = ['id', 'title', 'sub', 'data', 'date', 'ip', 'block', 'top', 'code']
     create_data['rb'] = ['block', 'end', 'today', 'blocker', 'why', 'band']
     create_data['back'] = ['title', 'link', 'type']
     create_data['custom'] = ['user', 'css']
@@ -216,6 +215,11 @@ if setup_tool != 0:
             except:
                 curs.execute(db_change("alter table " + create_table + " add " + create + " longtext default ''"))
 
+            try:
+                curs.execute(db_change('create index index_' + create_table + '_' + create + ' on ' + create_table + '(' + create + ')'))
+            except:
+                pass
+
     update()
 
 # Init
@@ -226,7 +230,7 @@ if not curs.fetchall():
 
 if not os.path.exists(app_var['path_data_image']):
     os.makedirs(app_var['path_data_image'])
-    
+
 if not os.path.exists('views'):
     os.makedirs('views')
 
@@ -241,14 +245,14 @@ for i in range(len(server_set_key)):
     server_set_val = curs.fetchall()
     if not server_set_val:
         server_set_val = server_init.init(server_set_key[i])
-        
+
         curs.execute(db_change('insert into other (name, data) values (?, ?)'), [server_set_key[i], server_set_val])
         conn.commit()
     else:
         server_set_val = server_set_val[0][0]
-    
+
     print(dislay_set_key[i] + ' : ' + server_set_val)
-    
+
     server_set[server_set_key[i]] = server_set_val
 
 curs.execute(db_change('select data from other where name = "key"'))
@@ -269,32 +273,33 @@ if not adsense_result:
 curs.execute(db_change('delete from other where name = "ver"'))
 curs.execute(db_change('insert into other (name, data) values ("ver", ?)'), [version_list['master']['c_ver']])
 
-def back_up():
-    print('----')
+if set_data['db_type'] == 'sqlite':
+    def back_up():
+        print('----')
+        try:
+            shutil.copyfile(set_data['db'] + '.db', 'back_' + set_data['db'] + '.db')
+
+            print('Back up : OK')
+        except:
+            print('Back up : Error')
+
+        threading.Timer(60 * 60 * back_time, back_up).start()
+
     try:
-        shutil.copyfile(set_data['db'] + '.db', 'back_' + set_data['db'] + '.db')
-        
-        print('Back up : OK')
+        curs.execute(db_change('select data from other where name = "back_up"'))
+        back_up_time = curs.fetchall()
+
+        back_time = int(back_up_time[0][0])
     except:
-        print('Back up : Error')
-
-    threading.Timer(60 * 60 * back_time, back_up).start()
-
-try:
-    curs.execute(db_change('select data from other where name = "back_up"'))
-    back_up_time = curs.fetchall()
-    
-    back_time = int(back_up_time[0][0])
-except:
-    back_time = 0
-    
-print('----')
-if back_time != 0:
-    print('Back up state : ' + str(back_time) + ' hours')
-    
-    back_up()
-else:
-    print('Back up state : Turn off')
+        back_time = 0
+
+    print('----')
+    if back_time != 0:
+        print('Back up state : ' + str(back_time) + ' hours')
+
+        back_up()
+    else:
+        print('Back up state : Turn off')
 
 if set_data['db_type'] == 'mysql':
     def mysql_dont_off():
@@ -307,29 +312,11 @@ if set_data['db_type'] == 'mysql':
 
     mysql_dont_off()
 
-conn.commit()
-
-def count_all_title():
-    curs.execute(db_change("select count(title) from data"))
-    count_data = curs.fetchall()
-    if count_data:
-        count_data = count_data[0][0]
-    else:
-        count_data = 0
-
-    curs.execute(db_change('delete from other where name = "count_all_title"'))
-    curs.execute(db_change('insert into other (name, data) values ("count_all_title", ?)'), [str(count_data)])
-
-    conn.commit()
-
-    threading.Timer(60 * 60 * 24, count_all_title).start()
-
 curs.execute(db_change('select data from other where name = "count_all_title"'))
-all_title = curs.fetchall()
-if not all_title:
+if not curs.fetchall():
     curs.execute(db_change('insert into other (name, data) values ("count_all_title", "0")'))
 
-count_all_title()  
+conn.commit()
 
 # Func
 @app.route('/del_alarm')
@@ -349,7 +336,7 @@ def inter_wiki_del(tools = None, name = None):
     return inter_wiki_del_2(conn, tools, name)
 
 @app.route('/<regex("plus_(?:inter_wiki|edit_top|image_license|(?:edit|email|file|name)_filter)"):tools>', methods=['POST', 'GET'])
-@app.route('/<regex("plus_edit_filter"):tools>/<name>', methods=['POST', 'GET'])
+@app.route('/<regex("plus_(?:inter_wiki|edit_top|image_license|(?:edit|email|file|name|edit)_filter)"):tools>/<name>', methods=['POST', 'GET'])
 def inter_wiki_plus(tools = None, name = None):
     return inter_wiki_plus_2(conn, tools, name)
 
@@ -373,15 +360,19 @@ def list_acl():
 @app.route('/admin_plus/<name>', methods=['POST', 'GET'])
 def give_admin_groups(name = None):
     return give_admin_groups_2(conn, name)
-        
+
 @app.route('/admin_list')
 def list_admin():
     return list_admin_2(conn)
-        
+
 @app.route('/hidden/<everything:name>')
 def give_history_hidden(name = None):
     return give_history_hidden_2(conn, name)
-        
+
+@app.route('/add_history/<everything:name>', methods=['POST', 'GET'])
+def give_history_add(name = None):
+    return give_history_add_2(conn, name)
+
 @app.route('/user_log')
 def list_user():
     return list_user_2(conn)
@@ -394,10 +385,6 @@ def list_admin_use():
 def list_give():
     return list_give_2(conn)
 
-@app.route('/indexing', methods=['POST', 'GET'])
-def server_indexing():
-    return server_indexing_2(conn, set_data['db_type'])       
-
 @app.route('/restart', methods=['POST', 'GET'])
 def server_restart():
     return server_restart_2(conn)
@@ -413,7 +400,7 @@ def setting_oauth():
 @app.route('/adsense_setting', methods=['GET', 'POST'])
 def setting_adsense():
     return setting_adsense_2(conn)
-        
+
 @app.route('/xref/<everything:name>')
 def view_xref(name = None):
     return view_xref_2(conn, name)
@@ -421,7 +408,7 @@ def view_xref(name = None):
 @app.route('/please')
 def list_please():
     return list_please_2(conn)
-        
+
 @app.route('/recent_discuss')
 def recent_discuss():
     return recent_discuss_2(conn)
@@ -430,7 +417,7 @@ def recent_discuss():
 @app.route('/<regex("block_user|block_admin"):tool>/<name>')
 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)
@@ -443,24 +430,32 @@ def search_goto(name = 'test'):
 @app.route('/search/<everything:name>')
 def search_deep(name = 'test'):
     return search_deep_2(conn, name)
-         
+
 @app.route('/raw/<everything:name>')
-@app.route('/topic/<everything:name>/sub/<sub_title>/raw/<int:num>')
-def view_raw(name = None, sub_title = None, num = None):
-    return view_raw_2(conn, name, sub_title, num)
-        
+@app.route('/thread/<int:topic_num>/raw/<int:num>')
+def view_raw(name = None, topic_num = None, num = None):
+    return view_raw_2(conn, name, topic_num, num)
+
 @app.route('/revert/<everything:name>', methods=['POST', 'GET'])
 def edit_revert(name = None):
     return edit_revert_2(conn, name)
 
 @app.route('/edit/<everything:name>', methods=['POST', 'GET'])
-def edit(name = None):
+def edit(name = 'Test'):
     return edit_2(conn, name)
-        
+
+@app.route('/edit_req/<everything:name>', methods=['POST', 'GET'])
+def edit_req(name = 'Test'):
+    return edit_req_2(conn, name)
+
 @app.route('/delete/<everything:name>', methods=['POST', 'GET'])
 def edit_delete(name = None):
-    return edit_delete_2(conn, name, app_var)        
-            
+    return edit_delete_2(conn, name, app_var)
+
+@app.route('/many_delete', methods=['POST', 'GET'])
+def edit_many_delete(name = None):
+    return edit_many_delete_2(conn, app_var)
+
 @app.route('/move/<everything:name>', methods=['POST', 'GET'])
 def edit_move(name = None):
     return edit_move_2(conn, name)
@@ -468,49 +463,52 @@ def edit_move(name = None):
 @app.route('/other')
 def main_other():
     return main_other_2(conn)
-    
+
 @app.route('/manager', methods=['POST', 'GET'])
 @app.route('/manager/<int:num>', methods=['POST', 'GET'])
 def main_manager(num = 1):
-    return main_manager_2(conn, num, version_list['master']['r_ver'], set_data['db_type'])
-        
+    return main_manager_2(conn, num, version_list['master']['r_ver'])
+
 @app.route('/title_index')
 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):
-    return topic_block_2(conn, name, sub, num)
-        
-@app.route('/topic/<everything:name>/sub/<sub>/notice/<int:num>')
-def topic_top(name = None, sub = None, num = 1):
-    return topic_top_2(conn, name, sub, num)
-                
-@app.route('/topic/<everything:name>/sub/<sub>/setting', methods=['POST', 'GET'])
-def topic_stop(name = None, sub = None):
-    return topic_stop_2(conn, name, sub)
-
-@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)
-
-@app.route('/topic/<everything:name>/sub/<sub>', methods=['POST', 'GET'])
-def topic(name = None, sub = None):
-    return topic_2(conn, name, sub)
-        
+
+@app.route('/thread/<int:topic_num>/b/<int:num>')
+def topic_block(topic_num = 1, num = 1):
+    return topic_block_2(conn, topic_num, num)
+
+@app.route('/thread/<int:topic_num>/notice/<int:num>')
+def topic_top(topic_num = 1, num = 1):
+    return topic_top_2(conn, topic_num, num)
+
+@app.route('/thread/<int:topic_num>/setting', methods=['POST', 'GET'])
+def topic_stop(topic_num = 1):
+    return topic_stop_2(conn, topic_num)
+
+@app.route('/thread/<int:topic_num>/delete', methods=['POST', 'GET'])
+def topic_delete(topic_num = 1):
+    return topic_delete_2(conn, topic_num)
+
+@app.route('/thread/<int:topic_num>/tool')
+def topic_tool(topic_num = 1):
+    return topic_tool_2(conn, topic_num)
+
+@app.route('/thread/<int:topic_num>/admin/<int:num>')
+def topic_admin(topic_num = 1, num = 1):
+    return topic_admin_2(conn, topic_num, num)
+
+@app.route('/thread/<int:topic_num>', methods=['POST', 'GET'])
+def topic(topic_num = 1):
+    return topic_2(conn, topic_num)
+
 @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)
+def topic_close_list(name = 'test'):
+    return topic_close_list_2(conn, name)
 
 @app.route('/tool/<name>')
 def user_tool(name = None):
     return user_tool_2(conn, name)
-            
+
 @app.route('/login', methods=['POST', 'GET'])
 def login():
     return login_2(conn)
@@ -518,11 +516,11 @@ def login():
 @app.route('/oauth/<regex("discord|naver|facebook|kakao"):platform>/<regex("init|callback"):func>', methods=['GET', 'POST'])
 def login_oauth(platform = None, func = None):
     return login_oauth_2(conn, platform, func)
-                
+
 @app.route('/change', methods=['POST', 'GET'])
 def user_setting():
     return user_setting_2(conn, server_init)
-    
+
 @app.route('/pw_change', methods=['POST', 'GET'])
 def login_pw_change():
     return login_pw_change_2(conn)
@@ -530,7 +528,7 @@ def login_pw_change():
 @app.route('/check/<name>')
 def give_user_check(name = None):
     return give_user_check_2(conn, name)
-                
+
 @app.route('/register', methods=['POST', 'GET'])
 def login_register():
     return login_register_2(conn)
@@ -542,31 +540,31 @@ def login_need_email(tool = 'pass_find'):
 @app.route('/<regex("check_key|check_pass_key|email_replace"):tool>', methods=['POST', 'GET'])
 def login_check_key(tool = 'check_pass_key'):
     return login_check_key_2(conn, tool)
-           
+
 @app.route('/logout')
 def login_logout():
     return login_logout_2(conn)
-    
+
 @app.route('/ban', methods=['POST', 'GET'])
 @app.route('/ban/<name>', methods=['POST', 'GET'])
 def give_user_ban(name = None):
-    return give_user_ban_2(conn, name)         
-                
+    return give_user_ban_2(conn, name)
+
 @app.route('/acl/<everything:name>', methods=['POST', 'GET'])
 def give_acl(name = None):
     return give_acl_2(conn, name)
-            
+
 @app.route('/admin/<name>', methods=['POST', 'GET'])
 def give_admin(name = None):
     return give_admin_2(conn, name)
-    
+
 @app.route('/diff/<everything:name>')
 def view_diff_data(name = None):
     return view_diff_data_2(conn, name)
-        
+
 @app.route('/down/<everything:name>')
 def view_down(name = None):
-    return view_down_2(conn, name)   
+    return view_down_2(conn, name)
 
 @app.route('/w/<everything:name>')
 def view_read(name = None):
@@ -585,7 +583,7 @@ def recent_changes(name = None, tool = 'record'):
 @app.route('/history_tool/<everything:name>')
 def recent_history_tool(name = None):
     return recent_history_tool_2(conn, name)
-    
+
 @app.route('/history_delete/<everything:name>', methods=['POST', 'GET'])
 def recent_history_delete(name = None):
     return recent_history_delete_2(conn, name)
@@ -593,7 +591,7 @@ def recent_history_delete(name = None):
 @app.route('/upload', methods=['GET', 'POST'])
 def func_upload():
     return func_upload_2(conn)
-        
+
 @app.route('/user')
 def user_info():
     return user_info_2(conn)
@@ -614,7 +612,7 @@ def user_custom_head_view():
 @app.route('/count/<name>')
 def user_count_edit(name = None):
     return user_count_edit_2(conn, name)
-        
+
 @app.route('/random')
 def func_title_random():
     return func_title_random_2(conn)
@@ -626,12 +624,12 @@ def main_image_view(name = None):
 @app.route('/skin_set')
 def main_skin_set():
     return main_skin_set_2(conn)
-    
+
 # API
 @app.route('/api/w/<everything:name>', methods=['POST', 'GET'])
 def api_w(name = ''):
     return api_w_2(conn, name)
-    
+
 @app.route('/api/raw/<everything:name>')
 def api_raw(name = ''):
     return api_raw_2(conn, name)
@@ -653,9 +651,9 @@ def api_markup():
 def api_user_info(name = ''):
     return api_user_info_2(conn, name)
 
-@app.route('/api/topic/<everything:name>/sub/<sub>')
-def api_topic_sub(name = '', sub = '', time = ''):
-    return api_topic_sub_2(conn, name, sub, time)
+@app.route('/api/thread/<topic_num>')
+def api_topic_sub(name = '', topic_num = 1):
+    return api_topic_sub_2(conn, topic_num)
 
 @app.route('/api/search/<name>')
 def api_search(name = ''):
@@ -664,25 +662,25 @@ def api_search(name = ''):
 @app.route('/api/recent_changes')
 def api_recent_change():
     return api_recent_change_2(conn)
-    
-# File
-@app.route('/views/easter_egg.html')
-def main_easter_egg():
-    return main_easter_egg_2(conn)
 
+@app.route('/api/sha224/<everything:name>')
+def api_sha224(name = 'test'):
+    return api_sha224_2(conn, name)
+
+# File
 @app.route('/views/<everything:name>')
 def main_views(name = None):
     return main_views_2(conn, name)
 
 @app.route('/<data>')
 def main_file(data = None):
-    return main_file_2(conn, data) if re.search('\.txt$', data) else main_error_404_2(conn)
+    return main_file_2(conn, data)
 
 # End
 @app.errorhandler(404)
 def main_error_404(e):
     return main_error_404_2(conn)
-    
+
 app.secret_key = rep_key
 app.wsgi_app = werkzeug.debug.DebuggedApplication(app.wsgi_app, True)
 app.debug = True
@@ -690,5 +688,5 @@ app.debug = True
 if __name__ == "__main__":
     http_server = tornado.httpserver.HTTPServer(tornado.wsgi.WSGIContainer(app))
     http_server.listen(server_set['port'], address = server_set['host'])
-    
-    tornado.ioloop.IOLoop.instance().start()
+
+    tornado.ioloop.IOLoop.instance().start()

+ 37 - 32
emergency_tool.py

@@ -15,13 +15,13 @@ while 1:
             break
     except:
         if os.getenv('NAMU_DB') != None or os.getenv('NAMU_DB_TYPE') != None:
-            set_data = { 
-                "db" : os.getenv('NAMU_DB') if os.getenv('NAMU_DB') else 'data', 
+            set_data = {
+                "db" : os.getenv('NAMU_DB') if os.getenv('NAMU_DB') else 'data',
                 "db_type" : os.getenv('NAMU_DB_TYPE') if os.getenv('NAMU_DB_TYPE') else 'sqlite'
             }
 
             break
-        else:        
+        else:
             new_json = ['', '']
             normal_db_type = ['sqlite', 'mysql']
 
@@ -44,16 +44,16 @@ while 1:
             new_json[1] = str(input())
             if new_json[1] == '':
                 new_json[1] = 'data'
-                
+
             with open('data/set.json', 'w') as f:
                 f.write('{ "db" : "' + new_json[1] + '", "db_type" : "' + new_json[0] + '" }')
-                
+
             set_data = json.loads(open('data/set.json').read())
-            
+
             break
-        
+
 print('DB name : ' + set_data['db'])
-db_name = set_data['db']
+print('DB type : ' + set_data['db_type'])
 
 db_data_get(set_data['db_type'])
 
@@ -77,25 +77,25 @@ if set_data['db_type'] == 'mysql':
 
         with open('data/mysql.json', 'w') as f:
             f.write('{ "user" : "' + new_json[0] + '", "password" : "' + new_json[1] + '" }')
-                
+
         set_data_mysql = json.loads(open('data/mysql.json').read())
 
     conn = pymysql.connect(
-        host = 'localhost', 
-        user = set_data_mysql['user'], 
+        host = 'localhost',
+        user = set_data_mysql['user'],
         password = set_data_mysql['password'],
         charset = 'utf8mb4'
     )
     curs = conn.cursor()
 
     try:
-        curs.execute(db_change('create database ? default character set utf8mb4;')%pymysql.escape_string(db_name))
+        curs.execute(db_change('create database ? default character set utf8mb4;')%pymysql.escape_string(set_data['db']))
     except:
         pass
 
-    curs.execute(db_change('use ?')%pymysql.escape_string(db_name))
+    curs.execute(db_change('use ?')%pymysql.escape_string(set_data['db']))
 else:
-    conn = sqlite3.connect(db_name + '.db', check_same_thread = False)
+    conn = sqlite3.connect(set_data['db'] + '.db', check_same_thread = False)
     curs = conn.cursor()
 
 load_conn(conn)
@@ -113,15 +113,13 @@ print('8. Reset version')
 print('9. Delete set.json')
 print('10. Change name')
 print('11. Delete mysql.json')
+print('12. All title count reset')
 
 print('----')
 print('Select : ', end = '')
 what_i_do = input()
 
 if what_i_do == '1':
-    def parser(data):
-        namumark(data[0], data[1], 1)
-
     curs.execute(db_change("delete from back"))
     conn.commit()
 
@@ -131,13 +129,10 @@ if what_i_do == '1':
 
     for test in data:
         num += 1
-
-        t = threading.Thread(target = parser, args = [test])
-        t.start()
-        t.join()
-
-        if num % 10 == 0:
+        if num % 100 == 0:
             print(num)
+
+        render_do(test[0], test[1], 1, None)
 elif what_i_do == '2':
     curs.execute(db_change("delete from other where name = 'recaptcha'"))
     curs.execute(db_change("delete from other where name = 'sec_re'"))
@@ -151,12 +146,12 @@ elif what_i_do == '3':
     else:
         band = ''
 
-        curs.execute(db_change("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)"), 
-            [user_data, 
-            'release', 
-            get_time(), 
-            'tool:emergency', 
-            '', 
+        curs.execute(db_change("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)"),
+            [user_data,
+            'release',
+            get_time(),
+            'tool:emergency',
+            '',
             band
         ])
     curs.execute(db_change("delete from ban where block = ?"), [user_data])
@@ -182,7 +177,7 @@ elif what_i_do == '7':
     print('----')
     print('1. sha256')
     print('2. sha3')
-    
+
     print('----')
     print('Select : ', end = '')
     what_i_do = int(input())
@@ -202,7 +197,7 @@ elif what_i_do == '7':
             hashed = sha3.sha3_256(bytes(user_pw, 'utf-8')).hexdigest()
         else:
             hashed = hashlib.sha3_256(bytes(user_pw, 'utf-8')).hexdigest()
-       
+
     curs.execute(db_change("update user set pw = ? where id = ?"), [hashed, user_name])
 elif what_i_do == '8':
     curs.execute(db_change("update other set data = '00000' where name = 'ver'"))
@@ -221,11 +216,21 @@ elif what_i_do == '10':
     new_name = input()
 
     curs.execute(db_change("update user set id = ? where id = ?"), [new_name, user_name])
-else:
+elif what_i_do == '11':
     try:
         os.remove('data/mysql.json')
     except:
         pass
+else:
+    curs.execute(db_change("select count(title) from data"))
+    count_data = curs.fetchall()
+    if count_data:
+        count_data = count_data[0][0]
+    else:
+        count_data = 0
+
+    curs.execute(db_change('delete from other where name = "count_all_title"'))
+    curs.execute(db_change('insert into other (name, data) values ("count_all_title", ?)'), [str(count_data)])
 
 conn.commit()
 

+ 66 - 51
language/en-US.json

@@ -16,12 +16,13 @@
         "skin" : "Skin",
         "save" : "Save",
         "secret_key" : "Secret key",
+        "public_key" : "Public key",
         "host" : "Host",
         "port" : "Port",
         "restart" : "Restart",
         "document_name" : "Document[s] name",
-        "discussion_name" : "Discussion[s] name",
-        "user_name" : "User[s] name",
+        "discussion_name" : "Discussion[s] topic",
+        "user_name" : "Username",
         "go" : "Go",
         "document" : "Document",
         "discussion" : "Discussion",
@@ -61,9 +62,9 @@
         "tool" : "Tool",
         "recent" : "Recently",
         "password" : "Password",
-        "login" : "Sign-in",
-        "logout" : "Sign-out",
-        "register" : "Sign-up",
+        "login" : "Sign in",
+        "logout" : "Sign out",
+        "register" : "Sign up",
         "language" : "Language",
         "compare" : "Compare",
         "email" : "Email",
@@ -94,6 +95,8 @@
         "reference" : "Reference",
         "icon" : "Icon",
         "view" : "View",
+        "content" : "Content",
+        "off" : "Off",
         "_comment_1.1_" : "Time",
             "second" : "Second(s)",
             "hour" : "Hour(s)",
@@ -112,7 +115,7 @@
             "blocked" : "Blocked",
             "release" : "Release",
     "_comment_2_" : "Func",
-        "wiki_restart" : "Wiki engine restart",
+        "wiki_restart" : "Restart wiki engine",
         "update" : "Update",
         "need_document" : "Required Document(s)",
         "close_discussion" : "Closed discussion(s)",
@@ -122,11 +125,11 @@
         "edit_filter" : "Contents filter",
         "recent_ban" : "Recently Block(s)",
         "load" : "Import another document",
-        "edit_filter_rule" : "Contents filter[s] rule",
+        "edit_filter_rule" : "Contents filter rule",
         "move_history" : "History of move",
-        "other_tool" : "Other tool",
-        "admin_tool" : "Admin[s] tool",
-        "check_user" : "Check user",
+        "other_tool" : "Other tools",
+        "admin_tool" : "Administrator[s] tools",
+        "check_user" : "Check user[s] login history",
         "compare_target" : "Comparison target name",
         "authorize" : "Authorize",
         "indexing" : "DB Indexing",
@@ -134,7 +137,7 @@
         "pinned_release" : "Unpinned",
         "ban_release" : "Unblock",
         "discussion_tool" : "Discussion tools",
-        "discussion_raw" : "Discussion[s] raw",
+        "discussion_raw" : "Discussion raw",
         "oauth_signin_facebook" : "Sign-in with Facebook",
         "oauth_signin_naver" : "Sign-in with NAVER",
         "oauth_signin_discord" : "Sign-in with Discord",
@@ -150,15 +153,11 @@
         "login_able" : "Loginable",
         "band_ban" : "Range block",
         "band_blocked" : "Range blocked",
-        "document_acl" : "Document[s] ACL",
-        "discussion_acl" : "Discussion[s] ACL",
-        "view_acl" : "Document viewed ACL",
         "under_category" : "Sub-category",
         "count" : "Number of Contributions",
         "alarm" : "Notice(s)",
-        "user_document" : "User[s] document",
-        "user_head" : "User[s] <HEAD>",
-        "user_document_acl" : "User[s] document ACL",
+        "user_document" : "User document",
+        "user_head" : "Custom <HEAD>",
         "encryption_method" : "Encryption method",
         "check_key" : "Check authentication key",
         "reset_user_ok" : "Check Success",
@@ -168,20 +167,24 @@
         "use_push_alarm" : "Enable Push Notification",
         "edit_button_paragraph" : "Paragraph",
         "password_change" : "Password change",
-        "email_change" : "Email change",
-        "acl_change" : "Change document ACL",
-        "user_tool" : "User tool",
-        "skin_info" : "Skin info",
+        "email_change" : "Change email",
+        "acl_change" : "Change document[s] ACL",
+        "user_tool" : "User[s] tools",
+        "skin_info" : "Skin information",
         "closed_discussion" : "Closed discussion",
         "agreed_discussion" : "Agreed discussion",
-        "history_delete" : "History delete",
+        "history_delete" : "Delete history",
         "direct_input" : "Direct input",
         "acl_record" : "ACL record",
         "last_edit_time" : "Last edited time",
-        "admin_group" : "Admin group",
-        "topic_setting" : "Topic setting(s)",
+        "admin_group" : "Admin groups",
+        "topic_setting" : "Topic settings",
         "old_page" : "Old decument(s)",
         "skin_set" : "Skin setting(s)",
+        "many_delete" : "Bulk delete",
+        "edit_req" : "Edit request",
+        "edit_req_check" : "Check edit request",
+        "history_add" : "Add history",
         "_comment_2.1_" : "Filter",
             "_comment_2.1.1_" : "List",
                 "interwiki_list" : "Interwiki(s) list",
@@ -206,6 +209,7 @@
             "adsense_setting" : "Adsense settings",
             "adsense_enable" : "Adsense enable",
             "skin_setting" : "Skin settings",
+            "main_acl_setting" : "Default ACL settings",
             "_comment_2.2.1_" : "List",
                 "main_setting" : "Main settings",
                 "text_setting" : "Text settings",
@@ -219,17 +223,16 @@
                 "bottom_text" : "Bottom text",
                 "max_file_size" : "Max file size",
                 "backup_interval" : "Backup Cycles",
-                "wiki_skin" : "Wiki[s] Skin",
-                "default_acl" : "Default edit ACL",
-                "default_discussion_acl" : "Default discussion ACL",
+                "wiki_skin" : "Wiki[s] default Skin",
                 "no_register" : "No sign-up",
-                "hide_ip" : "Hide IP",
-                "wiki_host" : "Wiki[s] host",
-                "wiki_port" : "Wiki[s] port",
-                "wiki_secret_key" : "Wiki[s] secret key",
+                "hide_ip" : "Hide IP address",
+                "wiki_host" : "Wiki host address",
+                "wiki_port" : "Wiki port number",
+                "wiki_secret_key" : "Wiki secret key",
                 "email_required" : "Email required",
                 "google_imap_required" : "Google IMAP setting required",
                 "update_branch" : "Branch to import updates",
+                "slow_edit" : "Continuous edit limit",
             "_comment_2.2.3_" : "Text",
                 "register_text" : "Terms of sign-up",
                 "non_login_alert" : "Non-login alert",
@@ -272,8 +275,9 @@
                 "edit_record" : "Edit record",
                 "discussion_record" : "Discussion record",
         "_comment_2.4_" : "Topic tool",
-            "topic_tool" : "Discussion tool",
+            "topic_tool" : "Discussion management tools",
             "topic_state" : "Discussion status",
+            "topic_delete" : "Discussion delete",
         "_comment_2.5_" : "Period",
             "1_day" : "1 day",
             "5_day" : "5 days",
@@ -281,47 +285,58 @@
             "180_day" : "180 days",
             "360_day" : "360 days",
         "_comment_2.6_" : "ACL",
-            "admin_acl" : "Admin only",
-            "member_acl" : "Member only",
-            "50_edit_acl" : "Only members with 50 or more all document edits",
+            "admin_acl" : "Administrators only",
+            "member_acl" : "Members only",
+            "50_edit_acl" : "Only members with 50 or more document edits",
             "all_acl" : "All users",
             "email_acl" : "Only users with email",
             "owner_acl" : "Owner only",
+            "_comment_2.6_1_" : "Set",
+                "document_acl" : "Document ACL",
+                "discussion_acl" : "Discussion ACL",
+                "view_acl" : "Read ACL",
+                "user_document_acl" : "User document ACL",
+                "upload_acl" : "Upload ACL",
+                "edit_req_acl" : "Edit request ACL",
     "_comment_3_" : "Long",
         "ie_no_data_required" : "Operation cannot continue because all required data has not been collected.",
-        "oauth_settings_not_found" : "Administrator has not provided any data about using this feature.",
-        "oauth_disabled" : "Administrator has disabled this feature.",
+        "oauth_settings_not_found" : "The administrator has not provided any data about using this feature.",
+        "oauth_disabled" : "The administrator has disabled this feature.",
         "http_warring" : "Warning : If you are not on HTTPS connection, Your information can be leaked. We won't response to that.",
-        "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_head_warring" : "User <HEAD> will be deleted if you close the browser or when you sign in.",
+        "no_login_warring" : "You are not logged in. The IP address will be logged when editing or discussing with non-login.",
         "user_reset_sign" : "Your account information has changed like this.",
         "update_warring" : "Manual updates are recommended if your version is 0.2 or lower than the latest version. For Windows, the contents of the route folder disappear.",
         "defalut_edit_help" : "Describe it here",
         "markup_enabled" : "Markup enabled",
+        "many_delete_help" : "Please write down the document[s] name one by one on the line.",
+        "sqlite_only" : "SQLite only",
         "_comment_3.1_" : "Error",
-            "update_error" : "Auto update is not support.",
+            "update_error" : "Auto update is not supported.",
             "inter_error" : "Internal error.",
             "authority_error" : "Insufficient privileges.",
             "no_login_error" : "Non-login status.",
-            "no_exist_user_error" : "Account does not exist.",
-            "no_admin_block_error" : "Administrators can not block, check.",
-            "skin_error" : "This skin is not support setting.",
+            "no_exist_user_error" : "The account does not exist.",
+            "no_admin_block_error" : "You cannot block or check administrators.",
+            "skin_error" : "This skin is not support settings.",
             "same_id_exist_error" : "There are users with the same ID.",
             "long_id_error" : "ID must be shorter than 20 characters.",
-            "id_char_error" : "Only hangul, alphabet and space are allowed for ID.",
-            "file_exist_error" : "File does not exist.",
+            "id_char_error" : "Only Korean letters, alphabet and space are allowed for ID.",
+            "file_exist_error" : "The file does not exist.",
             "password_error" : "The password is different.",
             "recaptcha_error" : "Go through the reCAPTCHA.",
-            "file_extension_error" : "Only JPG, GIF, JPEG, PNG, WEBP is possible.",
+            "file_extension_error" : "Only JPG, GIF, JPEG, PNG, WEBP is allowed.",
             "edit_record_error" : "Edit reason can not be more than 500 characters.",
             "same_file_error" : "A file with the same name exists.",
-            "file_capacity_error" : "Maximum file capacity (MB) :",
-            "decument_exist_error" : "The document already exists where you want to move it.",
+            "file_capacity_error" : "Maximum file capacity (MB) : ",
+            "decument_exist_error" : "The document with that title already exists.",
             "password_diffrent_error" : "Reconfirm password and input password are different.",
             "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.",
+            "topic_long_error" : "The discussion[s] topic must not exceed 256 characters.",
             "email_error" : "No one has this email.",
             "regex_error" : "There is an error in the regular expression.",
-            "decument_404_error" : "This document does not exist."
-}
+            "decument_404_error" : "This document does not exist.",
+            "fast_edit_error" : "You can edit another document after this period (Second(s)) : ",
+            "too_many_dec_error" : "This feature is not supported because there are too many documents."
+}

+ 59 - 45
language/ko-KR.json

@@ -1,9 +1,9 @@
 {
     "document_name": "문서명",
     "non_login_alert": "비로그인 알림",
-    "hide": "숨기기",
+    "hide": "숨",
     "discussion_acl": "토론 ACL",
-    "ongoing": "진행중",
+    "ongoing": "진행 중",
     "user_tool": "사용자 도구",
     "compare_target": "비교 대상 이름",
     "email_title": "이메일 제목",
@@ -14,7 +14,7 @@
     "move_history": "이동 기록",
     "register": "회원가입",
     "reset_user_text": "암호 초기화 완료 문구",
-    "no_register": "가입불가",
+    "no_register": "가입 불가",
     "view_acl": "읽기 ACL",
     "notice": "알림",
     "login": "로그인",
@@ -36,14 +36,14 @@
     "history_hide_authority": "역사 숨김 권한",
     "go": "이동",
     "document_acl": "문서 ACL",
-    "secret_key": "비밀키",
+    "secret_key": "비밀 키",
     "raw": "원본",
     "file": "파일",
     "state": "상태",
     "authorize": "권한 부여",
     "check_user": "사용자 검사",
     "email_acl": "이메일을 가진 유저만",
-    "email_error": "이런 이메일을 가진 사용자가 없습니다.",
+    "email_error": "해당 이메일을 가진 사용자가 존재하지 않습니다.",
     "version": "버전",
     "open": "열기",
     "update_branch": "업데이트를 가져올 브랜치",
@@ -56,9 +56,9 @@
     "connect": "연결",
     "edit_record": "편집 기록",
     "preview": "미리보기",
-    "view" : "보기",
+    "view": "보기",
     "no_login_error": "비로그인 상태입니다.",
-    "upload": "업로드",
+    "upload": "파일 올리기",
     "user_name": "사용자 이름",
     "member_acl": "가입자만",
     "search": "검색",
@@ -66,13 +66,13 @@
     "edit_filter": "편집 필터",
     "no_exist_user_error": "계정이 존재하지 않습니다.",
     "compare": "비교",
-    "password_error": "비밀번호가 다릅니다.",
+    "password_error": "비밀번호가 올바르지 않습니다.",
     "default": "기본값",
     "wiki_name": "위키 이름",
     "acl_document_list": "ACL 문서 목록",
     "connection": "연결",
-    "oauth_disabled": "관리자가 이 기능을 비활성화시켰습니다.",
-    "random": "랜덤",
+    "oauth_disabled": "관리자가 이 기능을 비활성화 시켰습니다.",
+    "random": "무작위",
     "filter": "필터",
     "band_blocked": "대역 차단됨",
     "password_diffrent_error": "입력한 비밀번호와 비밀번호 확인이 서로 다릅니다.",
@@ -81,10 +81,10 @@
     "all_acl": "모든 사용자",
     "send": "전송",
     "not_sure": "확실하지 않음",
-    "file_name_error": "파일 이름에는 알파벳, 한글, 공백, 밑줄  빼기 기호만 사용할 수 있습니다.",
+    "file_name_error": "파일 이름에는 알파벳, 한글, 공백, 밑줄  빼기 기호만 사용할 수 있습니다.",
     "pass": "넘기기",
-    "recaptcha_error": "'나는 로봇이 아닙니다'를 통해 reCAPTCHA를 수행하세요.",
-    "file_capacity_error": "최대 파일 크기 (MB) :",
+    "recaptcha_error": "'로봇이 아닙니다'를 통해 reCAPTCHA를 통과하세요.",
+    "file_capacity_error": "최대 파일 크기 (MB) : ",
     "setting": "설정",
     "end": "끝",
     "error": "오류",
@@ -101,22 +101,22 @@
     "limitless": "무기한",
     "normal": "일반",
     "reset_user_ok": "검사 성공",
-    "in_progress": "진행중",
+    "in_progress": "진행 중",
     "under_category": "하위 분류",
     "range": "범위",
     "edit_filter_rule": "편집 필터 규칙",
     "oauth_connection": "Oauth 연결",
     "hide_ip": "IP 숨기기",
-    "topic_tool": "토론 도구",
+    "topic_tool": "토론 관리 도구",
     "user_document": "사용자 문서",
     "id": "아이디",
-    "no_login_warring": "비로그인 상태입니다. 편집시 지금 접속한 IP 명의로 기록됩니다.",
+    "no_login_warring": "비로그인 상태입니다. 편집시 지금 접속한 IP 기록됩니다.",
     "decument_404_error": "이 문서는 존재하지 않습니다.",
     "key": "키",
     "lastest": "최신",
     "now_password": "현재 비밀번호",
-    "same_file_error": "똑같은 이름의 파일이 존재합니다.",
-    "same_id_exist_error": "이미 같은 이름의 계정이 있습니다.",
+    "same_file_error": "동일한 이름의 파일이 존재합니다.",
+    "same_id_exist_error": "이미 동일한 이름의 계정이 존재합니다.",
     "max_file_size": "최대 파일 크기",
     "new_password": "새 비밀번호",
     "authority_use_list": "권한 사용 목록",
@@ -124,32 +124,31 @@
     "main_body": "본문 상단",
     "all_document_list": "모든 문서 목록",
     "update": "업데이트",
-    "login_able": "로그인 가능",
+    "login_able": "로그인 허용",
     "discussion_tool": "토론 도구",
     "regex": "정규표현식",
     "file_filter_add": "파일명 필터 추가",
     "wiki_restart": "위키 엔진 재시작",
-    "oauth_settings_not_found": "관리자가 이 기능을 수행하는데 필요한 데이터를 제공하지 않았습니다.",
+    "oauth_settings_not_found": "관리자가 해당 기능을 수행하기 위해 필요한 데이터를 제공하지 않았습니다.",
     "discussion_raw": "토론 원본",
     "main_setting": "메인 설정",
     "password": "비밀번호",
     "update_error": "자동 업데이트가 지원되지 않습니다.",
     "need_document": "필요한 문서들",
     "sub": "하위",
-    "default_acl": "기본 수정 ACL",
     "template": "틀",
     "user_document_acl": "사용자 문서 ACL",
     "password_confirm": "비밀번호 확인",
     "pinned": "고정",
     "edit_filter_add": "편집 필터 추가",
     "ban_authority": "차단 권한",
-    "file_extension_error": "오직 JPG, GIF, JPEG, PNG, WEBP 만 업로드할 수 있습니다.",
+    "file_extension_error": "오직 JPG, GIF, JPEG, PNG, WEBP 만 업로드 할 수 있습니다.",
     "host": "호스트",
     "email_text": "이메일 내용",
     "recent": "최근",
     "admin_acl": "관리자만",
     "wiki_host": "위키 호스트",
-    "error_404": "는 문서 문구",
+    "error_404": "존재하지 않는 문서 문구",
     "member_list": "사용자 목록",
     "register_text": "회원가입 정책",
     "interwiki_list": "인터위키 목록",
@@ -161,10 +160,10 @@
     "wiki_skin": "위키 스킨",
     "admin_group": "관리자 그룹",
     "all": "전체",
-    "skin_error": "이 스킨은 설정을 지원하지 않습니다.",
+    "skin_error": "해당 스킨은 스킨 설정을 지원하지 않습니다.",
     "member": "가입자",
     "backlink": "역링크",
-    "no_admin_block_error": "관리자는 검사, 차단을 수행할 수 없습니다.",
+    "no_admin_block_error": "관리자는 검사, 차단을 할 수 없습니다.",
     "recaptcha": "reCAPTCHA",
     "create": "생성",
     "restart": "재시작",
@@ -172,7 +171,7 @@
     "edit_bottom_text": "편집창 하단 문구",
     "authority": "권한",
     "document": "문서",
-    "decument_exist_error": "이동하려는 이름에 이미 문서가 존재합니다.",
+    "decument_exist_error": "이동하려는 문서에 이미 문서가 존재합니다.",
     "skin_setting": "스킨 설정",
     "discussion_list": "토론 목록",
     "restart_required": "재시작 필요",
@@ -187,11 +186,11 @@
     "google_email": "Google 이메일",
     "previous": "이전",
     "name_or_ip_or_regex": "ID or IP or 정규식",
-    "editor": "에디터",
-    "wiki_secret_key": "위키 비밀키",
+    "editor": "편집자",
+    "wiki_secret_key": "위키 비밀 키",
     "band_ban": "대역 차단",
     "http_warring": "경고 : HTTPS 연결을 사용하지 않는다면 개인정보가 유출될 수 있습니다. 이 사항에 의해 입는 피해는 사용자에게 책임이 있음을 알려드립니다.",
-    "update_warring": "최신 버전보다 0.2 버전 이상 낮은 경우 수동 업데이트를 권장 드립니다. 윈도우의 경우 route 폴더의 내용이 사라집니다.",
+    "update_warring": "최신 버전보다 0.2 버전 이상 낮은 경우 수동 업데이트를 권장니다. 윈도우의 경우 route 폴더의 내용이 사라집니다.",
     "discussion_name": "토론명",
     "discussion": "토론",
     "main": "메인",
@@ -200,10 +199,10 @@
     "interwiki_add": "인터위키 추가",
     "return": "돌아가기",
     "logout": "로그아웃",
-    "bottom_text": "하단 텍스트",
+    "bottom_text": "하단 내용",
     "30_day": "30일",
-    "topic_long_error": "토론 이름이 256자를 넘지 않아야 합니다.",
-    "error_401": "ACL 기 제한 문서 문구",
+    "topic_long_error": "토론 이름은 256자를 넘을 수 없습니다.",
+    "error_401": "ACL 기 제한 문서 문구",
     "history": "역사",
     "admin_group_list": "관리자 그룹 목록",
     "time": "시간",
@@ -215,17 +214,17 @@
     "writer": "작성자",
     "oauth_signin_facebook": "페이스북 아이디로 로그인",
     "long_id_error": "ID는 20자보다 짧아야 합니다.",
-    "edit_record_error": "수정 요약은 500자를 넘길 수 없습니다.",
+    "edit_record_error": "사유는 500자를 넘을 수 없습니다.",
     "revert": "복원",
     "discussion_authority": "토론 관리 권한",
     "user_setting": "사용자 설정",
     "admin_list": "관리자 목록",
     "add": "추가",
-    "check_key": "인증키 검사",
+    "check_key": "인증 키 확인",
     "file_filter_list": "파일명 필터 목록",
     "5_day": "5일",
     "email_filter_list": "이메일 필터 목록",
-    "user_reset_sign": "사용자의 계정 정보가 다음과 같이 변경 되었습니다.",
+    "user_reset_sign": "사용자의 계정 정보가 다음과 같이 변경되었습니다.",
     "ban_period": "차단 기간",
     "use_push_alarm": "푸쉬 알림 사용",
     "email_filter_add": "이메일 필터 추가",
@@ -244,14 +243,13 @@
     "user_head": "사용자 <HEAD>",
     "agreement": "동의",
     "stop": "중지",
-    "ie_no_data_required": "이 기능을 수행하는데 필요한 데이터가 제공되지 않았습니다.",
+    "ie_no_data_required": "이 기능을 수행하기 위해 필요한 데이터가 제공되지 않았습니다.",
     "port": "포트",
-    "reload": "다시 로드",
+    "reload": "새로고침",
     "indexing": "DB 인덱싱",
     "topic_state": "토론 상태",
     "watchlist": "주시 목록",
     "main_page": "대문",
-    "default_discussion_acl": "기본 토론 ACL",
     "user": "사용자",
     "skin_info": "스킨 정보",
     "new_connection": "연결...",
@@ -260,7 +258,7 @@
     "recent_change": "최근 편집",
     "destruction": "취소",
     "count": "기여 횟수",
-    "main_head": "전역 <HEAD>",
+    "main_head": "메인 <HEAD>",
     "recent_ban": "최근 차단",
     "google_app_password": "Google 앱 비밀번호",
     "id_filter_list": "ID 필터 목록",
@@ -297,9 +295,25 @@
     "last_edit_time": "최근 수정 시각",
     "link": "링크",
     "icon": "아이콘",
-    "topic_setting" : "토론 설정",
-    "old_page" : "오래된 문서",
-    "skin_set" : "스킨 설정",
-    "edit_help" : "편집창 문구",
-    "defalut_edit_help" : "이곳에 내용을 써주세요"
-}
+    "topic_setting": "토론 설정",
+    "old_page": "오래된 문서",
+    "skin_set": "스킨 설정",
+    "edit_help": "편집 창 문구",
+    "defalut_edit_help": "이곳에 내용을 입력해 주세요.",
+    "many_delete": "대량 삭제",
+    "many_delete_help": "한 줄에 한 개씩 적어주세요.",
+    "content": "내용",
+    "upload_acl": "파일 업로드 ACL",
+    "topic_delete": "토론 삭제",
+    "edit_req": "편집 요청",
+    "edit_req_check": "편집 요청 검사",
+    "sqlite_only": "SQLite만",
+    "off": "끄기",
+    "slow_edit": "편집 속도 제한 시간",
+    "public_key": "공개 키",
+    "fast_edit_error": "편집 속도가 너무 빠릅니다. 제한 (초) : ",
+    "main_acl_setting": "기본 ACL 설정",
+    "edit_req_acl": "편집 요청 ACL",
+    "history_add" : "역사 추가",
+    "too_many_dec_error" : "문서 수가 너무 많아서 지원하지 않는 기능 입니다."
+}

+ 4 - 3
readme-en.md

@@ -54,10 +54,10 @@ You can clone this repository by entering the following command at the terminal
 
 # Contribute
 openNAMU may have some untested bugs. Your use of openNAMU and bug discovery will help develop openNAMU.
-[Create Issues](https://github.com/2du/openNAMU/issues/new)
+[[Create Issues]](https://github.com/2du/openNAMU/issues/new)
 
-openNAMU is open source project. Add new features and request pull requests. 
-[Create Pull Requests](https://github.com/2du/openNAMU/compare)
+openNAMU is a complete open source project. Add new features and create pull requests.
+[[Create Pull Requests]](https://github.com/2du/openNAMU/compare)
 
 # Lisence
 openNAMU is protected by [BSD 3-Clause License](./LICNESE). Please refer to the documentation for details.
@@ -79,3 +79,4 @@ openNAMU is protected by [BSD 3-Clause License](./LICNESE). Please refer to the
 
 # Etc.
  * Owner rights are granted to the first registor.
+ * [Test Server](http://namu.ml)

+ 3 - 2
readme.md

@@ -18,7 +18,7 @@
 ## 시작하기
 오픈나무는 파이썬 환경에서 동작하는 파이썬 애플리케이션으로, 파이썬 환경을 필요로 합니다.
 
-쉬운 오픈나무 설치를 위해 오픈나무 가이드를 따로 생성해두었으며, [이곳](https://github.com/2du/openNAMU/wiki/%EC%84%A4%EC%B9%98%EB%B2%95)에서 확인하실 수 있습니다.
+쉬운 오픈나무 설치를 위해 오픈나무 가이드를 따로 생성해두었으며, [이곳](https://github.com/openNAMU/openNAMU-Guide)에서 확인하실 수 있습니다.
 
 ## 클론
 아래 명령을 터미널(명령 프롬프트)에 입력하여 본 리포지토리를 클론할 수 있습니다.
@@ -38,7 +38,7 @@
 
 ### 포함된 외부 프로젝트
  * Quotes icon - [Dave Gandy](http://www.flaticon.com/free-icon/quote-left_25672)
- * Syntax highlighting - [highlightjs](https://highlightjs.org/) 
+ * Syntax highlighting - [highlightjs](https://highlightjs.org/)
  * Numerical expression - [MathJax](https://www.mathjax.org/)
  * Handling Keyboard Shortcuts [shortcut.js](http://www.openjs.com/scripts/events/keyboard_shortcuts/)
 
@@ -53,3 +53,4 @@
 
 ## 기타
  * 첫 가입자에게 소유자 권한이 부여됩니다.
+ * [테스트 서버](http://namu.ml)

+ 12 - 6
route/alarm.py

@@ -3,19 +3,25 @@ from .tool.func import *
 def alarm_2(conn):
     curs = conn.cursor()
 
-    data = '<ul>'    
-    
-    curs.execute(db_change("select data, date from alarm where name = ? order by date desc"), [ip_check()])
+    num = int(number_check(flask.request.args.get('num', '1')))
+    if num * 50 > 0:
+        sql_num = num * 50 - 50
+    else:
+        sql_num = 0
+
+    data = '<ul>'
+
+    curs.execute(db_change("select data, date from alarm where name = ? order by date desc limit ?, 50"), [ip_check(), sql_num])
     data_list = curs.fetchall()
     if data_list:
         data = '<a href="/del_alarm">(' + load_lang('delete') + ')</a><hr class=\"main_hr\">' + data
 
         for data_one in data_list:
             data += '<li>' + data_one[0] + ' (' + data_one[1] + ')</li>'
-    
-    data += '</ul>'
 
-    return easy_minify(flask.render_template(skin_check(), 
+    data += '</ul>' + next_fix('/alarm?num=', num, data_list)
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('notice'), wiki_set(), custom(), other2([0, 0])],
         data = data,
         menu = [['user', load_lang('return')]]

+ 1 - 1
route/alarm_del.py

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

+ 1 - 1
route/api_raw.py

@@ -8,7 +8,7 @@ def api_raw_2(conn, name):
         data = curs.fetchall()
         if data:
             json_data = { "title" : name, "data" : render_set(title = name, data = data[0][0], s_data = 1) }
-        
+
             return flask.jsonify(json_data)
         else:
             return flask.jsonify({})

+ 1 - 1
route/api_recent_change.py

@@ -14,7 +14,7 @@ def api_recent_change_2(conn):
     if page * num > 0:
         page = page * num - num
     else:
-        page = 0   
+        page = 0
 
     curs.execute(db_change('' + \
         'select id, title, date, ip, send, leng from history ' + \

+ 13 - 7
route/api_search.py

@@ -14,14 +14,20 @@ def api_search_2(conn, name):
     if page * num > 0:
         page = page * num - num
     else:
-        page = 0      
+        page = 0
 
-    curs.execute(db_change("" + \
-        "select distinct title, case when title like ? then 'title' else 'data' " + \
-        "end from data where title like ? or data like ? order by case " + \
-        "when title like ? then 1 else 2 end limit ?, ?"),
-        ['%' + name + '%', '%' + name + '%', '%' + name + '%', '%' + name + '%', page, num]
-    )
+    curs.execute(db_change('select data from other where name = "count_all_title"'))
+    if int(curs.fetchall()[0][0]) < 30000:
+        curs.execute(db_change("" + \
+            "select distinct title, case when title like ? then 'title' else 'data' " + \
+            "end from data where title like ? or data like ? order by case " + \
+            "when title like ? then 1 else 2 end limit ?, ?"),
+            ['%' + name + '%', '%' + name + '%', '%' + name + '%', '%' + name + '%', page, num]
+        )
+    else:
+        curs.execute(db_change("select title from data where title like ? order by title limit ?, 50"),
+            ['%' + name + '%', sql_num]
+        )
     all_list = curs.fetchall()
     if all_list:
         return flask.jsonify(all_list)

+ 6 - 0
route/api_sha224.py

@@ -0,0 +1,6 @@
+from .tool.func import *
+
+def api_sha224_2(conn, data):
+    curs = conn.cursor()
+
+    return flask.jsonify({ "data" : sha224_replace(data) })

+ 36 - 28
route/api_topic_sub.py

@@ -1,12 +1,16 @@
 from .tool.func import *
 
-def api_topic_sub_2(conn, name, sub, time):
+def api_topic_sub_2(conn, topic_num):
     curs = conn.cursor()
 
+    topic_change_data = topic_change(topic_num)
+    name = topic_change_data[0]
+    sub = topic_change_data[1]
+
     if flask.request.args.get('num', None):
         curs.execute(db_change("select id, data, date, ip, block, top from topic where title = ? and sub = ? and id + 0 = ? + 0 order by id + 0 asc"), [
-            name, 
-            sub, 
+            name,
+            sub,
             flask.request.args.get('num', '')
         ])
     elif flask.request.args.get('top', None):
@@ -18,7 +22,7 @@ def api_topic_sub_2(conn, name, sub, time):
     if data:
         json_data = {}
         admin = admin_check(3)
-                    
+
         for i in data:
             ip = ip_pas(i[3])
 
@@ -33,7 +37,9 @@ def api_topic_sub_2(conn, name, sub, time):
                     t_data_f = ''
                     b_color = 'toron_color_not'
 
-                curs.execute(db_change("select who from re_admin where what = ? order by time desc limit 1"), ['blind (' + name + ' - ' + sub + '#' + str(i[0]) + ')'])
+                curs.execute(db_change("select who from re_admin where what = ? order by time desc limit 1"), [
+                    'blind (' + name + ' - ' + sub + '#' + str(i[0]) + ')'
+                ])
                 who_blind = curs.fetchall()
                 if who_blind:
                     ip += ' (' + who_blind[0][0] + ' B)'
@@ -51,10 +57,10 @@ def api_topic_sub_2(conn, name, sub, time):
                             s_user = g_data[0][0]
                         else:
                             s_user = ''
-                    
+
                 if flask.request.args.get('top', None):
                     t_color = 'toron_color_red'
-                elif i[3] == s_user:
+                elif i[3] == s_user and i[5] != '1':
                     t_color = 'toron_color_green'
                 elif i[5] == '1':
                     t_color = 'toron_color_blue'
@@ -62,27 +68,27 @@ def api_topic_sub_2(conn, name, sub, time):
                     t_color = 'toron_color'
 
                 if admin == 1 or b_color != 'toron_color_not':
-                    ip += ' <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/admin/' + i[0] + '">(' + load_lang('discussion_tool') + ')</a>'
-                    
+                    ip += ' <a href="/thread/' + str(topic_num) + '/admin/' + i[0] + '">(' + load_lang('discussion_tool') + ')</a>'
+
                 if t_data_f == '':
                     t_data_f = '[br]'
-            
-                all_data = '''
-                    <table id="toron">
-                        <tbody>
-                            <tr>
-                                <td id="''' + t_color + '''">
-                                    <a href="javascript:void(0);" id="''' + i[0] + '">#' + i[0] + '</a> ' + ip + ' <span style="float: right;">' + i[2] + '''</span>
-                                </td>
-                            </tr>
-                            <tr>
-                                <td id="''' + b_color + '">' + render_set(data = t_data_f, include = 'topic_' + i[0]) + '''</td>
-                            </tr>
-                        </tbody>
-                    </table>
-                    <hr class="main_hr">
-                '''
-                
+
+                all_data = '' + \
+                    '<table id="toron">' + \
+                        '<tbody>' + \
+                            '<tr>' + \
+                               '<td id="' + t_color + '">' + \
+                                    '<a href="javascript:void(0);" id="' + i[0] + '">#' + i[0] + '</a> ' + ip + ' <span style="float: right;">' + i[2] + '</span>' + \
+                                '</td>' + \
+                            '</tr>' + \
+                            '<tr>' + \
+                                '<td id="' + b_color + '">' + render_set(data = t_data_f, include = 'topic_' + i[0]) + '</td>' + \
+                            '</tr>' + \
+                        '</tbody>' + \
+                    '</table>' + \
+                    '<hr class="main_hr">' + \
+                ''
+
                 json_data[i[0]] = {
                     "data" : all_data
                 }
@@ -90,7 +96,9 @@ def api_topic_sub_2(conn, name, sub, time):
                 if i[4] != 'O' or (i[4] == 'O' and admin == 1):
                     t_data_f = i[1]
                 else:
-                    curs.execute(db_change("select who from re_admin where what = ? order by time desc limit 1"), ['blind (' + name + ' - ' + sub + '#' + str(i[0]) + ')'])
+                    curs.execute(db_change("select who from re_admin where what = ? order by time desc limit 1"), [
+                        'blind (' + name + ' - ' + sub + '#' + str(i[0]) + ')'
+                    ])
                     who_blind = curs.fetchall()
                     if who_blind:
                         t_data_f = '[[user:' + who_blind[0][0] + ']] block'
@@ -100,7 +108,7 @@ def api_topic_sub_2(conn, name, sub, time):
                 json_data[i[0]] = {
                     "data" : t_data_f,
                     "date" : i[2],
-                    "ip" : i[3],
+                    "ip" : ip_pas(i[3], 1),
                     "block" : i[4],
                 }
 

+ 26 - 18
route/api_user_info.py

@@ -7,6 +7,9 @@ def api_user_info_2(conn, name):
         plus_d = ''
         plus_t = []
 
+        curs.execute(db_change("delete from ban where (end < ? and end like '2%')"), [get_time()])
+        conn.commit()
+
         plus_d = '''
             <table class="user_info_table">
                 <tbody>
@@ -25,7 +28,7 @@ def api_user_info_2(conn, name):
                 </tbody>
             </table>
         '''
-        
+
         curs.execute(db_change("select acl from user where id = ?"), [name])
         data = curs.fetchall()
         if data:
@@ -39,28 +42,33 @@ def api_user_info_2(conn, name):
         if ban_check(name) == 0:
             plus_t += [load_lang('normal')]
         else:
-            match = re.search("^([0-9]{1,3}\.[0-9]{1,3})", name)
-            if match:
-                match = match.groups()[0]
-            else:
-                match = '-'
+            plus_t += [load_lang('blocked') + '<br>']
 
-            curs.execute(db_change("select end, login, band from ban where block = ? or block = ?"), [name, match])
-            block_data = curs.fetchall()
-            if block_data:
-                if block_data[0][0] != '':
-                    plus_t += [load_lang('period') + ' : ' + block_data[0][0]]
-                else:
-                    plus_t += [load_lang('limitless')]
+            match = re.search("^([0-9]{1,3}\.[0-9]{1,3})", name)
+            match = match.groups()[0] if match else '-'
+            regex_ban = 0
 
-                if block_data[0][1] != '':
-                    plus_t += [load_lang('login_able')]
+            curs.execute(db_change("select login, block, end, why from ban where band = 'regex'"))
+            for test_r in curs.fetchall():
+                if re.compile(test_r[1]).search(name):
+                    plus_t[1] += load_lang('type') + ' : ' + load_lang('regex')
+                    plus_t[1] += '<br>' + load_lang('period') + ' : ' + (test_r[2] if test_r[2] != '' else load_lang('limitless'))
+                    plus_t[1] += ('<br>' + load_lang('login_able') if test_r[0] == 'O' else '')
+                    plus_t[1] += ('<br>' + load_lang('why') + ' : ' + test_r[3] if test_r[3] != '' else '')
+                    regex_ban = 1
 
-                if block_data[0][2] == 'O':
-                    plus_t += [load_lang('band_blocked')]
+            if regex_ban == 0:
+                curs.execute(db_change("select end, login, band, why from ban where block = ? or block = ?"), [name, match])
+                block_data = curs.fetchall()
+                if block_data:
+                    plus_t[1] += load_lang('type') + ' : ' + (load_lang('band_blocked') if block_data[0][2] == 'O' else load_lang('normal'))
+                    plus_t[1] += (' (' + load_lang('login_able') + ')' if block_data[0][1] != '' else '')
+                    plus_t[1] += '<br>' + load_lang('period') + ' : ' + (block_data[0][0] if block_data[0][0] != '' else load_lang('limitless'))
+                    plus_t[1] += ('<br>' + load_lang('band_blocked') if block_data[0][2] == 'O' else '')
+                    plus_t[1] += ('<br>' + load_lang('why') + ' : ' + block_data[0][3] if block_data[0][3] != '' else '')
 
         plus_d = plus_d.format(ip_pas(name), plus_t[0], plus_t[1])
 
         return flask.jsonify({ "data" : plus_d })
     else:
-        pass
+        return flask.jsonify({})

+ 1 - 1
route/api_version.py

@@ -21,7 +21,7 @@ def api_version_2(conn, r_ver, c_ver):
                 n_ver = json_data[up_data]['r_ver']
         except:
             pass
-        
+
     json_data = { "version" : r_ver, "db_version" : c_ver, "lastest_version" : n_ver  }
 
     return flask.jsonify(json_data)

+ 3 - 3
route/api_w.py

@@ -13,7 +13,7 @@ def api_w_2(conn, name):
         if acl_check(name, 'render') != 1:
             if flask.request.method == 'POST':
                 g_data = render_set(title = name, data = flask.request.form.get('data', ''), num = 2)
-                
+
                 return flask.jsonify({ "title" : name, "data" : g_data[0], "js_data" : g_data[1] })
             else:
                 curs.execute(db_change("select data from data where title = ?"), [name])
@@ -22,10 +22,10 @@ def api_w_2(conn, name):
                     if flask.request.args.get('include', 'include_1'):
                         include_re = re.compile('\[include\(((?:(?!\)\]).)+)\)\]', re.I)
                         category_re = re.compile('\[\[(?:(?:category|분류):(?:(?!\[\[|\]\]).)+)\]\]', re.I)
-                        
+
                         json_data = include_re.sub('', data[0][0])
                         json_data = category_re.sub('', json_data, )
-                        
+
                         g_data = render_set(title = name, data = json_data, num = 2, include = flask.request.args.get('include', 'include_1'))
                     else:
                         json_data = g_data[0]

+ 46 - 30
route/edit.py

@@ -4,8 +4,13 @@ def edit_2(conn, name):
     curs = conn.cursor()
 
     ip = ip_check()
+    section = flask.request.args.get('section', None)
+
+    curs.execute(db_change("select data from data where title = ?"), [name])
+    old = curs.fetchall()
+
     if acl_check(name) == 1:
-        return re_error('/ban')
+        return redirect('/edit_req/' + url_pas(name))
     
     if flask.request.method == 'POST':
         if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
@@ -13,33 +18,44 @@ def edit_2(conn, name):
         else:
             captcha_post('', 0)
 
-        if flask.request.form.get('otent', '') == flask.request.form.get('content', ''):
+        if slow_edit_check() == 1:
+            return re_error('/error/24')
+
+        today = get_time()
+        content = flask.request.form.get('content', '')
+
+        if flask.request.form.get('otent', '') == content:
             return redirect('/w/' + url_pas(name))
-            
-        if edit_filter_do(flask.request.form.get('content', '')) == 1:
+        
+        if edit_filter_do(content) == 1:
             return re_error('/error/21')
 
-        today = get_time()
-        content = savemark(flask.request.form.get('content', ''))
+        content = savemark(content)
         
-        curs.execute(db_change("select data from data where title = ?"), [name])
-        old = curs.fetchall()
         if old:
             leng = leng_check(len(flask.request.form.get('otent', '')), len(content))
             
-            if flask.request.args.get('section', None):
+            if section:
                 content = old[0][0].replace(flask.request.form.get('otent', ''), content)
-                
-            curs.execute(db_change("update data set data = ? where title = ?"), [content, name])
         else:
             leng = '+' + str(len(content))
-            
+
+        if old:
+            curs.execute(db_change("update data set data = ? where title = ?"), [content, name])
+        else:
             curs.execute(db_change("insert into data (title, data) values (?, ?)"), [name, content])
 
-        curs.execute(db_change("select user from scan where title = ?"), [name])
-        for _ in curs.fetchall():
-            curs.execute(db_change("insert into alarm (name, data, date) values (?, ?, ?)"), [ip, ip + ' - <a href="/w/' + url_pas(name) + '">' + name + '</a> (Edit)', today])
+            curs.execute(db_change('select data from other where name = "count_all_title"'))
+            curs.execute(db_change("update other set data = ? where name = 'count_all_title'"), [str(int(curs.fetchall()[0][0]) + 1)])
 
+        curs.execute(db_change("select user from scan where title = ?"), [name])
+        for scan_user in curs.fetchall():
+            curs.execute(db_change("insert into alarm (name, data, date) values (?, ?, ?)"), [
+                scan_user[0],
+                ip + ' | <a href="/w/' + url_pas(name) + '">' + name + '</a> | Edit', 
+                today
+            ])
+                
         history_plus(
             name,
             content,
@@ -62,17 +78,15 @@ def edit_2(conn, name):
         
         return redirect('/w/' + url_pas(name))
     else:            
-        curs.execute(db_change("select data from data where title = ?"), [name])
-        new = curs.fetchall()
-        if new:
-            if flask.request.args.get('section', None):
-                data = re.sub('\n(?P<in>={1,6})', '<br>\g<in>', html.escape('\n' + re.sub('\r\n', '\n', new[0][0]) + '\n'))
+        if old:
+            if section:
+                data = re.sub('\n(?P<in>={1,6})', '<br>\g<in>', html.escape('\n' + re.sub('\r\n', '\n', old[0][0]) + '\n'))
                 i = 0
 
                 while 1:
                     g_data = re.search('((?:<br>)(?:(?:(?!\n|<br>).)+)(?:\n*(?:(?:(?!<br>).)+\n*)+)?)', data)
                     if g_data:
-                        if int(flask.request.args.get('section', '1')) - 1 == i:
+                        if int(section) - 1 == i:
                             data = html.unescape(re.sub('<br>(?P<in>={1,6})', '\n\g<in>', g_data.groups()[0]))
                             
                             break
@@ -83,26 +97,28 @@ def edit_2(conn, name):
                     else:
                         break
             else:
-                data = new[0][0]
+                data = old[0][0]
         else:
             data = ''
             
         data_old = data
-        
-        if not flask.request.args.get('section', None):
+        get_name = ''
+
+        if not section:
             get_name =  '''
                 <a href="/manager/15?plus=''' + url_pas(name) + '">(' + load_lang('load') + ')</a> <a href="/edit_filter">(' + load_lang('edit_filter_rule') + ''')</a>
                 <hr class=\"main_hr\">
             '''
-        else:
-            get_name = ''
             
         if flask.request.args.get('plus', None):
             curs.execute(db_change("select data from data where title = ?"), [flask.request.args.get('plus', 'test')])
             get_data = curs.fetchall()
             if get_data:
                 data = get_data[0][0]
-                get_name = ''
+
+        save_button = load_lang('save')
+        menu_plus = [['delete/' + url_pas(name), load_lang('delete')], ['move/' + url_pas(name), load_lang('move')]]
+        sub = load_lang('edit')
 
         curs.execute(db_change('select data from other where name = "edit_bottom_text"'))
         sql_d = curs.fetchall()
@@ -119,7 +135,7 @@ def edit_2(conn, name):
             p_text = load_lang('defalut_edit_help')
 
         return easy_minify(flask.render_template(skin_check(), 
-            imp = [name, wiki_set(), custom(), other2([' (' + load_lang('edit') + ')', 0])],
+            imp = [name, wiki_set(), custom(), other2([' (' + sub + ')', 0])],
             data =  get_name + '''
                 <form method="post">
                     <script>do_stop_exit();</script>
@@ -130,12 +146,12 @@ def edit_2(conn, name):
                     <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
                     <hr class=\"main_hr\">
                     ''' + captcha_get() + ip_warring() + '''
-                    <button id="save" type="submit" onclick="go_save_zone = 1;">''' + load_lang('save') + '''</button>
+                    <button id="save" type="submit" onclick="go_save_zone = 1;">''' + save_button + '''</button>
                     <button id="preview" type="button" onclick="load_preview(\'''' + url_pas(name) + '\')">' + load_lang('preview') + '''</button>
                 </form>
                 ''' + b_text + '''
                 <hr class=\"main_hr\">
                 <div id="see_preview"></div>
             ''',
-            menu = [['w/' + url_pas(name), load_lang('return')], ['delete/' + url_pas(name), load_lang('delete')], ['move/' + url_pas(name), load_lang('move')]]
+            menu = [['w/' + url_pas(name), load_lang('return')]] + menu_plus
         ))

+ 18 - 12
route/edit_delete.py

@@ -6,33 +6,36 @@ def edit_delete_2(conn, name, app_var):
     ip = ip_check()
     if acl_check(name) == 1:
         return re_error('/ban')
-    
+
     if flask.request.method == 'POST':
         if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
             return re_error('/error/13')
         else:
             captcha_post('', 0)
 
+        if slow_edit_check() == 1:
+            return re_error('/error/24')
+
         curs.execute(db_change("select data from data where title = ?"), [name])
         data = curs.fetchall()
         if data:
             today = get_time()
             leng = '-' + str(len(data[0][0]))
-            
+
             history_plus(
-                name, 
-                '', 
-                today, 
-                ip, 
-                flask.request.form.get('send', ''), 
+                name,
+                '',
+                today,
+                ip,
+                flask.request.form.get('send', ''),
                 leng,
                 'delete'
             )
-            
+
             curs.execute(db_change("select title, link from back where title = ? and not type = 'cat' and not type = 'no'"), [name])
             for data in curs.fetchall():
                 curs.execute(db_change("insert into back (title, link, type) values (?, ?, 'no')"), [data[0], data[1]])
-            
+
             curs.execute(db_change("delete from back where link = ?"), [name])
             curs.execute(db_change("delete from data where title = ?"), [name])
             conn.commit()
@@ -42,16 +45,19 @@ def edit_delete_2(conn, name, app_var):
             file_check = file_check.groups()
             os.remove(os.path.join(
                 app_var['path_data_image'],
-                hashlib.sha224(bytes(file_check[0], 'utf-8')).hexdigest() + '.' + file_check[1]
+                sha224_replace(file_check[0], 'utf-8') + '.' + file_check[1]
             ))
-            
+
+        curs.execute(db_change('select data from other where name = "count_all_title"'))
+        curs.execute(db_change("update other set data = ? where name = 'count_all_title'"), [str(int(curs.fetchall()[0][0]) - 1)])
+
         return redirect('/w/' + url_pas(name))
     else:
         curs.execute(db_change("select title from data where title = ?"), [name])
         if not curs.fetchall():
             return redirect('/w/' + url_pas(name))
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('delete') + ')', 0])],
             data =  '''
                     <form method="post">

+ 62 - 0
route/edit_many_delete.py

@@ -0,0 +1,62 @@
+from .tool.func import *
+
+def edit_many_delete_2(conn, app_var):
+    curs = conn.cursor()
+
+    ip = ip_check()
+    if admin_check() != 1:
+        return re_error('/ban')
+
+    if flask.request.method == 'POST':
+        all_title = re.findall(r'([^\n]+)\n', flask.request.form.get('content', '').replace('\r\n', '\n') + '\n')
+        for name in all_title:
+            curs.execute(db_change("select data from data where title = ?"), [name])
+            data = curs.fetchall()
+            if data:
+                today = get_time()
+                leng = '-' + str(len(data[0][0]))
+
+                history_plus(
+                    name,
+                    '',
+                    today,
+                    ip,
+                    flask.request.form.get('send', ''),
+                    leng,
+                    'delete'
+                )
+
+                curs.execute(db_change("select title, link from back where title = ? and not type = 'cat' and not type = 'no'"), [name])
+                for data in curs.fetchall():
+                    curs.execute(db_change("insert into back (title, link, type) values (?, ?, 'no')"), [data[0], data[1]])
+
+                curs.execute(db_change("delete from back where link = ?"), [name])
+                curs.execute(db_change("delete from data where title = ?"), [name])
+                conn.commit()
+
+            file_check = re.search('^file:(.+)\.(.+)$', name)
+            if file_check:
+                file_check = file_check.groups()
+                os.remove(os.path.join(
+                    app_var['path_data_image'],
+                    sha224_replace(file_check[0]) + '.' + file_check[1]
+                ))
+
+            curs.execute(db_change('select data from other where name = "count_all_title"'))
+            curs.execute(db_change("update other set data = ? where name = 'count_all_title'"), [str(int(curs.fetchall()[0][0]) - 1)])
+
+        return redirect('/recent_changes')
+    else:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('many_delete'), wiki_set(), custom(), other2([0, 0])],
+            data = '''
+                <form method="post">
+                    <textarea rows="25" placeholder="''' + load_lang('many_delete_help') + '''" name="content"></textarea>
+                    <hr class=\"main_hr\">
+                    <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
+                    <hr class=\"main_hr\">
+                    <button type="submit">''' + load_lang('delete') + '''</button>
+                </form>
+            ''',
+            menu = [['manager/1', load_lang('return')]]
+        ))     

+ 24 - 21
route/edit_move.py

@@ -12,31 +12,34 @@ def edit_move_2(conn, name):
         else:
             captcha_post('', 0)
 
+        if slow_edit_check() == 1:
+            return re_error('/error/24')
+
         curs.execute(db_change("select title from history where title = ?"), [flask.request.form.get('title', None)])
         if curs.fetchall():
             if admin_check(None, 'merge documents') == 1:
                 curs.execute(db_change("select data from data where title = ?"), [flask.request.form.get('title', None)])
                 data = curs.fetchall()
-                if data:            
+                if data:
                     curs.execute(db_change("delete from data where title = ?"), [flask.request.form.get('title', None)])
                     curs.execute(db_change("delete from back where link = ?"), [flask.request.form.get('title', None)])
-                
+
                 curs.execute(db_change("select data from data where title = ?"), [name])
                 data = curs.fetchall()
-                if data:            
+                if data:
                     curs.execute(db_change("update data set title = ? where title = ?"), [flask.request.form.get('title', None), name])
                     curs.execute(db_change("update back set link = ? where link = ?"), [flask.request.form.get('title', None), name])
-                    
+
                     data_in = data[0][0]
                 else:
                     data_in = ''
 
                 history_plus(
-                    name, 
-                    data_in, 
-                    get_time(), 
-                    ip_check(), 
-                    flask.request.form.get('send', ''), 
+                    name,
+                    data_in,
+                    get_time(),
+                    ip_check(),
+                    flask.request.form.get('send', ''),
                     '0',
                     'marge <a>' + name + '</a> - <a>' + flask.request.form.get('title', 'test') + '</a> move'
                 )
@@ -46,7 +49,7 @@ def edit_move_2(conn, name):
 
                 curs.execute(db_change("select id from history where title = ? order by id + 0 desc limit 1"), [flask.request.form.get('title', None)])
                 data = curs.fetchall()
-                
+
                 num = data[0][0]
 
                 curs.execute(db_change("select id from history where title = ? order by id + 0 asc"), [name])
@@ -62,24 +65,24 @@ def edit_move_2(conn, name):
         else:
             curs.execute(db_change("select data from data where title = ?"), [name])
             data = curs.fetchall()
-            if data:            
+            if data:
                 curs.execute(db_change("update data set title = ? where title = ?"), [flask.request.form.get('title', None), name])
                 curs.execute(db_change("update back set link = ? where link = ?"), [flask.request.form.get('title', None), name])
-                
+
                 data_in = data[0][0]
             else:
                 data_in = ''
-                
+
             history_plus(
-                name, 
-                data_in, 
-                get_time(), 
-                ip_check(), 
-                flask.request.form.get('send', ''), 
+                name,
+                data_in,
+                get_time(),
+                ip_check(),
+                flask.request.form.get('send', ''),
                 '0',
                 '<a>' + name + '</a> - <a>' + flask.request.form.get('title', 'test') + '</a> move'
             )
-            
+
             curs.execute(db_change("update back set type = 'no' where title = ? and not type = 'cat' and not type = 'no'"), [name])
             curs.execute(db_change("delete from back where title = ? and not type = 'cat' and type = 'no'"), [flask.request.form.get('title', None)])
 
@@ -87,8 +90,8 @@ def edit_move_2(conn, name):
             conn.commit()
 
             return redirect('/w/' + url_pas(flask.request.form.get('title', None)))
-    else:            
-        return easy_minify(flask.render_template(skin_check(), 
+    else:
+        return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('move') + ')', 0])],
             data =  '''
                     <form method="post">

+ 163 - 0
route/edit_req.py

@@ -0,0 +1,163 @@
+from .tool.func import *
+
+def edit_req_2(conn, name):
+    curs = conn.cursor()
+
+    ip = ip_check()
+    get_ver = flask.request.args.get('r', None)
+    if get_ver:
+        section = None
+    else:
+        section = flask.request.args.get('section', None)
+
+    if acl_check(name) == 1:
+        if acl_check(name, 'edit_req') == 1 or re.search('^user:', name) or ban_check() == 1 or get_ver:
+            return re_error('/ban')
+    else:
+        if not get_ver:
+            return redirect('/edit/' + url_pas(name))
+        else:
+            get_ver = int(number_check(get_ver))
+
+    if not get_ver:
+        curs.execute(db_change("select data from data where title = ?"), [name])
+        old = curs.fetchall()
+        if not old:
+            return redirect('/w/' + url_pas(name))
+    else:
+        curs.execute(db_change("select data, send, ip, date from history where title = ? and id = ? and type = 'req'"), [name, str(get_ver)])
+        old = curs.fetchall()
+        if not old:
+            return redirect('/w/' + url_pas(name))
+
+    if flask.request.method == 'POST':
+        if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
+            return re_error('/error/13')
+        else:
+            captcha_post('', 0)
+
+        if slow_edit_check() == 1:
+            return re_error('/error/24')
+
+        today = get_time()
+        if get_ver:
+            content = old[0][0]
+        else:
+            content = flask.request.form.get('content', '')
+
+            if flask.request.form.get('otent', '') == content:
+                return redirect('/w/' + url_pas(name))
+
+            if edit_filter_do(content) == 1:
+                return re_error('/error/21')
+
+        content = savemark(content)
+
+        if old:
+            leng = leng_check(len(flask.request.form.get('otent', '')), len(content))
+
+            if section:
+                content = old[0][0].replace(flask.request.form.get('otent', ''), content)
+        else:
+            leng = '+' + str(len(content))
+
+        if get_ver:
+            if old:
+                curs.execute(db_change("update data set data = ? where title = ?"), [content, name])
+            else:
+                curs.execute(db_change("insert into data (title, data) values (?, ?)"), [name, content])
+
+                curs.execute(db_change('select data from other where name = "count_all_title"'))
+                curs.execute(db_change("update other set data = ? where name = 'count_all_title'"), [str(int(curs.fetchall()[0][0]) + 1)])
+
+            curs.execute(db_change("select user from scan where title = ?"), [name])
+            for scan_user in curs.fetchall():
+                curs.execute(db_change("insert into alarm (name, data, date) values (?, ?, ?)"), [
+                    scan_user[0],
+                    ip + ' | <a href="/w/' + url_pas(name) + '">' + name + '</a> | Edit',
+                    today
+                ])
+
+            curs.execute(db_change("update history set type = '', send = ? where title = ? and id = ? and ip = ? and date = ? and type = 'req'"), [
+                old[0][1] + ' (' + ip + ' pass)',
+                name,
+                str(get_ver),
+                old[0][2],
+                old[0][3]
+            ])
+
+            curs.execute(db_change("delete from back where link = ?"), [name])
+            curs.execute(db_change("delete from back where title = ? and type = 'no'"), [name])
+
+            render_set(
+                title = name,
+                data = content,
+                num = 1
+            )
+        else:
+            history_plus(
+                name,
+                content,
+                today,
+                ip,
+                flask.request.form.get('send', ''),
+                leng,
+                '',
+                'req'
+            )
+
+        conn.commit()
+
+        if get_ver:
+            return redirect('/w/' + url_pas(name))
+        else:
+            return redirect('/recent_changes?set=req')
+    else:
+        if old:
+            data = old[0][0]
+        else:
+            data = ''
+
+        data_old = data
+        get_name = ''
+
+        save_button = load_lang('edit_req') if not get_ver else load_lang('edit_req_check')
+        menu_plus = [[]]
+        sub = load_lang('edit_req')
+        disable = '' if not get_ver else 'disabled'
+
+        curs.execute(db_change('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 = ''
+
+        curs.execute(db_change('select data from other where name = "edit_help"'))
+        sql_d = curs.fetchall()
+        if sql_d and sql_d[0][0] != '':
+            p_text = sql_d[0][0]
+        else:
+            p_text = load_lang('defalut_edit_help')
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [name, wiki_set(), custom(), other2([' (' + sub + ')', 0])],
+            data =  get_name + '''
+                <form method="post">
+                    <script>do_stop_exit();</script>
+                    ''' + edit_button() + '''
+                    <textarea rows="25" ''' + disable + ''' id="content" placeholder="''' + p_text + '''" name="content">''' + html.escape(re.sub('\n$', '', data)) + '''</textarea>
+                    <textarea id="origin" name="otent">''' + html.escape(re.sub('\n$', '', data_old)) + '''</textarea>
+                    <hr class=\"main_hr\">
+                    <input ''' + disable + ''' placeholder="''' + load_lang('why') + '''" name="send" type="text">
+                    <hr class=\"main_hr\">
+                    ''' + captcha_get() + ip_warring() + '''
+                    <button id="save" type="submit" onclick="go_save_zone = 1;">''' + save_button + '''</button>
+                    <button id="preview" type="button" onclick="load_preview(\'''' + url_pas(name) + '\')">' + load_lang('preview') + '''</button>
+                </form>
+                ''' + b_text + '''
+                <hr class=\"main_hr\">
+                <div id="see_preview"></div>
+            ''',
+            menu = [['w/' + url_pas(name), load_lang('return')]] + menu_plus
+        ))

+ 15 - 12
route/edit_revert.py

@@ -17,7 +17,10 @@ def edit_revert_2(conn, name):
             return re_error('/error/13')
         else:
             captcha_post('', 0)
-    
+
+        if slow_edit_check() == 1:
+            return re_error('/error/24')
+
         curs.execute(db_change("select data from history where title = ? and id = ?"), [name, str(num)])
         data = curs.fetchall()
         if data:
@@ -26,8 +29,8 @@ def edit_revert_2(conn, name):
 
         curs.execute(db_change("delete from back where link = ?"), [name])
         conn.commit()
-        
-        if data:                                
+
+        if data:
             curs.execute(db_change("select data from data where title = ?"), [name])
             data_old = curs.fetchall()
             if data_old:
@@ -36,13 +39,13 @@ def edit_revert_2(conn, name):
             else:
                 leng = '+' + str(len(data[0][0]))
                 curs.execute(db_change("insert into data (title, data) values (?, ?)"), [name, data[0][0]])
-                
+
             history_plus(
-                name, 
-                data[0][0], 
-                get_time(), 
-                ip_check(), 
-                flask.request.form.get('send', ''), 
+                name,
+                data[0][0],
+                get_time(),
+                ip_check(),
+                flask.request.form.get('send', ''),
                 leng,
                 'r' + str(num) + ''
             )
@@ -52,16 +55,16 @@ def edit_revert_2(conn, name):
                 data = data[0][0],
                 num = 1
             )
-            
+
             conn.commit()
-            
+
         return redirect('/w/' + url_pas(name))
     else:
         curs.execute(db_change("select title from history where title = ? and id = ?"), [name, str(num)])
         if not curs.fetchall():
             return redirect('/w/' + url_pas(name))
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('revert') + ')', 0])],
             data =  '''
                     <form method="post">

+ 17 - 17
route/func_upload.py

@@ -3,9 +3,9 @@ from .tool.func import *
 def func_upload_2(conn):
     curs = conn.cursor()
 
-    if ban_check() == 1:
+    if acl_check(None, 'upload') == 1:
         return re_error('/ban')
-    
+
     if flask.request.method == 'POST':
         if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
             return re_error('/error/13')
@@ -18,21 +18,21 @@ def func_upload_2(conn):
 
         if int(wiki_set(3)) * 1024 * 1024 < flask.request.content_length:
             return re_error('/error/17')
-        
+
         value = os.path.splitext(data.filename)[1]
         if not value in ['.jpeg', '.jpg', '.gif', '.png', '.webp', '.JPEG', '.JPG', '.GIF', '.PNG', '.WEBP']:
             return re_error('/error/14')
-    
+
         if flask.request.form.get('f_name', None):
             name = flask.request.form.get('f_name', None) + value
         else:
             name = data.filename
-        
+
         piece = os.path.splitext(name)
         if re.search('[^ㄱ-힣0-9a-zA-Z_\- ]', piece[0]):
             return re_error('/error/22')
 
-        e_data = sha224(piece[0]) + piece[1]
+        e_data = sha224_replace(piece[0]) + piece[1]
 
         curs.execute(db_change("select title from data where title = ?"), ['file:' + name])
         if curs.fetchall():
@@ -44,7 +44,7 @@ def func_upload_2(conn):
             t_re = re.compile(i[0])
             if t_re.search(name):
                 return redirect('/file_filter')
-            
+
         ip = ip_check()
 
         if flask.request.form.get('f_lice_sel', 'direct_input') == 'direct_input':
@@ -63,21 +63,21 @@ def func_upload_2(conn):
                 lice += ' : '  + flask.request.form.get('f_lice', None)
 
             lice += '[[category:' + re.sub('\]', '_', flask.request.form.get('f_lice_sel', None)) + ']]'
-            
+
         if os.path.exists(os.path.join(app_var['path_data_image'], e_data)):
             os.remove(os.path.join(app_var['path_data_image'], e_data))
-            
+
             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))
 
         file_d = '[[file:' + name + ']][br][br]{{{[[file:' + name + ']]}}}[br][br]' + lice
-        
+
         curs.execute(db_change("insert into data (title, data) values (?, ?)"), ['file:' + name, file_d])
         curs.execute(db_change("insert into acl (title, decu, dis, why, view) values (?, 'admin', '', '', '')"), ['file:' + name])
 
         render_set(
-            title = name,
+            title = 'file:' + name,
             data = file_d,
             num = 1
         )
@@ -85,16 +85,16 @@ def func_upload_2(conn):
         history_plus(
             'file:' + name,
             file_d,
-            get_time(), 
-            ip, 
+            get_time(),
+            ip,
             ip,
             '0',
             'upload'
         )
-        
+
         conn.commit()
-        
-        return redirect('/w/file:' + name)      
+
+        return redirect('/w/file:' + name)
     else:
         license_list = '''
             <option value="direct_input">''' + load_lang('direct_input') + '''</option>
@@ -107,7 +107,7 @@ def func_upload_2(conn):
                 <option value="''' + i[0] + '''">''' + i[0] + '''</option>
             '''
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('upload'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
                 <a href="/file_filter">(''' + load_lang('file_filter_list') + ''')</a>

+ 25 - 25
route/give_acl.py

@@ -5,17 +5,17 @@ def give_acl_2(conn, name):
 
     check_ok = ''
     ip = ip_check()
-    
+
     if flask.request.method == 'POST':
         check_data = 'acl (' + name + ')'
     else:
         check_data = None
-    
+
     user_data = re.search('^user:(.+)$', name)
     if user_data:
         if check_data and ip_or_user(ip) != 0:
             return redirect('/login')
-        
+
         if user_data.groups()[0] != ip_check():
             if admin_check(5) != 1:
                 if check_data:
@@ -38,17 +38,17 @@ def give_acl_2(conn, name):
             curs.execute(db_change("update acl set view = ? where title = ?"), [flask.request.form.get('view', ''), name])
         else:
             curs.execute(db_change("insert into acl (title, decu, dis, why, view) values (?, ?, ?, ?, ?)"), [
-                name, 
-                flask.request.form.get('decu', ''), 
-                flask.request.form.get('dis', ''), 
-                flask.request.form.get('why', ''), 
+                name,
+                flask.request.form.get('decu', ''),
+                flask.request.form.get('dis', ''),
+                flask.request.form.get('why', ''),
                 flask.request.form.get('view', '')
             ])
-        
+
         curs.execute(db_change("select title from acl where title = ? and decu = '' and dis = '' and view = ''"), [name])
         if curs.fetchall():
             curs.execute(db_change("delete from acl where title = ?"), [name])
-            
+
         all_d = ''
         for i in ['decu', 'dis', 'view']:
             if flask.request.form.get(i, '') == '':
@@ -59,20 +59,20 @@ def give_acl_2(conn, name):
                 all_d += flask.request.form.get(i, '')
                 if i != 'view':
                     all_d += ' | '
-            
+
         admin_check(5, check_data + ' (' + all_d + ')')
 
         conn.commit()
-            
-        return redirect('/acl/' + url_pas(name))            
+
+        return redirect('/acl/' + url_pas(name))
     else:
         data = '<h2>' + load_lang('document_acl') + '</h2><hr class=\"main_hr\"><select name="decu" ' + check_ok + '>'
-    
+
         if re.search('^user:', name):
             acl_list = ['', 'user', 'all']
         else:
             acl_list = ['', 'user', 'admin', 'owner', '50_edit', 'email']
-        
+
         curs.execute(db_change("select decu from acl where title = ?"), [name])
         acl_data = curs.fetchall()
         for data_list in acl_list:
@@ -80,14 +80,14 @@ def give_acl_2(conn, name):
                 check = 'selected="selected"'
             else:
                 check = ''
-            
+
             data += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
-            
+
         data += '</select>'
-        
+
         if not re.search('^user:', name):
             data += '<hr class=\"main_hr\"><h2>' + load_lang('discussion_acl') + '</h2><hr class=\"main_hr\"><select name="dis" ' + check_ok + '>'
-        
+
             curs.execute(db_change("select dis, why, view from acl where title = ?"), [name])
             acl_data = curs.fetchall()
             for data_list in acl_list:
@@ -95,9 +95,9 @@ def give_acl_2(conn, name):
                     check = 'selected="selected"'
                 else:
                     check = ''
-                    
+
                 data += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
-                
+
             data += '</select>'
 
             data += '<hr class=\"main_hr\"><h2>' + load_lang('view_acl') + '</h2><hr class=\"main_hr\"><select name="view" ' + check_ok + '>'
@@ -106,9 +106,9 @@ def give_acl_2(conn, name):
                     check = 'selected="selected"'
                 else:
                     check = ''
-                    
+
                 data += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
-                
+
             data += '''
                 </select>
                 <hr class=\"main_hr\">
@@ -123,14 +123,14 @@ def give_acl_2(conn, name):
                     <li>owner : ''' + load_lang('owner_acl') + '''</li>
                 </ul>
             '''
-                
+
             if check_ok == '':
                 if acl_data:
                     data += '<hr class=\"main_hr\"><input value="' + html.escape(acl_data[0][1]) + '" placeholder="' + load_lang('why') + '" name="why" type="text" ' + check_ok + '>'
                 else:
                     data += '<hr class=\"main_hr\"><input placeholder="' + load_lang('why') + '" name="why" type="text" ' + check_ok + '>'
-            
-        return easy_minify(flask.render_template(skin_check(), 
+
+        return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('acl') + ')', 0])],
             data =  '''
                 <form method="post">

+ 8 - 8
route/give_admin.py

@@ -4,7 +4,7 @@ def give_admin_2(conn, name):
     curs = conn.cursor()
 
     owner = admin_check()
-    
+
     curs.execute(db_change("select acl from user where id = ?"), [name])
     user = curs.fetchall()
     if not user:
@@ -31,16 +31,16 @@ def give_admin_2(conn, name):
             curs.execute(db_change("update user set acl = 'user' where id = ?"), [name])
         else:
             curs.execute(db_change("update user set acl = ? where id = ?"), [flask.request.form.get('select', None), name])
-        
+
         conn.commit()
-        
-        return redirect('/admin/' + url_pas(name))            
+
+        return redirect('/admin/' + url_pas(name))
     else:
         if admin_check(7) != 1:
-            return re_error('/error/3')            
+            return re_error('/error/3')
 
         div = '<option value="X">X</option>'
-        
+
         curs.execute(db_change('select distinct name from alist order by name asc'))
         for data in curs.fetchall():
             if user[0][0] == data[0]:
@@ -52,8 +52,8 @@ def give_admin_2(conn, name):
                         div += '<option value="' + data[0] + '">' + data[0] + '</option>'
                 else:
                     div += '<option value="' + data[0] + '">' + data[0] + '</option>'
-        
-        return easy_minify(flask.render_template(skin_check(), 
+
+        return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('authorize') + ')', 0])],
             data =  '''
                     <form method="post">

+ 9 - 9
route/give_admin_groups.py

@@ -2,19 +2,19 @@ from .tool.func import *
 
 def give_admin_groups_2(conn, name):
     curs = conn.cursor()
-    
+
     if flask.request.method == 'POST':
         if admin_check(None, 'admin_plus (' + name + ')') != 1:
             return re_error('/error/3')
 
         curs.execute(db_change("delete from alist where name = ?"), [name])
-        
+
         if flask.request.form.get('ban', 0) != 0:
             curs.execute(db_change("insert into alist (name, acl) values (?, 'ban')"), [name])
 
         if flask.request.form.get('toron', 0) != 0:
             curs.execute(db_change("insert into alist (name, acl) values (?, 'toron')"), [name])
-            
+
         if flask.request.form.get('check', 0) != 0:
             curs.execute(db_change("insert into alist (name, acl) values (?, 'check')"), [name])
 
@@ -29,17 +29,17 @@ def give_admin_groups_2(conn, name):
 
         if flask.request.form.get('owner', 0) != 0:
             curs.execute(db_change("insert into alist (name, acl) values (?, 'owner')"), [name])
-            
+
         conn.commit()
-        
+
         return redirect('/admin_plus/' + url_pas(name))
-    else:        
+    else:
         data = '<ul>'
-        
+
         exist_list = ['', '', '', '', '', '', '', '']
 
         curs.execute(db_change('select acl from alist where name = ?'), [name])
-        acl_list = curs.fetchall()    
+        acl_list = curs.fetchall()
         for go in acl_list:
             if go[0] == 'ban':
                 exist_list[0] = 'checked="checked"'
@@ -68,7 +68,7 @@ def give_admin_groups_2(conn, name):
 
         data += '</ul>'
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2(['(' + load_lang('admin_group') + ')', 0])],
             data =  '''
                 <form method="post">

+ 65 - 0
route/give_history_add.py

@@ -0,0 +1,65 @@
+from .tool.func import *
+
+def give_history_add_2(conn, name):
+    curs = conn.cursor()
+
+    ip = ip_check()
+    if admin_check() != 1:
+        return re_error('/ban')
+
+    if flask.request.method == 'POST':
+        admin_check(None, 'history_add (' + name + ')')
+
+        today = get_time()
+        content = flask.request.form.get('content', '')
+        content = savemark(content)
+        leng = '+' + str(len(content))
+
+        history_plus(
+            name,
+            content,
+            today,
+            'Add:' + flask.request.form.get('get_ip', ''),
+            flask.request.form.get('send', ''),
+            leng
+        )
+
+        conn.commit()
+
+        return redirect('/history/' + url_pas(name))
+    else:
+        curs.execute(db_change('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 = ''
+
+        curs.execute(db_change('select data from other where name = "edit_help"'))
+        sql_d = curs.fetchall()
+        if sql_d and sql_d[0][0] != '':
+            p_text = sql_d[0][0]
+        else:
+            p_text = load_lang('defalut_edit_help')
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('history_add'), wiki_set(), custom(), other2([' (' + name + ')', 0])],
+            data = '''
+                <form method="post">
+                    <script>do_stop_exit();</script>
+                    ''' + edit_button() + '''
+                    <textarea rows="25" id="content" placeholder="''' + p_text + '''" name="content"></textarea>
+                    <hr class=\"main_hr\">
+                    <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
+                    <hr class=\"main_hr\">
+                    <input placeholder="''' + load_lang('name') + '''" name="get_ip" type="text">
+                    <hr class=\"main_hr\">
+                    <button id="save" type="submit" onclick="go_save_zone = 1;">''' + load_lang('save') + '''</button>
+                    <button id="preview" type="button" onclick="load_preview(\'''' + url_pas(name) + '\')">' + load_lang('preview') + '''</button>
+                </form>
+                ''' + b_text + '''
+                <hr class=\"main_hr\">
+                <div id="see_preview"></div>
+            ''',
+            menu = [['history/' + url_pas(name), load_lang('return')]]
+        ))

+ 2 - 2
route/give_history_hidden.py

@@ -11,7 +11,7 @@ def give_history_hidden_2(conn, name):
             curs.execute(db_change("update history set hide = '' where title = ? and id = ?"), [name, num])
         else:
             curs.execute(db_change("update history set hide = 'O' where title = ? and id = ?"), [name, num])
-            
+
         conn.commit()
-    
+
     return redirect('/history/' + url_pas(name))

+ 12 - 12
route/give_user_ban.py

@@ -15,7 +15,7 @@ def give_user_ban_2(conn, name):
 
     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')
 
@@ -36,15 +36,15 @@ def give_user_ban_2(conn, name):
             type_d = None
 
         ban_insert(
-            name, 
-            end, 
-            flask.request.form.get('why', ''), 
-            flask.request.form.get('login', ''), 
+            name,
+            end,
+            flask.request.form.get('why', ''),
+            flask.request.form.get('login', ''),
             ip_check(),
             type_d
         )
 
-        return redirect('/block_log')     
+        return redirect('/block_log')
     else:
         if admin_check(1) != 1:
             return re_error('/error/3')
@@ -60,7 +60,7 @@ def give_user_ban_2(conn, name):
                 data = '<ul><li>' + load_lang('limitless') + '</li>'
             else:
                 data = '<ul><li>' + load_lang('period') + ' : ' + end[0][0] + '</li>'
-                
+
             curs.execute(db_change("select block from ban where block = ? and login = 'O'"), [name])
             if curs.fetchall():
                 data += '<li>' + load_lang('login_able') + '</li>'
@@ -72,14 +72,14 @@ def give_user_ban_2(conn, name):
         else:
             if name:
                 main_name = 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:
@@ -94,7 +94,7 @@ def give_user_ban_2(conn, name):
                 plus = '<input type="checkbox" name="login"> ' + load_lang('login_able') + '<hr class=\"main_hr\">'
                 now = 0
                 b_now = load_lang('ban')
-                
+
             time_data = [
                 ['86400', load_lang('1_day')],
                 ['432000‬', load_lang('5_day')],
@@ -108,7 +108,7 @@ def give_user_ban_2(conn, name):
                 insert_data += '<a href="javascript:insert_v(\'second\', \'' + i[0] + '\')">(' + i[1] + ')</a> '
 
             data = name + '''
-                <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''                
+                <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''
                 <hr class=\"main_hr\">
                 <input placeholder="''' + load_lang('ban_period') + ''' (''' + load_lang('second') + ''')" name="second" id="second" type="text">
                 <hr class=\"main_hr\">
@@ -117,7 +117,7 @@ def give_user_ban_2(conn, name):
                 <hr class=\"main_hr\">
             ''' + plus
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [main_name, wiki_set(), custom(), other2([now, 0])],
             data = '''
                 <form method="post">

+ 11 - 11
route/give_user_check.py

@@ -11,13 +11,13 @@ def give_user_check_2(conn, name):
 
     if admin_check(4, 'check (' + name + ')') != 1:
         return re_error('/error/3')
-        
+
     num = int(number_check(flask.request.args.get('num', '1')))
     if num * 50 > 0:
         sql_num = num * 50 - 50
     else:
         sql_num = 0
-    
+
     if flask.request.args.get('plus', None):
         end_check = 1
 
@@ -27,18 +27,18 @@ def give_user_check_2(conn, name):
                 ('ip' if ip_or_user(flask.request.args.get('plus', None)) == 1 else 'name') + " = ? " + \
                 "order by today desc limit ?, 50" + \
             ""), [
-            name, 
-            flask.request.args.get('plus', None), 
+            name,
+            flask.request.args.get('plus', None),
             sql_num
         ])
     else:
         end_check = 0
-        
+
         curs.execute(db_change("" + \
             "select name, ip, ua, today from ua_d " + \
             "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ? order by today desc limit ?, 50" + \
         ""), [name, sql_num])
-    
+
     record = curs.fetchall()
     if record:
         if not flask.request.args.get('plus', None):
@@ -55,7 +55,7 @@ def give_user_check_2(conn, name):
                             <td id="main_table_width">''' + load_lang('time') + '''</td>
                         </tr>
                 '''
-        
+
         for data in record:
             if data[2]:
                 ua = data[2]
@@ -72,20 +72,20 @@ def give_user_check_2(conn, name):
                         <td colspan="3">''' + ua + '''</td>
                     </tr>
                     '''
-        
+
         div +=  '''
                     </tbody>
                 </table>
                 '''
     else:
         return re_error('/error/2')
-        
+
     if end_check == 1:
         div += next_fix('/check/' + url_pas(name) + '?plus=' + flask.request.args.get('plus', None) + '&num=', num, record)
     else:
         div += next_fix('/check/' + url_pas(name) + '?num=', num, record)
-            
-    return easy_minify(flask.render_template(skin_check(),    
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('check'), wiki_set(), custom(), other2([0, 0])],
         data = div,
         menu = [['manager', load_lang('return')]]

+ 14 - 14
route/inter_wiki.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def inter_wiki_2(conn, tools):
     curs = conn.cursor()
-    
+
     div = ''
     admin = admin_check()
 
@@ -17,15 +17,14 @@ def inter_wiki_2(conn, tools):
         del_link = 'del_email_filter'
         plus_link = 'plus_email_filter'
         title = load_lang('email_filter_list')
-        div =   '''
-                <ul>
-                    <li>gmail.com</li>
-                    <li>naver.com</li>
-                    <li>daum.net</li>
-                    <li>hanmail.net</li>
-                    <li>hanmail2.net</li>
-                </ul>
-                '''
+        div = '''
+            <ul>
+                <li>gmail.com</li>
+                <li>naver.com</li>
+                <li>daum.net</li>
+                <li>kakao.com</li>
+            </ul>
+        '''
 
         curs.execute(db_change("select html from html_filter where kind = 'email'"))
     elif tools == 'name_filter':
@@ -55,14 +54,14 @@ def inter_wiki_2(conn, tools):
         title = load_lang('file_filter_list')
         div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'file'"))  
+        curs.execute(db_change("select html from html_filter where kind = 'file'"))
     elif tools == 'image_license':
         del_link = 'del_image_license'
         plus_link = 'plus_image_license'
         title = load_lang('image_license_list')
         div = ''
 
-        curs.execute(db_change("select html from html_filter where kind = 'image_license'"))  
+        curs.execute(db_change("select html from html_filter where kind = 'image_license'"))
     else:
         del_link = 'del_edit_top'
         plus_link = 'plus_edit_top'
@@ -87,6 +86,7 @@ def inter_wiki_2(conn, tools):
                     div += ' : ' + data[1]
 
             if admin == 1:
+                div += ' <a href="/' + plus_link + '/' + url_pas(data[0]) + '">(' + load_lang('edit') + ')</a>'
                 div += ' <a href="/' + del_link + '/' + url_pas(data[0]) + '">(' + load_lang('delete') + ')</a>'
 
             div += '</li>'
@@ -99,8 +99,8 @@ def inter_wiki_2(conn, tools):
         if admin == 1:
             div += '<a href="/' + plus_link + '">(' + load_lang('add') + ')</a>'
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [title, wiki_set(), custom(), other2([0, 0])],
         data = div,
-        menu = [['other', load_lang('return')]]
+        menu = [['manager/1', load_lang('return')]]
     ))

+ 3 - 3
route/inter_wiki_del.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def inter_wiki_del_2(conn, tools, name):
     curs = conn.cursor()
-    
+
     if admin_check(None, tools) == 1:
         if tools == 'del_inter_wiki':
             curs.execute(db_change("delete from inter where title = ?"), [name])
@@ -15,10 +15,10 @@ def inter_wiki_del_2(conn, tools, name):
         elif tools == 'del_email_filter':
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'email'"), [name])
         elif tools == 'del_image_license':
-            curs.execute(db_change("delete from html_filter where html = ? and kind = 'image_license'"), [name])    
+            curs.execute(db_change("delete from html_filter where html = ? and kind = 'image_license'"), [name])
         else:
             curs.execute(db_change("delete from html_filter where html = ? and kind = 'edit_top'"), [name])
-        
+
         conn.commit()
 
         return redirect('/' + re.sub('^del_', '', tools))

+ 95 - 35
route/inter_wiki_plus.py

@@ -2,15 +2,18 @@ from .tool.func import *
 
 def inter_wiki_plus_2(conn, tools, name):
     curs = conn.cursor()
-    
+
     if flask.request.method == 'POST':
         if tools == 'plus_inter_wiki':
+            if name:
+                curs.execute(db_change("delete from inter where title = ?"), [name])
+
             curs.execute(db_change('insert into inter (title, link, icon) values (?, ?, ?)'), [
-                flask.request.form.get('title', None), 
-                flask.request.form.get('link', None),
-                flask.request.form.get('icon', None)
+                flask.request.form.get('title', 'test'),
+                flask.request.form.get('link', 'test'),
+                flask.request.form.get('icon', '')
             ])
-            
+
             admin_check(None, 'inter_wiki_plus')
         elif tools == 'plus_edit_filter':
             if admin_check(1, 'edit_filter edit') != 1:
@@ -24,13 +27,14 @@ def inter_wiki_plus_2(conn, tools, name):
             try:
                 re.compile(flask.request.form.get('content', 'test'))
 
-                curs.execute(db_change("select name from filter where name = ?"), [name])
-                if curs.fetchall():
-                    curs.execute(db_change("update filter set regex = ?, sub = ? where name = ?"), [flask.request.form.get('content', 'test'), end, name])
-                else:
-                    curs.execute(db_change("insert into filter (name, regex, sub) values (?, ?, ?)"), [name, flask.request.form.get('content', 'test'), end])
+                curs.execute(db_change("delete from filter where name = ?"), [name])
+                curs.execute(db_change("insert into filter (name, regex, sub) values (?, ?, ?)"), [
+                    name,
+                    flask.request.form.get('content', 'test'),
+                    end
+                ])
             except:
-                return re_error('/error/23')                
+                return re_error('/error/23')
         else:
             plus_d = ''
 
@@ -38,38 +42,48 @@ def inter_wiki_plus_2(conn, tools, name):
                 try:
                     re.compile(flask.request.form.get('title', 'test'))
                 except:
-                    return re_error('/error/23') 
+                    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') 
-                
+                    return re_error('/error/23')
+
                 admin_check(None, 'file_filter edit')
-                
+
                 type_d = 'file'
             elif tools == 'plus_email_filter':
                 admin_check(None, 'email_filter edit')
-                
+
                 type_d = 'email'
             elif tools == 'plus_image_license':
                 admin_check(None, 'image_license edit')
-                
+
                 type_d = 'image_license'
             else:
                 admin_check(None, 'edit_top edit')
-                
+
                 type_d = 'edit_top'
                 plus_d = flask.request.form.get('markup', 'test')
-            
-            curs.execute(db_change('insert into html_filter (html, kind, plus) values (?, ?, ?)'), [flask.request.form.get('title', 'test'), type_d, plus_d])
-        
+
+            if name:
+                curs.execute(db_change("delete from html_filter where html = ? and kind = ?"), [
+                    name,
+                    type_d
+                ])
+
+            curs.execute(db_change('insert into html_filter (html, kind, plus) values (?, ?, ?)'), [
+                flask.request.form.get('title', 'test'),
+                type_d,
+                plus_d
+            ])
+
         conn.commit()
-    
+
         return redirect('/' + re.sub('^plus_', '', tools))
     else:
         if admin_check(1) != 1:
@@ -78,20 +92,36 @@ def inter_wiki_plus_2(conn, tools, name):
             stat = ''
 
         if tools == 'plus_inter_wiki':
+            if name:
+                curs.execute(db_change("select title, link, icon from inter where title = ?"), [name])
+                exist = curs.fetchall()
+                if exist:
+                    value = exist[0]
+                else:
+                    value = ['', '', '']
+            else:
+                value = ['', '', '']
+
             title = load_lang('interwiki_add')
             form_data = '''
-                <input placeholder="''' + load_lang('name') + '''" type="text" name="title">
+                ''' + load_lang('name') + '''
+                <hr class=\"main_hr\">
+                <input value="''' + value[0] + '''" type="text" name="title">
+                <hr class=\"main_hr\">
+                ''' + load_lang('link') + '''
+                <hr class=\"main_hr\">
+                <input value="''' + value[1] + '''" type="text" name="link">
                 <hr class=\"main_hr\">
-                <input placeholder="''' + load_lang('link') + '''" type="text" name="link">
+                ''' + load_lang('icon') + ''' (HTML)
                 <hr class=\"main_hr\">
-                <input placeholder="''' + load_lang('icon') + ''' (HTML)" type="text" name="icon">
+                <input value="''' + value[2] + '''" type="text" name="icon">
             '''
         elif tools == 'plus_edit_filter':
             curs.execute(db_change("select regex, sub from filter where name = ?"), [name])
             exist = curs.fetchall()
             if exist:
                 textarea = exist[0][0]
-                
+
                 if exist[0][1] == 'X':
                     time_check = 'checked="checked"'
                     time_data = ''
@@ -117,7 +147,7 @@ def inter_wiki_plus_2(conn, tools, name):
 
             title = load_lang('edit_filter_add')
             form_data = '''
-                <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''                
+                <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''
                 <hr class=\"main_hr\">
                 <input placeholder="''' + load_lang('second') + '''" id="second" name="second" type="text" value="''' + html.escape(time_data) + '''">
                 <hr class=\"main_hr\">
@@ -125,25 +155,55 @@ def inter_wiki_plus_2(conn, tools, name):
             '''
         elif tools == 'plus_name_filter':
             title = load_lang('id_filter_add')
-            form_data = '<input placeholder="' + load_lang('regex') + '" type="text" name="title">'
+            form_data = '' + \
+                load_lang('regex') + \
+                '<hr class=\"main_hr\">' + \
+                '<input value="' + (name if name else '') + '" 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">'
+            form_data = '' + \
+                load_lang('regex') + \
+                '<hr class=\"main_hr\">' + \
+                '<input value="' + (name if name else '') + '" type="text" name="title">' + \
+            ''
         elif tools == 'plus_email_filter':
             title = load_lang('email_filter_add')
-            form_data = '<input placeholder="' + load_lang('email') + '" type="text" name="title">'
+            form_data = '' + \
+                load_lang('email') + \
+                '<hr class=\"main_hr\">' + \
+                '<input value="' + (name if name else '') + '" type="text" name="title">' + \
+            ''
         elif tools == 'plus_image_license':
             title = load_lang('image_license_add')
-            form_data = '<input placeholder="' + load_lang('license') + '" type="text" name="title">'
+            form_data = '' + \
+                load_lang('license') + \
+                '<hr class=\"main_hr\">' + \
+                '<input value="' + (name if name else '') + '" type="text" name="title">' + \
+            ''
         else:
             title = load_lang('edit_tool_add')
+            if name:
+                curs.execute(db_change("select plus from html_filter where html = ? and kind = 'edit_top'"), [name])
+                exist = curs.fetchall()
+                if exist:
+                    value = exist[0][0]
+                else:
+                    value = ''
+            else:
+                value = ''
+
             form_data = '''
-                <input placeholder="''' + load_lang('title') + '''" type="text" name="title">
+                ''' + load_lang('title') + '''
+                <hr class=\"main_hr\">
+                <input value="''' + (name if name else '') + '''" type="text" name="title">
+                <hr class=\"main_hr\">
+                ''' + load_lang('markup') + '''
                 <hr class=\"main_hr\">
-                <input placeholder="''' + load_lang('markup') + '''" type="text" name="markup">
+                <input value="''' + value + '''" type="text" name="markup">
             '''
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [title, wiki_set(), custom(), other2([0, 0])],
             data =  '''
                     <form method="post">

+ 23 - 28
route/list_acl.py

@@ -2,17 +2,9 @@ from .tool.func import *
 
 def list_acl_2(conn):
     curs = conn.cursor()
-    
-    div = '''
-        <table id="main_table_set">
-            <tbody>
-                <tr>
-                    <td id="main_table_width_quarter">''' + load_lang('document_name') + '''</td>
-                    <td id="main_table_width_quarter">''' + load_lang('document_acl') + '''</td>
-                    <td id="main_table_width_quarter">''' + load_lang('discussion_acl') + '''</td>
-                    <td id="main_table_width_quarter">''' + load_lang('view_acl') + '''</td>
-    '''
-    
+
+    div = '<ul>'
+
     curs.execute(db_change("select title, decu, dis, view, why from acl where decu != '' or dis != '' or view != '' order by title desc"))
     list_data = curs.fetchall()
     for data in list_data:
@@ -28,23 +20,26 @@ def list_acl_2(conn):
                 else:
                     acl += [data[i]]
 
-            div +=  '''
-                <tr>
-                    <td>
-                        <a href="/w/''' + url_pas(data[0]) + '">' + data[0] + '''</a>
-                    </td>
-                    <td>''' + acl[0] + '''</td>
-                    <td>''' + acl[1] + '''</td>
-                    <td>''' + acl[2] + '''</td>
-                </tr>
-            '''
-        
-    div +=  '''
-            </tbody>
-        </table>
-    '''
-    
-    return easy_minify(flask.render_template(skin_check(), 
+            curs.execute(db_change("select time from re_admin where what like ? order by time desc limit 1"), ['acl (' + data[0] + ')%'])
+            time_data = curs.fetchall()
+            if time_data:
+                time_data = ' | ' + time_data[0][0]
+            else:
+                time_data = ''
+
+            div += '' + \
+                '<li>' + \
+                    '<a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a> | ' + \
+                    load_lang('document_acl') + ' : ' + acl[0] + ' | ' + \
+                    load_lang('discussion_acl') + ' : ' + acl[1] + ' | ' + \
+                    load_lang('view_acl') + ' : ' + acl[2] + \
+                    time_data + \
+                '</li>' + \
+            ''
+
+    div += '</ul>'
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('acl_document_list'), wiki_set(), custom(), other2([0, 0])],
         data = div,
         menu = [['other', load_lang('return')]]

+ 5 - 5
route/list_admin.py

@@ -4,19 +4,19 @@ def list_admin_2(conn):
     curs = conn.cursor()
 
     div = '<ul>'
-    
+
     curs.execute(db_change("select id, acl, date from user where not acl = 'user' order by date desc"))
     for data in curs.fetchall():
         name = ip_pas(data[0]) + ' <a href="/admin_plus/' + url_pas(data[1]) + '">(' + data[1] + ')</a>'
-        
+
         if data[2] != '':
             name += '(' + data[2] + ')'
 
         div += '<li>' + name + '</li>'
-        
+
     div += '</ul>'
-                
-    return easy_minify(flask.render_template(skin_check(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('admin_list'), wiki_set(), custom(), other2([0, 0])],
         data = div,
         menu = [['other', load_lang('return')]]

+ 3 - 3
route/list_admin_use.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def list_admin_use_2(conn):
     curs = conn.cursor()
-    
+
     num = int(number_check(flask.request.args.get('num', '1')))
     if num * 50 > 0:
         sql_num = num * 50 - 50
@@ -23,13 +23,13 @@ def list_admin_use_2(conn):
             ])
 
         get_list = curs.fetchall()
-        for data in get_list:            
+        for data in get_list:
             list_data += '<li>' + ip_pas(data[0]) + ' / ' + data[1] + ' / ' + data[2] + '</li>'
 
         list_data += '</ul>'
         list_data += next_fix('/admin_log?num=', num, get_list)
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('authority_use_list'), wiki_set(), custom(), other2([0, 0])],
             data = '''
                 <form method="post">

+ 14 - 14
route/list_block.py

@@ -8,7 +8,7 @@ def list_block_2(conn, name, tool):
         sql_num = num * 50 - 50
     else:
         sql_num = 0
-    
+
     div = '''
         <table id="main_table_set">
             <tbody>
@@ -18,19 +18,19 @@ def list_block_2(conn, name, tool):
                     <td id="main_table_width">''' + load_lang('period') + '''</td>
                 </tr>
     '''
-    
+
     data_list = ''
 
     curs.execute(db_change("delete from ban where (end < ? and end like '2%')"), [get_time()])
     conn.commit()
-    
-    if not name:        
+
+    if not name:
         if flask.request.args.get('type', '') == 'ongoing':
             sub = ' (' + load_lang('in_progress') + ')'
             menu = [['block_log', load_lang('normal')]]
 
             curs.execute(db_change("select why, block, '', end, '', band from ban where ((end > ? and end like '2%') or end = '') order by end desc limit ?, 50"), [
-                get_time(), 
+                get_time(),
                 sql_num
             ])
         else:
@@ -41,18 +41,18 @@ def list_block_2(conn, name, tool):
                 <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(db_change("select why, block, blocker, end, today, band from rb order by today desc limit ?, 50"), [sql_num])
     else:
         menu = [['block_log', load_lang('normal')]]
-        
+
         if tool == 'block_user':
             sub = ' (' + load_lang('blocked') + ')'
-            
+
             curs.execute(db_change("select why, block, blocker, end, today, band from rb where block = ? order by today desc limit ?, 50"), [name, sql_num])
         else:
             sub = ' (' + load_lang('admin') + ')'
-            
+
             curs.execute(db_change("select why, block, blocker, end, today, band from rb where blocker = ? order by today desc limit ?, 50"), [name, sql_num])
 
     if data_list == '':
@@ -62,7 +62,7 @@ def list_block_2(conn, name, tool):
         why = html.escape(data[0])
         if why == '':
             why = '<br>'
-        
+
         if data[5] == 'O':
             ip = data[1] + ' (' + load_lang('range') + ')'
         elif data[5] == 'regex':
@@ -88,7 +88,7 @@ def list_block_2(conn, name, tool):
             start = ''
         else:
             start = load_lang('start') + ' : ' + data[4]
-            
+
         div += '''
             <tr>
                 <td>''' + ip + '''</td>
@@ -105,13 +105,13 @@ def list_block_2(conn, name, tool):
         '''
 
     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(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('recent_ban'), wiki_set(), custom(), other2([sub, 0])],
         data = div,
         menu = menu

+ 3 - 3
route/list_give.py

@@ -7,15 +7,15 @@ def list_give_2(conn):
     back = ''
 
     curs.execute(db_change("select distinct name from alist order by name asc"))
-    for data in curs.fetchall():                      
+    for data in curs.fetchall():
         if back != data[0]:
             back = data[0]
 
         list_data += '<li><a href="/admin_plus/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
-    
+
     list_data += '</ul><hr class=\"main_hr\"><a href="/manager/8">(' + load_lang('add') + ')</a>'
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('admin_group_list'), wiki_set(), custom(), other2([0, 0])],
         data = list_data,
         menu = [['manager', load_lang('return')]]

+ 6 - 5
route/list_not_close_topic.py

@@ -4,15 +4,16 @@ def list_not_close_topic_2(conn):
     curs = conn.cursor()
 
     div = '<ul>'
-    
-    curs.execute(db_change('select title, sub from rd where stop != "O" order by date desc'))
+
+    curs.execute(db_change('select title, sub, date from rd where stop != "O" order by date desc'))
     n_list = curs.fetchall()
     for data in n_list:
-        div += '<li><a href="/topic/' + url_pas(data[0]) + '/sub/' + url_pas(data[1]) + '">' + html.escape(data[0]) + ' (' + data[1] + ')</a></li>'
-            
+        curs.execute(db_change("select code from topic where id = '1' and title = ? and sub = ?"), [data[0], data[1]])
+        div += '<li><a href="/thread/' + url_pas(curs.fetchall()[0][0]) + '">' + html.escape(data[0]) + '</a> (' + data[1] + ') | ' + data[2] + '</li>'
+
     div += '</ul>'
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('open_discussion_list'), wiki_set(), custom(), other2([0, 0])],
         data = div,
         menu = [['manager', load_lang('return')]]

+ 7 - 3
route/list_old_page.py

@@ -9,8 +9,12 @@ def list_old_page_2(conn):
     else:
         sql_num = 0
 
+    curs.execute(db_change('select data from other where name = "count_all_title"'))
+    if int(curs.fetchall()[0][0]) < 30000:
+        return re_error('/error/25')
+
     div = '<ul>'
-    
+
     curs.execute(db_change('' + \
         'select title, date from history h ' + \
         "where title not like 'user:%' and title not like 'category:%' and title not like 'file:%' and " + \
@@ -23,10 +27,10 @@ def list_old_page_2(conn):
     n_list = curs.fetchall()
     for data in n_list:
         div += '<li><a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a> (' + re.sub(' .*$', '', data[1]) + ')</li>'
-    
+
     div += '</ul>' + next_fix('/old_page?num=', num, n_list)
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('old_page'), wiki_set(), custom(), other2([0, 0])],
         data = div,
         menu = [['other', load_lang('return')]]

+ 10 - 6
route/list_please.py

@@ -8,17 +8,21 @@ def list_please_2(conn):
         sql_num = num * 50 - 50
     else:
         sql_num = 0
-        
+
+    curs.execute(db_change('select data from other where name = "count_all_title"'))
+    if int(curs.fetchall()[0][0]) < 30000:
+        return re_error('/error/25')
+
     div = '<ul>'
-    
+
     curs.execute(db_change("select distinct title from back where type = 'no' order by title asc limit ?, 50"), [sql_num])
     data_list = curs.fetchall()
     for data in data_list:
-        div += '<li><a id="not_thing" href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'   
-        
+        div += '<li><a id="not_thing" href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
+
     div += '</ul>' + next_fix('/please?num=', num, data_list)
-    
-    return easy_minify(flask.render_template(skin_check(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('need_document'), wiki_set(), custom(), other2([0, 0])],
         data = div,
         menu = [['other', load_lang('return')]]

+ 6 - 7
route/list_title_index.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def list_title_index_2(conn):
     curs = conn.cursor()
-    
+
     page = int(number_check(flask.request.args.get('page', '1')))
     num = int(number_check(flask.request.args.get('num', '100')))
     if page * num > 0:
@@ -23,15 +23,14 @@ def list_title_index_2(conn):
         data += '<hr class=\"main_hr\"><ul>'
 
     for list_data in title_list:
-        data += '<li>' + str(all_list) + '. <a href="/w/' + url_pas(list_data[0]) + '">' + list_data[0] + '</a></li>'        
+        data += '<li>' + str(all_list) + '. <a href="/w/' + url_pas(list_data[0]) + '">' + list_data[0] + '</a></li>'
         all_list += 1
 
     if page == 1:
         count_end = []
 
         curs.execute(db_change('select data from other where name = "count_all_title"'))
-        all_title = curs.fetchall()
-        if int(all_title[0][0]) < 50000:
+        if int(curs.fetchall()[0][0]) < 30000:
             curs.execute(db_change("select count(title) from data"))
             count = curs.fetchall()
             if count:
@@ -49,7 +48,7 @@ def list_title_index_2(conn):
                     count_end += [0]
 
             count_end += [count_end[0] - count_end[1]  - count_end[2]  - count_end[3]]
-        
+
             data += '''
                 </ul>
                 <hr class=\"main_hr\">
@@ -73,8 +72,8 @@ def list_title_index_2(conn):
 
     data += '</ul>' + next_fix('/title_index?num=' + str(num) + '&page=', page, title_list, num)
     sub = ' (' + str(num) + ')'
-    
-    return easy_minify(flask.render_template(skin_check(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('all_document_list'), wiki_set(), custom(), other2([sub, 0])],
         data = data,
         menu = [['other', load_lang('return')]]

+ 5 - 5
route/list_user.py

@@ -8,11 +8,11 @@ def list_user_2(conn):
         sql_num = num * 50 - 50
     else:
         sql_num = 0
-        
+
     list_data = '<ul>'
 
     admin_one = admin_check(1)
-    
+
     curs.execute(db_change("select id, date from user order by date desc limit ?, 50"), [sql_num])
     user_list = curs.fetchall()
     for data in user_list:
@@ -24,9 +24,9 @@ def list_user_2(conn):
                 ban_button = ' <a href="/ban/' + url_pas(data[0]) + '">(' + load_lang('ban') + ')</a>'
         else:
             ban_button = ''
-            
+
         list_data += '<li>' + ip_pas(data[0]) + ban_button
-        
+
         if data[1] != '':
             list_data += ' (' + data[1] + ')'
 
@@ -39,7 +39,7 @@ def list_user_2(conn):
 
     list_data += next_fix('/user_log?num=', num, user_list)
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('member_list'), wiki_set(), custom(), other2([0, 0])],
         data = list_data,
         menu = [['other', load_lang('return')]]

+ 11 - 10
route/list_user_topic.py

@@ -8,7 +8,7 @@ def list_user_topic_2(conn, name):
         sql_num = num * 50 - 50
     else:
         sql_num = 0
-    
+
     one_admin = admin_check(1)
 
     div =   '''
@@ -20,13 +20,13 @@ def list_user_topic_2(conn, name):
                         <td id="main_table_width">''' + load_lang('time') + '''</td>
                     </tr>
             '''
-    
+
     curs.execute(db_change("select title, id, sub, ip, date from topic where ip = ? order by date desc limit ?, 50"), [name, sql_num])
     data_list = curs.fetchall()
     for data in data_list:
         title = html.escape(data[0])
         sub = html.escape(data[2])
-        
+
         if one_admin == 1:
             curs.execute(db_change("select * from ban where block = ?"), [data[3]])
             if curs.fetchall():
@@ -35,20 +35,21 @@ def list_user_topic_2(conn, name):
                 ban = ' <a href="/ban/' + url_pas(data[3]) + '">(' + load_lang('ban') + ')</a>'
         else:
             ban = ''
-            
-        div += '<tr><td><a href="/topic/' + url_pas(data[0]) + '/sub/' + url_pas(data[2]) + '#' + data[1] + '">' + title + '#' + data[1] + '</a> (' + sub + ')</td>'
+
+        curs.execute(db_change("select code from topic where id = '1' and title = ? and sub = ?"), [title, sub])
+        div += '<tr><td><a href="/thread/' + url_pas(curs.fetchall()[0][0]) + '#' + data[1] + '">' + title + '#' + data[1] + '</a> (' + sub + ')</td>'
         div += '<td>' + ip_pas(data[3]) + ban + '</td><td>' + data[4] + '</td></tr>'
 
     div += '</tbody></table>'
-    div += next_fix('/topic_record/' + url_pas(name) + '?num=', num, data_list)      
-    
+    div += next_fix('/topic_record/' + url_pas(name) + '?num=', num, data_list)
+
     curs.execute(db_change("select end from ban where block = ?"), [name])
     if curs.fetchall():
         sub = ' (' + load_lang('blocked') + ')'
     else:
-        sub = 0 
-    
-    return easy_minify(flask.render_template(skin_check(), 
+        sub = 0
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('discussion_record'), wiki_set(), custom(), other2([sub, 0])],
         data = div,
         menu = [['other', load_lang('other')], ['user', load_lang('user')], ['count/' + url_pas(name), load_lang('count')], ['record/' + url_pas(name), load_lang('record')]]

+ 14 - 14
route/login.py

@@ -6,16 +6,16 @@ def login_2(conn):
     ip = ip_check()
     if ip_or_user(ip) == 0:
         return redirect('/user')
-    
+
     if ban_check(tool = 'login') == 1:
         return re_error('/ban')
-        
-    if flask.request.method == 'POST':        
+
+    if flask.request.method == 'POST':
         if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
             return re_error('/error/13')
         else:
             captcha_post('', 0)
-            
+
         agent = flask.request.headers.get('User-Agent')
 
         curs.execute(db_change("select pw, encode from user where id = ?"), [flask.request.form.get('id', None)])
@@ -24,7 +24,7 @@ def login_2(conn):
             return re_error('/error/2')
 
         pw_check_d = pw_check(
-            flask.request.form.get('pw', ''), 
+            flask.request.form.get('pw', ''),
             user[0][0],
             user[0][1],
             flask.request.form.get('id', None)
@@ -34,7 +34,7 @@ def login_2(conn):
 
         flask.session['state'] = 1
         flask.session['id'] = flask.request.form.get('id', None)
-        
+
         curs.execute(db_change("select css from custom where user = ?"), [flask.request.form.get('id', None)])
         css_data = curs.fetchall()
         if css_data:
@@ -45,8 +45,8 @@ def login_2(conn):
         curs.execute(db_change("insert into ua_d (name, ip, ua, today, sub) values (?, ?, ?, ?, '')"), [flask.request.form.get('id', None), ip_check(1), agent, get_time()])
 
         conn.commit()
-        
-        return redirect('/user')  
+
+        return redirect('/user')
     else:
         oauth_check = 0
         oauth_content = '<hr class=\"main_hr\"><div class="oauth-wrapper"><ul class="oauth-list">'
@@ -64,22 +64,22 @@ def login_2(conn):
                         </a>
                     </li>
                 '''.format(
-                    oauth_supported[i], 
-                    oauth_supported[i], 
-                    oauth_supported[i], 
+                    oauth_supported[i],
+                    oauth_supported[i],
+                    oauth_supported[i],
                     load_lang('oauth_signin_' + oauth_supported[i])
                 )
 
                 oauth_check = 1
-        
+
         oauth_content += '</ul></div>'
 
         if oauth_check == 0:
             oauth_content = ''
 
         http_warring = '<hr class=\"main_hr\"><span>' + load_lang('http_warring') + '</span>'
-        
-        return easy_minify(flask.render_template(skin_check(),    
+
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('login'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
                     <form method="post">

+ 22 - 22
route/login_check_key.py

@@ -24,7 +24,7 @@ def login_check_key_2(conn, tool):
                 else:
                     b_text = ''
 
-                return easy_minify(flask.render_template(skin_check(),    
+                return easy_minify(flask.render_template(skin_check(),
                     imp = [load_lang('reset_user_ok'), wiki_set(), custom(), other2([0, 0])],
                     data = b_text + load_lang('id') + ' : ' + d_id + '<br>' + load_lang('password') + ' : ' + pw,
                     menu = [['user', load_lang('return')]]
@@ -33,56 +33,56 @@ def login_check_key_2(conn, tool):
                 return redirect('/pass_find')
         else:
             ip = ip_check()
-            
+
             if 'c_id' in flask.session and flask.session['c_key'] == flask.request.form.get('key', None):
                 curs.execute(db_change('select data from other where name = "encode"'))
                 db_data = curs.fetchall()
-                
+
                 if tool == 'check_key':
                     curs.execute(db_change("select id from user limit 1"))
                     if not curs.fetchall():
                         curs.execute(db_change("insert into user (id, pw, acl, date, encode) values (?, ?, 'owner', ?, ?)"), [
-                            flask.session['c_id'], 
-                            flask.session['c_pw'], 
-                            get_time(), 
+                            flask.session['c_id'],
+                            flask.session['c_pw'],
+                            get_time(),
                             db_data[0][0]
                         ])
-    
+
                         first = 1
                     else:
                         curs.execute(db_change("insert into user (id, pw, acl, date, encode) values (?, ?, 'user', ?, ?)"), [
-                            flask.session['c_id'], 
-                            flask.session['c_pw'], 
-                            get_time(), 
+                            flask.session['c_id'],
+                            flask.session['c_pw'],
+                            get_time(),
                             db_data[0][0]
                         ])
-    
+
                         first = 0
-    
+
                     agent = flask.request.headers.get('User-Agent')
-    
+
                     curs.execute(db_change("insert into user_set (name, id, data) values ('email', ?, ?)"), [
-                        flask.session['c_id'], 
+                        flask.session['c_id'],
                         flask.session['c_email']
                     ])
                     curs.execute(db_change("insert into ua_d (name, ip, ua, today, sub) values (?, ?, ?, ?, '')"), [
-                        flask.session['c_id'], 
-                        ip, 
-                        agent, 
+                        flask.session['c_id'],
+                        ip,
+                        agent,
                         get_time()
                     ])
-    
+
                     flask.session['state'] = 1
                     flask.session['id'] = flask.session['c_id']
                     flask.session['head'] = ''
-                            
+
                     conn.commit()
                 else:
                     curs.execute(db_change('delete from user_set where name = "email" and id = ?'), [ip])
                     curs.execute(db_change('insert into user_set (name, id, data) values ("email", ?, ?)'), [ip, flask.session['c_email']])
-                    
+
                     first = 0
-                          
+
                 flask.session.pop('c_id', None)
                 flask.session.pop('c_pw', None)
                 flask.session.pop('c_key', None)
@@ -107,7 +107,7 @@ def login_check_key_2(conn, tool):
         else:
             b_text = ''
 
-        return easy_minify(flask.render_template(skin_check(),    
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('check_key'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
                 <form method="post">

+ 8 - 8
route/login_need_email.py

@@ -28,7 +28,7 @@ def login_need_email_2(conn, tool):
                     i_text = 'Key : ' + flask.session['c_key']
 
                 send_email(flask.request.form.get('email', ''), t_text, i_text)
-                
+
                 return redirect('/check_pass_key')
             else:
                 return re_error('/error/12')
@@ -37,9 +37,9 @@ def login_need_email_2(conn, tool):
                 flask.session['c_key'] = ''.join(random.choice("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") for i in range(16))
                 flask.session['c_id'] = ip_check()
                 flask.session['c_pw'] = ''
-            
+
             if 'c_id' in flask.session:
-                main_email = ['naver.com', 'gmail.com', 'daum.net', 'hanmail.net', 'hanmail2.net']
+                main_email = ['naver.com', 'gmail.com', 'daum.net', 'kakao.com']
                 data = re.search('@([^@]+)$', flask.request.form.get('email', ''))
                 if data:
                     data = data.groups()[0]
@@ -51,7 +51,7 @@ def login_need_email_2(conn, tool):
                             flask.session.pop('c_id', None)
                             flask.session.pop('c_pw', None)
                             flask.session.pop('c_key', None)
-                            
+
                             # user 대신 오류 화면 보여주게 수정 필요
                             return redirect('/user')
                         else:
@@ -71,14 +71,14 @@ def login_need_email_2(conn, tool):
 
                             send_email(flask.request.form.get('email', ''), t_text, i_text)
                             flask.session['c_email'] = flask.request.form.get('email', '')
-                  
+
                             if tool == 'email_change':
                                 return redirect('/email_replace')
                             else:
                                 return redirect('/check_key')
                     else:
                         return redirect('/email_filter')
-            
+
             return redirect('/user')
     else:
         if tool == 'pass_find':
@@ -89,7 +89,7 @@ def login_need_email_2(conn, tool):
             else:
                 b_text = ''
 
-            return easy_minify(flask.render_template(skin_check(),    
+            return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('password_search'), wiki_set(), custom(), other2([0, 0])],
                 data =  b_text + '''
                         <form method="post">
@@ -110,7 +110,7 @@ def login_need_email_2(conn, tool):
             else:
                 b_text = ''
 
-            return easy_minify(flask.render_template(skin_check(),    
+            return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('email'), wiki_set(), custom(), other2([0, 0])],
                 data =  '''
                         <a href="/email_filter">(''' + load_lang('email_filter_list') + ''')</a>

+ 30 - 30
route/login_oauth.py

@@ -32,15 +32,15 @@ def login_oauth_2(conn, platform, func):
 
     if func == 'init':
         if oauth_data['client_id'] == '' or oauth_data['client_secret'] == '':
-            return easy_minify(flask.render_template(skin_check(), 
-                imp = [load_lang('error'), wiki_set(), custom(), other2([0, 0])], 
-                data = load_lang('oauth_disabled'), 
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('error'), wiki_set(), custom(), other2([0, 0])],
+                data = load_lang('oauth_disabled'),
                 menu = [['user', load_lang('return')]]
             ))
         elif publish_url == 'https://':
-            return easy_minify(flask.render_template(skin_check(), 
-                imp = [load_lang('error'), wiki_set(), custom(), other2([0, 0])], 
-                data = load_lang('oauth_setting_not_found'), 
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('error'), wiki_set(), custom(), other2([0, 0])],
+                data = load_lang('oauth_setting_not_found'),
                 menu = [['user', load_lang('return')]]
             ))
 
@@ -58,24 +58,24 @@ def login_oauth_2(conn, platform, func):
 
         if platform == 'discord':
             return redirect(api_url['redirect'] + '?client_id={}&redirect_uri={}&response_type=code&scope=identify'.format(
-                data['client_id'], 
+                data['client_id'],
                 data['redirect_uri']
             ))
         elif platform == 'naver':
             return redirect(api_url['redirect'] + '?response_type=code&client_id={}&redirect_uri={}&state={}'.format(
-                data['client_id'], 
-                data['redirect_uri'], 
+                data['client_id'],
+                data['redirect_uri'],
                 data['state']
             ))
         elif platform == 'facebook':
             return redirect(api_url['redirect'] + '?client_id={}&redirect_uri={}&state={}'.format(
-                data['client_id'], 
-                data['redirect_uri'], 
+                data['client_id'],
+                data['redirect_uri'],
                 data['state']
             ))
         elif platform == 'kakao':
             return redirect(api_url['redirect'] + '?client_id={}&redirect_uri={}&response_type=code'.format(
-                data['client_id'], 
+                data['client_id'],
                 data['redirect_uri']
             ))
 
@@ -122,15 +122,15 @@ def login_oauth_2(conn, platform, func):
             profile_result =  urllib.request.urlopen(profile_exchange).read().decode('utf-8')
             profile_result_json = json.loads(profile_result)
             stand_json = {
-                'id'        : profile_result_json['id'], 
+                'id'        : profile_result_json['id'],
                 'name'      : profile_result_json['username'] + '#' + profile_result_json['discriminator'],
                 'picture'   : profile_result_json['avatar']
             }
         elif platform == 'naver':
             token_access = api_url['token'] + '?grant_type=authorization_code&client_id={}&client_secret={}&code={}&state={}'.format(
-                data['client_id'], 
-                data['client_secret'], 
-                code, 
+                data['client_id'],
+                data['client_secret'],
+                code,
                 state
             )
             token_result = urllib.request.urlopen(token_access).read().decode('utf-8')
@@ -151,9 +151,9 @@ def login_oauth_2(conn, platform, func):
             }
         elif platform == 'facebook':
             token_access = api_url['token'] + '?client_id={}&redirect_uri={}&client_secret={}&code={}'.format(
-                data['client_id'], 
-                data['redirect_uri'], 
-                data['client_secret'], 
+                data['client_id'],
+                data['redirect_uri'],
+                data['client_secret'],
                 code
             )
             token_result = urllib.request.urlopen(token_access).read().decode('utf-8')
@@ -164,8 +164,8 @@ def login_oauth_2(conn, platform, func):
             profile_result_json = json.loads(profile_result)
 
             stand_json = {
-                'id': profile_result_json['id'], 
-                'name': profile_result_json['name'], 
+                'id': profile_result_json['id'],
+                'name': profile_result_json['name'],
                 'picture': profile_result_json['picture']['data']['url']
             }
         elif platform == 'kakao':
@@ -199,26 +199,26 @@ def login_oauth_2(conn, platform, func):
             profile_result =  urllib.request.urlopen(profile_exchange).read().decode('utf-8')
             profile_result_json = json.loads(profile_result)
             stand_json = {
-                'id'        : profile_result_json['id'], 
+                'id'        : profile_result_json['id'],
                 'name'      : profile_result_json['properties']['nickname'],
                 'picture'   : profile_result_json['properties']['profile_image']
             }
-        
+
         if flask.session['referrer'][0:6] == 'change':
             curs.execute(db_change('select * from oauth_conn where wiki_id = ? and provider = ?'), [flask.session['id'], platform])
             oauth_result = curs.fetchall()
             if len(oauth_result) == 0:
                 curs.execute(db_change('insert into oauth_conn (provider, wiki_id, sns_id, name, picture) values(?, ?, ?, ?, ?)'), [
-                    platform, 
-                    flask.session['id'], 
-                    stand_json['id'], 
-                    stand_json['name'], 
+                    platform,
+                    flask.session['id'],
+                    stand_json['id'],
+                    stand_json['name'],
                     stand_json['picture']
                 ])
             else:
                 curs.execute(db_change('update oauth_conn set name = ? picture = ? where wiki_id = ?'), [
-                    stand_json['name'], 
-                    stand_json['picture'], 
+                    stand_json['name'],
+                    stand_json['picture'],
                     flask.session['id']
                 ])
 
@@ -231,5 +231,5 @@ def login_oauth_2(conn, platform, func):
             else:
                 flask.session['state'] = 1
                 flask.session['id'] = curs_result[0][2]
-        
+
         return redirect(flask.session['refer'])

+ 5 - 5
route/login_pw_change.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def login_pw_change_2(conn):
     curs = conn.cursor()
-    
+
     if ban_check() == 1:
         return re_error('/ban')
 
@@ -19,9 +19,9 @@ def login_pw_change_2(conn):
             user = curs.fetchall()
             if not user:
                 return re_error('/error/2')
-               
+
             pw_check_d = pw_check(
-                flask.request.form.get('pw4', ''), 
+                flask.request.form.get('pw4', ''),
                 user[0][0],
                 user[0][1],
                 ip
@@ -30,12 +30,12 @@ def login_pw_change_2(conn):
                 return re_error('/error/10')
 
             hashed = pw_encode(flask.request.form.get('pw2', None))
-                
+
             curs.execute(db_change("update user set pw = ? where id = ?"), [hashed, ip])
 
             return redirect('/user')
     else:
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('password_change'), wiki_set(), custom(), other2([0, 0])],
             data = '''
                 <form method="post">

+ 11 - 11
route/login_register.py

@@ -15,8 +15,8 @@ def login_register_2(conn):
         set_d = curs.fetchall()
         if set_d and set_d[0][0] == 'on':
             return re_error('/ban')
-    
-    if flask.request.method == 'POST': 
+
+    if flask.request.method == 'POST':
         if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
             return re_error('/error/13')
         else:
@@ -30,7 +30,7 @@ def login_register_2(conn):
 
         if re.search('(?:[^A-Za-zㄱ-힣0-9 ])', flask.request.form.get('id', None)):
             return re_error('/error/8')
-            
+
         curs.execute(db_change('select html from html_filter where kind = "name"'))
         set_d = curs.fetchall()
         for i in set_d:
@@ -46,7 +46,7 @@ def login_register_2(conn):
             return re_error('/error/6')
 
         hashed = pw_encode(flask.request.form.get('pw', None))
-        
+
         curs.execute(db_change('select data from other where name = "email_have"'))
         sql_data = curs.fetchall()
         if sql_data and sql_data[0][0] != '':
@@ -72,29 +72,29 @@ def login_register_2(conn):
             ip = ip_check()
             agent = flask.request.headers.get('User-Agent')
 
-            curs.execute(db_change("insert into ua_d (name, ip, ua, today, sub) values (?, ?, ?, ?, '')"), [flask.request.form.get('id', None), ip, agent, get_time()])  
+            curs.execute(db_change("insert into ua_d (name, ip, ua, today, sub) values (?, ?, ?, ?, '')"), [flask.request.form.get('id', None), ip, agent, get_time()])
 
             flask.session['state'] = 1
             flask.session['id'] = flask.request.form.get('id', None)
             flask.session['head'] = ''
-                  
+
             conn.commit()
-            
+
             if first == 0:
                 return redirect('/change')
             else:
                 return redirect('/setting')
-    else:        
+    else:
         contract = ''
-        
+
         curs.execute(db_change('select data from other where name = "contract"'))
         data = curs.fetchall()
         if data and data[0][0] != '':
             contract = data[0][0] + '<hr class=\"main_hr\">'
-        
+
         http_warring = '<hr class=\"main_hr\"><span>' + load_lang('http_warring') + '</span>'
 
-        return easy_minify(flask.render_template(skin_check(),    
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('register'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
                     <form method="post">

+ 0 - 10
route/main_easter_egg.py

@@ -1,10 +0,0 @@
-from .tool.func import *
-
-def main_easter_egg_2(conn):
-    curs = conn.cursor()
-
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = ['easter_egg.html', wiki_set(), custom(), other2([0, 0])],
-        data = open('./views/easter_egg.html', 'r').read(),
-        menu = 0
-    ))

+ 15 - 3
route/main_file.py

@@ -1,9 +1,21 @@
 from .tool.func import *
+from . import main_error_404
 
 def main_file_2(conn, data):
     curs = conn.cursor()
 
-    if data == 'robots.txt' and not os.path.exists('robots.txt'):
-        return flask.Response('User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/', mimetype='text/plain')
+    if data == 'easter_egg.html':
+        return easy_minify(flask.render_template(skin_check(),
+            imp = ['easter_egg.html', wiki_set(), custom(), other2([0, 0])],
+            data = open('./views/main_css/file/easter_egg.html', 'r').read(),
+            menu = 0
+        ))
+    elif re.search('\.txt$', data) or data == 'sitemap.xml':
+        if data == 'robots.txt' and not os.path.exists('robots.txt'):
+            return flask.Response('User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/', mimetype='text/plain')
+        elif os.path.exists(data):
+            return flask.send_from_directory('./', data)
+        else:
+            return main_error_404.main_error_404_2(conn)
     else:
-        return flask.send_from_directory('./', data)
+        return main_error_404.main_error_404_2(conn)

+ 1 - 1
route/main_image_view.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 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)):
         return flask.send_from_directory('./' + app_var['path_data_image'], name)
     else:

+ 19 - 19
route/main_manager.py

@@ -1,27 +1,27 @@
 from .tool.func import *
 
-def main_manager_2(conn, num, r_ver, db_type):
+def main_manager_2(conn, num, r_ver):
     curs = conn.cursor()
-    
+
     title_list = {
-        0 : [load_lang('document_name'), 'acl'], 
-        1 : [0, 'check'], 
+        0 : [load_lang('document_name'), 'acl'],
+        1 : [0, 'check'],
         2 : [load_lang('file_name'), 'plus_file_filter'],
-        3 : [0, 'admin'], 
-        4 : [0, 'record'], 
-        5 : [0, 'topic_record'], 
-        6 : [load_lang('name'), 'admin_plus'], 
-        7 : [load_lang('name'), 'plus_edit_filter'], 
-        8 : [load_lang('document_name'), 'search'], 
-        9 : [0, 'block_user'], 
-        10 : [0, 'block_admin'], 
-        11 : [load_lang('document_name'), 'watch_list'], 
-        12 : [load_lang('compare_target'), 'check'], 
+        3 : [0, 'admin'],
+        4 : [0, 'record'],
+        5 : [0, 'topic_record'],
+        6 : [load_lang('name'), 'admin_plus'],
+        7 : [load_lang('name'), 'plus_edit_filter'],
+        8 : [load_lang('document_name'), 'search'],
+        9 : [0, 'block_user'],
+        10 : [0, 'block_admin'],
+        11 : [load_lang('document_name'), 'watch_list'],
+        12 : [load_lang('compare_target'), 'check'],
         13 : [load_lang('document_name'), 'edit']
     }
-    
+
     if num == 1:
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('admin_tool'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
                     <h2>''' + load_lang('admin') + '''</h2>
@@ -30,16 +30,17 @@ def main_manager_2(conn, num, r_ver, db_type):
                         <li><a href="/manager/3">''' + load_lang('check_user') + '''</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>
                     </ul>
                     <br>
                     <h2>''' + load_lang('owner') + '''</h2>
                     <ul>
                         <li><a href="/give_log">''' + load_lang('admin_group_list') + '''</a></li>
+                        <li><a href="/many_delete">''' + load_lang('many_delete') + '''</a></li>
                         <li><a href="/setting">''' + load_lang('setting') + '''</a></li>
                     </ul>
                     <h3>''' + load_lang('filter') + '''</h3>
                     <ul>
+                        <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
                         <li><a href="/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
                         <li><a href="/edit_top">''' + load_lang('edit_tool_list') + '''</a></li>
                         <li><a href="/image_license">''' + load_lang('image_license_list') + '''</a></li>
@@ -50,7 +51,6 @@ def main_manager_2(conn, num, r_ver, db_type):
                     <br>
                     <h2>''' + load_lang('server') + '''</h2>
                     <ul>
-                        ''' + (('<li><a href="/indexing">' + load_lang('indexing') + '</a></li>') if db_type == 'sqlite' else '') + '''
                         <li><a href="/restart">''' + load_lang('wiki_restart') + '''</a></li>
                         <li><a href="/update">''' + load_lang('update') + '''</a></li>
                         <li><a href="/oauth_setting">''' + load_lang('oauth_setting') + '''</a></li>
@@ -79,7 +79,7 @@ def main_manager_2(conn, num, r_ver, db_type):
             else:
                 placeholder = title_list[(num - 2)][0]
 
-            return easy_minify(flask.render_template(skin_check(), 
+            return easy_minify(flask.render_template(skin_check(),
                 imp = ['Redirect', wiki_set(), custom(), other2([0, 0])],
                 data =  '''
                         <form method="post">

+ 2 - 2
route/main_other.py

@@ -2,8 +2,8 @@ from .tool.func import *
 
 def main_other_2(conn):
     curs = conn.cursor()
-    
-    return easy_minify(flask.render_template(skin_check(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('other_tool'), wiki_set(), custom(), other2([0, 0])],
         data = '''
             <h2>''' + load_lang('record') + '''</h2>

+ 1 - 1
route/main_skin_set.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def main_skin_set_2(conn):
     curs = conn.cursor()
-    
+
     data = flask.make_response(re_error('/error/5'))
 
     curs.execute(db_change("select data from other where name = 'language'"))

+ 1 - 1
route/main_views.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def main_views_2(conn, name):
     curs = conn.cursor()
-    
+
     if re.search('\/', name):
         m = re.search('^(.*)\/(.*)$', name)
         if m:

+ 104 - 93
route/recent_changes.py

@@ -10,110 +10,121 @@ def recent_changes_2(conn, name, tool):
             '&second=' + flask.request.form.get('a', '1')
         )
     else:
-        one_admin = admin_check(1)
-        six_admin = admin_check(6)
-        
         ban = ''
         select = ''
+        sub = ''
 
         div = '''
-            <hr class=\"main_hr\">
             <table id="main_table_set">
                 <tbody>
                     <tr>
         '''
-        
-        if name:
-            num = int(number_check(flask.request.args.get('num', '1')))
-            if num * 50 > 0:
-                sql_num = num * 50 - 50
-            else:
-                sql_num = 0      
 
+        num = int(number_check(flask.request.args.get('num', '1')))
+        if num * 50 > 0:
+            sql_num = num * 50 - 50
+        else:
+            sql_num = 0
+
+        if name:
             if tool == 'history':
+                sub += ' (' + load_lang('history') + ')'
+
                 div += '''
                     <td id="main_table_width">''' + load_lang('version') + '''</td>
                     <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                    <td id="main_table_width">''' + load_lang('time') + '''</td></tr>
+                    <td id="main_table_width">''' + load_lang('time') + '''</td>
                 '''
-                
-                # 기본적인 move만 구현
-                tool_select = flask.request.args.get('tool', None)
-                if tool_select and tool_select == 'move':
-                    curs.execute(db_change('' + \
-                        'select id, title, date, ip, send, leng from history ' + \
-                        'where send like ? or send like ? ' + \
-                        'order by id + 0 desc ' + \
-                        "limit ?, 50" + \
-                    ''), ['%(<a>' + name +'</a>%', '%<a>' + name + '</a> move)', sql_num])
+
+                tool_select = flask.request.args.get('tool', 'normal')
+                if tool_select == 'move':
+                    plus_sql = 'where (send like ? or send like ?) and type = "" '
+                    plus_list = ['%(<a>' + name +'</a>%', '%<a>' + name + '</a> move)', sql_num]
+                    sub += ' (' + load_lang('move') + ')'
+                elif tool_select == 'delete':
+                    plus_sql = 'where (send like "%(delete)") and title = ? and type = "" '
+                    plus_list = [name, sql_num]
+                    sub += ' (' + load_lang('delete') + ')'
+                elif tool_select == 'revert':
+                    plus_sql = 'where (send like ?) and title = ? and type = "" '
+                    plus_list = ['%(r%)', name, sql_num]
+                    sub += ' (' + load_lang('revert') + ')'
                 else:
-                    curs.execute(db_change('' + \
-                        'select id, title, date, ip, send, leng from history ' + \
-                        'where title = ? ' + \
-                        'order by id + 0 desc ' + \
-                        "limit ?, 50" + \
-                    ''), [name, sql_num])
+                    plus_sql = 'where title = ? and type = "" '
+                    plus_list = [name, sql_num]
+
+                curs.execute(db_change('' + \
+                    'select id, title, date, ip, send, leng from history ' + \
+                    plus_sql + \
+                    'order by id + 0 desc ' + \
+                    "limit ?, 50" + \
+                ''), plus_list)
             else:
                 div +=  '''
-                        <td id="main_table_width">''' + load_lang('document_name') + '''</td>
-                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                        <td id="main_table_width">''' + load_lang('time') + '''</td>
-                    </tr>
+                    <td id="main_table_width">''' + load_lang('document_name') + '''</td>
+                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                    <td id="main_table_width">''' + load_lang('time') + '''</td>
                 '''
 
                 div = '<a href="/topic_record/' + url_pas(name) + '">(' + load_lang('discussion') + ')</a><hr class=\"main_hr\">' + div
-                
+
                 curs.execute(db_change('' + \
                     'select id, title, date, ip, send, leng from history ' + \
-                    "where ip = ? order by date desc limit ?, 50" + \
+                    "where ip = ? and type = '' order by date desc limit ?, 50" + \
                 ''), [name, sql_num])
         else:
-            num = int(number_check(flask.request.args.get('num', '1')))
-            if num * 50 > 0:
-                sql_num = num * 50 - 50
-            else:
-                sql_num = 0            
-            
             div +=  '''
-                    <td id="main_table_width">''' + load_lang('document_name') + '''</td>
-                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                    <td id="main_table_width">''' + load_lang('time') + '''</td>
-                </tr>
+                <td id="main_table_width">''' + load_lang('document_name') + '''</td>
+                <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                <td id="main_table_width">''' + load_lang('time') + '''</td>
             '''
 
-            set_user = flask.request.args.get('set', 'normal')
-            if set_user == 'normal':
-                div = '<a href="?set=user">(' + load_lang('user_document') + ')</a>' + div
+            set_type = flask.request.args.get('set', 'normal')
+            if set_type == 'normal':
+                div = '' + \
+                    '<a href="?set=user">(' + load_lang('user_document') + ')</a> ' + \
+                    '<a href="?set=req">(' + load_lang('edit_req') + ')</a>' + \
+                    '<hr class="main_hr">' + div + \
+                ''
+
+            if set_type == 'req':
+                plus_sql = "where type = 'req' "
+            elif set_type == 'user':
+                plus_sql = "where title like 'user:%' and type = '' "
+            else:
+                plus_sql = "where not title like 'user:%' and type = '' "
 
             curs.execute(db_change('' + \
                 'select id, title, date, ip, send, leng from history ' + \
-                "where " + ('' if set_user == 'user' else 'not ') + "title like 'user:%' " + \
+                plus_sql + \
                 'order by date desc ' + \
                 'limit ?, 50' + \
             ''), [sql_num])
 
+        div += '</tr>'
+
         data_list = curs.fetchall()
-        for data in data_list:    
-            select += '<option value="' + data[0] + '">' + data[0] + '</option>'     
+        for data in data_list:
+            select += '<option value="' + data[0] + '">' + data[0] + '</option>'
             send = '<br>'
-            
+
             if data[4]:
                 if not re.search("^(?: *)$", data[4]):
                     send = data[4]
-            
+
             if re.search("\+", data[5]):
                 leng = '<span style="color:green;">(' + data[5] + ')</span>'
             elif re.search("\-", data[5]):
                 leng = '<span style="color:red;">(' + data[5] + ')</span>'
             else:
                 leng = '<span style="color:gray;">(' + data[5] + ')</span>'
-                
+
             ip = ip_pas(data[3])
             if tool == 'history':
                 m_tool = '<a href="/history_tool/' + url_pas(data[1]) + '?num=' + data[0] + '&type=history">(' + load_lang('tool') + ')</a>'
             else:
                 m_tool = '<a href="/history_tool/' + url_pas(data[1]) + '?num=' + data[0] + '">(' + load_lang('tool') + ')</a>'
-            
+
             style = ['', '']
             date = data[2]
 
@@ -122,16 +133,13 @@ def recent_changes_2(conn, name, tool):
                 where title = ? and id = ? and hide = 'O'
             '''), [data[1], data[0]])
             hide = curs.fetchall()
-            
-            if six_admin == 1:
-                if hide:                    
+
+            if admin_check(6) == 1:
+                if hide:
                     style[0] = 'id="toron_color_grey"'
                     style[1] = 'id="toron_color_grey"'
-                    
-                    if send == '<br>':
-                        send = '(' + load_lang('hide') + ')'
-                    else:
-                        send += ' (' + load_lang('hide') + ')'
+
+                    send += ' (' + load_lang('hide') + ')'
             elif not hide:
                 pass
             else:
@@ -147,8 +155,11 @@ def recent_changes_2(conn, name, tool):
             if tool == 'history':
                 title = '<a href="/w/' + url_pas(name) + '?num=' + data[0] + '">r' + data[0] + '</a> '
             else:
-                title = '<a href="/w/' + url_pas(data[1]) + '">' + html.escape(data[1]) + '</a> '
-                title += '<a href="/history/' + url_pas(data[1]) + '">(r' + data[0] + ')</a> '
+                if not name and set_type == 'req':
+                    title = '<a href="/edit_req/' + url_pas(data[1]) + '?r=' + data[0] + '">' + html.escape(data[1]) + ' (r' + data[0] + ')</a> '
+                else:
+                    title = '<a href="/w/' + url_pas(data[1]) + '">' + html.escape(data[1]) + '</a> '
+                    title += '<a href="/history/' + url_pas(data[1]) + '">(r' + data[0] + ')</a> '
 
             div +=  '''
                 <tr ''' + style[0] + '''>
@@ -165,54 +176,54 @@ def recent_changes_2(conn, name, tool):
                 </tbody>
             </table>
         '''
-        sub = ''
 
         if name:
             if tool == 'history':
-                if not tool_select:
+                if tool_select == 'normal':
+                    div = '' + \
+                        '<a href="?tool=move">(' + load_lang('move') + ')</a> ' + \
+                        '<a href="?tool=delete">(' + load_lang('delete') + ')</a> ' + \
+                        '<a href="?tool=revert">(' + load_lang('revert') + ')</a>' + \
+                        '<hr class="main_hr">' + div + \
+                    ''
+
                     div = '''
-                        <a href="?tool=move">(''' + load_lang('move') + ''')</a>
+                        <form method="post">
+                            <select name="a">''' + select + '''</select> <select name="b">''' + select + '''</select>
+                            <button type="submit">''' + load_lang('compare') + '''</button>
+                        </form>
                         <hr class=\"main_hr\">
                     ''' + div
-                    
-                div = '''
-                    <form method="post">
-                        <select name="a">''' + select + '''</select> <select name="b">''' + select + '''</select>
-                        <button type="submit">''' + load_lang('compare') + '''</button>
-                    </form>
-                    <hr class=\"main_hr\">
-                ''' + div
+
+                    menu = [['w/' + url_pas(name), load_lang('return')]]
+
+                    if admin_check() == 1:
+                        menu += [['add_history/' + url_pas(name), load_lang('add_history')]]
+                else:
+                    menu = [['history/' + url_pas(name), load_lang('return')]]
+
                 title = name
-                
-                sub += ' (' + load_lang('history') + ')'
-                
-                menu = [['w/' + url_pas(name), load_lang('document')], ['raw/' + url_pas(name), load_lang('raw')]]
-                
-                div += next_fix('/history/' + url_pas(name) + '?num=', num, data_list)
+                div += next_fix('/history/' + url_pas(name) + '?tool=' + tool_select + '&num=', num, data_list)
             else:
-                curs.execute(db_change("select end from ban where block = ?"), [name])
-                if curs.fetchall():
-                    sub += ' (' + load_lang('blocked') + ')'
-
                 title = load_lang('edit_record')
-                
                 menu = [['other', load_lang('other')], ['user', load_lang('user')], ['count/' + url_pas(name), load_lang('count')]]
-                
                 div += next_fix('/record/' + url_pas(name) + '?num=', num, data_list)
         else:
             menu = 0
             title = load_lang('recent_change')
-                
-            div += next_fix('/recent_changes?num=', num, data_list)
+            div += next_fix('/recent_changes?set=' + set_type + '&num=', num, data_list)
 
-            if set_user == 'user':
+            if set_type == 'user':
                 sub = ' (' + load_lang('user') + ')'
                 menu = [['recent_changes', load_lang('return')]]
-        
+            elif set_type == 'req':
+                sub = ' (' + load_lang('edit_req') + ')'
+                menu = [['recent_changes', load_lang('return')]]
+
         if sub == '':
             sub = 0
-                
-        return easy_minify(flask.render_template(skin_check(), 
+
+        return easy_minify(flask.render_template(skin_check(),
             imp = [title, wiki_set(), custom(), other2([sub, 0])],
             data = div,
             menu = menu

+ 16 - 9
route/recent_discuss.py

@@ -4,14 +4,14 @@ def recent_discuss_2(conn):
     curs = conn.cursor()
 
     div = ''
-    
+
     if flask.request.args.get('what', 'normal') == 'normal':
         div += '<a href="/recent_discuss?what=close">(' + load_lang('close_discussion') + ')</a>'
-       
+
         m_sub = 0
     else:
         div += '<a href="/recent_discuss">(' + load_lang('open_discussion') + ')</a>'
-        
+
         m_sub = ' (' + load_lang('closed') + ')'
 
     div +=  '''
@@ -23,21 +23,28 @@ def recent_discuss_2(conn):
                         <td id="main_table_width_half">''' + load_lang('time') + '''</td>
                     </tr>
             '''
-    
+
     if m_sub == 0:
         curs.execute(db_change("select title, sub, date from rd where not stop = 'O' order by date desc limit 50"))
     else:
         curs.execute(db_change("select title, sub, date from rd where stop = 'O' order by date desc limit 50"))
-        
+
     for data in curs.fetchall():
+        curs.execute(db_change("select code from topic where id = '1' and title = ? and sub = ?"), [data[0], data[1]])
+        get_code = curs.fetchall()
+        if get_code and get_code[0][0] != '':
+            get_code = get_code[0][0]
+        else:
+            get_code = '1'
+
         title = html.escape(data[0])
         sub = html.escape(data[1])
 
-        div += '<tr><td><a href="/topic/' + url_pas(data[0]) + '/sub/' + url_pas(data[1]) + '">' + title + '</a> (' + sub + ')</td><td>' + data[2] + '</td></tr>'
-    
+        div += '<tr><td><a href="/thread/' + get_code + '">' + title + '</a> (' + sub + ')</td><td>' + data[2] + '</td></tr>'
+
     div += '</tbody></table>'
-            
-    return easy_minify(flask.render_template(skin_check(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('recent_discussion'), wiki_set(), custom(), other2([m_sub, 0])],
         data = div,
         menu = 0

+ 1 - 1
route/recent_history_delete.py

@@ -16,7 +16,7 @@ def recent_history_delete_2(conn, name):
 
         return redirect('/history/' + url_pas(name))
     else:
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2(['(r' + num + ')', 0])],
             data = '''
                 <form method="post">

+ 3 - 3
route/recent_history_tool.py

@@ -9,7 +9,7 @@ def recent_history_tool_2(conn, name):
         <h2>''' + load_lang('tool') + '''</h2>
         <ul>
             <li>
-                <a href="/raw/''' + url_pas(name) + '?num=' + num + '">' + load_lang('raw') + '''</a> 
+                <a href="/raw/''' + url_pas(name) + '?num=' + num + '">' + load_lang('raw') + '''</a>
             </li>
     '''
 
@@ -55,8 +55,8 @@ def recent_history_tool_2(conn, name):
     data += '''
         </ul>
     '''
-                
-    return easy_minify(flask.render_template(skin_check(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [name, wiki_set(), custom(), other2(['(r' + num + ')', 0])],
         data = data,
         menu = [['history/' + url_pas(name), load_lang('return')]]

+ 29 - 20
route/search_deep.py

@@ -13,16 +13,16 @@ def search_deep_2(conn, name):
         sql_num = 0
 
     div = '<ul>'
-    
+
     div_plus = ''
     test = ''
-    
+
     curs.execute(db_change("select title from data where title = ?"), [name])
     if curs.fetchall():
         link_id = ''
     else:
         link_id = 'id="not_thing"'
-    
+
     div =   '''
             <ul>
                 <li>
@@ -32,29 +32,38 @@ def search_deep_2(conn, name):
             <hr class=\"main_hr\">
             <ul>
             '''
+    curs.execute(db_change('select data from other where name = "count_all_title"'))
+    if int(curs.fetchall()[0][0]) < 30000:
+        curs.execute(db_change("" + \
+            "select distinct title, case " + \
+            "when title like ? then 'title' else 'data' end from data " + \
+            "where title like ? or data like ? order by case " + \
+            "when title like ? then 1 else 2 end limit ?, 50"),
+            ['%' + name + '%', '%' + name + '%', '%' + name + '%', '%' + name + '%', sql_num]
+        )
+        all_list = curs.fetchall()
+        if all_list:
+            test = all_list[0][1]
 
-    curs.execute(db_change("" + \
-        "select distinct title, case when title like ? then 'title' else 'data' " + \
-        "end from data where title like ? or data like ? order by case " + \
-        "when title like ? then 1 else 2 end limit ?, 50"),
-        ['%' + name + '%', '%' + name + '%', '%' + name + '%', '%' + name + '%', sql_num]
-    )
-    all_list = curs.fetchall()
-    if all_list:
-        test = all_list[0][1]
-        
-        for data in all_list:
-            if data[1] != test:
-                div_plus += '</ul><hr class=\"main_hr\"><ul>'
-                
-                test = data[1]
+            for data in all_list:
+                if data[1] != test:
+                    div_plus += '</ul><hr class=\"main_hr\"><ul>'
 
-            div_plus += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a> (' + data[1] + ')</li>'
+                    test = data[1]
+
+                div_plus += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a> (' + data[1] + ')</li>'
+    else:
+        curs.execute(db_change("select title from data where title like ? order by title limit ?, 50"),
+            ['%' + name + '%', sql_num]
+        )
+        all_list = curs.fetchall()
+        for data in all_list:
+            div_plus += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a> (title)</li>'
 
     div += div_plus + '</ul>'
     div += next_fix('/search/' + url_pas(name) + '?num=', num, all_list)
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [name, wiki_set(), custom(), other2([' (' + load_lang('search') + ')', 0])],
         data = div,
         menu = 0

+ 0 - 63
route/server_indexing.py

@@ -1,63 +0,0 @@
-from .tool.func import *
-
-def server_indexing_2(conn, db_type):
-    curs = conn.cursor()
-
-    if db_type == 'sqlite':
-        if admin_check() != 1:
-            return re_error('/error/3')
-
-        if flask.request.method == 'POST':
-            admin_check(None, 'indexing')
-
-            curs.execute(db_change("select name from sqlite_master where type = 'index'"))
-            data = curs.fetchall()
-            if data:
-                for delete_index in data:
-                    print('Delete : ' + delete_index[0])
-
-                    sql = 'drop index if exists ' + delete_index[0]
-                    
-                    try:
-                        curs.execute(db_change(sql))
-                    except:
-                        pass
-            else:
-                curs.execute(db_change("select name from sqlite_master where type in ('table', 'view') and name not like 'sqlite_%' union all select name from sqlite_temp_master where type in ('table', 'view') order by 1;"))
-                for table in curs.fetchall():            
-                    curs.execute(db_change('select sql from sqlite_master where name = ?'), [table[0]])
-                    cul = curs.fetchall()
-                    
-                    r_cul = re.findall('(?:([^ (]*) text)', str(cul[0]))
-                    
-                    for n_cul in r_cul:
-                        print('Create : index_' + table[0] + '_' + n_cul)
-
-                        sql = 'create index index_' + table[0] + '_' + n_cul + ' on ' + table[0] + '(' + n_cul + ')'
-                        try:
-                            curs.execute(db_change(sql))
-                        except:
-                            pass
-
-            conn.commit()
-            
-            return redirect()  
-        else:
-            curs.execute(db_change("select name from sqlite_master where type = 'index'"))
-            data = curs.fetchall()
-            if data:
-                b_data = load_lang('delete')
-            else:
-                b_data = load_lang('create')
-
-            return easy_minify(flask.render_template(skin_check(), 
-                imp = [load_lang('indexing'), wiki_set(), custom(), other2([0, 0])],
-                data =  '''
-                        <form method="post">
-                            <button type="submit">''' + b_data + '''</button>
-                        </form>
-                        ''',
-                menu = [['manager', load_lang('return')]]
-            ))   
-    else:
-        return redirect('/')

+ 2 - 2
route/server_now_update.py

@@ -43,13 +43,13 @@ def server_now_update_2(conn, r_ver):
             else:
                 print('Update error')
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('update'), wiki_set(), custom(), other2([0, 0])],
             data = load_lang("update_error") + ' <a href="https://github.com/2DU/opennamu">(Github)</a>',
             menu = [['manager/1', load_lang('return')]]
         ))
     else:
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('update'), wiki_set(), custom(), other2([0, 0])],
             data = load_lang('update_warring') + '''
                 <hr class=\"main_hr\">

+ 1 - 1
route/server_restart.py

@@ -14,7 +14,7 @@ def server_restart_2(conn):
 
         os.execl(sys.executable, sys.executable, *sys.argv)
     else:
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('wiki_restart'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
                     <form method="post">

+ 212 - 137
route/setting.py

@@ -15,67 +15,65 @@ def setting_2(conn, num):
             'robots.txt',
             'Google',
             load_lang('main_bottom_body'),
+            load_lang('main_acl_setting')
         ]
-        
+
         x = 0
-        
         li_data = ''
-        
+
         for li in li_list:
             x += 1
             li_data += '<li><a href="/setting/' + str(x) + '">' + li + '</a></li>'
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('setting'), wiki_set(), custom(), other2([0, 0])],
             data = '<h2>' + load_lang('list') + '</h2><ul>' + li_data + '</ul>',
             menu = [['manager', load_lang('return')]]
         ))
     elif num == 1:
         i_list = {
-            0 : 'name', 
-            1 : 'logo', 
-            2 : 'frontpage', 
-            3 : 'license', 
-            4 : 'upload', 
-            5 : 'skin', 
-            6 : 'edit', 
-            7 : 'reg', 
-            8 : 'ip_view', 
-            9 : 'back_up', 
-            10 : 'port', 
-            11 : 'key', 
-            12 : 'update', 
-            13 : 'email_have', 
-            14 : 'discussion', 
-            15 : 'encode', 
-            16 : 'host'
+            0 : 'name',
+            1 : 'logo',
+            2 : 'frontpage',
+            3 : 'license',
+            4 : 'upload',
+            5 : 'skin',
+            7 : 'reg',
+            8 : 'ip_view',
+            9 : 'back_up',
+            10 : 'port',
+            11 : 'key',
+            12 : 'update',
+            13 : 'email_have',
+            15 : 'encode',
+            16 : 'host',
+            19 : 'slow_edit'
         }
         n_list = {
-            0 : 'Wiki', 
-            1 : '', 
-            2 : 'FrontPage', 
-            3 : 'CC 0', 
-            4 : '2', 
-            5 : '', 
-            6 : 'normal', 
-            7 : '', 
-            8 : '', 
-            9 : '0', 
-            10 : '3000', 
-            11 : 'test', 
-            12 : 'stable', 
-            13 : '', 
-            14 : 'normal', 
-            15 : 'sha3', 
-            16 : '0.0.0.0'
+            0 : 'Wiki',
+            1 : '',
+            2 : 'FrontPage',
+            3 : 'CC 0',
+            4 : '2',
+            5 : '',
+            7 : '',
+            8 : '',
+            9 : '0',
+            10 : '3000',
+            11 : 'test',
+            12 : 'stable',
+            13 : '',
+            15 : 'sha3',
+            16 : '0.0.0.0',
+            19 : '0'
         }
-        
+
         if flask.request.method == 'POST':
             for i in i_list:
                 curs.execute(db_change("update other set data = ? where name = ?"), [
-                    flask.request.form.get(i_list[i], n_list[i]), 
-                    i_list[i]]
-                )
+                    flask.request.form.get(i_list[i], n_list[i]),
+                    i_list[i]
+                ])
 
             conn.commit()
 
@@ -83,66 +81,49 @@ def setting_2(conn, num):
 
             return redirect('/setting/1')
         else:
-            d_list = []
-            
+            d_list = {}
+
             for i in i_list:
                 curs.execute(db_change('select data from other where name = ?'), [i_list[i]])
                 sql_d = curs.fetchall()
                 if sql_d:
-                    d_list += [sql_d[0][0]]
+                    d_list[i] = sql_d[0][0]
                 else:
                     curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i_list[i], n_list[i]])
-                    
-                    d_list += [n_list[i]]
+
+                    d_list[i] = n_list[i]
 
             conn.commit()
-            
-            div = ''
-            acl_list = ['normal', 'user', 'admin', 'owner', '50_edit', 'email']
-            for i in acl_list:
-                if i == d_list[6]:
-                    div = '<option value="' + i + '">' + i + '</option>' + div
-                else:
-                    div += '<option value="' + i + '">' + i + '</option>'
 
-            div4 = ''
-            for i in acl_list:
-                if i == d_list[14]:
-                    div4 = '<option value="' + i + '">' + i + '</option>' + div4
+            acl_div = ['']
+            encode_data = ['sha256', 'sha3']
+            for acl_data in encode_data:
+                if acl_data == d_list[15]:
+                    acl_div[0] = '<option value="' + acl_data + '">' + acl_data + '</option>' + acl_div[0]
                 else:
-                    div4 += '<option value="' + i + '">' + i + '</option>'
-
-            ch_1 = ''
-            if d_list[7]:
-                ch_1 = 'checked="checked"'
-
-            ch_2 = ''
-            if d_list[8]:
-                ch_2 = 'checked="checked"'
-            
-            ch_3 = ''
-            if d_list[13]:
-                ch_3 = 'checked="checked"'
+                    acl_div[0] += '<option value="' + acl_data + '">' + acl_data + '</option>'
+
+            check_box_div = ['', '', '']
+            for i in range(0, 3):
+                if i == 0:
+                    acl_num = 7
+                elif i == 1:
+                    acl_num = 8
+                else:
+                    acl_num = 13
 
-            div2 = load_skin(d_list[5])
+                if d_list[acl_num]:
+                    check_box_div[i] = 'checked="checked"'
 
-            div3 =''
+            branch_div =''
             if d_list[12] == 'stable':
-                div3 += '<option value="stable">stable</option>'
-                div3 += '<option value="master">master</option>'
+                branch_div += '<option value="stable">stable</option>'
+                branch_div += '<option value="master">master</option>'
             else:
-                div3 += '<option value="master">master</option>'
-                div3 += '<option value="stable">stable</option>'
-                
-            div5 =''
-            encode_data = ['sha256', 'sha3']
-            for i in encode_data:
-                if d_list[15] == i:
-                    div5 = '<option value="' + i + '">' + i + '</option>' + div5
-                else:
-                    div5 += '<option value="' + i + '">' + i + '</option>'
+                branch_div += '<option value="master">master</option>'
+                branch_div += '<option value="stable">stable</option>'
 
-            return easy_minify(flask.render_template(skin_check(), 
+            return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('main_setting'), wiki_set(), custom(), other2([0, 0])],
                 data = '''
                     <form method="post">
@@ -162,31 +143,23 @@ def setting_2(conn, num):
                         <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>
+                        <span>''' + load_lang('max_file_size') + ''' (MB)</span>
                         <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>
+                        <span>''' + load_lang('backup_interval') + ' (' + load_lang('hour') + ') (' + load_lang('off') + ' : 0) (' + load_lang('sqlite_only') + ') (' + load_lang('restart_required') + ''')</span>
                         <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>
                         <hr class=\"main_hr\">
-                        <select name="skin">''' + div2 + '''</select>
-                        <hr class=\"main_hr\">
-                        <span>''' + load_lang('default_acl') + '</span> <a href="/acl/TEST">(' + load_lang('reference') + ''')</a>
+                        <select name="skin">''' + load_skin(d_list[5]) + '''</select>
                         <hr class=\"main_hr\">
-                        <select name="edit">''' + div + '''</select>
+                        <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
                         <hr class=\"main_hr\">
-                        <span>''' + load_lang('default_discussion_acl') + '''</span>
+                        <input type="checkbox" name="ip_view" ''' + check_box_div[1] + '''> ''' + load_lang('hide_ip') + '''
                         <hr class=\"main_hr\">
-                        <select name="discussion">''' + div4 + '''</select>
-                        <hr class=\"main_hr\">
-                        <input type="checkbox" name="reg" ''' + ch_1 + '''> ''' + load_lang('no_register') + '''
-                        <hr class=\"main_hr\">
-                        <input type="checkbox" name="ip_view" ''' + ch_2 + '''> ''' + load_lang('hide_ip') + '''
-                        <hr class=\"main_hr\">
-                        <input type="checkbox" name="email_have" ''' + ch_3 + '''> ''' + load_lang('email_required') + ' <a href="/setting/6">{' + load_lang('google_imap_required') + '''}</a>
+                        <input type="checkbox" name="email_have" ''' + check_box_div[2] + '''> ''' + load_lang('email_required') + ' <a href="/setting/6">(' + load_lang('google_imap_required') + ''')</a>
                         <hr class=\"main_hr\">
                         <span>''' + load_lang('wiki_host') + '''</span>
                         <hr class=\"main_hr\">
@@ -202,11 +175,15 @@ def setting_2(conn, num):
                         <hr class=\"main_hr\">
                         <span>''' + load_lang('update_branch') + '''</span>
                         <hr class=\"main_hr\">
-                        <select name="update">''' + div3 + '''</select>
+                        <select name="update">''' + branch_div + '''</select>
                         <hr class=\"main_hr\">
                         <span>''' + load_lang('encryption_method') + '''</span>
                         <hr class=\"main_hr\">
-                        <select name="encode">''' + div5 + '''</select>
+                        <select name="encode">''' + acl_div[0] + '''</select>
+                        <hr class=\"main_hr\">
+                        <span>''' + load_lang('slow_edit') + ' (' + load_lang('second') + ') (' + load_lang('off') + ''' : 0)</span>
+                        <hr class=\"main_hr\">
+                        <input name="''' + i_list[19] + '''" value="''' + html.escape(d_list[19]) + '''">
                         <hr class=\"main_hr\">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
                     </form>
@@ -215,8 +192,8 @@ def setting_2(conn, num):
             ))
     elif num == 2:
         i_list = [
-            'contract', 
-            'no_login_warring', 
+            'contract',
+            'no_login_warring',
             'edit_bottom_text',
             'check_key_text',
             'email_title',
@@ -231,18 +208,18 @@ def setting_2(conn, num):
         if flask.request.method == 'POST':
             for i in i_list:
                 curs.execute(db_change("update other set data = ? where name = ?"), [
-                    flask.request.form.get(i, ''), 
+                    flask.request.form.get(i, ''),
                     i
                 ])
 
             conn.commit()
-            
+
             admin_check(None, 'edit_set')
 
             return redirect('/setting/2')
         else:
             d_list = []
-            
+
             for i in i_list:
                 curs.execute(db_change('select data from other where name = ?'), [i])
                 sql_d = curs.fetchall()
@@ -250,12 +227,12 @@ def setting_2(conn, num):
                     d_list += [sql_d[0][0]]
                 else:
                     curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
-                    
+
                     d_list += ['']
 
             conn.commit()
 
-            return easy_minify(flask.render_template(skin_check(), 
+            return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('text_setting'), wiki_set(), custom(), other2([0, 0])],
                 data = '''
                     <form method="post">
@@ -329,7 +306,7 @@ def setting_2(conn, num):
                     coverage = ''
                 else:
                     coverage = flask.request.args.get('skin', '')
-                
+
             curs.execute(db_change("select name from other where name = ? and coverage = ?"), [info_d, coverage])
             if curs.fetchall():
                 curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [
@@ -339,7 +316,7 @@ def setting_2(conn, num):
                 ])
             else:
                 curs.execute(db_change("insert into other (name, data, coverage) values (?, ?, ?)"), [info_d, flask.request.form.get('content', ''), coverage])
-            
+
             conn.commit()
 
             admin_check(None, 'edit_set')
@@ -350,35 +327,52 @@ def setting_2(conn, num):
                 curs.execute(db_change("select data from other where name = 'body'"))
                 title = '_body'
                 start = ''
+                plus = '''
+                    <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
+                    <hr class=\"main_hr\">
+                    <div id="see_preview"></div>
+                '''
             elif num == 7:
                 curs.execute(db_change("select data from other where name = 'bottom_body'"))
                 title = '_bottom_body'
                 start = ''
+                plus = '''
+                    <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
+                    <hr class=\"main_hr\">
+                    <div id="see_preview"></div>
+                '''
             else:
                 curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [flask.request.args.get('skin', '')])
                 title = '_head'
-                start = '<a href="?">(' + load_lang('all') + ')</a> ' + \
-                ' '.join(['<a href="?skin=' + i + '">(' + i + ')</a>' for i in load_skin('', 1)]) + \
-                '''
+                start = '' + \
+                    '<a href="?">(' + load_lang('all') + ')</a> ' + \
+                    ' '.join(['<a href="?skin=' + i + '">(' + i + ')</a>' for i in load_skin('', 1)]) + '''
                     <hr class=\"main_hr\">
                     <span>&lt;style&gt;CSS&lt;/style&gt;<br>&lt;script&gt;JS&lt;/script&gt;</span>
                     <hr class=\"main_hr\">
                 '''
-                
+                plus = ''
+
             head = curs.fetchall()
             if head:
                 data = head[0][0]
             else:
                 data = ''
 
-            return easy_minify(flask.render_template(skin_check(), 
-                imp = [load_lang(data = 'main' + title, safe = 1), wiki_set(), custom(), other2([0, 0])],
+            if flask.request.args.get('skin', '') != '':
+                sub_plus = ' (' + flask.request.args.get('skin', '') + ')'
+            else:
+                sub_plus = ''
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang(data = 'main' + title, safe = 1), wiki_set(), custom(), other2([' (HTML)' + sub_plus, 0])],
                 data = '''
                     <form method="post">
                         ''' + start + '''
-                        <textarea rows="25" name="content">''' + html.escape(data) + '''</textarea>
+                        <textarea rows="25" name="content" id="content">''' + html.escape(data) + '''</textarea>
                         <hr class=\"main_hr\">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        ''' + plus + '''
                     </form>
                 ''',
                 menu = [['setting', load_lang('return')]]
@@ -390,16 +384,16 @@ def setting_2(conn, num):
                 curs.execute(db_change("update other set data = ? where name = 'robot'"), [flask.request.form.get('content', '')])
             else:
                 curs.execute(db_change("insert into other (name, data) values ('robot', ?)"), [flask.request.form.get('content', '')])
-            
+
             conn.commit()
-            
+
             fw = open('./robots.txt', 'w')
             fw.write(re.sub('\r\n', '\n', flask.request.form.get('content', '')))
             fw.close()
-            
+
             admin_check(None, 'edit_set')
 
-            return redirect('/setting/4')
+            return redirect('/setting/5')
         else:
             if not os.path.exists('robots.txt'):
                 curs.execute(db_change('select data from other where name = "robot"'))
@@ -429,7 +423,7 @@ def setting_2(conn, num):
             if not data or data == '':
                 data = ''.join(lines)
 
-            return easy_minify(flask.render_template(skin_check(), 
+            return easy_minify(flask.render_template(skin_check(),
                 imp = ['robots.txt', wiki_set(), custom(), other2([0, 0])],
                 data = '''
                     <a href="/robots.txt">(''' + load_lang('view') + ''')</a>
@@ -444,9 +438,9 @@ def setting_2(conn, num):
             ))
     elif num == 6:
         i_list = [
-            'recaptcha', 
-            'sec_re', 
-            'g_email', 
+            'recaptcha',
+            'sec_re',
+            'g_email',
             'g_pass'
         ]
 
@@ -460,15 +454,15 @@ def setting_2(conn, num):
                 curs.execute(db_change("update other set data = ? where name = ?"), [into_data, data])
 
             conn.commit()
-            
+
             admin_check(None, 'edit_set')
 
             return redirect('/setting/6')
         else:
             d_list = []
-            
+
             x = 0
-            
+
             for i in i_list:
                 curs.execute(db_change('select data from other where name = ?'), [i])
                 sql_d = curs.fetchall()
@@ -476,27 +470,27 @@ def setting_2(conn, num):
                     d_list += [sql_d[0][0]]
                 else:
                     curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
-                    
+
                     d_list += ['']
 
                 x += 1
 
             conn.commit()
 
-            return easy_minify(flask.render_template(skin_check(), 
+            return easy_minify(flask.render_template(skin_check(),
                 imp = ['Google', wiki_set(), custom(), other2([0, 0])],
                 data = '''
                     <form method="post">
-                        <h2><a href="https://www.google.com/recaptcha/admin">recaptcha</a></h2>
-                        <span>''' + load_lang('recaptcha') + ''' (HTML)</span>
+                        <h2><a href="https://www.google.com/recaptcha/admin">''' + load_lang('recaptcha') + '''</a></h2>
+                        <span>HTML</span>
                         <hr class=\"main_hr\">
-                        <input name="recaptcha" value="''' + html.escape(d_list[0]) + '''">
+                        <input name="recaptcha" placeholder='&lt;div class="g-recaptcha" data-sitekey="''' + load_lang('public_key') + '''"&gt;&lt;/div&gt;' value="''' + html.escape(d_list[0]) + '''">
                         <hr class=\"main_hr\">
-                        <span>''' + load_lang('recaptcha') + ' (' + load_lang('secret_key') + ''')</span>
+                        <span>''' + load_lang('secret_key') + '''</span>
                         <hr class=\"main_hr\">
                         <input 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>
+                        <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>
                         <hr class=\"main_hr\">
                         <input name="g_email" value="''' + html.escape(d_list[2]) + '''">
@@ -510,5 +504,86 @@ def setting_2(conn, num):
                 ''',
                 menu = [['setting', load_lang('return')]]
             ))
+    elif num == 8:
+        i_list = {
+            1 : 'edit',
+            2 : 'discussion',
+            3 : 'upload_acl',
+            4 : 'all_view_acl',
+            5 : 'edit_req_acl'
+        }
+        n_list = {
+            1 : 'normal',
+            2 : 'normal',
+            3 : 'normal',
+            4 : 'normal',
+            5 : 'normal'
+        }
+
+        if flask.request.method == 'POST':
+            for i in i_list:
+                curs.execute(db_change("update other set data = ? where name = ?"), [
+                    flask.request.form.get(i_list[i], n_list[i]),
+                    i_list[i]
+                ])
+
+            conn.commit()
+
+            admin_check(None, 'edit_set')
+
+            return redirect('/setting/8')
+        else:
+            d_list = {}
+
+            for i in i_list:
+                curs.execute(db_change('select data from other where name = ?'), [i_list[i]])
+                sql_d = curs.fetchall()
+                if sql_d:
+                    d_list[i] = sql_d[0][0]
+                else:
+                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i_list[i], n_list[i]])
+
+                    d_list[i] = n_list[i]
+
+            conn.commit()
+
+            acl_div = ['', '', '', '', '']
+            acl_list = ['normal', 'user', 'admin', 'owner', '50_edit', 'email']
+            for i in range(0, 5):
+                for acl_data in acl_list:
+                    if acl_data == d_list[i + 1]:
+                        acl_div[i] = '<option value="' + acl_data + '">' + acl_data + '</option>' + acl_div[i]
+                    else:
+                        acl_div[i] += '<option value="' + acl_data + '">' + acl_data + '</option>'
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('main_acl_setting'), wiki_set(), custom(), other2([0, 0])],
+                data = '''
+                    <form method="post">
+                        <span>''' + load_lang('document_acl') + '</span> <a href="/acl/TEST">(' + load_lang('reference') + ''')</a>
+                        <hr class=\"main_hr\">
+                        <select name="edit">''' + acl_div[0] + '''</select>
+                        <hr class=\"main_hr\">
+                        <span>''' + load_lang('discussion_acl') + '''</span>
+                        <hr class=\"main_hr\">
+                        <select name="discussion">''' + acl_div[1] + '''</select>
+                        <hr class=\"main_hr\">
+                        <span>''' + load_lang('upload_acl') + '''</span>
+                        <hr class=\"main_hr\">
+                        <select name="upload_acl">''' + acl_div[2] + '''</select>
+                        <hr class=\"main_hr\">
+                        <span>''' + load_lang('view_acl') + '''</span>
+                        <hr class=\"main_hr\">
+                        <select name="all_view_acl">''' + acl_div[3] + '''</select>
+                        <hr class=\"main_hr\">
+                        <span>''' + load_lang('edit_req_acl') + '''</span>
+                        <hr class=\"main_hr\">
+                        <select name="edit_req_acl">''' + acl_div[4] + '''</select>
+                        <hr class=\"main_hr\">
+                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
+                menu = [['setting', load_lang('return')]]
+            ))
     else:
         return redirect()

+ 5 - 5
route/setting_adsense.py

@@ -5,7 +5,7 @@ def setting_adsense_2(conn):
 
     if admin_check(None, 'adsense setting') != 1:
         return re_error('/error/3')
-    
+
     if flask.request.method == 'POST':
         try:
             adsense_enabled = flask.request.form.get('adsense_enabled')
@@ -16,15 +16,15 @@ def setting_adsense_2(conn):
                 data = '<h2>ie_no_data_required</h2>' + load_lang('ie_no_data_required'),
                 menu = [['other', load_lang('return')]]
             ))
-        
+
         if adsense_enabled == 'on':
             curs.execute(db_change('update other set data = "True" where name = "adsense"'))
         else:
             curs.execute(db_change('update other set data = "False" where name = "adsense"'))
-        
+
         curs.execute(db_change('update other set data = ? where name = "adsense_code"'), [adsense_code])
         conn.commit()
-        
+
         return redirect('/adsense_setting')
 
     body_content = ''
@@ -51,7 +51,7 @@ def setting_adsense_2(conn):
             <button type="submit" value="publish">{}</button>
         </form>
     '''
-    
+
     body_content += template.format(
         'checked' if adsense_enabled == 'True' else '',
         load_lang('adsense_enable'),

+ 11 - 11
route/setting_oauth.py

@@ -10,7 +10,7 @@ def setting_oauth_2(conn):
         try:
             facebook_client_id = flask.request.form['facebook_client_id']
             facebook_client_secret = flask.request.form['facebook_client_secret']
-            
+
             naver_client_id = flask.request.form['naver_client_id']
             naver_client_secret = flask.request.form['naver_client_secret']
         except:
@@ -42,7 +42,7 @@ def setting_oauth_2(conn):
                     }
                 }
             ''')
-        
+
         return flask.redirect('/oauth_setting')
 
     oauth_supported = load_oauth('_README')['support']
@@ -56,7 +56,7 @@ def setting_oauth_2(conn):
                     target_box.checked = true;
                 } else {
                     target_box.checked = false;
-                } 
+                }
             }
         </script>
     '''
@@ -81,18 +81,18 @@ def setting_oauth_2(conn):
             '''.format(
                 oauth_supported[i],
                 load_target,
-                oauth_supported[i], 
-                load_target, 
-                oauth_supported[i], 
-                load_target, 
-                oauth_supported[i], 
-                load_target, 
+                oauth_supported[i],
+                load_target,
+                oauth_supported[i],
+                load_target,
+                oauth_supported[i],
+                load_target,
                 oauth_data['client_{}'.format(load_target)]
             )
-    
+
     body_content += '<button id="save" type="submit">' + load_lang('save') + '</button></form>'
     body_content += '<script>' + init_js + '</script>'
-    
+
     return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('oauth_setting'), wiki_set(), custom(), other2([0, 0])],
         data = body_content,

+ 206 - 200
route/tool/func.py

@@ -124,14 +124,14 @@ def last_change(data):
 
                         if e_data == 0:
                             re_data_3 = re.compile("<" + i_data[0] + ">")
-                            data = re_data_3.sub("<" + i_data[0] + " class=\"" + json_data[j_data]["class"] + "\">", data)        
+                            data = re_data_3.sub("<" + i_data[0] + " class=\"" + json_data[j_data]["class"] + "\">", data)
                 else:
                     re_data = re.compile("<(?P<in>" + j_data + "(?: (?:(?!>).)*)?)>")
                     data = re_data.sub("<\g<in> class=\"" + json_data[j_data]["class"] + "\">", data)
 
     return data
 
-def easy_minify(data, tool = None):    
+def easy_minify(data, tool = None):
     return last_change(data)
 
 def render_set(title = '', data = '', num = 0, s_data = 0, include = None):
@@ -141,7 +141,7 @@ def render_set(title = '', data = '', num = 0, s_data = 0, include = None):
         return data
     else:
         if data != None:
-            return namumark(title, data, num, include)
+            return render_do(title, data, num, include)
         else:
             return 'HTTP Request 404'
 
@@ -155,25 +155,36 @@ def captcha_get():
             curs.execute(db_change('select data from other where name = "sec_re"'))
             sec_re = curs.fetchall()
             if sec_re and sec_re[0][0] != '':
-                data += recaptcha[0][0] + '<hr class=\"main_hr\">'
+                data += '<script src="https://www.google.com/recaptcha/api.js" async defer></script>' + recaptcha[0][0] + '<hr class=\"main_hr\">'
 
     return data
 
 def update():
-    #v3.1.2
+    #v3.1.5
     try:
-        curs.execute(db_change('select title, dec from acl where dec != ""'))
+        num = 1
+        curs.execute(db_change('select title, sub from topic where id = "1" order by date asc'))
         db_data = curs.fetchall()
         for i in db_data:
-            curs.execute(db_change("update acl set decu = ? where title = ?"), [i[1], i[0]])
+            curs.execute(db_change("update topic set code = ? where title = ? and sub = ? and id = '1'"), [str(num), i[0], i[1]])
+            num += 1
 
-        print('Fix table acl column dec to decu')
+        print('----')
+        print('Add topic code')
         print('----')
     except:
         pass
 
     conn.commit()
 
+def topic_change(num):
+    curs.execute(db_change('select title, sub from topic where id = "1" and code = ?'), [str(num)])
+    db_data = curs.fetchall()
+    if db_data:
+        return [db_data[0][0], db_data[0][1]]
+    else:
+        return ['Test', 'Test']
+
 def pw_encode(data, data2 = '', type_d = ''):
     if type_d == '':
         curs.execute(db_change('select data from other where name = "encode"'))
@@ -193,7 +204,7 @@ def pw_encode(data, data2 = '', type_d = ''):
             salt_data = bytes(data2, 'utf-8')
         else:
             salt_data = bcrypt.gensalt(11)
-            
+
         return bcrypt.hashpw(bytes(data, 'utf-8'), salt_data).decode()
 
 def pw_check(data, data2, type_d = 'no', id_d = ''):
@@ -207,7 +218,7 @@ def pw_check(data, data2, type_d = 'no', id_d = ''):
             set_data = type_d
     else:
         set_data = db_data[0][0]
-    
+
     while 1:
         if set_data in ['sha256', 'sha3']:
             data3 = pw_encode(data = data, type_d = set_data)
@@ -243,7 +254,7 @@ def captcha_post(re_data, num = 1):
                     data = urllib.request.urlopen('https://www.google.com/recaptcha/api/siteverify?secret=' + sec_re[0][0] + '&response=' + re_data)
                 except:
                     pass
-                    
+
                 if data and data.getcode() == 200:
                     json_data = json.loads(data.read().decode(data.headers.get_content_charset()))
                     if json_data['success'] == True:
@@ -319,7 +330,7 @@ def ip_or_user(data = ''):
 
 def edit_button():
     insert_list = []
-    
+
     curs.execute(db_change("select html, plus from html_filter where kind = 'edit_top'"))
     db_data = curs.fetchall()
     for get_data in db_data:
@@ -355,7 +366,7 @@ def skin_check(set_n = 0):
     if skin_exist and skin_exist[0][0] != '':
         if os.path.exists(os.path.abspath('./views/' + skin_exist[0][0] + '/index.html')) == 1:
             skin = skin_exist[0][0]
-    
+
     curs.execute(db_change('select data from user_set where name = "skin" and id = ?'), [ip_check()])
     skin_exist = curs.fetchall()
     if skin_exist and skin_exist[0][0] != '':
@@ -385,31 +396,21 @@ def other2(data):
         data += ['']
 
     req_list = ''
-    
-    css_filter = {
-        'main.css' : '2'
-    }
-    for i_data in os.listdir(os.path.join("views", "main_css", "css")):
-        if i_data in css_filter:
-            req_list += '<link rel="stylesheet" href="/views/main_css/css/' + i_data + '?ver=' + css_filter[i_data] + '">'
-        else:
-            req_list += '<link rel="stylesheet" href="/views/main_css/css/' + i_data + '?ver=1">'
-    
-    js_filter = {
-        'load_include.js' : '2',
-        'render_html.js' : '3',
-        'do_open_foot.js' : '4',
-        'topic_main_load.js' : '2',
-        'topic_plus_load.js' : '2',
-        'do_stop_exit.js' : '2',
-        'do_open_folding.js' : '2',
-        'shotcuts_set.js' : '2'
-    }
-    for i_data in os.listdir(os.path.join("views", "main_css", "js")):
-        if i_data in js_filter:
-            req_list += '<script src="/views/main_css/js/' + i_data + '?ver=' + js_filter[i_data] + '"></script>'
-        else:
-            req_list += '<script src="/views/main_css/js/' + i_data + '?ver=1"></script>'
+    main_css_ver = 2
+
+    if not 'main_css_load' in flask.session or not 'main_css_ver' in flask.session or flask.session['main_css_ver'] != main_css_ver:
+        for i_data in os.listdir(os.path.join("views", "main_css", "css")):
+            file_date = str(int(os.path.getmtime(os.path.join("views", "main_css", "css", i_data))))
+            req_list += '<link rel="stylesheet" href="/views/main_css/css/' + i_data + '?ver=' + file_date + '">'
+
+        for i_data in os.listdir(os.path.join("views", "main_css", "js")):
+            file_date = str(int(os.path.getmtime(os.path.join("views", "main_css", "js", i_data))))
+            req_list += '<script src="/views/main_css/js/' + i_data + '?ver=' + file_date + '"></script>'
+
+        flask.session['main_css_load'] = req_list
+        flask.session['main_css_ver'] = main_css_ver
+    else:
+        req_list = flask.session['main_css_load']
 
     data = data[0:2] + ['', '''
         <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
@@ -434,9 +435,6 @@ def cut_100(data):
 
     return data[0:100] + '...'
 
-def change_space(data):
-    return re.sub(' ', ' ', data)
-
 def wiki_set(num = 1):
     if num == 1:
         data_list = []
@@ -463,7 +461,7 @@ def wiki_set(num = 1):
             data_list += [db_data[0][0]]
         else:
             data_list += [data_list[0]]
-            
+
         curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [skin_check(1)])
         db_data = curs.fetchall()
         if db_data and db_data[0][0] != '':
@@ -492,7 +490,7 @@ def wiki_set(num = 1):
         var_data = '2'
 
         curs.execute(db_change('select data from other where name = "upload"'))
-    
+
     db_data = curs.fetchall()
     if db_data and db_data[0][0] != '':
         return db_data[0][0]
@@ -504,14 +502,14 @@ def diff(seqm):
 
     for opcode, a0, a1, b0, b1 in seqm.get_opcodes():
         if opcode == 'equal':
-            output += [seqm.a[a0:a1]]
+            output += [html.escape(seqm.a[a0:a1])]
         elif opcode == 'insert':
-            output += ["<span style='background:#CFC;'>" + seqm.b[b0:b1] + "</span>"]
+            output += ["<span style='background:#CFC;'>" + html.escape(seqm.b[b0:b1]) + "</span>"]
         elif opcode == 'delete':
-            output += ["<span style='background:#FDD;'>" + seqm.a[a0:a1] + "</span>"]
+            output += ["<span style='background:#FDD;'>" + html.escape(seqm.a[a0:a1]) + "</span>"]
         elif opcode == 'replace':
-            output += ["<span style='background:#FDD;'>" + seqm.a[a0:a1] + "</span>"]
-            output += ["<span style='background:#CFC;'>" + seqm.b[b0:b1] + "</span>"]
+            output += ["<span style='background:#FDD;'>" + html.escape(seqm.a[a0:a1]) + "</span>"]
+            output += ["<span style='background:#CFC;'>" + html.escape(seqm.b[b0:b1]) + "</span>"]
 
     end = ''.join(output)
     end = end.replace('\r\n', '\n')
@@ -526,7 +524,7 @@ def diff(seqm):
         data = re.search('((?:(?!\n).)*)\n', end)
         if data:
             data = data.groups()[0]
-            
+
             left += 1
             if re.search('<span style=\'(?:(?:(?!\').)+)\'>', data):
                 num += 1
@@ -545,9 +543,9 @@ def diff(seqm):
             end = re.sub('((?:(?!\n).)*)\n', '', end, 1)
         else:
             break
-            
+
     return sub
-           
+
 def admin_check(num = None, what = None, name = ''):
     if name == '':
         ip = ip_check()
@@ -597,37 +595,44 @@ def admin_check(num = None, what = None, name = ''):
                     num = None
                 else:
                     break
-                    
+
     return 0
 
-def ip_pas(raw_ip):
+def ip_pas(raw_ip, type_d = 0):
     hide = 0
 
-    if ip_or_user(raw_ip) != 0:    
+    if ip_or_user(raw_ip) != 0:
         curs.execute(db_change("select data from other where name = 'ip_view'"))
         data = curs.fetchall()
         if data and data[0][0] != '':
-            ip = re.sub('((?:(?!\.).)+)\.((?:(?!\.).)+)$', '*.*', raw_ip)
+            if re.search('\.', raw_ip):
+                ip = re.sub('\.([^.]*)\.([^.]*)$', '.*.*', raw_ip)
+            else:
+                ip = re.sub(':([^:]*):([^:]*)$', ':*:*', raw_ip)
 
             if not admin_check(1):
                 hide = 1
         else:
             ip = raw_ip
     else:
-        curs.execute(db_change("select title from data where title = ?"), ['user:' + raw_ip])
-        if curs.fetchall():
-            ip = '<a href="/w/' + url_pas('user:' + raw_ip) + '">' + raw_ip + '</a>'
+        if type_d == 0:
+            curs.execute(db_change("select title from data where title = ?"), ['user:' + raw_ip])
+            if curs.fetchall():
+                ip = '<a href="/w/' + url_pas('user:' + raw_ip) + '">' + raw_ip + '</a>'
+            else:
+                ip = '<a id="not_thing" href="/w/' + url_pas('user:' + raw_ip) + '">' + raw_ip + '</a>'
+
+            if admin_check('all', None, raw_ip) == 1:
+                ip = '<b>' + ip + '</b>'
         else:
-            ip = '<a id="not_thing" href="/w/' + url_pas('user:' + raw_ip) + '">' + raw_ip + '</a>'
+            ip = raw_ip
 
-        if admin_check('all', None, raw_ip) == 1:
-            ip = '<b>' + ip + '</b>'
+    if type_d == 0:
+        if ban_check(raw_ip) == 1:
+            ip = '<s>' + ip + '</s>'
 
-    if ban_check(raw_ip) == 1:
-        ip = '<s>' + ip + '</s>'
-         
-    if hide == 0:
-        ip += ' <a href="/tool/' + url_pas(raw_ip) + '">(' + load_lang('tool') + ')</a>'
+        if hide == 0:
+            ip += ' <a href="/tool/' + url_pas(raw_ip) + '">(' + load_lang('tool') + ')</a>'
 
     return ip
 
@@ -643,50 +648,33 @@ def custom():
     ip = ip_check()
     if ip_or_user(ip) == 0:
         user_icon = 1
-    else:
-        user_icon = 0
+        user_name = ip
 
-    if user_icon != 0:
         curs.execute(db_change('select data from user_set where name = "email" and id = ?'), [ip])
         data = curs.fetchall()
         if data:
             email = data[0][0]
         else:
             email = ''
-    else:
-        email = ''
-
-    if user_icon != 0:
-        user_name = ip
-    else:
-        user_name = load_lang('user')
-        
-    if admin_check('all') == 1:
-        user_admin = '1'
 
-        curs.execute(db_change("select acl from user where id = ?"), [ip])
-        user_acl = curs.fetchall()
+        if admin_check('all') == 1:
+            user_admin = '1'
+            user_acl_list = []
 
-        user_acl_list = []
-        curs.execute(db_change('select acl from alist where name = ?'), [user_acl[0][0]])
-        user_acl = curs.fetchall()
-        for i in user_acl:
-            user_acl_list += [i[0]]
+            curs.execute(db_change("select acl from user where id = ?"), [ip])
+            curs.execute(db_change('select acl from alist where name = ?'), [curs.fetchall()[0][0]])
+            user_acl = curs.fetchall()
+            for i in user_acl:
+                user_acl_list += [i[0]]
 
-        if user_acl != []:
-            user_acl_list = user_acl_list
+            if user_acl != []:
+                user_acl_list = user_acl_list
+            else:
+                user_acl_list = '0'
         else:
+            user_admin = '0'
             user_acl_list = '0'
-    else:
-        user_admin = '0'
-        user_acl_list = '0'
-        
-    if ban_check() == 1:
-        user_ban = '1'
-    else:
-        user_ban = '0'
 
-    if user_icon == 1:
         curs.execute(db_change("select count(name) from alarm where name = ?"), [ip])
         count = curs.fetchall()
         if count:
@@ -694,14 +682,37 @@ def custom():
         else:
             user_notice = '0'
     else:
+        user_icon = 0
+        user_name = load_lang('user')
+        email = ''
+        user_admin = '0'
+        user_acl_list = '0'
         user_notice = '0'
 
-    return ['', '', user_icon, user_head, email, user_name, user_admin, user_ban, user_notice, user_acl_list]
+    curs.execute(db_change("select title from rd where title = ? and stop = ''"), ['user:' + ip])
+    if curs.fetchall():
+        user_topic = '1'
+    else:
+        user_topic = '0'
+
+    return [
+        '',
+        '',
+        user_icon,
+        user_head,
+        email,
+        user_name,
+        user_admin,
+        str(ban_check()),
+        user_notice,
+        user_acl_list,
+        ip,
+        user_topic
+    ]
 
 def load_skin(data = '', set_n = 0):
-    div2 = ''
-    div3 = []
-    system_file = ['main_css', 'easter_egg.html']
+    skin_return_data = ''
+    system_file = ['main_css']
 
     if data == '':
         ip = ip_check()
@@ -712,50 +723,67 @@ def load_skin(data = '', set_n = 0):
         if not data:
             curs.execute(db_change('select data from other where name = "skin"'))
             data = curs.fetchall()
-            if not data:
+            if not data or data[0][0] == '':
                 data = [['marisa']]
 
         if set_n == 0:
             for skin_data in os.listdir(os.path.abspath('views')):
                 if not skin_data in system_file:
                     if data[0][0] == skin_data:
-                        div2 = '<option value="' + skin_data + '">' + skin_data + '</option>' + div2
+                        skin_return_data = '<option value="' + skin_data + '">' + skin_data + '</option>' + skin_return_data
                     else:
-                        div2 += '<option value="' + skin_data + '">' + skin_data + '</option>'
+                        skin_return_data += '<option value="' + skin_data + '">' + skin_data + '</option>'
         else:
-            div2 = []
+            skin_return_data = []
             for skin_data in os.listdir(os.path.abspath('views')):
                 if not skin_data in system_file:
                     if data[0][0] == skin_data:
-                        div2 = [skin_data] + div2
+                        skin_return_data = [skin_data] + skin_return_data
                     else:
-                        div2 += [skin_data]
+                        skin_return_data += [skin_data]
     else:
         if set_n == 0:
             for skin_data in os.listdir(os.path.abspath('views')):
                 if not skin_data in system_file:
                     if data == skin_data:
-                        div2 = '<option value="' + skin_data + '">' + skin_data + '</option>' + div2
+                        skin_return_data = '<option value="' + skin_data + '">' + skin_data + '</option>' + skin_return_data
                     else:
-                        div2 += '<option value="' + skin_data + '">' + skin_data + '</option>'
+                        skin_return_data += '<option value="' + skin_data + '">' + skin_data + '</option>'
         else:
-            div2 = []
+            skin_return_data = []
             for skin_data in os.listdir(os.path.abspath('views')):
                 if not skin_data in system_file:
                     if data == skin_data:
-                        div2 = [skin_data] + div2
+                        skin_return_data = [skin_data] + skin_return_data
                     else:
-                        div2 += [skin_data]
+                        skin_return_data += [skin_data]
+
+    return skin_return_data
+
+def slow_edit_check():
+    curs.execute(db_change("select data from other where name = 'slow_edit'"))
+    slow_edit = curs.fetchall()
+    if slow_edit and slow_edit != '0' and admin_check(5) != 1:
+        slow_edit = slow_edit[0][0]
 
-    return div2
+        curs.execute(db_change("select date from history where ip = ? order by date desc limit 1"), [ip_check()])
+        last_edit_data = curs.fetchall()
+        if last_edit_data:
+            last_edit_data = int(re.sub(' |:|-', '', last_edit_data[0][0]))
+            now_edit_data = int((datetime.datetime.now() - datetime.timedelta(seconds = int(slow_edit))).strftime("%Y%m%d%H%M%S"))
+
+            if last_edit_data > now_edit_data:
+                return 1
+
+    return 0
 
 def acl_check(name = 'test', tool = '', sub = 'test'):
     ip = ip_check()
-    
+
     if ban_check() == 1:
         return 1
 
-    if tool != 'topic' and tool != 'render':
+    if tool != 'topic' and tool != 'render' and name:
         acl_c = re.search("^user:((?:(?!\/).)*)", name)
         if acl_c:
             acl_n = acl_c.groups()
@@ -774,7 +802,7 @@ def acl_check(name = 'test', tool = '', sub = 'test'):
 
                 if ip != acl_n[0] or re.search("(\.|:)", ip):
                     return 1
-            
+
             if ip == acl_n[0] and not re.search("(\.|:)", ip) and not re.search("(\.|:)", acl_n[0]):
                 return 0
             else:
@@ -785,7 +813,7 @@ def acl_check(name = 'test', tool = '', sub = 'test'):
 
     if tool == '':
         end = 3
-    elif tool == 'topic':
+    elif tool == 'topic' or tool == 'render':
         end = 2
     else:
         end = 1
@@ -794,30 +822,36 @@ def acl_check(name = 'test', tool = '', sub = 'test'):
         if tool == '':
             if i == 0:
                 curs.execute(db_change("select decu from acl where title = ?"), [name])
-                acl_data = curs.fetchall()
             elif i == 1:
                 curs.execute(db_change('select data from other where name = "edit"'))
-                acl_data = curs.fetchall()
             else:
                 curs.execute(db_change("select view from acl where title = ?"), [name])
-                acl_data = curs.fetchall()
 
             num = 5
         elif tool == 'topic':
             if i == 0:
                 curs.execute(db_change("select dis from acl where title = ?"), [name])
-                acl_data = curs.fetchall()
             else:
                 curs.execute(db_change('select data from other where name = "discussion"'))
-                acl_data = curs.fetchall()
 
             num = 3
+        elif tool == 'upload':
+            curs.execute(db_change("select data from other where name = 'upload_acl'"))
+
+            num = 5
+        elif tool == 'edit_req':
+            curs.execute(db_change("select data from other where name = 'edit_req_acl'"))
+
+            num = 5
         else:
-            curs.execute(db_change("select view from acl where title = ?"), [name])
-            acl_data = curs.fetchall()
+            if i == 0:
+                curs.execute(db_change("select view from acl where title = ?"), [name])
+            if i == 1:
+                curs.execute(db_change("select data from other where name = 'all_view_acl'"))
 
             num = 5
 
+        acl_data = curs.fetchall()
         if acl_data and acl_data[0][0] != 'normal':
             if acl_data[0][0] == 'user':
                 if ip_or_user(ip) == 1:
@@ -833,7 +867,7 @@ def acl_check(name = 'test', tool = '', sub = 'test'):
             if acl_data[0][0] == '50_edit':
                 if ip_or_user(ip) == 1:
                     return 1
-                
+
                 if admin_check(num) != 1:
                     curs.execute(db_change("select count(title) from history where ip = ?"), [ip])
                     count = curs.fetchall()
@@ -848,7 +882,7 @@ def acl_check(name = 'test', tool = '', sub = 'test'):
             if acl_data[0][0] == 'email':
                 if ip_or_user(ip) == 1:
                     return 1
-                
+
                 if admin_check(num) != 1:
                     curs.execute(db_change("select data from user_set where id = ? and name = 'email'"), [ip])
                     email = curs.fetchall()
@@ -871,6 +905,9 @@ def ban_check(ip = None, tool = None):
     if not ip:
         ip = ip_check()
 
+    if admin_check(None, None, ip) == 1:
+        return 0
+
     band = re.search("^([0-9]{1,3}\.[0-9]{1,3})", ip)
     if band:
         band_it = band.groups()[0]
@@ -890,7 +927,7 @@ def ban_check(ip = None, tool = None):
                     return 1
             else:
                 return 1
-    
+
     curs.execute(db_change("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()
     if band_d:
@@ -910,9 +947,6 @@ def ban_check(ip = None, tool = None):
             return 1
 
     return 0
-        
-def topic_check(name, sub):
-    return acl_check(name, 'topic', sub)
 
 def ban_insert(name, end, why, login, blocker, type_d = None):
     now_time = get_time()
@@ -930,11 +964,11 @@ def ban_insert(name, end, why, login, blocker, type_d = None):
     curs.execute(db_change("select block from ban where ((end > ? and end like '2%') or end = '') and block = ? and band = ?"), [get_time(), name, band])
     if curs.fetchall():
         curs.execute(db_change("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)"), [
-            name, 
+            name,
             'release',
-            now_time, 
-            blocker, 
-            '', 
+            now_time,
+            blocker,
+            '',
             band
         ])
         curs.execute(db_change("delete from ban where block = ? and band = ?"), [name, band])
@@ -955,7 +989,7 @@ def ban_insert(name, end, why, login, blocker, type_d = None):
 
         curs.execute(db_change("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)"), [name, r_time, now_time, blocker, why, band])
         curs.execute(db_change("insert into ban (block, end, why, band, login) values (?, ?, ?, ?, ?)"), [name, r_time, why, band, login])
-    
+
     conn.commit()
 
 def rd_plus(title, sub, date):
@@ -967,9 +1001,18 @@ def rd_plus(title, sub, date):
 
     conn.commit()
 
-def history_plus(title, data, date, ip, send, leng, t_check = ''):
-    curs.execute(db_change("select id from history where title = ? order by id + 0 desc limit 1"), [title])
+def history_plus(title, data, date, ip, send, leng, t_check = '', d_type = ''):
+    curs.execute(db_change("select id from history where title = ? and type = '' order by id + 0 desc limit 1"), [title])
     id_data = curs.fetchall()
+    id_data = str(int(id_data[0][0]) + 1) if id_data else '1'
+
+    if d_type != 'req':
+        curs.execute(db_change("select title from history where title = ? and id = ? and type = 'req'"), [title, id_data])
+        if curs.fetchall():
+            curs.execute(db_change("update history set type = 'req_close' where title = ? and id = ? and type = 'req'"), [
+                title,
+                id_data
+            ])
 
     send = re.sub('\(|\)|<|>', '', send)
 
@@ -979,14 +1022,15 @@ def history_plus(title, data, date, ip, send, leng, t_check = ''):
     if t_check != '':
         send += ' (' + t_check + ')'
 
-    curs.execute(db_change("insert into history (id, title, data, date, ip, send, leng, hide) values (?, ?, ?, ?, ?, ?, ?, '')"), [
-        str(int(id_data[0][0]) + 1) if id_data else '1',
+    curs.execute(db_change("insert into history (id, title, data, date, ip, send, leng, hide, type) values (?, ?, ?, ?, ?, ?, ?, '', ?)"), [
+        id_data,
         title,
         data,
         date,
         ip,
         send,
-        leng
+        leng,
+        d_type
     ])
 
 def leng_check(first, second):
@@ -996,7 +1040,7 @@ def leng_check(first, second):
         all_plus = '-' + str(first - second)
     else:
         all_plus = '0'
-        
+
     return all_plus
 
 def number_check(data):
@@ -1013,15 +1057,15 @@ def edit_filter_do(data):
             match = re.compile(data_list[0], re.I)
             if match.search(data):
                 ban_insert(
-                    ip_check(), 
-                    '0' if data_list[1] == 'X' else data_list[1], 
-                    'edit filter', 
-                    None, 
+                    ip_check(),
+                    '0' if data_list[1] == 'X' else data_list[1],
+                    'edit filter',
+                    None,
                     'tool:edit filter'
                 )
-                
+
                 return 1
-    
+
     return 0
 
 def redirect(data = '/'):
@@ -1029,60 +1073,16 @@ def redirect(data = '/'):
 
 def re_error(data):
     conn.commit()
-    
-    if data == '/ban':
-        ip = ip_check()
-
-        end = '<li>' + load_lang('why') + ' : ' + load_lang('authority_error') + '</li>'
 
+    if data == '/ban':
         if ban_check() == 1:
-            end = '<li>' + load_lang('state') + ' : ' + load_lang('ban') + '</li>'
-            ok_sign = 1
+            end = '<div id="get_user_info"></div><script>load_user_info("' + ip_check() + '");</script>'
+        else:
+            end = load_lang('authority_error')
 
-            band = re.search("^([0-9]{1,3}\.[0-9]{1,3})", ip)
-            if band:
-                band_it = band.groups()[0]
-            else:
-                band_it = '-'
-
-            curs.execute(db_change("delete from ban where (end < ? and end like '2%')"), [get_time()])
-            conn.commit()
-
-            curs.execute(db_change("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] if test_r[2] != '' else load_lang('limitless')) + '</li>'
-                    if test_r[0] == 'O':
-                        end += '<li>' + load_lang('login_able') + ' (' + load_lang('not_sure') + ')</li>'
-
-                    end += '<hr class=\"main_hr\">'
-            
-            curs.execute(db_change("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] if band_d[0][1] != '' else load_lang('limitless')) + '</li>'
-                if band_d[0][0] == 'O':
-                    end += '<li>' + load_lang('login_able') + ' (' + load_lang('not_sure') + ')</li>'
-
-                end += '<hr class=\"main_hr\">'
-
-            curs.execute(db_change("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] if ban_d[0][1] != '' else load_lang('limitless')) + '</li>'
-                if ban_d[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(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('error'), wiki_set(1), custom(), other2([0, 0])],
-            data = '<h2>' + load_lang('error') + '</h2><ul>' + end + '</ul>',
+            data = '<h2>' + load_lang('error') + '</h2>' + end,
             menu = 0
         ))
     else:
@@ -1122,7 +1122,7 @@ def re_error(data):
             elif num == 16:
                 data = load_lang('same_file_error')
             elif num == 17:
-                data = load_lang('file_capacity_error') + ' ' + wiki_set(3)
+                data = load_lang('file_capacity_error') + wiki_set(3)
             elif num == 19:
                 data = load_lang('decument_exist_error')
             elif num == 20:
@@ -1133,17 +1133,23 @@ def re_error(data):
                 data = load_lang('file_name_error')
             elif num == 23:
                 data = load_lang('regex_error')
+            elif num == 24:
+                curs.execute(db_change("select data from other where name = 'slow_edit'"))
+                slow_data = curs.fetchall()
+                data = load_lang('fast_edit_error') + slow_data[0][0]
+            elif num == 25:
+                data = load_lang('too_many_dec_error')
             else:
                 data = '???'
 
             if num == 5:
-                return easy_minify(flask.render_template(skin_check(), 
+                return easy_minify(flask.render_template(skin_check(),
                     imp = [load_lang('skin_set'), wiki_set(1), custom(), other2([0, 0])],
                     data = '<div id="main_skin_set"><h2>' + load_lang('error') + '</h2><ul><li>' + data + '</li></ul></div>',
                     menu = 0
                 ))
             else:
-                return easy_minify(flask.render_template(skin_check(), 
+                return easy_minify(flask.render_template(skin_check(),
                     imp = [load_lang('error'), wiki_set(1), custom(), other2([0, 0])],
                     data = '<h2>' + load_lang('error') + '</h2><ul><li>' + data + '</li></ul>',
                     menu = 0

+ 1 - 1
route/tool/init.py

@@ -29,7 +29,7 @@ server_set_var = {
         'display' : 'Markup',
         'require' : 'select',
         'default' : 'namumark',
-        'list' : ['namumark', 'markdown', 'raw']
+        'list' : ['namumark', 'markdown', 'raw', 'js_namumark']
     },
     'encode' : {
         'display' : 'Encryption method',

+ 16 - 10
route/tool/mark.py

@@ -1,4 +1,4 @@
-from .set_mark.namu import namu
+from .set_mark.namumark import namumark
 from .set_mark.markdown import markdown
 
 from .set_mark.tool import *
@@ -20,9 +20,9 @@ def load_conn2(data):
 def send_parser(data):
     if not re.search('^<br>$', data):
         data = html.escape(data)
-        
+
         javascript = re.compile('javascript:', re.I)
-        
+
         data = javascript.sub('', data)
 
         while 1:
@@ -33,20 +33,26 @@ def send_parser(data):
                 data = re.sub('&lt;a(?: (?:(?:(?!&gt;).)*))?&gt;(?P<in>(?:(?!&lt;).)*)&lt;\/a&gt;', '<a href="/w/' + urllib.parse.quote(re_data).replace('/','%2F') + '">' + re_data + '</a>', data, 1)
             else:
                 break
-        
+
     return data
-    
+
 def plusing(data):
     for data_in in data:
         curs.execute(db_change("select title from back where title = ? and link = ? and type = ?"), [data_in[1], data_in[0], data_in[2]])
         if not curs.fetchall():
             curs.execute(db_change("insert into back (title, link, type) values (?, ?, ?)"), [data_in[1], data_in[0], data_in[2]])
 
-def namumark(title, data, num, include):
+def render_do(title, data, num, include):
     curs.execute(db_change('select data from other where name = "markup"'))
     rep_data = curs.fetchall()
     if rep_data[0][0] == 'namumark':
-        data = namu(conn, data, title, num, include)
+        data = namumark(conn, data, title, num, include)
+    elif rep_data[0][0] == 'js_namumark':
+        data = [
+            '<div id="render_contect">' + html.escape(data) + '</div>',
+            '<script>render_namumark("render_contect")</script>',
+            []
+        ]
     elif rep_data[0][0] == 'markdown':
         data = markdown(conn, data, title, num)
     elif rep_data[0][0] == 'raw':
@@ -55,7 +61,7 @@ def namumark(title, data, num, include):
         data = ['', '', []]
 
     if num == 1:
-        data_num = len(data[2]) 
+        data_num = len(data[2])
         data_in_num = int(data_num / multiprocessing.cpu_count())
         data_in = []
 
@@ -69,9 +75,9 @@ def namumark(title, data, num, include):
             thread_start = threading.Thread(target = plusing, args = [data_in_for])
             thread_start.start()
             thread_start.join()
-        
+
         conn.commit()
-        
+
     if num == 2:
         return [data[0], data[1]]
     else:

+ 2 - 2
route/tool/set_mark/markdown.py

@@ -6,9 +6,9 @@ import re
 
 def markdown(conn, data, title, main_num):
     curs = conn.cursor()
-    
+
     data = '<div id="render_contect">' + re.sub('\r\n', '<br>', html.escape(data)) + '</div>'
     plus_data = '<script>render_markdown();</script>'
     backlink = []
-    
+
     return [data, plus_data, backlink]

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 389 - 273
route/tool/set_mark/namumark.py


+ 0 - 0
route/tool/set_mark/namumark_backlink.py


+ 18 - 28
route/tool/set_mark/tool.py

@@ -19,30 +19,20 @@ def db_change(data):
         data = data.replace('?', '%s')
 
     return data
-    
+
 def ip_check(d_type = 0):
-    if d_type == 0:
-        if flask.session and ('state' and 'id') in flask.session:
-            ip = flask.session['id']
-        else:
-            try:
-                ip = flask.request.environ.get('HTTP_X_REAL_IP', flask.request.environ.get('HTTP_X_FORWARDED_FOR', flask.request.remote_addr))
-                
-                if ip == '::1' or ip == '127.0.0.1':
-                    ip = flask.request.environ.get('HTTP_X_FORWARDED_FOR', flask.request.remote_addr)
-            except:
-                ip = '-'
-    else:
-        try:
-            ip = flask.request.environ.get('HTTP_X_REAL_IP', flask.request.environ.get('HTTP_X_FORWARDED_FOR', flask.request.remote_addr))
-            
-            if ip == '::1' or ip == '127.0.0.1':
-                ip = flask.request.environ.get('HTTP_X_FORWARDED_FOR', flask.request.remote_addr)
-        except:
-            ip = '-'
-            
-    return str(ip)
+    ip = ''
+    if d_type == 0 and (flask.session and ('state' and 'id') in flask.session):
+        ip = flask.session['id']
     
+    if ip == '':
+        ip = flask.request.environ.get('HTTP_X_REAL_IP', flask.request.environ.get('HTTP_X_FORWARDED_FOR', flask.request.remote_addr))
+
+        if ip == '::1' or ip == '127.0.0.1':
+            ip = flask.request.environ.get('HTTP_X_FORWARDED_FOR', flask.request.remote_addr)
+
+    return str(ip)
+
 def link_fix(main_link):
     if re.search('^:', main_link):
         main_link = re.sub('^:', '', main_link)
@@ -51,27 +41,27 @@ def link_fix(main_link):
     main_link = re.sub('^파일:', 'file:', main_link)
     main_link = re.sub('^분류:', 'category:', main_link)
 
-    other_link = re.search('[^\\\\]?(#.+)$', main_link)
+    other_link = re.search('[^\\\\]?(#[^#]+)$', main_link)
     if other_link:
         other_link = other_link.groups()[0]
 
-        main_link = re.sub('(#.+)$', '', main_link)
+        main_link = re.sub('(#[^#]+)$', '', main_link)
     else:
         other_link = ''
 
     main_link = re.sub('\\\\#', '%23', main_link)
-        
+
     return [main_link, other_link]
 
 def savemark(data):
     data = re.sub("\[date\(now\)\]", get_time(), data)
-    
+
     ip = ip_check()
     if not re.search("\.", ip):
         name = '[[user:' + ip + '|' + ip + ']]'
     else:
         name = ip
-        
+
     data = re.sub("\[name\]", name, data)
 
     return data
@@ -79,7 +69,7 @@ def savemark(data):
 def url_pas(data):
     return urllib.parse.quote(data).replace('/','%2F')
 
-def sha224(data):
+def sha224_replace(data):
     return hashlib.sha224(bytes(data, 'utf-8')).hexdigest()
 
 def md5_replace(data):

+ 40 - 24
route/topic.py

@@ -1,16 +1,24 @@
 from .tool.func import *
 
-def topic_2(conn, name, sub):
+def topic_2(conn, topic_num):
     curs = conn.cursor()
-    
-    ban = topic_check(name, sub)
+
+    if flask.request.method == 'POST':
+        name = flask.request.form.get('topic', 'test')
+        sub = flask.request.form.get('title', 'test')
+    else:
+        topic_change_data = topic_change(topic_num)
+        name = topic_change_data[0]
+        sub = topic_change_data[1]
+
+    ban = acl_check(name, 'topic', sub)
     admin = admin_check(3)
 
     curs.execute(db_change("select id from topic where title = ? and sub = ? limit 1"), [name, sub])
     topic_exist = curs.fetchall()
     if not topic_exist and len(sub) > 256:
         return re_error('/error/11')
-    
+
     if flask.request.method == 'POST':
         if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
             return re_error('/error/13')
@@ -19,10 +27,10 @@ def topic_2(conn, name, sub):
 
         ip = ip_check()
         today = get_time()
-        
+
         if ban == 1:
             return re_error('/ban')
-        
+
         curs.execute(db_change("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1"), [name, sub])
         old_num = curs.fetchall()
         if old_num:
@@ -51,40 +59,46 @@ def topic_2(conn, name, sub):
 
             if y_check == 1:
                 curs.execute(db_change('insert into alarm (name, data, date) values (?, ?, ?)'), [
-                    match.groups()[0], 
-                    ip + ' | <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '">' + name + ' | ' + sub + ' | #' + str(num) + '</a>', 
+                    match.groups()[0],
+                    ip + ' | <a href="/thread/' + str(topic_num) + '#' + str(num) + '">' + name + ' | ' + sub + ' | #' + str(num) + '</a>',
                     today
                 ])
-        
+
         cate_re = re.compile('\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
         data = cate_re.sub('[br]', flask.request.form.get('content', 'Test'))
-        
+
         for rd_data in re.findall("(?:#([0-9]+))", data):
             curs.execute(db_change("select ip from topic where title = ? and sub = ? and id = ?"), [name, sub, rd_data])
             ip_data = curs.fetchall()
             if ip_data and ip_or_user(ip_data[0][0]) == 0:
                 curs.execute(db_change('insert into alarm (name, data, date) values (?, ?, ?)'), [
-                    ip_data[0][0], 
-                    ip + ' | <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num) + '">' + name + ' | ' + sub + ' | #' + str(num) + '</a>', 
+                    ip_data[0][0],
+                    ip + ' | <a href="/thread/' + str(topic_num) + '#' + str(num) + '">' + name + ' | ' + sub + ' | #' + str(num) + '</a>',
                     today
                 ])
-            
-        data = re.sub("(?P<in>#(?:[0-9]+))", '[[\g<in>]]', data)
 
+        data = re.sub("(?P<in>#(?:[0-9]+))", '[[\g<in>]]', data)
         data = savemark(data)
 
         rd_plus(name, sub, today)
-
-        curs.execute(db_change("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '')"), [str(num), name, sub, data, today, ip])
+        curs.execute(db_change("insert into topic (id, title, sub, data, date, ip, block, top, code) values (?, ?, ?, ?, ?, ?, '', '', ?)"), [
+            str(num),
+            name,
+            sub,
+            data,
+            today,
+            ip,
+            str(topic_num) if num == 1 else ''
+        ])
         conn.commit()
-        
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#reload')
+
+        return redirect('/thread/' + str(topic_num))
     else:
         data = ''
-    
+
         curs.execute(db_change("select stop from rd where title = ? and sub = ? and stop != ''"), [name, sub])
         close_data = curs.fetchall()
-        if (close_data and admin != 1) or topic_check(name, sub) == 1:
+        if (close_data and admin != 1) or ban == 1:
             display = 'display: none;'
         else:
             display = ''
@@ -93,13 +107,15 @@ def topic_2(conn, name, sub):
             <div id="top_topic"></div>
             <div id="main_topic"></div>
             <div id="plus_topic"></div>
-            <script>topic_top_load("''' + name + '''", "''' + sub + '''");</script>
-            <a href="/topic/''' + url_pas(name) + '''/sub/''' + url_pas(sub) + '''/tool">(''' + load_lang('topic_tool') + ''')</a>
+            <script>topic_top_load("''' + str(topic_num) + '''");</script>
+            <a href="/thread/''' + str(topic_num) + '/tool">(' + load_lang('topic_tool') + ''')</a>
             <hr class=\"main_hr\">
             <form style="''' + display + '''" method="post">
-                <textarea id="content" style="height: 100px;" name="content"></textarea>
+                <textarea rows="10" id="content" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
                 <hr class=\"main_hr\">
                 ''' + captcha_get() + (ip_warring() if display == '' else '') + '''
+                <input style="display: none;" name="topic" value="''' + name + '''">
+                <input style="display: none;" name="title" value="''' + sub + '''">
                 <button type="submit">''' + load_lang('send') + '''</button>
                 <button id="preview" type="button" onclick="load_preview(\'''' + url_pas(name) + '\')">' + load_lang('preview') + '''</button>
             </form>
@@ -107,7 +123,7 @@ def topic_2(conn, name, sub):
             <div id="see_preview"></div>
         '''
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('discussion') + ')', 0])],
             data = '''
                 <h2 id="topic_top_title">''' + sub + '''</h2>

+ 12 - 8
route/topic_admin.py

@@ -1,12 +1,16 @@
 from .tool.func import *
 
-def topic_admin_2(conn, name, sub, num):
+def topic_admin_2(conn, topic_num, num):
     curs = conn.cursor()
 
+    topic_change_data = topic_change(topic_num)
+    name = topic_change_data[0]
+    sub = topic_change_data[1]
+
     curs.execute(db_change("select block, ip, date from topic where title = ? and sub = ? and id = ?"), [name, sub, str(num)])
     data = curs.fetchall()
     if not data:
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))
+        return redirect('/thread/' + str(topic_num))
 
     ban = '''
         <h2>''' + load_lang('state') + '''</h2>
@@ -18,7 +22,7 @@ def topic_admin_2(conn, name, sub, num):
         <h2>''' + load_lang('other_tool') + '''</h2>
         <ul>
             <li>
-                <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/raw/' + str(num) + '''">''' + load_lang('raw') + '''</a>
+                <a href="/thread/''' + str(topic_num) + '/raw/' + str(num) + '''">''' + load_lang('raw') + '''</a>
             </li>
         </ul>
     '''
@@ -29,7 +33,7 @@ def topic_admin_2(conn, name, sub, num):
 
         curs.execute(db_change("select end from ban where block = ?"), [data[0][1]])
         user_ban_d = curs.fetchall()
-        
+
         ban += '''
             <br>
             <h2>''' + load_lang('admin_tool') + '''</h2>
@@ -40,20 +44,20 @@ def topic_admin_2(conn, name, sub, num):
                     </a>
                 </li>
                 <li>
-                    <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/b/' + str(num) + '''">
+                    <a href="/thread/''' + str(topic_num) + '/b/' + str(num) + '''">
                         ''' + (load_lang('hide_release') if data[0][0] == 'O' else load_lang('hide')) + '''
                     </a>
                 </li>
                 <li>
-                    <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/notice/' + str(num) + '''">
+                    <a href="/thread/''' + str(topic_num) + '/notice/' + str(num) + '''">
                         ''' + (load_lang('pinned_release') if top_topic_d else load_lang('pinned')) + '''
                     </a>
                 </li>
             </ul>
         '''
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('discussion_tool'), wiki_set(), custom(), other2([' (#' + str(num) + ')', 0])],
         data = ban,
-        menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num), load_lang('return')]]
+        menu = [['thread/' + str(topic_num) + '#' + str(num), load_lang('return')]]
     ))

+ 9 - 5
route/topic_block.py

@@ -1,8 +1,12 @@
 from .tool.func import *
 
-def topic_block_2(conn, name, sub, num):
+def topic_block_2(conn, topic_num, num):
     curs = conn.cursor()
 
+    topic_change_data = topic_change(topic_num)
+    name = topic_change_data[0]
+    sub = topic_change_data[1]
+
     if admin_check(3, 'blind (' + name + ' - ' + sub + '#' + str(num) + ')') != 1:
         return re_error('/error/3')
 
@@ -13,9 +17,9 @@ def topic_block_2(conn, name, sub, num):
             curs.execute(db_change("update topic set block = '' where title = ? and sub = ? and id = ?"), [name, sub, str(num)])
         else:
             curs.execute(db_change("update topic set block = 'O' where title = ? and sub = ? and id = ?"), [name, sub, str(num)])
-        
+
         rd_plus(name, sub, get_time())
-        
+
         conn.commit()
-        
-    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num))
+
+    return redirect('/thread/' + str(topic_num) + '#' + str(num))

+ 84 - 77
route/topic_close_list.py

@@ -1,85 +1,92 @@
 from .tool.func import *
 
-def topic_close_list_2(conn, name, tool):
+def topic_close_list_2(conn, name):
     curs = conn.cursor()
-    
+
     div = ''
-    
-    if flask.request.method == 'POST':
-        t_num = ''
-        
-        while 1:
-            curs.execute(db_change("select title from topic where title = ? and sub = ? limit 1"), [name, flask.request.form.get('topic', None) + t_num])
-            if curs.fetchall():
-                if t_num == '':
-                    t_num = ' 2'
-                else:
-                    t_num = ' ' + str(int(t_num.replace(' ', '')) + 1)
-            else:
-                break
-
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(flask.request.form.get('topic', 'test') + t_num))
+    tool = flask.request.args.get('tool', '')
+
+    plus = ''
+    menu = [['topic/' + url_pas(name), load_lang('return')]]
+
+    if tool == 'close':
+        curs.execute(db_change("select sub from rd where title = ? and stop = 'O' order by sub asc"), [name])
+
+        sub = load_lang('closed_discussion')
+    elif tool == 'agree':
+        curs.execute(db_change("select sub from rd where title = ? and agree = 'O' order by sub asc"), [name])
+
+        sub = load_lang('agreed_discussion')
     else:
-        plus = ''
-        menu = [['topic/' + url_pas(name), load_lang('return')]]
-        
-        if tool == 'close':
-            curs.execute(db_change("select sub from rd where title = ? and stop = 'O' order by sub asc"), [name])
-            
-            sub = load_lang('closed_discussion')
-        elif tool == 'agree':
-            curs.execute(db_change("select sub from rd where title = ? and agree = 'O' order by sub asc"), [name])
-            
-            sub = load_lang('agreed_discussion')
+        sub = load_lang('discussion_list')
+        menu = [['w/' + url_pas(name), load_lang('document')]]
+
+        if acl_check(name, 'topic', sub) == 1:
+            display = 'display: none;'
+        else:
+            display = ''
+
+        curs.execute(db_change("select code from topic order by code + 0 desc limit 1"))
+        t_data = curs.fetchall()
+        if t_data:
+            topic_num = str(int(t_data[0][0]) + 1)
         else:
-            curs.execute(db_change("select sub from rd where title = ? order by date desc"), [name])
-            
-            sub = load_lang('discussion_list')
-            
-            menu = [['w/' + url_pas(name), load_lang('document')]]
-            
-            plus =  '''
-                <a href="/topic/''' + url_pas(name) + '''/close">(''' + load_lang('closed_discussion') + ''')</a> <a href="/topic/''' + url_pas(name) + '''/agree">(''' + load_lang('agreed_discussion') + ''')</a>
+            topic_num = '1'
+
+        plus = '''
+            <a href="/topic/''' + url_pas(name) + '?tool=close">(' + load_lang('closed_discussion') + ')</a> <a href="/topic/' + url_pas(name) + '?tool=agree">(' + load_lang('agreed_discussion') + ''')</a>
+            <hr class=\"main_hr\">
+            <form style="''' + display + '" method="post" action="/thread/' + topic_num + '''">
+                <input placeholder="''' + load_lang('discussion_name') + '''" name="title">
                 <hr class=\"main_hr\">
-                <input placeholder="''' + load_lang('discussion_name') + '''" name="topic" type="text">
+                <textarea rows="10" id="content" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
                 <hr class=\"main_hr\">
-                <button type="submit">''' + load_lang('go') + '''</button>
-            '''
-
-        t_num = 0
-        for data in curs.fetchall():
-            t_num += 1
-            
-            curs.execute(db_change("select data, date, ip, block from topic where title = ? and sub = ? and id = '1'"), [name, data[0]])
-            if curs.fetchall():                
-                it_p = 0
-                
-                if sub == load_lang('discussion_list'):
-                    curs.execute(db_change("select title from rd where title = ? and sub = ? and stop = 'O' order by sub asc"), [name, data[0]])
-                    if curs.fetchall():
-                        it_p = 1
-                
-                if it_p != 1:
-                    curs.execute(db_change("select id from topic where title = ? and sub = ? order by date desc limit 1"), [name, data[0]])
-                    t_data = curs.fetchall()
-                
-                    div += '''
-                        <h2><a href="/topic/''' + url_pas(name) + '''/sub/''' + url_pas(data[0]) + '''">''' + str(t_num) + '''. ''' + data[0] + '''</a></h2>
-                        <div id="topic_pre_''' + str(t_num) + '''"></div>
-                        <div id="topic_back_pre_''' + str(t_num) + '''"></div>
-                        <script>
-                            topic_list_load("''' + name + '''", "''' + data[0] + '''", "1", "topic_pre_''' + str(t_num) + '''");
-                            if("''' + str(t_num) + '''" !== "1") {
-                                topic_list_load("''' + name + '''", "''' + data[0] + '''", "''' + t_data[0][0] + '''", "topic_back_pre_''' + str(t_num) + '''");
-                            }
-                        </script>
-                    '''
-
-        if div == '':
-            plus = re.sub('^<br>', '', plus)
-        
-        return easy_minify(flask.render_template(skin_check(), 
-            imp = [name, wiki_set(), custom(), other2([' (' + sub + ')', 0])],
-            data = '<form method="post">' + div + plus + '</form>',
-            menu = menu
-        ))
+                ''' + captcha_get() + (ip_warring() if display == '' else '') + '''
+                <input style="display: none;" name="topic" value="''' + name + '''">
+                <button type="submit">''' + load_lang('send') + '''</button>
+                <button id="preview" type="button" onclick="load_preview(\'''' + url_pas(name) + '\')">' + load_lang('preview') + '''</button>
+            </form>
+            <hr class=\"main_hr\">
+            <div id="see_preview"></div>
+        '''
+
+        curs.execute(db_change("select sub from rd where title = ? order by date desc"), [name])
+
+    t_num = 0
+    for data in curs.fetchall():
+        t_num += 1
+
+        curs.execute(db_change("select code from topic where title = ? and sub = ? and id = '1'"), [name, data[0]])
+        first_topic = curs.fetchall()
+        if first_topic:
+            it_p = 0
+
+            if tool == '':
+                curs.execute(db_change("select title from rd where title = ? and sub = ? and stop = 'O' order by sub asc"), [name, data[0]])
+                if curs.fetchall():
+                    it_p = 1
+
+            if it_p != 1:
+                curs.execute(db_change("select id from topic where title = ? and sub = ? order by date desc limit 1"), [name, data[0]])
+                t_data = curs.fetchall()
+
+                div += '''
+                    <h2><a href="/thread/''' + first_topic[0][0] + '">' + str(t_num) + '. ' + data[0] + '''</a></h2>
+                    <div id="topic_pre_''' + str(t_num) + '''"></div>
+                    <div id="topic_back_pre_''' + str(t_num) + '''"></div>
+                    <script>
+                        topic_list_load(''' + first_topic[0][0] + ', 1, "topic_pre_' + str(t_num) + '''");
+                        if(''' + str(t_data[0][0]) + ''' !== 1) {
+                            topic_list_load(''' + first_topic[0][0] + ', ' + t_data[0][0] + ', "topic_back_pre_' + str(t_num) + '''");
+                        }
+                    </script>
+                '''
+
+    if div == '':
+        plus = re.sub('^<br>', '', plus)
+
+    return easy_minify(flask.render_template(skin_check(),
+        imp = [name, wiki_set(), custom(), other2([' (' + sub + ')', 0])],
+        data = div + plus,
+        menu = menu
+    ))

+ 29 - 0
route/topic_delete.py

@@ -0,0 +1,29 @@
+from .tool.func import *
+
+def topic_delete_2(conn, topic_num):
+    curs = conn.cursor()
+
+    if admin_check(None) != 1:
+        return re_error('/error/3')
+
+    topic_change_data = topic_change(topic_num)
+    name = topic_change_data[0]
+    sub = topic_change_data[1]
+
+    if flask.request.method == 'POST':
+        curs.execute(db_change("delete from topic where title = ? and sub = ?"), [name, sub])
+        curs.execute(db_change("delete from rd where title = ? and sub = ?"), [name, sub])
+        conn.commit()
+
+        return redirect('/topic/' + url_pas(name))
+    else:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('topic_delete'), wiki_set(), custom(), other2([0, 0])],
+            data = '''
+                <hr class=\"main_hr\">
+                <form method="post">
+                    <button type="submit">''' + load_lang('start') + '''</button>
+                </form>
+            ''',
+            menu = [['thread/' + str(topic_num) + '/tool', load_lang('return')]]
+        ))

+ 14 - 10
route/topic_stop.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def topic_stop_2(conn, name, sub):
+def topic_stop_2(conn, topic_num):
     curs = conn.cursor()
 
     if admin_check(3) != 1:
@@ -9,6 +9,10 @@ def topic_stop_2(conn, name, sub):
     ip = ip_check()
     time = get_time()
 
+    topic_change_data = topic_change(topic_num)
+    name = topic_change_data[0]
+    sub = topic_change_data[1]
+
     if flask.request.method == 'POST':
         curs.execute(db_change("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1"), [name, sub])
         topic_check = curs.fetchall()
@@ -20,7 +24,7 @@ def topic_stop_2(conn, name, sub):
             curs.execute(db_change("update rd set stop = ?, agree = ? where title = ? and sub = ?"), [
                 stop_d,
                 agree_d,
-                name, 
+                name,
                 sub
             ])
 
@@ -32,17 +36,17 @@ def topic_stop_2(conn, name, sub):
                 t_state = 'Normal'
 
             curs.execute(db_change("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')"), [
-                str(int(topic_check[0][0]) + 1), 
-                name, 
-                sub, 
-                t_state + (' (Agree)' if agree_d != '' else '') + (('[br][br]Why : ' + why_d) if why_d else ''), 
-                time, 
+                str(int(topic_check[0][0]) + 1),
+                name,
+                sub,
+                t_state + (' (Agree)' if agree_d != '' else '') + (('[br][br]Why : ' + why_d) if why_d else ''),
+                time,
                 ip
             ])
 
             rd_plus(name, sub, time)
 
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))    
+        return redirect('/thread/' + str(topic_num))
     else:
         stop_d_list = ''
         agree_check = ''
@@ -74,7 +78,7 @@ def topic_stop_2(conn, name, sub):
             agree_check = ''
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2([' (' + load_lang('topic_setting') + ')', 0])],
+            imp = [load_lang('topic_setting'), wiki_set(), custom(), other2([0, 0])],
             data = '''
                 <hr class=\"main_hr\">
                 <form method="post">
@@ -89,5 +93,5 @@ def topic_stop_2(conn, name, sub):
                     <button type="submit">''' + load_lang('save') + '''</button>
                 </form>
             ''',
-            menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool', load_lang('return')]]
+            menu = [['thread/' + str(topic_num) + '/tool', load_lang('return')]]
         ))

+ 21 - 5
route/topic_tool.py

@@ -1,10 +1,14 @@
 from .tool.func import *
 
-def topic_tool_2(conn, name, sub):
+def topic_tool_2(conn, topic_num):
     curs = conn.cursor()
 
     data = ''
 
+    topic_change_data = topic_change(topic_num)
+    name = topic_change_data[0]
+    sub = topic_change_data[1]
+
     curs.execute(db_change("select stop, agree from rd where title = ? and sub = ?"), [name, sub])
     close_data = curs.fetchall()
     if close_data:
@@ -21,7 +25,7 @@ def topic_tool_2(conn, name, sub):
         data = '''
             <h2>''' + load_lang('admin_tool') + '''</h2>
             <ul>
-                <li><a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '''/setting">''' + load_lang('topic_setting') + '''</a></li>
+                <li><a href="/thread/''' + str(topic_num) + '/setting">' + load_lang('topic_setting') + '''</a></li>
             </ul>
         '''
     data += '''
@@ -32,8 +36,20 @@ def topic_tool_2(conn, name, sub):
         </ul>
     '''
 
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = [name, wiki_set(), custom(), other2([' (' + load_lang('topic_tool') + ')', 0])],
+    if admin_check(None) == 1:
+        data += '''
+            <h2>''' + load_lang('owner') + '''</h2>
+            <ul>
+                <li>
+                    <a href="/thread/''' + str(topic_num) + '''/delete">
+                        ''' + load_lang('topic_delete') + '''
+                    </a>
+                </li>
+            </ul>
+        '''
+
+    return easy_minify(flask.render_template(skin_check(),
+        imp = [load_lang('topic_tool'), wiki_set(), custom(), other2([0, 0])],
         data = data,
-        menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub), load_lang('return')]]
+        menu = [['thread/' + str(topic_num), load_lang('return')]]
     ))

+ 8 - 4
route/topic_top.py

@@ -1,8 +1,12 @@
 from .tool.func import *
 
-def topic_top_2(conn, name, sub, num):
+def topic_top_2(conn, topic_num, num):
     curs = conn.cursor()
-    
+
+    topic_change_data = topic_change(topic_num)
+    name = topic_change_data[0]
+    sub = topic_change_data[1]
+
     if admin_check(3, 'notice (' + name + ' - ' + sub + '#' + str(num) + ')') != 1:
         return re_error('/error/3')
 
@@ -15,9 +19,9 @@ def topic_top_2(conn, name, sub, num):
                 curs.execute(db_change("update topic set top = '' where title = ? and sub = ? and id = ?"), [name, sub, str(num)])
             else:
                 curs.execute(db_change("update topic set top = 'O' where title = ? and sub = ? and id = ?"), [name, sub, str(num)])
-        
+
         rd_plus(name, sub, get_time())
 
         conn.commit()
 
-    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num))        
+    return redirect('/thread/' + str(topic_num) + '#' + str(num))

+ 1 - 1
route/user_count_edit.py

@@ -22,7 +22,7 @@ def user_count_edit_2(conn, name):
     else:
         t_data = 0
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('count'), wiki_set(), custom(), other2([0, 0])],
         data =  '''
                 <ul>

+ 3 - 3
route/user_custom_head_view.py

@@ -12,7 +12,7 @@ def user_custom_head_view_2(conn):
                 curs.execute(db_change("update custom set css = ? where user = ?"), [flask.request.form.get('content', None), ip + ' (head)'])
             else:
                 curs.execute(db_change("insert into custom (user, css) values (?, ?)"), [ip + ' (head)', flask.request.form.get('content', None)])
-            
+
             conn.commit()
 
         flask.session['head'] = flask.request.form.get('content', None)
@@ -30,7 +30,7 @@ def user_custom_head_view_2(conn):
                 data = ''
         else:
             start = '<span>' + load_lang('user_head_warring') + '</span><hr class=\"main_hr\">'
-            
+
             if 'head' in flask.session:
                 data = flask.session['head']
             else:
@@ -38,7 +38,7 @@ def user_custom_head_view_2(conn):
 
         start += '<span>&lt;style&gt;CSS&lt;/style&gt;<br>&lt;script&gt;JS&lt;/script&gt;</span><hr class=\"main_hr\">'
 
-        return easy_minify(flask.render_template(skin_check(), 
+        return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang(data = 'user_head', safe = 1), wiki_set(), custom(), other2([0, 0])],
             data =  start + '''
                     <form method="post">

+ 8 - 7
route/user_info.py

@@ -5,13 +5,14 @@ def user_info_2(conn):
 
     ip = ip_check()
 
-    curs.execute(db_change('select name from alarm where name = ? limit 1'), [ip_check()])
-    if curs.fetchall():
-        plus2 = '<li><a href="/alarm">' + load_lang('alarm') + ' (O)</a></li>'
+    curs.execute(db_change("select count(name) from alarm where name = ?"), [ip])
+    count = curs.fetchall()
+    if count:
+        plus2 = '<li><a href="/alarm">' + load_lang('alarm') + ' (' + str(count[0][0]) + ')</a></li>'
     else:
-        plus2 = '<li><a href="/alarm">' + load_lang('alarm') + '</a></li>'
+        plus2 = '<li><a href="/alarm">' + load_lang('alarm') + ' (0)</a></li>'
 
-    if ip_or_user(ip) == 0:  
+    if ip_or_user(ip) == 0:
         plus = '''
             <li><a href="/logout">''' + load_lang('logout') + '''</a></li>
             <li><a href="/change">''' + load_lang('user_setting') + '''</a></li>
@@ -19,7 +20,7 @@ def user_info_2(conn):
 
         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:        
+    else:
         plus = '''
             <li><a href="/login">''' + load_lang('login') + '''</a></li>
             <li><a href="/register">''' + load_lang('register') + '''</a></li>
@@ -31,7 +32,7 @@ def user_info_2(conn):
         if test and test[0][0] != '':
             plus += '<li><a href="/pass_find">' + load_lang('password_search') + '</a></li>'
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('user_tool'), wiki_set(), custom(), other2([0, 0])],
         data = '''
             <h2>''' + load_lang('state') + '''</h2>

+ 5 - 5
route/user_setting.py

@@ -10,7 +10,7 @@ def user_setting_2(conn, server_init):
         return re_error('/ban')
 
     if ip_or_user(ip) == 0:
-        if flask.request.method == 'POST':    
+        if flask.request.method == 'POST':
             auto_list = ['email', 'skin', 'lang']
 
             for auto_data in auto_list:
@@ -22,9 +22,9 @@ def user_setting_2(conn, server_init):
                         curs.execute(db_change("insert into user_set (name, id, data) values (?, ?, ?)"), [auto_data, ip, flask.request.form.get(auto_data, '')])
 
             conn.commit()
-            
+
             return redirect('/change')
-        else:        
+        else:
             curs.execute(db_change('select data from user_set where name = "email" and id = ?'), [ip])
             data = curs.fetchall()
             if data:
@@ -58,12 +58,12 @@ def user_setting_2(conn, server_init):
                     oauth_content += '<li>{}</li>'.format(oauth_provider[i].capitalize() + ' : <img src="{}" width="17px" height="17px"> {}'.format(oauth_data[0][1], oauth_data[0][0]))
                 else:
                     oauth_content += '<li>{}</li>'.format(oauth_provider[i].capitalize() + ' <a href="/oauth/{}/init">({})</a>'.format(oauth_provider[i], load_lang('connect')))
-            
+
             oauth_content += '</ul>'
 
             http_warring = '<hr class=\"main_hr\"><span>' + load_lang('http_warring') + '</span>'
 
-            return easy_minify(flask.render_template(skin_check(),    
+            return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('user_setting'), wiki_set(), custom(), other2([0, 0])],
                 data = '''
                     <form method="post">

+ 4 - 4
route/user_tool.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def user_tool_2(conn, name):
     curs = conn.cursor()
-    
+
     data = '''
         <h2>''' + load_lang('tool') + '''</h2>
         <ul>
@@ -10,14 +10,14 @@ def user_tool_2(conn, name):
             <li><a href="/topic/user:''' + url_pas(name) + '''">''' + load_lang('user_discussion') + '''</a></li>
         </ul>
     '''
-            
+
     if admin_check(1) == 1:
         curs.execute(db_change("select block from ban where block = ?"), [name])
         if curs.fetchall():
             ban_name = load_lang('ban_release')
         else:
             ban_name = load_lang('ban')
-    
+
         data += '''
             <h2>''' + load_lang('admin') + '''</h2>
             <ul>
@@ -26,7 +26,7 @@ def user_tool_2(conn, name):
             </ul>
         '''
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [name, wiki_set(), custom(), other2([' (' + load_lang('tool') + ')', 0])],
         data = data,
         menu = 0

+ 7 - 10
route/view_diff_data.py

@@ -19,18 +19,15 @@ def view_diff_data_2(conn, name):
         curs.execute(db_change("select data from history where id = ? and title = ?"), [second, name])
         second_raw_data = curs.fetchall()
         if second_raw_data:
-            first_data = html.escape(first_raw_data[0][0])            
-            second_data = html.escape(second_raw_data[0][0])
-
             if first == second:
-                result = '-'
-            else:            
-                diff_data = difflib.SequenceMatcher(None, first_data, second_data)
-                result = re.sub('\r', '', diff(diff_data))
-            
-            return easy_minify(flask.render_template(skin_check(), 
+                result = ''
+            else:
+                diff_data = difflib.SequenceMatcher(None, first_raw_data[0][0], second_raw_data[0][0])
+                result = '<pre>' + diff(diff_data) + '</pre>'
+
+            return easy_minify(flask.render_template(skin_check(),
                 imp = [name, wiki_set(), custom(), other2([' (' + load_lang('compare') + ')', 0])],
-                data = '<pre>' + result + '</pre>',
+                data = result,
                 menu = [['history/' + url_pas(name), load_lang('return')]]
             ))
 

+ 3 - 3
route/view_down.py

@@ -8,10 +8,10 @@ def view_down_2(conn, name):
     curs.execute(db_change("select title from data where title like ?"), [name + '/%'])
     for data in curs.fetchall():
         div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
-        
+
     div += '</ul>'
-    
-    return easy_minify(flask.render_template(skin_check(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [name, wiki_set(), custom(), other2([' (' + load_lang('sub') + ')', 0])],
         data = div,
         menu = [['w/' + url_pas(name), load_lang('return')]]

+ 16 - 10
route/view_raw.py

@@ -1,26 +1,32 @@
 from .tool.func import *
 
-def view_raw_2(conn, name, sub_title, num):
+def view_raw_2(conn, name, topic_num, num):
     curs = conn.cursor()
 
     if acl_check(name, 'render') == 1:
         return re_error('/ban')
-    
+
+    sub_title = None
+    if topic_num:
+        topic_change_data = topic_change(topic_num)
+        name = topic_change_data[0]
+        sub_title = topic_change_data[1]
+
     v_name = name
     sub = ' (' + load_lang('raw') + ')'
-    
+
     if not num:
         num = flask.request.args.get('num', None)
         if num:
             num = int(number_check(num))
-    
+
     if not sub_title and num:
         curs.execute(db_change("select title from history where title = ? and id = ? and hide = 'O'"), [name, str(num)])
         if curs.fetchall() and admin_check(6) != 1:
             return re_error('/error/3')
-        
+
         curs.execute(db_change("select data from history where title = ? and id = ?"), [name, str(num)])
-        
+
         sub += ' (r' + str(num) + ')'
 
         menu = [['history/' + url_pas(name), load_lang('history')]]
@@ -29,22 +35,22 @@ def view_raw_2(conn, name, sub_title, num):
             curs.execute(db_change("select data from topic where id = ? and title = ? and sub = ? and block = ''"), [str(num), name, sub_title])
         else:
             curs.execute(db_change("select data from topic where id = ? and title = ? and sub = ?"), [str(num), name, sub_title])
-        
+
         v_name = load_lang('discussion_raw')
         sub = ' (#' + str(num) + ')'
 
         menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub_title) + '#' + str(num), load_lang('discussion')], ['topic/' + url_pas(name) + '/sub/' + url_pas(sub_title) + '/admin/' + str(num), load_lang('return')]]
     else:
         curs.execute(db_change("select data from data where title = ?"), [name])
-        
+
         menu = [['w/' + url_pas(name), load_lang('return')]]
 
     data = curs.fetchall()
     if data:
         p_data = html.escape(data[0][0])
         p_data = '<textarea readonly rows="25">' + p_data + '</textarea>'
-        
-        return easy_minify(flask.render_template(skin_check(), 
+
+        return easy_minify(flask.render_template(skin_check(),
             imp = [v_name, wiki_set(), custom(), other2([sub, 0])],
             data = p_data,
             menu = menu

+ 29 - 30
route/view_read.py

@@ -4,7 +4,7 @@ def view_read_2(conn, name):
     curs = conn.cursor()
 
     sub = ''
-    acl = ''
+    acl = 0
     div = ''
     ip = ip_check()
 
@@ -17,38 +17,37 @@ def view_read_2(conn, name):
             r_db = curs.fetchall()
             if r_db:
                 r_data = link_fix(r_db[0][0])
-            
+
                 return redirect('/w/' + r_data[0] + '?from=' + name + r_data[1])
 
     curs.execute(db_change("select sub from rd where title = ? and not stop = 'O' order by date desc"), [name])
     if curs.fetchall():
-        sub += ' (' + load_lang('discussion') + ')'
         topic = 1
     else:
         topic = 0
 
     curs.execute(db_change("select link from back where title = ? and type = 'cat' order by link asc"), [name])
-                
+
     curs.execute(db_change("select title from data where title like ?"), ['%' + name + '/%'])
     if curs.fetchall():
         down = 1
     else:
         down = 0
-        
+
     m = re.search("^(.*)\/(.*)$", name)
     if m:
         uppage = m.groups()[0]
     else:
         uppage = 0
-        
-    if re.search('^category:', name):        
+
+    if re.search('^category:', name):
         curs.execute(db_change("select link from back where title = ? and type = 'cat' order by link asc"), [name])
         back = curs.fetchall()
         if back:
             div = '<br><h2 id="cate_normal">' + load_lang('category') + '</h2><ul>'
             u_div = ''
 
-            for data in back:    
+            for data in back:
                 if re.search('^category:', data[0]):
                     u_div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
                 else:
@@ -56,14 +55,14 @@ def view_read_2(conn, name):
                     db_data = curs.fetchall()
                     if db_data:
                         div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a> <a id="inside" href="/xref/' + url_pas(data[0]) + '">(' + load_lang('backlink') + ')</a></li>'
-                    else: 
+                    else:
                         div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
 
             div += '</ul>'
-            
+
             if div == '<br><h2 id="cate_normal">' + load_lang('category') + '</h2><ul></ul>':
                 div = ''
-            
+
             if u_div != '':
                 div += '<br><h2 id="cate_under">' + load_lang('under_category') + '</h2><ul>' + u_div + '</ul>'
 
@@ -76,7 +75,7 @@ def view_read_2(conn, name):
         curs.execute(db_change("select title, data from history where title = ? and id = ?"), [name, str(num)])
     else:
         curs.execute(db_change("select title, data from data where title = ?"), [name])
-    
+
     data = curs.fetchall()
     if data:
         else_data = data[0][1]
@@ -86,12 +85,12 @@ def view_read_2(conn, name):
     curs.execute(db_change("select decu from acl where title = ?"), [name])
     data = curs.fetchall()
     if data:
-        acl += ' (' + load_lang('acl') + ')'
-            
+        acl = 1
+
     if flask.request.args.get('from', None) and else_data:
         else_data = re.sub('^\r\n', '', else_data)
         else_data = re.sub('\r\n$', '', else_data)
-            
+
     end_data = render_set(
         title = name,
         data = else_data
@@ -99,7 +98,7 @@ def view_read_2(conn, name):
 
     if end_data == 'HTTP Request 401.3':
         response_data = 401
-        
+
         curs.execute(db_change('select data from other where name = "error_401"'))
         sql_d = curs.fetchall()
         if sql_d and sql_d[0][0] != '':
@@ -108,14 +107,14 @@ def view_read_2(conn, name):
             end_data = '<h2>' + load_lang('error') + '</h2><ul><li>' + load_lang('authority_error') + '</li></ul>'
     elif end_data == 'HTTP Request 404':
         response_data = 404
-        
+
         curs.execute(db_change('select data from other where name = "error_404"'))
         sql_d = curs.fetchall()
         if sql_d and sql_d[0][0] != '':
             end_data = '<h2>' + load_lang('error') + '</h2><ul><li>' + sql_d[0][0] + '</li></ul>'
         else:
             end_data = '<h2>' + load_lang('error') + '</h2><ul><li>' + load_lang('decument_404_error') + '</li></ul>'
-            
+
         curs.execute(db_change('select ip, date, leng, send from history where title = ? order by id desc limit 3'), [name])
         sql_d = curs.fetchall()
         if sql_d:
@@ -127,17 +126,17 @@ def view_read_2(conn, name):
                     leng = '<span style="color:red;">(' + i[2] + ')</span>'
                 else:
                     leng = '<span style="color:gray;">(' + i[2] + ')</span>'
-            
+
                 end_data += '<li>' + i[1] + ' | ' + ip_pas(i[0]) + ' | ' + leng + (' | ' + i[3] if i[3] != '' else '') + '</li>'
-                
+
             end_data += '<li><a href="/history/' + url_pas(name) + '">(...)</a></li></ul>'
     else:
         response_data = 200
-    
+
     if num:
         menu = [['history/' + url_pas(name), load_lang('history')]]
         sub = ' (r' + str(num) + ')'
-        acl = ''
+        acl = 0
         r_date = 0
     else:
         if response_data == 404:
@@ -145,7 +144,7 @@ def view_read_2(conn, name):
         else:
             menu = [['edit/' + url_pas(name), load_lang('edit')]]
 
-        menu += [['topic/' + url_pas(name), load_lang('discussion'), topic], ['history/' + url_pas(name), load_lang('history')], ['xref/' + url_pas(name), load_lang('backlink')], ['acl/' + url_pas(name), load_lang('acl')]]
+        menu += [['topic/' + url_pas(name), load_lang('discussion'), topic], ['history/' + url_pas(name), load_lang('history')], ['xref/' + url_pas(name), load_lang('backlink')], ['acl/' + url_pas(name), load_lang('acl'), acl]]
 
         if flask.request.args.get('from', None):
             menu += [['w/' + url_pas(name), load_lang('pass')]]
@@ -161,7 +160,7 @@ def view_read_2(conn, name):
 
         if down:
             menu += [['down/' + url_pas(name), load_lang('sub')]]
-    
+
         curs.execute(db_change("select date from history where title = ? order by date desc limit 1"), [name])
         date = curs.fetchall()
         if date:
@@ -170,7 +169,7 @@ def view_read_2(conn, name):
             r_date = 0
 
     div = end_data + div
-            
+
     adsense_code = '<div align="center" style="display: block; margin-bottom: 10px;">{}</div>'
 
     curs.execute(db_change("select data from other where name = 'adsense'"))
@@ -180,7 +179,7 @@ def view_read_2(conn, name):
         adsense_code = adsense_code.format(curs.fetchall()[0][0])
     else:
         adsense_code = adsense_code.format('')
-    
+
     div = adsense_code + '<div>' + div + '</div>'
 
     match = re.search("^user:([^/]*)", name)
@@ -195,7 +194,7 @@ def view_read_2(conn, name):
     body = curs.fetchall()
     if body:
         div = body[0][0] + '<hr class=\"main_hr\">' + div
-        
+
     curs.execute(db_change("select data from other where name = 'bottom_body'"))
     body = curs.fetchall()
     if body:
@@ -209,9 +208,9 @@ def view_read_2(conn, name):
             watch_list = 1
     else:
         watch_list = 0
-        
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = [flask.request.args.get('show', name), wiki_set(), custom(), other2([sub + acl, r_date, watch_list])],
+
+    return easy_minify(flask.render_template(skin_check(),
+        imp = [flask.request.args.get('show', name), wiki_set(), custom(), other2([sub, r_date, watch_list])],
         data = div,
         menu = menu
     )), response_data

+ 9 - 9
route/view_xref.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def view_xref_2(conn, name):
     curs = conn.cursor()
-    
+
     if acl_check(name, 'render') == 1:
         return re_error('/ban')
 
@@ -11,12 +11,12 @@ def view_xref_2(conn, name):
         sql_num = num * 50 - 50
     else:
         sql_num = 0
-        
+
     div = '<ul>'
 
     if re.search('#', name):
         name = re.sub('#', '\\\\#', name)
-    
+
     curs.execute(db_change("" + \
         "select link, type from back " + \
         "where (title = ? and not type = 'cat' and not type = 'no') or (title like ? and type = 'redirect')" + \
@@ -29,20 +29,20 @@ def view_xref_2(conn, name):
     data_list = curs.fetchall()
     for data in data_list:
         div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a>'
-        
-        if data[1]:                
+
+        if data[1]:
             div += ' (' + data[1] + ')'
-        
+
         curs.execute(db_change("select title from back where title = ? and type = 'include'"), [data[0]])
         db_data = curs.fetchall()
         if db_data:
             div += ' <a id="inside" href="/xref/' + url_pas(data[0]) + '">(' + load_lang('backlink') + ')</a>'
 
         div += '</li>'
-      
+
     div += '</ul>' + next_fix('/xref/' + url_pas(name) + '?num=', num, data_list)
-    
-    return easy_minify(flask.render_template(skin_check(), 
+
+    return easy_minify(flask.render_template(skin_check(),
         imp = [name, wiki_set(), custom(), other2([' (' + load_lang('backlink') + ')', 0])],
         data = div,
         menu = [['w/' + url_pas(name), load_lang('return')]]

+ 2 - 2
route/watch_list.py

@@ -4,7 +4,7 @@ def watch_list_2(conn):
     curs = conn.cursor()
 
     div = 'Limit : 10<hr class=\"main_hr\">'
-    ip = ip_check()    
+    ip = ip_check()
 
     if ip_or_user(ip) != 0:
         return redirect('/login')
@@ -22,7 +22,7 @@ def watch_list_2(conn):
 
     div += '<a href="/manager/13">(' + load_lang('add') + ')</a>'
 
-    return easy_minify(flask.render_template(skin_check(), 
+    return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('watchlist'), wiki_set(), custom(), other2([0, 0])],
         data = div,
         menu = [['manager', load_lang('return')]]

+ 2 - 2
route/watch_list_name.py

@@ -2,7 +2,7 @@ from .tool.func import *
 
 def watch_list_name_2(conn, name):
     curs = conn.cursor()
-    
+
     ip = ip_check()
     if ip_or_user(ip) != 0:
         return redirect('/login')
@@ -17,7 +17,7 @@ def watch_list_name_2(conn, name):
         curs.execute(db_change("delete from scan where user = ? and title = ?"), [ip, name])
     else:
         curs.execute(db_change("insert into scan (user, title) values (?, ?)"), [ip, name])
-    
+
     conn.commit()
 
     return redirect('/watch_list')

+ 3 - 3
version.json

@@ -1,8 +1,8 @@
 {
     "master" : {
-        "r_ver" : "v3.1.4-stable-03",
-        "c_ver" : "400004",
-        "s_ver" : "5"
+        "r_ver" : "v3.1.5-stable-01",
+        "c_ver" : "400007",
+        "s_ver" : "7"
     }, "stable" : {
         "r_ver" : "v3.1.4-stable-03",
         "c_ver" : "400004",

+ 0 - 53
views/easter_egg.html

@@ -1,53 +0,0 @@
-<iframe width="560" height="315" src="https://www.youtube.com/embed/7wzZbLKnUuA" allowfullscreen></iframe>
-<hr class="main_hr">
-<pre>
-    Nagareteku toki no naka de demo kedarusa ga hora guruguru mawatte
-    Watashi kara hanareru kokoro mo mienai wa sou shiranai
-    
-    Jibun kara ugoku koto mo naku toki no sukima ni nagasare tsuzukete
-    Shiranai wa mawari no koto nado watashi wa watashi sore dake
-    
-    Yume miteru? Nani mo mitenai? Kataru mo muda na jibun no kotoba
-    Kanashimu nante tsukareru dake yo nani mo kanjizu sugoseba ii no
-    
-    Tomadou kotoba ataerarete mo jibun no kokoro tada uwa no sora
-    Moshi watashi kara ugoku no naraba subete kaeru no nara kuro ni suru
-    
-    Konna jibun ni mirai wa aru no? Konna sekai ni watashi wa iru no?
-    Ima setsunai no? Ima kanashii no? Jibun no koto mo wakaranai mama
-    
-    Ayumu koto sae tsukareru dake yo hito no koto nado shiri mo shinaiwa
-    Konna watashi mo kawareru no nara moshi kawareru no nara shiro ni naru?
-    
-    Nagareteku toki no naka de demo kedarusa ga hora guruguru mawatte
-    Watashi kara hanareru kokoro mo mienaiwa sou shiranai
-    
-    Jibun kara ugoku koto mo naku toki no sukima ni nagasare tsuzukete
-    Shiranai wa mawari no koto nado watashi wa watashi sore dake
-    
-    Yume miteru? Nani mo mitenai? Kataru mo muda na jibun no kotoba
-    Kanashimu nante tsukareru dake yo nani mo kanjizu sugoseba ii no
-    
-    Tomadou kotoba ataerarete mo jibun no kokoro tada uwa no sora
-    Moshi watashi kara ugoku no naraba subete kaeru no nara kuro ni suru
-    
-    Muda na jikan ni mirai wa aru no? Konna tokoro ni watashi wa iru no?
-    Watashi no koto o iitai naraba kotoba ni suru no nara "roku de nashi"
-    
-    Konna tokoro ni watashi wa iru no? Konna jikan ni watashi wa iru no?
-    Konna watashi mo kawareru no nara moshi kawareru no nara shiro ni naru?
-    
-    Ima yume miteru? Nani mo mitenai? Kataru mo muda na jibun no kotoba?
-    Kanashimu nante tsukareru dake yo nani mo kanjizu sugoseba ii no
-    
-    Tomadou kotoba ataerarete mo jibun no kokoro tada uwa no sora
-    Moshi watashi kara ugoku no naraba subete kaeru no nara kuro ni suru
-    
-    Ugoku no naraba ugoku no naraba subete kowasu wa subete kowasu wa
-    Kanashimu naraba kanashimu naraba watashi no kokoro shiroku kawareru?
-    
-    Anata no koto mo watashi no koto mo subete no koto mo mada shiranai no
-    Omoi mabuta wo aketa no naraba subete kowasu no nara kuro ni nare!!!
-
-    <a href="https://touhou.fandom.com/wiki/Lyrics:_Bad_Apple!!">Ref - Touhou wiki</a>
-</pre>    

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

@@ -1,7 +1,7 @@
 textarea { width: 100%; }
 input { width: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; }
 #last { margin-top: 30px; }
-#toc { border: 1px solid; padding: 20px; width: fit-content; width: -moz-fit-content; margin-top: 10px; }
+#toc { border: 1px solid; padding: 20px; width: fit-content; width: -moz-fit-content; clear: both; margin-top: 10px; }
 #toc-name { font-size: 18px; }
 table { border-collapse: collapse; }
 td { border: 1px solid; padding: 5px; }
@@ -42,4 +42,7 @@ blockquote { background-image: url(/views/acme/img/quote.png); background-positi
 @media (max-width: 400px) { .foot_plus { width: 80%; right: calc(100% - 92%); }}
 @media (max-height: 400px) { .foot_plus { height: 80%; top: calc(100% - 92%); }}
 .foot_in { overflow-y: scroll; height: calc(100% - 20px); }
-#origin { display: none; }
+#origin { display: none; }
+.all_in_data { display: block; width: 100%; }
+.table_safe { max-width: 100%; }
+.change_space { white-space: pre; }

+ 14 - 0
views/main_css/file/easter_egg.html

@@ -0,0 +1,14 @@
+<div id="easter_egg"></div>
+<script>
+    var random_num = String(Math.floor(Math.random() * 3));
+    var random_code = '';
+    if(random_num === '2') {
+        random_code = 'Fsppuynb440';
+    } else if(random_num === '1') {
+        random_code = 'DbTIoBK9Wvo';
+    } else {
+        random_code = 'nytZOF0hp_c'
+    }
+
+    document.getElementById('easter_egg').innerHTML = '<iframe style="width: 560px; height: 315px;" src="https://www.youtube.com/embed/' + random_code + '" allowfullscreen></iframe>';
+</script>

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

@@ -1,16 +1,16 @@
 // https://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript
 
 function do_insert_data(name, data) {
-    if(document.selection) { 
+    if(document.selection) {
         document.getElementById(name).focus();
 
         sel = document.selection.createRange();
-        sel.text = data; 
+        sel.text = data;
     } else if(document.getElementById(name).selectionStart || document.getElementById(name).selectionStart == '0') {
         var startPos = document.getElementById(name).selectionStart;
         var endPos = document.getElementById(name).selectionEnd;
 
-        document.getElementById(name).value = document.getElementById(name).value.substring(0, startPos) + data + document.getElementById(name).value.substring(endPos, document.getElementById(name).value.length); 
+        document.getElementById(name).value = document.getElementById(name).value.substring(0, startPos) + data + document.getElementById(name).value.substring(endPos, document.getElementById(name).value.length);
     } else {
         document.getElementById(name).value += data;
     }

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác