Преглед изворни кода

Merge pull request #2053 from openNAMU/beta

이 참에 stable 갱신
잉여개발기 пре 2 година
родитељ
комит
be6606606f
100 измењених фајлова са 3215 додато и 2396 уклоњено
  1. 2 0
      .dockerignore
  2. 261 147
      app.py
  3. 47 0
      create_service.sh
  4. 9 45
      emergency_tool.py
  5. 75 17
      lang/en-US.json
  6. 73 21
      lang/ko-KR.json
  7. 1 0
      requirements-optional.txt
  8. 3 5
      requirements.txt
  9. 12 8
      route/__init__.py
  10. 1 1
      route/api_recent_change.py
  11. 1 0
      route/api_search.py
  12. 41 22
      route/api_topic.py
  13. 22 1
      route/api_user_info.py
  14. 1 1
      route/api_w.py
  15. 13 9
      route/api_w_raw.py
  16. 6 0
      route/api_w_render.py
  17. 36 0
      route/bbs_delete.py
  18. 0 42
      route/bbs_main.py
  19. 181 55
      route/bbs_w.py
  20. 8 1
      route/bbs_w_comment_tool.py
  21. 68 0
      route/bbs_w_delete.py
  22. 19 57
      route/bbs_w_edit.py
  23. 31 0
      route/bbs_w_hide.py
  24. 46 0
      route/bbs_w_pinned.py
  25. 36 81
      route/bbs_w_post.py
  26. 6 3
      route/bbs_w_set.py
  27. 19 1
      route/bbs_w_tool.py
  28. 52 65
      route/edit.py
  29. 0 3
      route/edit_backlink_reset.py
  30. 1 3
      route/edit_delete.py
  31. 83 146
      route/edit_move.py
  32. 38 35
      route/edit_revert.py
  33. 4 7
      route/edit_upload.py
  34. 21 19
      route/filter_all.py
  35. 283 0
      route/filter_all_add.py
  36. 17 10
      route/filter_all_delete.py
  37. 0 41
      route/filter_document.py
  38. 0 62
      route/filter_document_add.py
  39. 0 13
      route/filter_document_delete.py
  40. 0 239
      route/filter_inter_wiki_add.py
  41. 4 4
      route/give_admin_groups.py
  42. 26 13
      route/give_auth.py
  43. 5 5
      route/give_delete_admin_group.py
  44. 43 65
      route/give_user_ban.py
  45. 1 1
      route/list_admin.py
  46. 6 7
      route/list_admin_auth_use.py
  47. 2 2
      route/list_admin_group.py
  48. 50 7
      route/list_image_file.py
  49. 13 9
      route/list_long_page.py
  50. 30 0
      route/list_no_link.py
  51. 9 7
      route/list_old_page.py
  52. 1 5
      route/list_please.py
  53. 2 2
      route/login_find_email.py
  54. 21 53
      route/login_find_email_check.py
  55. 13 17
      route/login_login.py
  56. 2 6
      route/login_login_2fa.py
  57. 2 6
      route/login_login_2fa_email.py
  58. 0 5
      route/login_register.py
  59. 2 2
      route/login_register_email.py
  60. 21 13
      route/login_register_submit.py
  61. 16 1
      route/main_func_easter_egg.py
  62. 1 1
      route/main_func_error_404.py
  63. 1 1
      route/main_setting.py
  64. 26 31
      route/main_setting_acl.py
  65. 6 4
      route/main_setting_head.py
  66. 67 27
      route/main_setting_main.py
  67. 23 10
      route/main_setting_phrase.py
  68. 26 37
      route/main_setting_sitemap.py
  69. 91 0
      route/main_setting_sitemap_set.py
  70. 55 13
      route/main_setting_skin_set.py
  71. 0 1
      route/main_sys_restart.py
  72. 0 1
      route/main_sys_shutdown.py
  73. 1 2
      route/main_sys_update.py
  74. 12 10
      route/main_tool_admin.py
  75. 3 3
      route/main_tool_other.py
  76. 18 6
      route/main_tool_redirect.py
  77. 3 1
      route/main_view.py
  78. 1 0
      route/main_view_image.py
  79. 9 38
      route/recent_app_submit.py
  80. 0 3
      route/recent_block.py
  81. 104 93
      route/recent_change.py
  82. 9 36
      route/recent_history_add.py
  83. 1 1
      route/recent_history_delete.py
  84. 1 1
      route/recent_history_reset.py
  85. 1 1
      route/recent_history_send.py
  86. 1 1
      route/recent_record_reset.py
  87. 1 4
      route/recent_record_topic.py
  88. 309 307
      route/tool/func.py
  89. 29 41
      route/tool/func_render.py
  90. 348 134
      route/tool/func_render_namumark.py
  91. 1 2
      route/tool/func_tool.py
  92. 10 29
      route/topic.py
  93. 2 9
      route/topic_comment_tool.py
  94. 3 2
      route/topic_tool_delete.py
  95. 16 2
      route/user_alarm.py
  96. 6 2
      route/user_alarm_delete.py
  97. 230 141
      route/user_challenge.py
  98. 7 5
      route/user_info.py
  99. 5 4
      route/user_setting.py
  100. 2 2
      route/user_setting_email.py

+ 2 - 0
.dockerignore

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

+ 261 - 147
app.py

@@ -2,7 +2,6 @@
 import os
 import re
 import logging
-import shutil
 
 from route.tool.func import *
 from route import *
@@ -42,16 +41,10 @@ with get_db_connect() as conn:
 
     if data_db_set['type'] == 'mysql':
         try:
-            curs.execute(db_change(
-                'create database ' + data_db_set['name'] + ' ' + \
-                'default character set utf8mb4'
-            ))
+            curs.execute(db_change('create database ' + data_db_set['name'] + ' default character set utf8mb4'))
         except:
             try:
-                curs.execute(db_change(
-                    'alter database ' + data_db_set['name'] + ' ' + \
-                    'character set utf8mb4'
-                ))
+                curs.execute(db_change('alter database ' + data_db_set['name'] + ' character set utf8mb4'))
             except:
                 pass
 
@@ -65,7 +58,6 @@ with get_db_connect() as conn:
 
                 try:
                     curs.execute(db_change('select ' + create + ' from ' + create_table + ' limit 1'))
-
                     db_pass = 1
                 except:
                     pass
@@ -73,49 +65,49 @@ with get_db_connect() as conn:
                 if db_pass == 0:
                     try:
                         curs.execute(db_change('create table ' + create_table + '(test longtext default (""))'))
-
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
                     try:
                         curs.execute(db_change('create table ' + create_table + '(test longtext default "")'))
-
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
                     try:
                         curs.execute(db_change('create table ' + create_table + '(test longtext)'))
-
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
                     try:
                         curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext default ('')"))
-
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
                     try:
                         curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext default ''"))
-
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
                     try:
                         curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext"))
-
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
@@ -153,6 +145,7 @@ with get_db_connect() as conn:
 
     app.config['JSON_AS_ASCII'] = False
     app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
+    app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 3600
 
     log = logging.getLogger('waitress')
     log.setLevel(logging.ERROR)
@@ -168,8 +161,6 @@ with get_db_connect() as conn:
     sql_data = curs.fetchall()
     app.secret_key = sql_data[0][0]
 
-    print('----')
-
     # Init-DB_Data
     server_set = {}
     server_set_var = get_init_set_list()
@@ -208,100 +199,224 @@ with get_db_connect() as conn:
 
         server_set[i] = server_set_val
 
-    print('----')
-
-    # Init-DB_care
-    if data_db_set['type'] == 'sqlite':
-        def back_up(back_time, back_up_where):
-            print('----')
+        conn.commit()
 
-            try:
+def back_up(data_db_set):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+    
+        try:
+            curs.execute(db_change('select data from other where name = "back_up"'))
+            back_time = curs.fetchall()
+            back_time = float(number_check(back_time[0][0], True)) if back_time and back_time[0][0] != '' else 0
+
+            curs.execute(db_change('select data from other where name = "backup_count"'))
+            back_up_count = curs.fetchall()
+            back_up_count = int(number_check(back_up_count[0][0])) if back_up_count and back_up_count[0][0] != '' else 3
+
+            if back_time != 0:
+                curs.execute(db_change('select data from other where name = "backup_where"'))
+                back_up_where = curs.fetchall()
+                back_up_where = back_up_where[0][0] if back_up_where and back_up_where[0][0] != '' else data_db_set['name'] + '.db'
+
+                print('Back up state : ' + str(back_time) + ' hours')
+                print('Back up directory : ' + back_up_where)
+                if back_up_count != 0:
+                    print('Back up max number : ' + str(back_up_count))
+
+                    file_dir = os.path.split(back_up_where)[0]
+                    file_dir = '.' if file_dir == '' else file_dir
+                    
+                    file_name = os.path.split(back_up_where)[1]
+                    file_name = re.sub(r'\.db$', '_[0-9]{14}.db', file_name)
+
+                    backup_file = [for_a for for_a in os.listdir(file_dir) if re.search('^' + file_name + '$', for_a)]
+                    backup_file = sorted(backup_file)
+                    
+                    if len(backup_file) >= back_up_count:
+                        remove_dir = os.path.join(file_dir, backup_file[0])
+                        os.remove(remove_dir)
+                        print('Back up : Remove (' + remove_dir + ')')
+
+                now_time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
+                new_file_name = re.sub(r'\.db$', '_' + now_time + '.db', back_up_where)
                 shutil.copyfile(
                     data_db_set['name'] + '.db', 
-                    back_up_where
+                    new_file_name
                 )
 
-                print('Back up : OK')
-            except:
-                print('Back up : Error')
-
-            threading.Timer(
-                60 * 60 * back_time, 
-                back_up,
-                [back_time, back_up_where]
-            ).start()
-
-        curs.execute(db_change('select data from other where name = "back_up"'))
-        back_time = curs.fetchall()
-        back_time = int(number_check(back_time[0][0])) if back_time and back_time != '' else 0
-        if back_time != 0:
-            curs.execute(db_change('select data from other where name = "backup_where"'))
-            back_up_where = curs.fetchall()
-            if back_up_where and back_up_where[0][0] != '':
-                back_up_where = back_up_where[0][0]
+                print('Back up : OK (' + new_file_name + ')')
             else:
-                back_up_where = 'back_' + data_db_set['name'] + '.db'
+                print('Back up state : Turn off')
 
-            print('Back up state : ' + str(back_time) + ' hours')
+                back_time = 1
+        except Exception as e:
+            print('Back up : Error')
+            print(e)
 
-            back_up(back_time, back_up_where)
-        else:
-            print('Back up state : Turn off')
+            back_time = 1
 
-    print('Now running... http://localhost:' + server_set['port'])
+        threading.Timer(60 * 60 * back_time, back_up, [data_db_set]).start()
+
+def do_every_day():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+        
+        # 오늘의 날짜 불러오기
+        time_today = get_time().split()[0]
     
-    conn.commit()
+        # vote 관리
+        curs.execute(db_change('select id, type from vote where type = "open" or type = "n_open"'))
+        for for_a in curs.fetchall():
+            curs.execute(db_change('select data from vote where id = ? and name = "end_date" and type = "option"'), [for_a[0]])
+            db_data = curs.fetchall()
+            if db_data:
+                time_db = db_data[0][0].split()[0]
+                if time_today > time_db:
+                    curs.execute(db_change("update vote set type = ? where user = '' and id = ? and type = ?"), ['close' if for_a[1] == 'open' else 'n_close', for_a[0], for_a[1]])
+
+        # ban 관리
+        curs.execute(db_change("update rb set ongoing = '' where end < ? and end != '' and ongoing = '1'"), [get_time()])
+
+        # auth 관리
+        curs.execute(db_change('select id, data from user_set where name = "auth_date"'))
+        db_data = curs.fetchall()
+        for for_a in db_data:
+            time_db = for_a[1].split()[0]
+            if time_today > time_db:
+                curs.execute(db_change("update user_set set data = 'user' where id = ? and name = 'acl'"), [for_a[0]])
+                curs.execute(db_change('delete from user_set where name = "auth_date" and id = ?'), [for_a[0]])
+                
+        # acl 관리
+        curs.execute(db_change("select doc_name, doc_rev, set_data from data_set where set_name = 'acl_date'"))
+        db_data = curs.fetchall()
+        for for_a in db_data:
+            time_db = for_a[2].split()[0]
+            if time_today > time_db:
+                curs.execute(db_change("delete from acl where title = ? and type = ?"), [for_a[0], for_a[1]])
+                curs.execute(db_change("delete from data_set where doc_name = ? and doc_rev = ? and set_name = 'acl_date'"), [for_a[0], for_a[1]])
+                
+        # ua 관리
+        curs.execute(db_change('select data from other where name = "ua_expiration_date"'))
+        db_data = curs.fetchall()
+        if db_data and db_data[0][0] != '':
+            time_db = int(number_check(db_data[0][0]))
+            
+            time_calc = datetime.date.today() - datetime.timedelta(days = time_db)
+            time_calc = time_calc.strftime('%Y-%m-%d %H:%M:%S')
+            
+            curs.execute(db_change("delete from ua_d where today < ?"), [time_calc])
+            
+        # auth history 관리
+        curs.execute(db_change('select data from other where name = "auth_history_expiration_date"'))
+        db_data = curs.fetchall()
+        if db_data and db_data[0][0] != '':
+            time_db = int(number_check(db_data[0][0]))
+            
+            time_calc = datetime.date.today() - datetime.timedelta(days = time_db)
+            time_calc = time_calc.strftime('%Y-%m-%d %H:%M:%S')
+            
+            curs.execute(db_change("delete from re_admin where time < ?"), [time_calc])
+
+        # 전체 문서 수 재계산
+        curs.execute(db_change("select count(*) from data"))
+        count_data = curs.fetchall()
+        if count_data:
+            count_data = count_data[0][0]
+        else:
+            count_data = 0
 
-# Init-custom
-if os.path.exists('custom.py'):
-    from custom import custom_run
-    custom_run('error', app)
+        curs.execute(db_change('delete from other where name = "count_all_title"'))
+        curs.execute(db_change('insert into other (name, data, coverage) values ("count_all_title", ?, "")'), [str(count_data)])
 
-# Func
-# Func-inter_wiki
-app.route('/inter_wiki', defaults = { 'tool' : 'inter_wiki' })(filter_inter_wiki)
-app.route('/inter_wiki/del/<everything:name>', defaults = { 'tool' : 'del_inter_wiki' })(filter_inter_wiki_delete)
-app.route('/inter_wiki/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_inter_wiki' })(filter_inter_wiki_add)
-app.route('/inter_wiki/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_inter_wiki' })(filter_inter_wiki_add)
+        # 사이트맵 생성 관리
+        curs.execute(db_change('select data from other where name = "sitemap_auto_make"'))
+        db_data = curs.fetchall()
+        if db_data and db_data[0][0] != '':
+            main_setting_sitemap(1)
 
-app.route('/filter/document/list')(filter_document)
-app.route('/filter/document/add/<everything:name>', methods = ['POST', 'GET'])(filter_document_add)
-app.route('/filter/document/add', methods = ['POST', 'GET'])(filter_document_add)
-app.route('/filter/document/del/<name>')(filter_document_delete)
+            print('Make sitemap')
 
-app.route('/edit_top', defaults = { 'tool' : 'edit_top' })(filter_inter_wiki)
-app.route('/edit_top/del/<everything:name>', defaults = { 'tool' : 'del_edit_top' })(filter_inter_wiki_delete)
-app.route('/edit_top/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_top' })(filter_inter_wiki_add)
+        conn.commit()
 
-app.route('/image_license', defaults = { 'tool' : 'image_license' })(filter_inter_wiki)
-app.route('/image_license/del/<everything:name>', defaults = { 'tool' : 'del_image_license' })(filter_inter_wiki_delete)
-app.route('/image_license/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_image_license' })(filter_inter_wiki_add)
+        threading.Timer(60 * 60 * 24, do_every_day).start()
 
-app.route('/edit_filter', defaults = { 'tool' : 'edit_filter' })(filter_inter_wiki)
-app.route('/edit_filter/del/<everything:name>', defaults = { 'tool' : 'del_edit_filter' })(filter_inter_wiki_delete)
-app.route('/edit_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_filter' })(filter_inter_wiki_add)
-app.route('/edit_filter/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_edit_filter' })(filter_inter_wiki_add)
+def auto_do_something(data_db_set):
+    if data_db_set['type'] == 'sqlite':
+        back_up(data_db_set)
 
-app.route('/email_filter', defaults = { 'tool' : 'email_filter' })(filter_inter_wiki)
-app.route('/email_filter/del/<everything:name>', defaults = { 'tool' : 'del_email_filter' })(filter_inter_wiki_delete)
-app.route('/email_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_email_filter' })(filter_inter_wiki_add)
+    do_every_day()
 
-app.route('/file_filter', defaults = { 'tool' : 'file_filter' })(filter_inter_wiki)
-app.route('/file_filter/del/<everything:name>', defaults = { 'tool' : 'del_file_filter' })(filter_inter_wiki_delete)
-app.route('/file_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_file_filter' })(filter_inter_wiki_add)
+auto_do_something(data_db_set)
 
-app.route('/name_filter', defaults = { 'tool' : 'name_filter' })(filter_inter_wiki)
-app.route('/name_filter/del/<everything:name>', defaults = { 'tool' : 'del_name_filter' })(filter_inter_wiki_delete)
-app.route('/name_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_name_filter' })(filter_inter_wiki_add)
+print('Now running... http://localhost:' + server_set['port'])
+    
+# Init-custom
+if os.path.exists('custom.py'):
+    from custom import custom_run
+    custom_run('error', app)
 
-app.route('/extension_filter', defaults = { 'tool' : 'extension_filter' })(filter_inter_wiki)
-app.route('/extension_filter/del/<everything:name>', defaults = { 'tool' : 'del_extension_filter' })(filter_inter_wiki_delete)
-app.route('/extension_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'plus_extension_filter' })(filter_inter_wiki_add)
+db_set_str = json.dumps(data_db_set)
+
+# Func
+# Func-inter_wiki
+app.route('/filter/inter_wiki', defaults = { 'tool' : 'inter_wiki' })(filter_all)
+app.route('/filter/inter_wiki/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'inter_wiki' })(filter_all_add)
+app.route('/filter/inter_wiki/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'inter_wiki' })(filter_all_add)
+app.route('/filter/inter_wiki/del/<everything:name>', defaults = { 'tool' : 'inter_wiki' })(filter_all_delete)
+
+app.route('/filter/outer_link', defaults = { 'tool' : 'outer_link' })(filter_all)
+app.route('/filter/outer_link/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'outer_link' })(filter_all_add)
+app.route('/filter/outer_link/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'outer_link' })(filter_all_add)
+app.route('/filter/outer_link/del/<everything:name>', defaults = { 'tool' : 'outer_link' })(filter_all_delete)
+
+app.route('/filter/document', defaults = { 'tool' : 'document' })(filter_all)
+app.route('/filter/document/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'document' })(filter_all_add)
+app.route('/filter/document/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'document' })(filter_all_add)
+app.route('/filter/document/del/<everything:name>', defaults = { 'tool' : 'document' })(filter_all_delete)
+
+app.route('/filter/edit_top', defaults = { 'tool' : 'edit_top' })(filter_all)
+app.route('/filter/edit_top/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'edit_top' })(filter_all_add)
+app.route('/filter/edit_top/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'edit_top' })(filter_all_add)
+app.route('/filter/edit_top/del/<everything:name>', defaults = { 'tool' : 'edit_top' })(filter_all_delete)
+
+app.route('/filter/image_license', defaults = { 'tool' : 'image_license' })(filter_all)
+app.route('/filter/image_license/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'image_license' })(filter_all_add)
+app.route('/filter/image_license/del/<everything:name>', defaults = { 'tool' : 'image_license' })(filter_all_delete)
+
+app.route('/filter/template', defaults = { 'tool' : 'template' })(filter_all)
+app.route('/filter/template/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'template' })(filter_all_add)
+app.route('/filter/template/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'template' })(filter_all_add)
+app.route('/filter/template/del/<everything:name>', defaults = { 'tool' : 'template' })(filter_all_delete)
+
+app.route('/filter/edit_filter', defaults = { 'tool' : 'edit_filter' })(filter_all)
+app.route('/filter/edit_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'edit_filter' })(filter_all_add)
+app.route('/filter/edit_filter/add/<everything:name>', methods = ['POST', 'GET'], defaults = { 'tool' : 'edit_filter' })(filter_all_add)
+app.route('/filter/edit_filter/del/<everything:name>', defaults = { 'tool' : 'edit_filter' })(filter_all_delete)
+
+app.route('/filter/email_filter', defaults = { 'tool' : 'email_filter' })(filter_all)
+app.route('/filter/email_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'email_filter' })(filter_all_add)
+app.route('/filter/email_filter/del/<everything:name>', defaults = { 'tool' : 'email_filter' })(filter_all_delete)
+
+app.route('/filter/file_filter', defaults = { 'tool' : 'file_filter' })(filter_all)
+app.route('/filter/file_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'file_filter' })(filter_all_add)
+app.route('/filter/file_filter/del/<everything:name>', defaults = { 'tool' : 'file_filter' })(filter_all_delete)
+
+app.route('/filter/name_filter', defaults = { 'tool' : 'name_filter' })(filter_all)
+app.route('/filter/name_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'name_filter' })(filter_all_add)
+app.route('/filter/name_filter/del/<everything:name>', defaults = { 'tool' : 'name_filter' })(filter_all_delete)
+
+app.route('/filter/extension_filter', defaults = { 'tool' : 'extension_filter' })(filter_all)
+app.route('/filter/extension_filter/add', methods = ['POST', 'GET'], defaults = { 'tool' : 'extension_filter' })(filter_all_add)
+app.route('/filter/extension_filter/del/<everything:name>', defaults = { 'tool' : 'extension_filter' })(filter_all_delete)
 
 # Func-list
 app.route('/list/document/old')(list_old_page)
 app.route('/list/document/old/<int:num>')(list_old_page)
 
+app.route('/list/document/no_link')(list_no_link)
+app.route('/list/document/no_link/<int:num>')(list_no_link)
+
 app.route('/list/document/acl')(list_acl)
 app.route('/list/document/acl/<int:arg_num>')(list_acl)
 
@@ -319,11 +434,13 @@ app.route('/list/document/short/<int:arg_num>', defaults = { 'tool' : 'short_pag
 
 app.route('/list/file')(list_image_file)
 app.route('/list/file/<int:arg_num>')(list_image_file)
+app.route('/list/image', defaults = { 'do_type' : 1 })(list_image_file)
+app.route('/list/image/<int:arg_num>', defaults = { 'do_type' : 1 })(list_image_file)
 
 app.route('/list/admin')(list_admin)
 
 app.route('/list/admin/auth_use', methods = ['POST', 'GET'])(list_admin_auth_use)
-app.route('/list/admin/auth_use/<arg_search>/<int:arg_num>', methods = ['POST', 'GET'])(list_admin_auth_use)
+app.route('/list/admin/auth_use_page/<int:arg_num>/<everything:arg_search>', methods = ['POST', 'GET'])(list_admin_auth_use)
 
 app.route('/list/user')(list_user)
 app.route('/list/user/<int:arg_num>')(list_user)
@@ -343,18 +460,16 @@ app.route('/auth/give/<name>', methods = ['POST', 'GET'])(give_auth)
 # /auth/give
 # /auth/give/<name>
 app.route('/auth/give/ban', methods = ['POST', 'GET'])(give_user_ban)
-app.route('/auth/give/ban/<name>', methods = ['POST', 'GET'])(give_user_ban)
+app.route('/auth/give/ban/<everything:name>', methods = ['POST', 'GET'])(give_user_ban)
 app.route('/auth/give/ban_regex/<everything:name>', methods = ['POST', 'GET'], defaults = { 'ban_type' : 'regex' })(give_user_ban)
 app.route('/auth/give/ban_multiple', methods = ['POST', 'GET'], defaults = { 'ban_type' : 'multiple' })(give_user_ban)
 
 # /auth/list
-app.route('/admin_group')(list_admin_group_2)
-
 # /auth/list/add/<name>
-app.route('/admin_plus/<name>', methods = ['POST', 'GET'])(give_admin_groups_2)
-
 # /auth/list/delete/<name>
-app.route('/delete_admin_group/<name>', methods = ['POST', 'GET'])(give_delete_admin_group_2)
+app.route('/auth/list')(list_admin_group_2)
+app.route('/auth/list/add/<name>', methods = ['POST', 'GET'])(give_admin_groups_2)
+app.route('/auth/list/delete/<name>', methods = ['POST', 'GET'])(give_delete_admin_group_2)
 
 app.route('/auth/give/fix/<user_name>', methods = ['POST', 'GET'])(give_user_fix)
 
@@ -367,25 +482,35 @@ app.route('/block_log/<regex("user"):tool>/<name>')(recent_block_2)
 app.route('/block_log/<regex("admin"):tool>/<name>')(recent_block_2)
 
 # Func-history
-app.route('/recent_change')(recent_change)
-app.route('/recent_changes')(recent_change)
+app.route('/recent_change', defaults = { 'tool' : 'recent' })(recent_change)
+app.route('/recent_change/<int:num>/<set_type>', defaults = { 'tool' : 'recent' })(recent_change)
+app.route('/recent_changes', defaults = { 'tool' : 'recent' })(recent_change)
+app.route('/recent_changes/<int:num>/<set_type>', defaults = { 'tool' : 'recent' })(recent_change)
 
 app.route('/record/<name>', defaults = { 'tool' : 'record' })(recent_change)
+app.route('/record/<int:num>/<set_type>/<name>', defaults = { 'tool' : 'record' })(recent_change)
+
 app.route('/record/reset/<name>', methods = ['POST', 'GET'])(recent_record_reset)
 app.route('/record/topic/<name>')(recent_record_topic)
 
+app.route('/record/bbs/<name>', defaults = { 'tool' : 'record' })(bbs_w)
+app.route('/record/bbs_comment/<name>', defaults = { 'tool' : 'comment_record' })(bbs_w)
+
 app.route('/history/<everything:name>', defaults = { 'tool' : 'history' }, methods = ['POST', 'GET'])(recent_change)
+app.route('/history_page/<int:num>/<set_type>/<everything:name>', defaults = { 'tool' : 'history' }, methods = ['POST', 'GET'])(recent_change)
+
 app.route('/history_tool/<int(signed = True):rev>/<everything:name>')(recent_history_tool)
 app.route('/history_delete/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])(recent_history_delete)
 app.route('/history_hidden/<int(signed = True):rev>/<everything:name>')(recent_history_hidden)
 app.route('/history_send/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])(recent_history_send)
 app.route('/history_reset/<everything:name>', methods = ['POST', 'GET'])(recent_history_reset)
 app.route('/history_add/<everything:name>', methods = ['POST', 'GET'])(recent_history_add)
-app.route('/history_add_preview/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(recent_history_add)
 
 # Func-view
 app.route('/xref/<everything:name>')(view_xref)
+app.route('/xref_page/<int:num>/<everything:name>')(view_xref)
 app.route('/xref_this/<everything:name>', defaults = { 'xref_type' : 2 })(view_xref)
+app.route('/xref_this_page/<int:num>/<everything:name>', defaults = { 'xref_type' : 2 })(view_xref)
 
 app.route('/raw/<everything:name>')(view_raw_2)
 app.route('/raw_acl/<everything:name>', defaults = { 'doc_acl' : 1 })(view_raw_2)
@@ -402,14 +527,12 @@ app.route('/w_rev/<int(signed = True):doc_rev>/<everything:name>')(view_read)
 app.route('/w_from/<everything:name>', defaults = { 'do_type' : 'from' })(view_read)
 app.route('/w/<everything:name>')(view_read)
 
-app.route('/random')(view_random)
+app.route('/random', defaults = { 'db_set' : db_set_str })(view_random)
 
 # Func-edit
 app.route('/edit/<everything:name>', methods = ['POST', 'GET'])(edit)
-app.route('/edit_preview/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(edit)
-app.route('/edit_from/<everything:name>', defaults = { 'do_type' : 'load' })(edit)
+app.route('/edit_from/<everything:name>', methods = ['POST', 'GET'], defaults = { 'do_type' : 'load' })(edit)
 app.route('/edit_section/<int:section>/<everything:name>', methods = ['POST', 'GET'])(edit)
-app.route('/edit_section_preview/<int:section>/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(edit)
 
 app.route('/upload', methods = ['POST', 'GET'])(edit_upload)
 
@@ -431,7 +554,6 @@ app.route('/recent_discuss/open', defaults = { 'tool' : 'open' })(recent_discuss
 
 app.route('/thread/<int:topic_num>', methods = ['POST', 'GET'])(topic)
 app.route('/thread/0/<everything:doc_name>', defaults = { 'topic_num' : '0' }, methods = ['POST', 'GET'])(topic)
-app.route('/thread_preview/<int:topic_num>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(topic)
 app.route('/topic/<everything:name>', methods = ['POST', 'GET'])(topic_list)
 
 app.route('/thread/<int:topic_num>/tool')(topic_tool)
@@ -451,13 +573,13 @@ app.route('/change', methods = ['POST', 'GET'])(user_setting)
 app.route('/change/key')(user_setting_key)
 app.route('/change/key/delete')(user_setting_key_delete)
 app.route('/change/pw', methods = ['POST', 'GET'])(user_setting_pw)
-app.route('/change/head', methods=['GET', 'POST'], defaults = { 'skin_name' : '' })(user_setting_head)
-app.route('/change/head/<skin_name>', methods=['GET', 'POST'])(user_setting_head)
-app.route('/change/head_reset', methods=['GET', 'POST'])(user_setting_head_reset)
+app.route('/change/head', methods = ['GET', 'POST'], defaults = { 'skin_name' : '' })(user_setting_head)
+app.route('/change/head/<skin_name>', methods = ['GET', 'POST'])(user_setting_head)
+app.route('/change/head_reset', methods = ['GET', 'POST'])(user_setting_head_reset)
 app.route('/change/skin_set')(user_setting_skin_set)
-app.route('/change/top_menu', methods=['GET', 'POST'])(user_setting_top_menu)
-app.route('/change/user_name', methods=['GET', 'POST'])(user_setting_user_name)
-app.route('/change/user_name/<user_name>', methods=['GET', 'POST'])(user_setting_user_name)
+app.route('/change/top_menu', methods = ['GET', 'POST'])(user_setting_top_menu)
+app.route('/change/user_name', methods = ['GET', 'POST'])(user_setting_user_name)
+app.route('/change/user_name/<user_name>', methods = ['GET', 'POST'])(user_setting_user_name)
 # 하위 호환용 S
 app.route('/skin_set')(user_setting_skin_set)
 # 하위 호환용 E
@@ -466,13 +588,14 @@ app.route('/change/skin_set/main', methods = ['POST', 'GET'])(user_setting_skin_
 app.route('/user')(user_info)
 app.route('/user/<name>')(user_info)
 
-app.route('/challenge')(user_challenge)
+app.route('/challenge', methods = ['GET', 'POST'])(user_challenge)
 
 app.route('/count')(user_count)
 app.route('/count/<name>')(user_count)
 
 app.route('/alarm')(user_alarm)
 app.route('/alarm/delete')(user_alarm_delete)
+app.route('/alarm/delete/<int:id>')(user_alarm_delete)
 
 app.route('/watch_list', defaults = { 'tool' : 'watch_list' })(user_watch_list)
 app.route('/watch_list/<everything:name>', defaults = { 'tool' : 'watch_list' })(user_watch_list_name)
@@ -518,29 +641,40 @@ app.route('/vote/list/close/<int:num>', defaults = { 'list_type' : 'close' })(vo
 app.route('/vote/add', methods = ['POST', 'GET'])(vote_add)
 
 # Func-bbs
-app.route('/bbs/main')(bbs_main)
+app.route('/bbs/main', defaults = { 'tool' : 'main' })(bbs_w)
 app.route('/bbs/make', methods = ['POST', 'GET'])(bbs_make)
 # app.route('/bbs/main/set')
 app.route('/bbs/w/<int:bbs_num>')(bbs_w)
+# app.route('/bbs/blind/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_hide)
+app.route('/bbs/delete/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_delete)
 app.route('/bbs/set/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_w_set)
 app.route('/bbs/edit/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_w_edit)
-app.route('/bbs/edit/preview/<int:bbs_num>', methods = ['POST', 'GET'], defaults = { 'do_type' : 'preview' })(bbs_w_edit)
 app.route('/bbs/w/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'])(bbs_w_post)
+# app.route('/bbs/blind/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'])(bbs_w_hide)
+app.route('/bbs/pinned/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'])(bbs_w_pinned)
+app.route('/bbs/delete/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'])(bbs_w_delete)
 app.route('/bbs/raw/<int:bbs_num>/<int:post_num>')(view_raw_2)
 app.route('/bbs/tool/<int:bbs_num>/<int:post_num>')(bbs_w_tool)
 app.route('/bbs/edit/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'])(bbs_w_edit)
-app.route('/bbs/edit/preview/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'], defaults = { 'do_type' : 'preview' })(bbs_w_edit)
-app.route('/bbs/w/preview/<int:bbs_num>/<int:post_num>', methods = ['POST'], defaults = { 'do_type' : 'preview' })(bbs_w_post)
 app.route('/bbs/tool/<int:bbs_num>/<int:post_num>/<comment_num>')(bbs_w_comment_tool)
 app.route('/bbs/raw/<int:bbs_num>/<int:post_num>/<comment_num>')(view_raw_2)
 app.route('/bbs/edit/<int:bbs_num>/<int:post_num>/<comment_num>', methods = ['POST', 'GET'])(bbs_w_edit)
-app.route('/bbs/edit/preview/<int:bbs_num>/<int:post_num>/<comment_num>', methods = ['POST', 'GET'])(bbs_w_edit)
+app.route('/bbs/delete/<int:bbs_num>/<int:post_num>/<comment_num>', methods = ['POST', 'GET'])(bbs_w_delete)
 
 # Func-api
-app.route('/api/w/<everything:name>/doc_tool/<tool>/doc_rev/<int(signed = True):rev>')(api_w)
-app.route('/api/w/<everything:name>/doc_tool/<tool>', methods = ['POST', 'GET'])(api_w)
+# 폐지 예정
+app.route('/api/w_rev/<int(signed = True):rev>/<tool>/<everything:name>', methods = ['GET', 'POST'])(api_w)
+app.route('/api/w_tool/<tool>/<everything:name>', methods = ['GET', 'POST'])(api_w)
 app.route('/api/w/<everything:name>', methods = ['GET', 'POST'])(api_w)
-app.route('/api/raw/<everything:name>')(api_raw)
+
+# app.route('/api/render_tool/<tool>/<everything:name>', methods = ['POST'])(api_w_render)
+# app.route('/api/render_tool/<tool>', methods = ['POST'])(api_w_render)
+# app.route('/api/render/<everything:name>', methods = ['POST'])(api_w_render)
+# app.route('/api/render', methods = ['POST'])(api_w_render)
+
+app.route('/api/raw_exist/<everything:name>', defaults = { 'exist_check' : 'on' })(api_w_raw)
+app.route('/api/raw_rev/<int(signed = True):rev>/<everything:name>')(api_w_raw)
+app.route('/api/raw/<everything:name>')(api_w_raw)
 
 app.route('/api/bbs/w/<sub_code>')(api_bbs_w_post)
 app.route('/api/bbs/w/comment/<sub_code>')(api_bbs_w_comment)
@@ -606,32 +740,11 @@ app.route('/setting/robot', methods = ['POST', 'GET'])(main_setting_robot)
 app.route('/setting/external', methods = ['POST', 'GET'])(main_setting_external)
 app.route('/setting/acl', methods = ['POST', 'GET'])(main_setting_acl)
 app.route('/setting/sitemap', methods = ['POST', 'GET'])(main_setting_sitemap)
+app.route('/setting/sitemap_set', methods = ['POST', 'GET'])(main_setting_sitemap_set)
 app.route('/setting/skin_set', methods = ['POST', 'GET'])(main_setting_skin_set)
 
 app.route('/easter_egg')(main_func_easter_egg)
 
-def main_easter_egg_go():
-    with get_db_connect() as conn:
-        print(platform.machine())
-        if platform.system() == 'Linux':
-            if platform.machine() in ["AMD64", "x86_64"]:
-                data = os.popen(os.path.join(".", "route_go", "bin", "main_easter_egg.amd64.bin")).read()
-            else:
-                data = os.popen(os.path.join(".", "route_go", "bin", "main_easter_egg.arm64.bin")).read()
-        else:
-            if platform.machine() in ["AMD64", "x86_64"]:
-                data = os.popen(os.path.join(".", "route_go", "bin", "main_easter_egg.amd64.exe")).read()
-            else:
-                data = os.popen(os.path.join(".", "route_go", "bin", "main_easter_egg.arm64.exe")).read()
-
-        return easy_minify(flask.render_template(skin_check(),
-            imp = ['Easter Egg', wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = data,
-            menu = 0
-        ))
-
-app.route('/easter_egg_go')(main_easter_egg_go)
-
 # views -> view
 app.route('/view/<path:name>')(main_view)
 app.route('/views/<path:name>')(main_view)
@@ -650,5 +763,6 @@ if __name__ == "__main__":
         app,
         host = server_set['host'],
         port = int(server_set['port']),
-        clear_untrusted_proxy_headers = True
-    )
+        clear_untrusted_proxy_headers = True,
+        threads = os.cpu_count()
+    )

+ 47 - 0
create_service.sh

@@ -0,0 +1,47 @@
+#!/bin/Bash
+
+#1단계 : 작업 디렉토리 & 서비스 명 받기
+read -p "설치된 디렉토리 (ex: /mnt/openNAMU) : " working_directory
+echo $working_directory
+
+read -p "원하는 서비스명 (ex: opennamu): " service_name
+echo $service_name
+
+read -p "설명 (ex: OpenNAMU 서비스입니다): " description
+echo $description
+
+read -p "로그위치 (ex: /var/log/openNAMU.log) : " log_path
+echo $log_path
+
+
+#2단계 : 파일제작
+cat <<EOF > /lib/systemd/system/${service_name}.service
+[Unit]
+Description=$description
+
+[Service]
+Type=simple
+
+WorkingDirectory=$working_directory
+ExecStart=/usr/bin/python3 $working_directory/app.py
+Restart=on-failure
+PIDFile=/run/$service_name.pid
+
+#rsyslog 사용
+#StandardOutput=syslog
+#StandardError=syslog
+#SyslogIdentifier=$service_name
+
+#systemctl 245 이후 로깅
+StandardOutput=append:$log_path
+StandardError=append:$log_path
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+
+#3단계 : 서비스 확인
+systemctl daemon-reload 
+systemctl start $service_name
+systemctl status $service_name

+ 9 - 45
emergency_tool.py

@@ -25,11 +25,9 @@ if data_db_load == 'Y':
     conn = load_db.__enter__()
     curs = conn.cursor()
 else:
-    print('----')
     print('You can use [9, 11, 19]')
 
 # Main
-print('----')
 print('1. Backlink reset')
 print('2. reCAPTCHA delete')
 print('3. Ban delete')
@@ -41,7 +39,6 @@ print('8. Change version')
 print('9. Delete set.json')
 print('10. Change name')
 print('11. Delete mysql.json')
-print('12. All title count reset')
 print('14. Delete Main <HEAD>')
 print('15. Give owner')
 print('16. Delete 2FA password')
@@ -54,17 +51,13 @@ print('22. Delete body top')
 print('23. Delete body bottom')
 print('24. SQLite to MySQL')
 
-print('----')
 what_i_do = input('Select : ')
-
 if what_i_do == '1':
-    print('----')
     go_num = input('All delete (Y) [Y, N] : ')
     if not go_num == 'N':
         curs.execute(db_change("delete from back"))
         conn.commit()
 
-    print('----')
     try:
         go_num = int(input('Count (100) : '))
     except ValueError:
@@ -72,7 +65,6 @@ if what_i_do == '1':
 
     num = 0
 
-    print('----')
     print('Load...')
 
     curs.execute(
@@ -86,11 +78,9 @@ if what_i_do == '1':
     )
     title = curs.fetchall()
 
-    print('----')
     print('Rest : ' + str(len(title)))
     print('Start : ' + title[0][0])
     time.sleep(1)
-    print('----')
 
     for name in title:
         num += 1
@@ -108,13 +98,12 @@ 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'"))
 elif what_i_do == '3':
-    print('----')
     user_data = input('IP or Name : ')
 
     curs.execute(
         db_change(
-            "insert into rb (block, end, today, blocker, why, band) "
-            "values (?, ?, ?, ?, ?, ?)"
+            "insert into rb (block, end, today, blocker, why, band, ongoing, login) "
+            "values (?, ?, ?, ?, ?, ?, '', '')"
         ),
         [
             user_data,
@@ -128,34 +117,27 @@ elif what_i_do == '3':
 
     curs.execute(db_change("update rb set ongoing = '' where block = ?"), [user_data])
 elif what_i_do == '4':
-    print('----')
     host = input('Host : ')
 
     curs.execute(db_change("update other set data = ? where name = 'host'"), [host])
 elif what_i_do == '5':
-    print('----')
     port = int(input('Port : '))
 
     curs.execute(db_change("update other set data = ? where name = 'port'"), [port])
 elif what_i_do == '6':
-    print('----')
     skin = input('Skin name : ')
 
     curs.execute(db_change("update other set data = ? where name = 'skin'"), [skin])
 elif what_i_do == '7':
-    print('----')
     user_name = input('User name : ')
-
-    print('----')
     user_pw = input('User password : ')
-    hashed = pw_encode(user_pw)
 
+    hashed = pw_encode(user_pw)
     curs.execute(db_change("update user_set set data = ? where id = ? and name = 'pw'"), [
         hashed,
         user_name
     ])
 elif what_i_do == '8':
-    print('----')
     new_ver = input('Insert version (0000000) : ')
 
     if new_ver == '':
@@ -166,10 +148,7 @@ elif what_i_do == '9':
     if os.path.exists(os.path.join('data', 'set.json')):
         os.remove(os.path.join('data', 'set.json'))
 elif what_i_do == '10':
-    print('----')
     user_name = input('User name : ')
-
-    print('----')
     new_name = input('New name : ')
 
     curs.execute(
@@ -179,42 +158,27 @@ elif what_i_do == '10':
 elif what_i_do == '11':
     if os.path.exists(os.path.join('data', 'mysql.json')):
         os.remove(os.path.join('data', 'mysql.json'))
-elif what_i_do == '12':
-    curs.execute(db_change("select count(*) 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, coverage) values ("count_all_title", ?, "")'), [str(count_data)])
 elif what_i_do == '14':
     curs.execute(db_change('delete from other where name = "head"'))
 elif what_i_do == '15':
-    print('----')
     user_name = input('User name : ')
 
     curs.execute(db_change("update user_set set data = 'owner' where id = ? and name = 'acl'"), [user_name])
 elif what_i_do == '16':
-    print('----')
     user_name = input('User name : ')
 
     curs.execute(db_change('select data from user_set where name = "2fa" and id = ?'), [user_name])
     if curs.fetchall():
         curs.execute(db_change("update user_set set data = '' where name = '2fa' and id = ?"), [user_name])
 elif what_i_do == '17':
-    print('----')
     markup = input('Markup name : ')
 
     curs.execute(db_change("update other set data = ? where name = 'markup'"), [markup])
 elif what_i_do == '18':
-    print('----')
     wiki_access_password = input('Password : ')
 
     curs.execute(db_change("update other set data = ? where name = 'wiki_access_password'"), [wiki_access_password])
 elif what_i_do == '19':
-    print('----')
     up_data = input('Insert branch (beta) [stable, beta, dev] : ')
 
     if not up_data in ['stable', 'beta', 'dev']:
@@ -240,13 +204,11 @@ elif what_i_do == '19':
         else:
             print('Error : update failed')
 elif what_i_do == '20':
-    print('----')
     domain = input('Domain (EX : 2du.pythonanywhere.com) : ')
 
     curs.execute(db_change('delete from other where name = "domain"'))
     curs.execute(db_change('insert into other (name, data, coverage) values ("domain", ?, "")'), [domain])
 elif what_i_do == '21':
-    print('----')
     tls_v = input('TLS (http) [http, https] : ')
     if not tls_v in ['http', 'https']:
         tls_v = 'http'
@@ -269,13 +231,16 @@ elif what_i_do == '24':
     create_data = get_db_table_list()
     for create_table in create_data:
         create = ['test'] + create_data[create_table]
-        create_r = ', '.join(['?' for _ in create])
+
+        create_r = ', '.join(['%s' for _ in create])
         create = ', '.join(create)
         
-        print('select ' + create + ' from ' + create_table)
+        mysql_curs.execute(db_change('delete from ' + create_table))
+        
         sqlite_curs.execute(db_change('select ' + create + ' from ' + create_table))
         db_data = sqlite_curs.fetchall()
-        mysql_curs.executemany(db_change("insert into " + create_table + " (" + create + ") values (" + create_r + ")"), db_data)
+        if db_data:
+            mysql_curs.executemany("insert into " + create_table + " (" + create + ") values (" + create_r + ")", db_data)
 else:
     raise ValueError(what_i_do)
 
@@ -285,5 +250,4 @@ if data_db_load == 'Y':
     except:
         pass
 
-print('----')
 print('OK')

+ 75 - 17
lang/en-US.json

@@ -1,6 +1,8 @@
 {
     "language_tag": "en-US",
     "_comment_1_" : "Common",
+        "sitemap_manual_create" : "Create sitemap manually",
+        "sitemap_auto_make" : "Create sitemap automatically",
         "data" : "Data",
         "volume" : "Volume",
         "server" : "Server",
@@ -55,7 +57,7 @@
         "close" : "Closed",
         "open" : "Open",
         "agreement" : "Agreement",
-        "template" : "Template",
+        "template" : "Template document",
         "file" : "File",
         "writer" : "Writer",
         "editor" : "Editor",
@@ -118,6 +120,12 @@
         "spread" : "Speard",
         "popup" : "Popup",
         "popover" : "Popover",
+        "trace" : "Trace",
+        "level" : "Level",
+        "challenge" : "Challenges",
+        "ua" : "UA",
+        "day" : "Day(s)",
+        "backup" : "Backup",
         "_comment_1.1_" : "Time",
             "second" : "Second(s)",
             "hour" : "Hour(s)",
@@ -214,7 +222,7 @@
         "topic_acl_setting" : "Discussion ACL setting",
         "topic_acl" : "Discussion ACL",
         "delete_admin_group": "Delete admin group",
-        "main_skin_set" : "Main skin setting(s)",
+        "main_skin_set" : "Main skin settings",
         "reset_backlink" : "Reset backlink",
         "link_in_this" : "Links in this document",
         "star_doc" : "Document(s) of interest",
@@ -233,7 +241,6 @@
         "key_change" : "Change key",
         "key_delete" : "Delete key",
         "email_delete" : "Delete email",
-        "challenge" : "Challenge",
         "user_title" : "User title",
         "multiple_ban" : "Multiple ban",
         "dont_move" : "Don't move",
@@ -242,10 +249,29 @@
         "document_set" : "Document settings",
         "user_added_menu" : "User added menu",
         "move_redirect_make" : "Redirect document generation (Only if possible)",
+        "redirect" : "Redirect",
+        "new_doc" : "New document(s)",
+        "table" : "Table",
+        "table_transparent" : "Table transparency",
+        "recaptcha_pass_acl" : "CAPTCHA Pass ACL",
+        "recaptcha_one_check_five_pass_acl" : "Passing the CAPTCHA once will result in 5 unimplemented ACL",
         "user_fix" : "Fix user",
         "main_user_name" : "Main user name",
         "change_user_name" : "Change main user name",
         "sub_user_name" : "Sub user name",
+        "start_with_search" : "Search from the first letter",
+        "challenge_and_level_manage" : "Challenges and level management",
+        "bbs_record" : "BBS post(s) record",
+        "bbs_comment_record" : "BBS comment(s) record",
+        "load_temp_save" : "Temporary save",
+        "load_temp_save_load" : "Load temporary save",
+        "bbs_comment_delete" : "Delete BBS comment",
+        "bbs_post_pinned" : "Pin BBS post",
+        "bbs_post_delete" : "Delete BBS post",
+        "outer_link_filter_list" : "External link auto image list",
+        "html_or_link" : "HTML or link",
+        "template_document_list" : "Template document(s) list",
+        "no_link_document_list" : "List of document(s) without link",
         "_comment_" : "BBS",
             "bbs" : "BBS",
             "bbs_main" : "BBS main",
@@ -270,7 +296,7 @@
                 "bbs_comment_acl" : "BBS ACL to write comment",
         "_comment_" : "Edit",
             "load" : "Load another document",
-            "turn_off_monaco" : "Turn off monaco editor",
+            "turn_off_monaco" : "Turn on/off monaco editor",
         "_comment_" : "Render",
             "toc" : "TOC",
             "category" : "Category",
@@ -297,6 +323,10 @@
                 "footnote_real_num_view" : "Footnote original number view",
                 "category_change_title" : "Don't rename documents in category",
                 "table_scroll" : "Use scroll in tables",
+                "list_view_change" : "Change how the number list is viewed",
+                "view_joke" : "Show contents of joke macro",
+                "math_scroll" : "Use scroll in math macros",
+                "view_history" : "Use trace in view",
             "_comment_" : "Option",
                 "change_to_normal" : "Change to plain text.",
                 "change_to_link" : "Change to Link.",
@@ -375,7 +405,7 @@
                 "requires_approval" : "Requires approval for register",
                 "approval_question": "Registeration questions",
                 "backup_where" : "Backup location",
-                "ua_get_off" : "Turn off members information collection",
+                "ua_get_off" : "Turn off UA collection",
                 "edit_bottom_compulsion" : "Edit reason required",
                 "edit_bottom_compulsion_acl" : "Edit reason required excluded target ACL",
                 "enable_comment_function" : "Using the comment function",
@@ -392,6 +422,9 @@
                 "move_with_redirect" : "Create a redirect when moving a document",
                 "slow_thread" : "Continuous thread upload limit",
                 "edit_timeout" : "render timeout",
+                "display_level_in_user_name" : "Displaying levels in username",
+                "ua_expiration_date" : "UA expiration deadline",
+                "document_content_max_length" : "Maximum document length",
             "_comment_" : "Text",
                 "register_text" : "Terms of sign-up",
                 "non_login_alert" : "Non-login alert",
@@ -411,7 +444,7 @@
                 "topic_text" : "Discussion textarea phrase",
                 "phrase_user_page_admin" : "Administrator user page phrase",
                 "phrase_user_page_owner" : "Onwer user page phrase",
-                "phrase_old_page_warring" : "Warning on previous revision document visit",
+                "phrase_old_page_warning" : "Warning on previous revision document visit",
             "_comment_" : "Ext_API",
                 "recaptcha" : "reCAPTCHA",
                 "hcaptcha" : "hCAPTCHA",
@@ -443,12 +476,17 @@
             "admin_list" : "Administrator(s) list",
             "member_list" : "Member(s) list",
             "authority_use_list" : "Authority use list",
+            "authority_use_list_off" : "Authority use list off",
+            "authority_use_list_expiration_date" : "Authority use list expiration deadline",
             "admin_group_list" : "Administrator group(s) list",
             "all_document_list" : "All document(s) list",
             "watchlist" : "Watchlist",
             "image_file_list" : "Image file(s) list",
             "short_page" : "Short page(s) list",
             "long_page" : "Long page(s) list",
+            "bbs_help" : "BBS editor help",
+            "bbs_comment_help" : "BBS comment editor help",
+            "outdated_doc_warning" : "Out of date document warning",
             "_comment_2.3.1_" : "ACL document list",
                 "acl_document_list" : "ACL document(s) list",
                 "acl_required" : "Required ACL",
@@ -464,6 +502,7 @@
                 "edit_record" : "Edit record",
                 "discussion_record" : "Discussion record",
         "_comment_2.4_" : "Topic",
+            "remove_blind_thread" : "Hide blind thread",
             "make_new_topic" : "Make new discussion",
             "topic_tool" : "Discussion management tools",
             "topic_state" : "Discussion status",
@@ -556,7 +595,6 @@
         "enter_html" : "Please enter HTML",
         "exp_edit_conflict" : "Editing conflict occurred",
         "same_ip_exist" : "Same IP exists",
-        "old_page_warring" : "This page is out of date.",
         "_comment_3.1_" : "Error",
             "update_error" : "Auto update is not supported.",
             "inter_error" : "Internal error.",
@@ -567,8 +605,8 @@
             "error_skin_set" : "The skin you are using does not support individual settings.",
             "error_skin_set_old" : "Some older skins may only work by using the old version link.",
             "same_id_exist_error" : "There are users using the same username.",
-            "long_id_error" : "Username must be shorter than 32 characters.",
-            "id_char_error" : "Only Korean letters and alphabets and numbers are allowed for Username.",
+            "long_id_error" : "Username must be shorter than 128 characters.",
+            "id_char_error" : "XSS characters(inequality symbol, quotation marks) and . and : are not available.",
             "file_exist_error" : "The file does not exist.",
             "password_error" : "Password does not match.",
             "recaptcha_error" : "Pass the reCAPTCHA.",
@@ -579,7 +617,7 @@
             "move_error" : "An error occurred while moving. All or part of it has not been moved.",
             "password_diffrent_error" : "Reconfirm password and input password are different.",
             "edit_filter_error" : "Censored by edit filter.",
-            "file_name_error" : "Only English alphabets, Korean alphabets, spaces, underscore, and hyphens are allowed for the file name.",
+            "file_name_error" : "You cannot use dots in the file name.",
             "topic_long_error" : "The discussions topic must not exceed 256 characters.",
             "email_error" : "No one has this email.",
             "regex_error" : "There is an error in the regular expression.",
@@ -598,26 +636,46 @@
             "error_title_length_too_long" : "Documents title or Discussion topic length is too long. Maximum number of characters : ",
             "error_password_length_too_short" : "Password length is too short. Minimum number of characters : ",
             "error_password_require_for_wiki_access" : "A password is required to access the wiki.",
-            "timeout_error" : "Running is taking too long. Maximum running time (Second(s)) : ",
+            "timeout_error" : "Rendering time is too long. Maximum rendering time (Second(s)) : ",
         "_comment_3.2_" : "Warning",
             "http_warning" : "Warning: If you are not on HTTPS connection, your information can be leaked. The users themselves have responsibility to any problems that happen because of this.",
             "user_head_warning" : "User data will be deleted if you close the browser or when you sign in.",
             "no_login_warning" : "You are not logged in. Your current IP address will be logged within editing or discussing until you log in.",
             "update_warning" : "Manual updates are recommended if your version is 0.2 or lower than the latest version. For Windows, the contents of the route folder will be deleted.",
-            "history_delete_warning" : "If you erase history, it's hard to restore it, so please be careful.",
+            "delete_warning" : "If you erase this, it's hard to restore it, so please be careful.",
             "user_css_warning" : "If you have a problem using this, connect here.",
             "main_css_warning" : "If you have a problem using this, use the emergency tool.",
             "not_support_skin_warning" : "It does not work on skins that do not support this feature.",
+            "old_page_warning" : "This page is out of date.",
+            "backup_warning" : "Warning. Files with the same name may be erased.",
         "_comment_" : "Challenge",
             "challenge_title_register" : "Hello, World!",
-            "challenge_info_register" : "Sign up",
+            "challenge_info_register" : "Sign up<br><br>Reward : 🌳 title",
     
             "challenge_title_first_contribute" : "Well begun is half done.",
-            "challenge_info_first_contribute" : "Make your 1st contribution",
+            "challenge_info_first_contribute" : "Make your 1st contribution<br><br>Reward : 🔰 title and 500 exp",
     
-            "challenge_title_tenthousandth_contribute" : "Rome wasn't built in a day.",
-            "challenge_info_tenthousandth_contribute" : "Make your 1000th contribution",
+            "challenge_title_tenth_contribute" : "Boys, Be Ambitious!",
+            "challenge_info_tenth_contribute" : "Make your 10th contribution<br><br>Reward : 📝 title and 1000 exp",
+
+            "challenge_title_hundredth_contribute" : "Knowledge is power.",
+            "challenge_info_hundredth_contribute" : "Make your 100th contribution<br><br>보상 : 🖊️ title and 3000 exp",
+
+            "challenge_title_thousandth_contribute" : "Rome wasn't built in a day.",
+            "challenge_info_thousandth_contribute" : "Make your 1000th contribution<br><br>Reward : 🏅 title and 10000 exp",
     
+            "challenge_title_first_discussion" : "Truth is generally the best vindication against slander.",
+            "challenge_info_first_discussion" : "Post the 1st discussion thread<br><br>Reward : 💬 title and 500 exp",
+
+            "challenge_title_tenth_discussion" : "I shall either find a way or make one.",
+            "challenge_info_tenth_discussion" : "Post the 10th discussion thread<br><br>Reward : 💡 title and 1000 exp",
+
+            "challenge_title_hundredth_discussion" : "When all think alike, no one thinks very much.",
+            "challenge_info_hundredth_discussion" : "Post the 100th discussion thread<br><br>Reward : 📢 title and 3000 exp",
+
             "challenge_title_thousandth_discussion" : "I think, therefore I am.",
-            "challenge_info_thousandth_discussion" : "Post the 1000th discussion thread"
+            "challenge_info_thousandth_discussion" : "Post the 1000th discussion thread<br><br>Reward : 📜 title and 10000 exp",
+
+            "challenge_title_admin" : "If you want to test a man's character, give him power.",
+            "challenge_info_admin" : "Be the administrator.<br><br>Reward : ✅ title and 10000 exp"
 }

+ 73 - 21
lang/ko-KR.json

@@ -1,5 +1,7 @@
 {
     "language_tag": "ko-KR",
+    "sitemap_manual_create" : "사이트맵 수동 생성",
+    "sitemap_auto_make" : "사이트맵 자동 생성",
     "delete_admin_group": "권한 그룹 삭제",
     "document_name": "문서명",
     "non_login_alert": "비로그인 알림",
@@ -81,7 +83,7 @@
     "markup_enabled": "문법 사용 가능",
     "send": "전송",
     "not_sure": "확실하지 않음",
-    "file_name_error": "파일명에는 알파벳, 한글, 공백, 밑줄 및 빼기 기호만 사용할 수 있습니다.",
+    "file_name_error": "파일명에는 점을 사용할 수 없습니다.",
     "pass": "넘기기",
     "recaptcha_error": "'로봇이 아닙니다'를 통해 reCAPTCHA를 통과하세요.",
     "file_capacity_error": "최대 파일 크기 (MB) : ",
@@ -132,7 +134,7 @@
     "update_error": "자동 업데이트가 지원되지 않습니다.",
     "need_document": "필요한 문서들",
     "sub": "하위",
-    "template": "",
+    "template": "템플릿 문서",
     "user_document_acl": "사용자 문서 ACL",
     "password_confirm": "비밀번호 확인",
     "pinned": "고정",
@@ -208,7 +210,7 @@
     "name": "이름",
     "period": "기간",
     "writer": "작성자",
-    "long_id_error": "ID는 32자보다 짧아야 합니다.",
+    "long_id_error": "ID는 128자보다 짧아야 합니다.",
     "edit_record_error": "사유는 500자를 넘을 수 없습니다.",
     "revert": "복원",
     "discussion_authority": "토론 관리 권한",
@@ -231,7 +233,7 @@
     "file_name": "파일명",
     "close_discussion": "닫힌 토론",
     "language": "언어",
-    "id_char_error": "오직 한글과 알파벳, 숫자만 사용 가능합니다.",
+    "id_char_error": "XSS 문자(부등호, 따옴표)와 .과 :는 사용 불가능합니다.",
     "id_filter_add": "ID 필터 추가",
     "skin": "스킨",
     "user_head": "사용자 <HEAD>",
@@ -383,7 +385,7 @@
     "input_email_error": "입력 값에 문제가 있습니다.",
     "short_page": "짧은 문서 목록",
     "long_page": "긴 문서 목록",
-    "ua_get_off": "가입자 정보 수집 끄기",
+    "ua_get_off": "UA 수집 끄기",
     "ext_api_req_set": "외부 API 필요 설정",
     "oauth": "OAuth",
     "basic_set": "기본 설정",
@@ -393,7 +395,7 @@
     "edit_set": "편집 관련 설정",
     "wiki_shutdown": "위키 엔진 종료",
     "shutdown": "종료",
-    "history_delete_warning": "역사를 지울 경우 복구하기 어려우니 신중하게 결정하세요.",
+    "delete_warning": "지울 경우 복구하기 어려우니 신중하게 결정하세요.",
     "history_reset": "문서 역사 초기화",
     "record_reset": "사용자 편집 기록 초기화",
     "email_setting": "이메일 설정",
@@ -411,15 +413,27 @@
     "hcaptcha": "hCAPTCHA",
     "captcha": "CAPTCHA",
     "make_new_topic": "새 토론 생성",
-    "old_page_warring": "이 문서는 오래되었습니다.",
+    "old_page_warning": "이 문서는 오래되었습니다.",
     "challenge_title_register": "Hello, World!",
-    "challenge_info_register": "가입을 하세요.",
+    "challenge_info_register": "가입을 하세요.<br><br>보상 : 🌳 칭호",
     "challenge_title_first_contribute": "시작이 반이다.",
-    "challenge_info_first_contribute": "첫 기여를 하세요.",
-    "challenge_title_tenthousandth_contribute": "대기만성",
-    "challenge_info_tenthousandth_contribute": "1000번째 기여를 하세요.",
+    "challenge_info_first_contribute": "첫 기여를 하세요.<br><br>보상 : 🔰 칭호와 500 경험치",
+    "challenge_title_tenth_contribute" : "소년이여, 야망을 가져라!",
+    "challenge_info_tenth_contribute" : "10번째 기여를 하세요.<br><br>보상 : 📝 칭호와 1000 경험치",
+    "challenge_title_hundredth_contribute" : "아는 것이 힘이다.",
+    "challenge_info_hundredth_contribute" : "100번째 기여를 하세요.<br><br>보상 : 🖊️ 칭호와 3000 경험치",
+    "challenge_title_thousandth_contribute": "대기만성",
+    "challenge_info_thousandth_contribute": "1000번째 기여를 하세요.<br><br>보상 : 🏅 칭호와 10000 경험치",
+    "challenge_title_first_discussion" : "진실은 보통 모함에 맞서는 최고의 해명이다.",
+    "challenge_info_first_discussion" : "1번째 토론 스레드를 올리세요.<br><br>보상 : 💬 칭호와 500 경험치",
+    "challenge_title_tenth_discussion" : "내가 길을 찾아내거나 직접 길을 만들겠다.",
+    "challenge_info_tenth_discussion" : "10번째 토론 스레드를 올리세요.<br><br>보상 : 💡 칭호와 1000 경험치",
+    "challenge_title_hundredth_discussion" : "모두가 비슷한 생각을 한다는 것은, 아무도 생각하고 있지 않다는 말이다.",
+    "challenge_info_hundredth_discussion" : "100번째 토론 스레드를 올리세요.<br><br>보상 : 📢 칭호와 3000 경험치",
     "challenge_title_thousandth_discussion": "나는 생각한다. 고로 존재한다.",
-    "challenge_info_thousandth_discussion": "1000번째 토론 스레드를 올리세요.",
+    "challenge_info_thousandth_discussion": "1000번째 토론 스레드를 올리세요.<br><br>보상 : 📜 칭호와 10000 경험치",
+    "challenge_title_admin" : "왕후장상의 씨가 어찌 따로 있단 말이냐!",
+    "challenge_info_admin" : "관리자가 되세요.<br><br>보상 : ✅ 칭호와 10000 경험치",
     "challenge": "도전과제",
     "user_title": "칭호",
     "alpha": "알파",
@@ -467,7 +481,7 @@
     "document_move_acl": "문서 이동 ACL",
     "document_delete_acl": "문서 삭제 ACL",
     "document_edit_acl": "문서 편집 ACL",
-    "phrase_old_page_warring": "이전 리비전 문서 방문시 경고문",
+    "phrase_old_page_warning": "이전 리비전 문서 방문시 경고문",
     "toc": "목차",
     "topic_view_acl": "토론 보기 ACL",
     "file_delete": "파일 삭제",
@@ -484,7 +498,7 @@
     "topic_normal": "일반",
     "topic_stop": "중지",
     "topic_close": "닫힘",
-    "turn_off_monaco": "모나코 에디터 끄기",
+    "turn_off_monaco": "모나코 에디터 켜기/끄기",
     "topic_agree": "토론 합의 완료",
     "user_css_warning": "만약 사용하다가 문제가 생기면 여기로 접속하세요.",
     "main_css_warning": "만약 사용하다가 문제가 생기면 이머전시 툴을 사용하세요.",
@@ -521,7 +535,7 @@
     "image_paste": "이미지 붙여넣기 (컨트롤 C + V로)",
     "monaco_editor": "모나코 에디터",
     "document_set": "문서 설정",
-    "move_redirect_make": "리다이렉트 문서 생성 (가능한 경우에만)",
+    "move_redirect_make": "넘겨주기 문서 생성 (가능한 경우에만)",
     "slow_edit_acl": "편집 속도 제한 시간 제외 대상 ACL",
     "edit_bottom_compulsion_acl": "편집 사유 필수 제외 대상 ACL",
     "main_skin_set_default": "기본 스킨 설정 기본값",
@@ -548,7 +562,7 @@
     "hide_user_name": "가입자 이름 숨기기",
     "comment": "댓글",
     "reply": "대댓글",
-    "timeout_error": "실행 시간이 너무 오래 걸립니다. 최대 실행 시간 (초) : ",
+    "timeout_error": "렌더링 시간이 너무 오래 걸립니다. 최대 실행 시간 (초) : ",
     "footnote_render": "각주 렌더링",
     "footnote_number": "각주 번호 출력",
     "only_number": "숫자만",
@@ -558,16 +572,54 @@
     "main_user_name": "메인 사용자명",
     "change_user_name": "메인 사용자명 변경",
     "last_comment_time": "마지막 댓글 시간",
-    "bbs_comment_tool": "BBS 댓글 도구",
-    "bbs_comment_edit": "BBS 댓글 수정",
-    "move_with_redirect": "문서 이동시 리다이렉트 문서 생성",
+    "bbs_comment_tool": "게시판 댓글 도구",
+    "bbs_comment_edit": "게시판 댓글 수정",
+    "move_with_redirect": "문서 이동시 넘겨주기 문서 생성",
     "slow_thread": "토론 올리기 제한 시간",
     "edit_timeout": "렌더링 제한 시간",
     "linux_only": "리눅스 OS 전용",
-    "bbs_post_tool": "BBS 게시글 도구",
+    "bbs_post_tool": "게시판 게시글 도구",
     "position": "위치",
     "category_change_title": "분류 내 문서명 변경 금지",
     "table_scroll": "표에 스크롤 사용",
     "data": "데이터",
-    "volume": "용량"
+    "volume": "용량",
+    "list_view_change": "숫자 리스트의 보기 방식 변경",
+    "view_joke": "농담 매크로 내용 보이기",
+    "math_scroll": "Math 매크로에서 스크롤 사용",
+    "remove_blind_thread": "숨겨진 토론 보이지 않기",
+    "trace": "추적",
+    "view_history": "문서 열람 추적 사용",
+    "start_with_search" : "첫 글자부터 검색",
+    "backup_warning" : "경고. 동일한 이름의 파일이 있는 경우 지워질 수 있습니다.",
+    "level" : "레벨",
+    "challenge_and_level_manage" : "도전과제와 레벨 관리",
+    "display_level_in_user_name" : "사용자 이름에 레벨 표시",
+    "ua" : "UA",
+    "day" : "일",
+    "ua_expiration_date" : "UA 만료 기한",
+    "backup" : "백업",
+    "document_content_max_length" : "문서 최대 길이",
+    "bbs_record" : "게시판 작성글 목록",
+    "bbs_comment_record" : "게시판 작성댓글 목록",
+    "load_temp_save" : "임시 저장",
+    "load_temp_save_load" : "임시 저장 불러오기",
+    "bbs_comment_delete" : "게시판 댓글 삭제",
+    "bbs_post_pinned" : "게시판 게시글 고정",
+    "bbs_post_delete" : "게시판 게시글 삭제",
+    "outer_link_filter_list" : "외부 링크 자동 이미지 목록",
+    "html_or_link" : "HTML 혹은 링크",
+    "template_document_list" : "템플릿 문서 목록",
+    "no_link_document_list" : "링크가 없는 문서 목록",
+    "authority_use_list_off" : "권한 사용 목록 끄기",
+    "authority_use_list_expiration_date" : "권한 사용 목록 만료 기한",
+    "bbs_help" : "게시판 편집기 도움말",
+    "bbs_comment_help" : "게시판 댓글 편집기 도움말",
+    "outdated_doc_warning" : "오래된 문서 경고",
+    "redirect" : "넘겨주기",
+    "new_doc" : "새 문서",
+    "table" : "표",
+    "table_transparent" : "표 투명화",
+    "recaptcha_pass_acl" : "캡차 통과 ACL",
+    "recaptcha_one_check_five_pass_acl" : "캡차 1회 통과시 5회 미시행 ACL"
 }

+ 1 - 0
requirements-optional.txt

@@ -0,0 +1 @@
+mysqlclient

+ 3 - 5
requirements.txt

@@ -4,10 +4,8 @@ flask
 waitress
 
 requests
-
-pymysql
-whoosh
-
 diff-match-patch
 
-pysha3; python_version < "3.6"
+pillow
+
+pymysql

+ 12 - 8
route/__init__.py

@@ -1,7 +1,8 @@
 from route.api_func_lang import api_func_lang
 from route.api_func_sha224 import api_func_sha224
 from route.api_image_view import api_image_view
-from route.api_raw import api_raw
+from route.api_w_raw import api_w_raw
+from route.api_w_render import api_w_render
 from route.api_recent_change import api_recent_change
 from route.api_recent_discuss import api_recent_discuss
 from route.api_search import api_search
@@ -17,9 +18,13 @@ from route.api_bbs_w_comment import api_bbs_w_comment
 from route.api_bbs_w_comment_one import api_bbs_w_comment_one
 
 from route.bbs_w_edit import bbs_w_edit
-from route.bbs_main import bbs_main
 from route.bbs_make import bbs_make
+# from route.bbs_w_hide import bbs_w_hide
+from route.bbs_w_pinned import bbs_w_pinned
+from route.bbs_w_delete import bbs_w_delete
 from route.bbs_w import bbs_w
+from route.bbs_delete import bbs_delete
+# from route.bbs_hide import bbs_hide
 from route.bbs_w_post import bbs_w_post
 from route.bbs_w_set import bbs_w_set
 from route.bbs_w_comment_tool import bbs_w_comment_tool
@@ -34,12 +39,9 @@ from route.edit_move import edit_move
 from route.edit_revert import edit_revert
 from route.edit_upload import edit_upload
 
-from route.filter_document import filter_document
-from route.filter_document_add import filter_document_add
-from route.filter_document_delete import filter_document_delete
-from route.filter_inter_wiki import filter_inter_wiki
-from route.filter_inter_wiki_add import filter_inter_wiki_add
-from route.filter_inter_wiki_delete import filter_inter_wiki_delete
+from route.filter_all import filter_all
+from route.filter_all_add import filter_all_add
+from route.filter_all_delete import filter_all_delete
 
 from route.give_admin_groups import give_admin_groups_2
 from route.give_auth import give_auth
@@ -54,6 +56,7 @@ from route.list_admin_group import list_admin_group_2
 from route.list_image_file import list_image_file
 from route.list_long_page import list_long_page
 from route.list_old_page import list_old_page
+from route.list_no_link import list_no_link
 from route.list_please import list_please
 from route.list_title_index import list_title_index
 from route.list_user import list_user
@@ -90,6 +93,7 @@ from route.main_setting_main_logo import main_setting_main_logo
 from route.main_setting_phrase import main_setting_phrase
 from route.main_setting_robot import main_setting_robot
 from route.main_setting_sitemap import main_setting_sitemap
+from route.main_setting_sitemap_set import main_setting_sitemap_set
 from route.main_setting_skin_set import main_setting_skin_set
 from route.main_setting_top_menu import main_setting_top_menu
 

+ 1 - 1
route/api_recent_change.py

@@ -9,7 +9,7 @@ def api_recent_change(num = 10):
 
         data_list = []
 
-        curs.execute(db_change('select id, title from rc where type = "" order by date desc limit ?'), [num])
+        curs.execute(db_change('select id, title from rc where type = "normal" order by date desc limit ?'), [num])
         for for_a in curs.fetchall():
             curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where id = ? and title = ?'), for_a)
             db_data = curs.fetchall()

+ 1 - 0
route/api_search.py

@@ -7,6 +7,7 @@ def api_search(name = 'Test', num = 10, page = 1):
         num = 1 if num > 1000 else num
         page = (page * (num - 1)) if page * num > 0 else 0
 
+        # 개편 예정
         curs.execute(db_change('select data from other where name = "count_all_title"'))
         if int(curs.fetchall()[0][0]) < 30000:
             curs.execute(db_change("" + \

+ 41 - 22
route/api_topic.py

@@ -1,29 +1,40 @@
 from .tool.func import *
 
-def api_topic_thread_make(user_id, date, data, code, color = '', blind = '', add_style = ''):
-    if blind != '':
+def api_topic_thread_make(user_id, date, data, code, color = '', blind = '', add_style = '', admin_check = 1, topic_num = ''):
+    if blind == 'O':
         if data == '':
             color_b = 'opennamu_comment_blind'
         else:
             color_b = 'opennamu_comment_blind_admin'
+
+        class_b = 'opennamu_comment_blind_js'
     else:
         color_b = 'opennamu_comment_blind_not'
+        class_b = ''
+
+    admin_check_box = ''
+    if admin_check == 1 and topic_num != '':
+        admin_check_box = '<input type="checkbox" class="opennamu_blind_button" id="opennamu_blind_' + topic_num + '_' + code + '">'
 
     return '''
-        <table class="opennamu_comment" style="''' + add_style + '''">
-            <tr>
-                <td class="opennamu_comment_color_''' + color + '''">
-                    <a href="#thread_shortcut" id="''' + code + '''">#''' + code + '''</a>
-                    ''' + user_id + '''
-                    <span style="float: right;">''' + date + '''</span>
-                </td>
-            </tr>
-            <tr>
-                <td class="''' + color_b + '''" id="opennamu_comment_data_main">
-                    ''' + data + '''
-                </td>
-            </tr>
-        </table>
+        <span class="''' + class_b + '''">
+            <table class="opennamu_comment" style="''' + add_style + '''">
+                <tr>
+                    <td class="opennamu_comment_color_''' + color + '''">
+                        ''' + admin_check_box + '''
+                        <a href="#thread_shortcut" id="''' + code + '''">#''' + code + '''</a>
+                        ''' + user_id + '''
+                        <span style="float: right;">''' + date + '''</span>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="''' + color_b + '''" id="opennamu_comment_data_main">
+                        ''' + data + '''
+                    </td>
+                </tr>
+            </table>
+            <hr class="main_hr">
+        </span>
     '''
 
 def api_topic_thread_pre_render(curs, data, num, ip, topic_num = '', name = '', sub = '', do_type = 'thread'):
@@ -177,11 +188,12 @@ def api_topic(topic_num = 1, tool = 'normal', num = '', render = ''):
                         for for_a in data_a['data']:
                             if tool == 'top':
                                 color = 'red'
+                            elif for_a["blind"] == '1':
+                                color = 'blue'
+                            elif data_a['data_main']["ip_first"] == for_a["ip"]:
+                                color = 'green'
                             else:
-                                if data_a['data_main']["ip_first"] == for_a["ip"]:
-                                    color = 'green'
-                                else:
-                                    color = 'default'
+                                color = 'default'
 
                             data_r += api_topic_thread_make(
                                 for_a["ip_pas"],
@@ -190,9 +202,16 @@ def api_topic(topic_num = 1, tool = 'normal', num = '', render = ''):
                                 for_a["id"],
                                 color = color,
                                 blind = for_a["blind"],
-                                add_style = ''
+                                add_style = '',
+                                admin_check = admin if tool == 'normal' else 0,
+                                topic_num = topic_num
                             )
-                            data_r += '<hr class="main_hr">'
+
+                    if admin == 1 and tool == 'normal':
+                        data_r += '''
+                            <a href="javascript:opennamu_thread_blind();">(''' + load_lang('hide') + ''' | ''' + load_lang('hide_release') + ''')</a>
+                            <hr class="main_hr">
+                        '''
 
                     return flask.jsonify({ "data" : data_r })
             else:

+ 22 - 1
route/api_user_info.py

@@ -24,7 +24,7 @@ def api_user_info(name = ''):
                 if db_data:
                     if db_data[0][0] != 'user':
                         curs.execute(db_change("select name from alist where name = ?"), [db_data[0][0]])
-                        if curs.fetchall():
+                        if curs.fetchall() or db_data[0][0] in get_default_admin_group():
                             data_result[user_name]['auth'] = db_data[0][0]
                         else:
                             data_result[user_name]['auth'] = '1'
@@ -32,6 +32,27 @@ def api_user_info(name = ''):
                         data_result[user_name]['auth'] = '1'
                 else:
                     data_result[user_name]['auth'] = '0'
+
+                curs.execute(db_change("select data from user_set where id = ? and name = 'auth_date'"), [user_name])
+                db_data = curs.fetchall()
+                if db_data:
+                    data_result[user_name]['auth_date'] = db_data[0][0]
+                else:
+                    data_result[user_name]['auth_date'] = '0'
+
+                curs.execute(db_change("select data from user_set where id = ? and name = 'level'"), [user_name])
+                db_data = curs.fetchall()
+                if db_data:
+                    data_result[user_name]['level'] = db_data[0][0]
+                else:
+                    data_result[user_name]['level'] = '0'
+
+                curs.execute(db_change("select data from user_set where id = ? and name = 'experience'"), [user_name])
+                db_data = curs.fetchall()
+                if db_data:
+                    data_result[user_name]['exp'] = db_data[0][0]
+                else:
+                    data_result[user_name]['exp'] = '0'
                     
                 # ban part
                 if ban_check(name) == 0:

+ 1 - 1
route/api_w.py

@@ -80,7 +80,7 @@ def api_w(name = 'Test', tool = '', rev = ''):
         else:
             if tool == '' or tool == 'view':
                 if acl_check(name, 'render') != 1:
-                    if check_int(rev) == '':
+                    if number_check(rev) == '':
                         curs.execute(db_change("select data from data where title = ?"), [name])
                     else:
                         curs.execute(db_change("select data from history where title = ? and id = ?"), [name, rev])

+ 13 - 9
route/api_raw.py → route/api_w_raw.py

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

+ 6 - 0
route/api_w_render.py

@@ -0,0 +1,6 @@
+from .tool.func import *
+
+def api_w_render(name = '', tool = ''):
+    data_org = flask.request.form.get('data', '')
+    
+    pass

+ 36 - 0
route/bbs_delete.py

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

+ 0 - 42
route/bbs_main.py

@@ -1,42 +0,0 @@
-from .tool.func import *
-
-def bbs_main():
-    with get_db_connect() as conn:
-        curs = conn.cursor()
-
-        curs.execute(db_change('select set_data, set_id from bbs_set where set_name = "bbs_name"'))
-        db_data = curs.fetchall()
-        
-        data = ''
-
-        if db_data:
-            data += '<ul class="opennamu_ul">'
-            for for_a in db_data:
-                curs.execute(db_change('select set_data from bbs_set where set_name = "bbs_type" and set_id = ?'), [for_a[1]])
-                db_data_2 = curs.fetchall()
-                bbs_type = db_data_2[0][0] if db_data_2 else 'comment'
-
-                if bbs_type == 'thread':
-                    bbs_type = load_lang('thread_base')
-                else:
-                    bbs_type = load_lang('comment_base')
-                
-                curs.execute(db_change('select set_data from bbs_data where set_id = ? and set_name = "date" order by set_code + 0 desc limit 1'), [for_a[1]])
-                db_data_2 = curs.fetchall()
-                last_date = ('(' + db_data_2[0][0] + ')') if db_data_2 else ''
-
-                data += '<li><a href="/bbs/w/' + for_a[1] + '">' + html.escape(for_a[0]) + ' (' + bbs_type + ') ' + last_date + '</a></li>'
-                # data += '<li></li>'
-
-            data += '</ul>'
-
-        if admin_check() == 1:
-            menu = [['bbs/make', load_lang('add')]]
-        else:
-            menu = []
-
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('bbs_main'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = data,
-            menu = [['other', load_lang('return')]] + menu
-        ))

+ 181 - 55
route/bbs_w.py

@@ -1,68 +1,194 @@
 from .tool.func import *
 
-def bbs_w(bbs_num = ''):
+def bbs_w(bbs_num = '', tool = 'bbs', page = 1, name = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
-
-        curs.execute(db_change('select set_data from bbs_set where set_id = ? and set_name = "bbs_name"'), [bbs_num])
-        db_data = curs.fetchall()
-        if not db_data:
-            return redirect('/bbs/main')
         
-        bbs_name = db_data[0][0]
-        bbs_num_str = str(bbs_num)
-
         data = ''
-        data += '''
-            <table id="main_table_set">
-                <tr id="main_table_top_tr">
-                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                    <td id="main_table_width">''' + load_lang('time') + '''</td>
-                    <td id="main_table_width">''' + load_lang('last_comment_time') + '''</td>
-                </tr>
-        '''
+        title_name = ''
+        sub = ''
+        bbs_name_dict = {}
+
+        admin_auth = admin_check()
+
+        if tool == 'bbs':
+            curs.execute(db_change('select set_data from bbs_set where set_id = ? and set_name = "bbs_name"'), [bbs_num])
+            db_data = curs.fetchall()
+            if not db_data:
+                return redirect('/bbs/main')
         
-        temp_id = ''
-        temp_dict = {}
-
-        curs.execute(db_change('select set_name, set_data, set_code, set_id from bbs_data where set_id like ? order by set_code + 0 desc'), [bbs_num])
-        db_data = curs.fetchall()
-        db_data = list(db_data) if db_data else []
-
-        for for_a in db_data + [['', '', '']]:
-            if temp_id != for_a[2]:
-                if temp_id != '':
-                    curs.execute(db_change('select count(*) from bbs_data where set_name = "comment_date" and (set_id = ? or set_id like ?) order by set_code + 0 desc'), [bbs_num_str + '-' + temp_dict['code'], bbs_num_str + '-' + temp_dict['code'] + '-%'])
-                    db_data = curs.fetchall()
-                    comment_count = str(db_data[0][0]) if db_data else '0'
-
-                    curs.execute(db_change('select set_data from bbs_data where set_name = "comment_date" and (set_id = ? or set_id like ?) order by set_data desc limit 1'), [bbs_num_str + '-' + temp_dict['code'], bbs_num_str + '-' + temp_dict['code'] + '-%'])
-                    db_data = curs.fetchall()
-                    last_comment_date = db_data[0][0] if db_data else '0'
-
-                    data += '''
-                        <tr>
-                            <td>''' + ip_pas(temp_dict['user_id']) + '''</td>
-                            <td>''' + temp_dict['date'] + '''</td>
-                            <td>''' + last_comment_date + '''</td>
-                        </tr>
-                        <tr>
-                            <td colspan="3">
-                                <a href="/bbs/w/''' + bbs_num_str + '/' + temp_dict['code'] + '">' + html.escape(temp_dict['title']) + '''</a> 
-                                (''' + comment_count + ''') 
-                            </td>
-                        </tr>
-                    '''
-
-                temp_id = for_a[2]
-                temp_dict['code'] = for_a[2]
-
-            temp_dict[for_a[0]] = for_a[1]
+            bbs_name = db_data[0][0]
+            bbs_num_str = str(bbs_num)
+
+            title_name = bbs_name
+            sub = '(' + load_lang('bbs') + ')'
+            menu = [['bbs/main', load_lang('return')], ['bbs/edit/' + bbs_num_str, load_lang('add')], ['bbs/set/' + bbs_num_str, load_lang('bbs_set')]]
+        elif tool == 'record':
+            curs.execute(db_change('select set_data, set_id from bbs_set where set_name = "bbs_name"'))
+            db_data = curs.fetchall()
+            bbs_name_dict = { for_a[1] : for_a[0] for for_a in db_data } if db_data else {}
+            
+            title_name = name
+            sub = '(' + load_lang('bbs_record') + ')'
+            menu = [['user/' + url_pas(name), load_lang('user_tool')]]
+        elif tool == 'comment_record':
+            curs.execute(db_change('select set_data, set_id from bbs_set where set_name = "bbs_name"'))
+            db_data = curs.fetchall()
+            bbs_name_dict = { for_a[1] : for_a[0] for for_a in db_data } if db_data else {}
+            
+            title_name = name
+            sub = '(' + load_lang('bbs_comment_record') + ')'
+            menu = [['user/' + url_pas(name), load_lang('user_tool')]]
+        else:
+            curs.execute(db_change('select set_data, set_id from bbs_set where set_name = "bbs_name"'))
+            db_data = curs.fetchall()
+            if db_data:
+                data += '<ul class="opennamu_ul">'
+                for for_a in db_data:
+                    bbs_name_dict[for_a[1]] = for_a[0]
+
+                    curs.execute(db_change('select set_data from bbs_set where set_name = "bbs_type" and set_id = ?'), [for_a[1]])
+                    db_data_2 = curs.fetchall()
+                    bbs_type = db_data_2[0][0] if db_data_2 else 'comment'
+
+                    if bbs_type == 'thread':
+                        bbs_type = load_lang('thread_base')
+                    else:
+                        bbs_type = load_lang('comment_base')
+                    
+                    curs.execute(db_change('select set_data from bbs_data where set_id = ? and set_name = "date" order by set_code + 0 desc limit 1'), [for_a[1]])
+                    db_data_2 = curs.fetchall()
+                    last_date = ('(' + db_data_2[0][0] + ')') if db_data_2 else ''
+
+                    data += '<li>'
+                    data += '<a href="/bbs/w/' + for_a[1] + '">' + html.escape(for_a[0]) + '</a> (' + bbs_type + ') ' + last_date
+                    data += '</li>'
+
+                data += '</ul>'
+            
+            data += '<hr class="main_hr">'
 
+            title_name = load_lang('bbs_main')
+            menu = [['other', load_lang('other_tool')]] + ([['bbs/make', load_lang('add')]] if admin_auth == 1 else [])
+
+        if tool == 'comment_record':
+            data += '''
+                <table id="main_table_set">
+                    <tr id="main_table_top_tr">
+                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                        <td id="main_table_width">''' + load_lang('time') + '''</td>
+                        <td id="main_table_width">''' + load_lang('comment') + '''</td>
+                    </tr>
+            '''
+        else:
+            data += '''
+                <table id="main_table_set">
+                    <tr id="main_table_top_tr">
+                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                        <td id="main_table_width">''' + load_lang('time') + '''</td>
+                        <td id="main_table_width">''' + load_lang('last_comment_time') + '''</td>
+                    </tr>
+            '''
+
+        if tool == 'bbs':
+            curs.execute(db_change('select set_code, set_id, set_name from bbs_data where set_name = "pinned" and set_id like ? order by set_data desc'), [bbs_num])
+            db_data = curs.fetchall()
+            db_data = list(db_data) if db_data else []
+            
+            curs.execute(db_change('select set_code, set_id from bbs_data where set_name = "title" and set_id like ? order by set_code + 0 desc'), [bbs_num])
+            db_data_2 = curs.fetchall()
+            db_data += list(db_data_2) if db_data_2 else []
+        elif tool == 'record':
+            try:
+                curs.execute(db_change('select set_code, set_id, set_data from bbs_data where set_name = "date" and (set_code, set_id) in (select set_code, set_id from bbs_data where set_name = "user_id" and set_data = ?) as sub_query order by set_data desc limit 50'), [name])
+            except:
+                curs.execute(db_change('select set_code, set_id from bbs_data where set_name = "user_id" and set_data = ? order by set_data desc limit 50'), [name])
+
+            db_data = curs.fetchall()
+        elif tool == 'comment_record':
+            try:
+                curs.execute(db_change('select set_code, set_id, set_data from bbs_data where set_name = "comment_date" and (set_code, set_id) in (select set_code, set_id from bbs_data where set_name = "comment_user_id" and set_data = ?) as sub_query order by set_data desc limit 50'), [name])
+            except:
+                curs.execute(db_change('select set_code, set_id from bbs_data where set_name = "comment_user_id" and set_data = ? order by set_data desc limit 50'), [name])
+            
+            db_data = curs.fetchall()
+        else:
+            curs.execute(db_change('select set_code, set_id, set_data from bbs_data where set_name = "date" order by set_data desc limit 50'))
+            db_data = curs.fetchall()
+
+        for for_b in db_data:
+            curs.execute(db_change('select set_name, set_data, set_code, set_id from bbs_data where set_code = ? and set_id = ?'), [for_b[0], for_b[1]])
+            db_data = curs.fetchall()
+            db_data = list(db_data) if db_data else []
+
+            temp_dict = { for_a[0] : for_a[1] for for_a in db_data }
+
+            bbs_name_select = ''
+            bbs_split = for_b[1].split('-')
+            if tool == 'comment_record':
+                bbs_name_select = '(' + bbs_name_dict[bbs_split[0]] + ')'
+            elif tool != 'bbs':
+                bbs_name_select = '(' + bbs_name_dict[for_b[1]] + ')'
+
+            if tool == 'bbs':
+                notice = 1 if len(for_b) > 2 else 0
+            else:
+                notice = 0
+
+            if tool == 'comment_record':
+                curs.execute(db_change('select set_name, set_data, set_code, set_id from bbs_data where set_name = "title" and set_code = ? and set_id = ?'), [bbs_split[1], bbs_split[0]])
+                db_data = curs.fetchall()
+                db_data = list(db_data) if db_data else []
+                for for_a in db_data:
+                    temp_dict[for_a[0]] = for_a[1]
+            
+                comment_link = ''
+                if len(bbs_split) > 2:
+                    comment_link = '-'.join(bbs_split[2:])
+                    
+                comment_link += ('-' + for_b[0] if comment_link != '' else for_b[0])
+                    
+                data += '''
+                    <tr>
+                        <td>''' + ip_pas(temp_dict['comment_user_id']) + '''</td>
+                        <td>''' + temp_dict['comment_date'] + '''</td>
+                        <td>''' + ('#' + comment_link) + '''</td>
+                    </tr>
+                    <tr>
+                        <td colspan="3">
+                            <a href="/bbs/w/''' + bbs_split[0] + '/' + bbs_split[1] + '#' + comment_link + '">' + html.escape(temp_dict['title']) + '''</a> 
+                            ''' + bbs_name_select + '''
+                        </td>
+                    </tr>
+                '''
+            else:
+                curs.execute(db_change('select count(*) from bbs_data where set_name = "comment_date" and (set_id = ? or set_id like ?) order by set_code + 0 desc'), [for_b[1] + '-' + for_b[0], for_b[1] + '-' + for_b[0] + '-%'])
+                db_data = curs.fetchall()
+                comment_count = str(db_data[0][0]) if db_data else '0'
+
+                curs.execute(db_change('select set_data from bbs_data where set_name = "comment_date" and (set_id = ? or set_id like ?) order by set_data desc limit 1'), [for_b[1] + '-' + for_b[0], for_b[1] + '-' + for_b[0] + '-%'])
+                db_data = curs.fetchall()
+                last_comment_date = db_data[0][0] if db_data else '0'
+            
+                data += '''
+                    <tr class="''' + ('opennamu_comment_color_red' if notice == 1 else '') + '''">
+                        <td>''' + ip_pas(temp_dict['user_id']) + '''</td>
+                        <td>''' + temp_dict['date'] + '''</td>
+                        <td>''' + last_comment_date + '''</td>
+                    </tr>
+                    <tr>
+                        <td colspan="3">
+                            <a href="/bbs/w/''' + for_b[1] + '/' + for_b[0] + '">' + html.escape(temp_dict['title']) + '''</a> 
+                            (''' + comment_count + ''') 
+                            ''' + bbs_name_select + '''
+                        </td>
+                    </tr>
+                '''
+                
         data += '</table>'
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [bbs_name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('bbs') + ')', 0])],
+            imp = [title_name, wiki_set(), wiki_custom(), wiki_css([sub, 0])],
             data = data,
-            menu = [['bbs/main', load_lang('return')], ['bbs/edit/' + bbs_num_str, load_lang('add')], ['bbs/set/' + bbs_num_str, load_lang('bbs_set')]]
+            menu = menu
         ))

+ 8 - 1
route/bbs_w_comment_tool.py

@@ -14,10 +14,17 @@ def bbs_w_comment_tool(bbs_num = '', post_num = '', comment_num = ''):
             <ul class="opennamu_ul">
                 <li><a href="/bbs/raw/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '/' + url_pas(comment_num) + '">' + load_lang('raw') + '''</a></li>
                 <li><a href="/bbs/edit/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '/' + url_pas(comment_num) + '">' + load_lang('edit') + '''</a></li>
-                <!-- <li><a href="/bbs/w/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '/blind">' + load_lang('hide') + '''</a></li> -->
             </ul>
         '''
 
+        if admin_check() == 1:
+            data += '''
+                <h3>''' + load_lang('owner') + '''</h2>
+                <ul class="opennamu_ul">
+                    <li><a href="/bbs/delete/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '/' + url_pas(comment_num) + '">' + load_lang('delete') + '''</a></li>
+                </ul>
+            '''
+
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('bbs_comment_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = data,

+ 68 - 0
route/bbs_w_delete.py

@@ -0,0 +1,68 @@
+from .tool.func import *
+
+from .api_bbs_w_post import api_bbs_w_post
+
+def bbs_w_delete(bbs_num = '', post_num = '', comment_num = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        curs.execute(db_change('select set_data from bbs_set where set_id = ? and set_name = "bbs_name"'), [bbs_num])
+        db_data = curs.fetchall()
+        if not db_data:
+            return redirect('/bbs/main')
+
+        bbs_name = db_data[0][0]
+        
+        bbs_num_str = str(bbs_num)
+        post_num_str = str(post_num)
+
+        if admin_check() != 1:
+            return redirect('/bbs/w/' + bbs_num_str)
+        
+        temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
+        if not 'user_id' in temp_dict:
+            return redirect('/bbs/main')
+        
+        if flask.request.method == 'POST':
+            if comment_num == '':
+                curs.execute(db_change('delete from bbs_data where set_code = ? and set_id = ?'), [post_num_str, bbs_num_str])
+                curs.execute(db_change('delete from bbs_set where set_code = ? and set_id = ?'), [post_num_str, bbs_num_str])
+                curs.execute(db_change('delete from bbs_data where set_id = ? or set_id like ?'), [bbs_num_str + '-' + post_num_str, bbs_num_str + '-' + post_num_str + '-%'])
+                
+                return redirect('/bbs/w/' + bbs_num_str)
+            else:
+                comment_num_split = comment_num.split('-')
+                
+                set_id = bbs_num_str + '-' + post_num_str
+                set_id_sub = '-'.join(comment_num_split[:-1])
+                if set_id_sub != '':
+                    set_id += '-' + set_id_sub
+
+                set_code = comment_num_split[len(comment_num_split) - 1]
+
+                print(set_id, set_code)
+
+                curs.execute(db_change("update bbs_data set set_data = '' where set_code = ? and set_id = ?"), [set_code, set_id])
+                
+                return redirect('/bbs/w/' + bbs_num_str + '/' + post_num_str)
+        else:
+            sub = '(' + bbs_name + ')'
+            sub += ' (' + post_num_str + ')'
+            
+            name = load_lang('bbs_comment_delete')
+            if comment_num == '':
+                name = load_lang('bbs_post_delete')
+            else:
+                sub += ' (' + comment_num + ')'
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [name, wiki_set(), wiki_custom(), wiki_css([sub, 0])],
+                data = render_simple_set('''
+                    <form method="post">
+                        <span>''' + load_lang('delete_warning') + '''</span>
+                        <hr class="main_hr">
+                        <button type="submit">''' + load_lang('delete') + '''</button>
+                    </form>
+                '''),
+                menu = [['bbs/w/' + bbs_num_str + '/' + post_num_str, load_lang('return')]]
+            ))

+ 19 - 57
route/bbs_w_edit.py

@@ -2,9 +2,10 @@ from .tool.func import *
 
 from .api_bbs_w_post import api_bbs_w_post
 from .api_bbs_w_comment_one import api_bbs_w_comment_one
+
 from .edit import edit_editor
 
-def bbs_w_edit(bbs_num = '', post_num = '', comment_num = '', do_type = ''):
+def bbs_w_edit(bbs_num = '', post_num = '', comment_num = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -37,7 +38,7 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = '', do_type = ''):
         
         i_list = ['post_view_acl', 'post_comment_acl']
 
-        if flask.request.method == 'POST' and do_type != 'preview':
+        if flask.request.method == 'POST':
             if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
                 return re_error('/error/13')
             else:
@@ -86,59 +87,28 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = '', do_type = ''):
         else:
             option_display = ''
 
-            d_list = ['' for _ in range(0, len(i_list))]
-            if do_type == 'preview':
-                title = flask.request.form.get('title', '')
-                data = flask.request.form.get('content', '')
-                data = data.replace('\r', '')
-                data_preview = render_set(
-                    doc_data = data,
-                    data_type = 'thread',
-                    data_in = 'bbs'
-                ) + '<hr>'
-                for for_a in range(0, len(i_list)):
-                    d_list[for_a] = flask.request.form.get(i_list[for_a], 'normal')
+            if comment_num != '':
+                temp_dict = json.loads(api_bbs_w_comment_one(bbs_num_str + '-' + post_num_str + '-' + comment_num).data)
+
+                title = ''
+                data = temp_dict['comment']
+                option_display = 'display: none;'
+            elif post_num == '':
+                title = ''
+                data = ''
             else:
-                if comment_num != '':
-                    temp_dict = json.loads(api_bbs_w_comment_one(bbs_num_str + '-' + post_num_str + '-' + comment_num).data)
-
-                    title = ''
-                    data = temp_dict['comment']
-                    data_preview = ''
-                    option_display = 'display: none;'
-                elif post_num == '':
-                    title = ''
-                    data = ''
-                    data_preview = ''
-                else:
-                    temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
-
-                    title = temp_dict['title']
-                    data = temp_dict['data']
-                    data_preview = ''
+                temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
+
+                title = temp_dict['title']
+                data = temp_dict['data']
 
             acl_div = ['' for _ in range(0, len(i_list))]
             acl_list = get_acl_list()
             for for_a in range(0, len(i_list)):
                 for data_list in acl_list:
-                    if data_list == d_list[for_a]:
-                        check = 'selected="selected"'
-                    else:
-                        check = ''
-
-                    acl_div[for_a] += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
-            
-            if comment_num != '':
-                form_action = 'formaction="/bbs/edit/' + bbs_num_str + '/' + post_num_str + '/' + url_pas(comment_num) + '"'
-                form_action_preview = 'formaction="/bbs/edit/preview/' + bbs_num_str + '/' + post_num_str + '/' + url_pas(comment_num) + '"'
-            elif post_num == '':
-                form_action = 'formaction="/bbs/edit/' + bbs_num_str + '"'
-                form_action_preview = 'formaction="/bbs/edit/preview/' + bbs_num_str + '"'
-            else:
-                form_action = 'formaction="/bbs/edit/' + bbs_num_str + '/' + post_num_str + '"'
-                form_action_preview = 'formaction="/bbs/edit/preview/' + bbs_num_str + '/' + post_num_str + '"'
+                    acl_div[for_a] += '<option value="' + data_list + '">' + (data_list if data_list != '' else 'normal') + '</option>'
     
-            editor_top_text = '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
+            editor_top_text = '<a href="/filter/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
 
             if editor_top_text != '':
                 editor_top_text += '<hr class="main_hr">'
@@ -158,15 +128,7 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = '', do_type = ''):
                         <hr style="''' + option_display + '''" class="main_hr">
 
                         ''' + edit_editor(curs, ip, data, 'bbs') + '''
-                        <hr class="main_hr">
-                        
-                        ''' + captcha_get() + ip_warning() + '''
-                        
-                        <button id="opennamu_save_button" type="submit" ''' + form_action + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('save') + '''</button>
-                        <button id="opennamu_preview_button" type="submit" ''' + form_action_preview + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
-                    
-                        <hr class="main_hr">
-                        <div id="opennamu_preview_area">''' + data_preview + '''</div>
+
                         <!--
                         <div style="''' + option_display + '''">
                             ''' + render_simple_set('''

+ 31 - 0
route/bbs_w_hide.py

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

+ 46 - 0
route/bbs_w_pinned.py

@@ -0,0 +1,46 @@
+from .tool.func import *
+
+from .api_bbs_w_post import api_bbs_w_post
+
+def bbs_w_pinned(bbs_num = '', post_num = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        curs.execute(db_change('select set_data from bbs_set where set_id = ? and set_name = "bbs_name"'), [bbs_num])
+        db_data = curs.fetchall()
+        if not db_data:
+            return redirect('/bbs/main')
+
+        bbs_name = db_data[0][0]
+        
+        bbs_num_str = str(bbs_num)
+        post_num_str = str(post_num)
+
+        if admin_check() != 1:
+            return redirect('/bbs/w/' + bbs_num_str)
+        
+        temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
+        if not 'user_id' in temp_dict:
+            return redirect('/bbs/main')
+        
+        if flask.request.method == 'POST':
+            curs.execute(db_change('select set_data from bbs_data where set_code = ? and set_id = ? and set_name = "pinned"'), [post_num_str, bbs_num_str])
+            if not curs.fetchall():
+                curs.execute(db_change("insert into bbs_data (set_name, set_code, set_id, set_data) values ('pinned', ?, ?, ?)"), [post_num_str, bbs_num_str, get_time()])
+            else:
+                curs.execute(db_change('delete from bbs_data where set_code = ? and set_id = ? and set_name = "pinned"'), [post_num_str, bbs_num_str])
+            
+            return redirect('/bbs/w/' + bbs_num_str)
+        else:
+            curs.execute(db_change('select set_data from bbs_data where set_code = ? and set_id = ? and set_name = "pinned"'), [post_num_str, bbs_num_str])
+            pinned = load_lang('pinned') if not curs.fetchall() else load_lang('pinned_release')
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('bbs_post_pinned'), wiki_set(), wiki_custom(), wiki_css(['(' + bbs_name + ')' + ' (' + post_num_str + ')', 0])],
+                data = render_simple_set('''
+                    <form method="post">
+                        <button type="submit">''' + pinned + '''</button>
+                    </form>
+                '''),
+                menu = [['bbs/w/' + bbs_num_str + '/' + post_num_str, load_lang('return')]]
+            ))

+ 36 - 81
route/bbs_w_post.py

@@ -19,37 +19,37 @@ def bbs_w_post_comment(user_id, sub_code, comment_num, bbs_num_str, post_num_str
     comment_add_count += comment_count
 
     for temp_dict in thread_data:
-        color = 'default'
-        if user_id == temp_dict['comment_user_id']:
-            color = 'green'
-
-        sub_code_check = re.sub(r'^[0-9]+-[0-9]+-', '', sub_code + '-' + temp_dict['code'])
-        margin_count = sub_code_check.count('-')
-
-        date = ''
-        date += '<a href="javascript:opennamu_change_comment(\'' + sub_code_check + '\');">(' + load_lang('comment') + ')</a> '
-        date += '<a href="/bbs/tool/' + bbs_num_str + '/' + post_num_str + '/' + sub_code_check + '">(' + load_lang('tool') + ')</a> '
-        date += temp_dict['comment_date']
-
-        comment_data += '<span style="padding-left: 20px;"></span>' * margin_count
-        comment_data += api_topic_thread_make(
-            ip_pas(temp_dict['comment_user_id']),
-            date,
-            render_set(
-                doc_data = temp_dict['comment'],
-                data_in = 'bbs_comment_' + sub_code_check
-            ),
-            sub_code_check,
-            color = color,
-            add_style = 'width: calc(100% - ' + str(margin_count * 20) + 'px);'
-        )
-
-        comment_default = ''
-        if comment_num == sub_code_check:
-            comment_default = 'selected'
-
-        comment_select += '<option value="' + sub_code_check + '" ' + comment_default + '>' + sub_code_check + '</option>'
-        comment_data += '<hr class="main_hr">'
+        if temp_dict['comment_user_id'] != '':
+            color = 'default'
+            if user_id == temp_dict['comment_user_id']:
+                color = 'green'
+
+            sub_code_check = re.sub(r'^[0-9]+-[0-9]+-', '', sub_code + '-' + temp_dict['code'])
+            margin_count = sub_code_check.count('-')
+
+            date = ''
+            date += '<a href="javascript:opennamu_change_comment(\'' + sub_code_check + '\');">(' + load_lang('comment') + ')</a> '
+            date += '<a href="/bbs/tool/' + bbs_num_str + '/' + post_num_str + '/' + sub_code_check + '">(' + load_lang('tool') + ')</a> '
+            date += temp_dict['comment_date']
+
+            comment_data += '<span style="padding-left: 20px;"></span>' * margin_count
+            comment_data += api_topic_thread_make(
+                ip_pas(temp_dict['comment_user_id']),
+                date,
+                render_set(
+                    doc_data = temp_dict['comment'],
+                    data_in = 'bbs_comment_' + sub_code_check
+                ),
+                sub_code_check,
+                color = color,
+                add_style = 'width: calc(100% - ' + str(margin_count * 20) + 'px);'
+            )
+
+            comment_default = ''
+            if comment_num == sub_code_check:
+                comment_default = 'selected'
+
+            comment_select += '<option value="' + sub_code_check + '" ' + comment_default + '>' + sub_code_check + '</option>'
 
         temp_data = bbs_w_post_comment(user_id, sub_code + '-' + temp_dict['code'], comment_num, bbs_num_str, post_num_str)
 
@@ -59,7 +59,7 @@ def bbs_w_post_comment(user_id, sub_code, comment_num, bbs_num_str, post_num_str
 
     return (comment_data, comment_select, comment_count, comment_add_count)
 
-def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
+def bbs_w_post(bbs_num = '', post_num = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -84,7 +84,7 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
         if not db_data_2:
             return redirect('/bbs/main')
         elif db_data_2[0][0] == 'thread':
-            if flask.request.method == 'POST' and do_type != 'preview':
+            if flask.request.method == 'POST':
                 if bbs_comment_acl == 1:
                     return redirect('/bbs/set/' + bbs_num_str)
                 
@@ -123,16 +123,6 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                     return re_error('/ban')
 
                 text = ''
-                data_preview = ''
-                if do_type == 'preview':
-                    text = flask.request.form.get('content', '')
-                    text = text.replace('\r', '')
-
-                    data_preview = render_set(
-                        doc_data = text,
-                        data_type = 'thread',
-                        data_in = 'bbs_comment_preview'
-                    )
 
                 date = ''
                 date += temp_dict['date']
@@ -150,7 +140,6 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                     '0',
                     color = 'green'
                 )
-                data += '<hr class="main_hr">'
 
                 user_id = temp_dict['user_id']
                 count = 0
@@ -178,25 +167,10 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                         str(count),
                         color = color
                     )
-                    data += '<hr class="main_hr">'
-
-                bbs_comment_form = ''
-                if bbs_comment_acl == 0:
-                    bbs_comment_form += '''                        
-                        ''' + edit_editor(curs, ip, text, 'bbs_comment') + '''
-                        <hr class="main_hr">
-                        
-                        ''' + captcha_get() + ip_warning() + '''
-
-                        <button id="opennamu_save_button" formaction="/bbs/w/''' + bbs_num_str + '''/''' + post_num_str + '''" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('send') + '''</button>
-                        <button id="opennamu_preview_button" formaction="/bbs/w/preview/''' + bbs_num_str + '''/''' + post_num_str + '''#opennamu_edit_textarea" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
-                        <hr class="main_hr">
-                    '''
 
                 data += '''
                     <form method="post">
-                        ''' + bbs_comment_form + '''
-                        ''' + data_preview + '''
+                        ''' + (edit_editor(curs, ip, text, 'bbs_comment') if bbs_comment_acl == 0 else '') + '''
                     </form>
                 '''
 
@@ -207,7 +181,7 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                 ))
         else:
             # db_data_2[0][0] == 'comment'
-            if flask.request.method == 'POST' and do_type != 'preview':
+            if flask.request.method == 'POST':
                 if bbs_comment_acl == 1:
                     return redirect('/bbs/set/' + bbs_num_str)
                 
@@ -278,17 +252,6 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                     
                 text = ''
                 comment_num = ''
-                data_preview = ''
-                if do_type == 'preview':
-                    text = flask.request.form.get('content', '')
-                    text = text.replace('\r', '')
-
-                    comment_num = flask.request.form.get('comment_select', '')
-
-                    data_preview = render_set(
-                        doc_data = text,
-                        data_in = 'bbs_comment_preview'
-                    )
 
                 date = ''
                 date += '<a href="javascript:opennamu_change_comment(\'0\');">(' + load_lang('comment') + ')</a> '
@@ -325,7 +288,7 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                 comment_add_count -= comment_count
 
                 if comment_data != '':
-                    data += '<hr class="main_hr"><hr>'
+                    data += '<hr>'
 
                 comment_select += '</select>'
                 if comment_data != '':
@@ -342,19 +305,11 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                         <hr class="main_hr">
                         
                         ''' + edit_editor(curs, ip, text, 'bbs_comment') + '''
-                        <hr class="main_hr">
-                        
-                        ''' + captcha_get() + ip_warning() + '''
-
-                        <button id="opennamu_save_button" formaction="/bbs/w/''' + bbs_num_str + '''/''' + post_num_str + '''" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('send') + '''</button>
-                        <button id="opennamu_preview_button" formaction="/bbs/w/preview/''' + bbs_num_str + '''/''' + post_num_str + '''#opennamu_edit_textarea" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
-                        <hr class="main_hr">
                     '''
 
                 data += '''
                     <form method="post">
                         ''' + bbs_comment_form + '''
-                        ''' + data_preview + '''
                     </form>
                     <script src="/views/main_css/js/route/bbs_w_post.js"></script>
                 '''

+ 6 - 3
route/bbs_w_set.py

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

+ 19 - 1
route/bbs_w_tool.py

@@ -13,10 +13,28 @@ def bbs_w_tool(bbs_num = '', post_num = ''):
             <h2>''' + load_lang('tool') + '''</h2>
             <ul class="opennamu_ul">
                 <li><a href="/bbs/raw/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '">' + load_lang('raw') + '''</a></li>
-                <!-- <li><a href="/bbs/blind/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '">' + load_lang('hide') + '''</a></li> -->
             </ul>
         '''
 
+        if admin_check() == 1:
+            curs.execute(db_change('select set_data from bbs_data where set_code = ? and set_id = ? and set_name = "pinned"'), [post_num_str, bbs_num_str])
+            pinned = load_lang('pinned') if not curs.fetchall() else load_lang('pinned_release')
+
+            data += '''
+                <h3>''' + load_lang('admin') + '''</h3>
+                <ul class="opennamu_ul">
+                    <!-- <li><a href="/bbs/blind/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '">' + load_lang('hide') + '''</a></li> -->
+                    <li><a href="/bbs/pinned/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '">' + pinned + '''</a></li>
+                </ul>
+            '''
+
+            data += '''
+                <h3>''' + load_lang('owner') + '''</h2>
+                <ul class="opennamu_ul">
+                    <li><a href="/bbs/delete/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '">' + load_lang('delete') + '''</a></li>
+                </ul>
+            '''
+
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('bbs_post_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = data,

+ 52 - 65
route/edit.py

@@ -23,7 +23,7 @@ def edit_timeout(func, args = (), timeout = 3):
         pool.join()
         return 0
         
-def edit_editor(curs, ip, data_main = '', do_type = 'edit'):
+def edit_editor(curs, ip, data_main = '', do_type = 'edit', addon = ''):
     monaco_editor_top = ''
     editor_display = ''
     add_get_file = ''
@@ -49,43 +49,53 @@ def edit_editor(curs, ip, data_main = '', do_type = 'edit'):
             
     p_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('default_edit_help')
     
+    monaco_editor_top += '<a href="javascript:opennamu_do_editor_temp_save();">(' + load_lang('load_temp_save') + ')</a> <a href="javascript:opennamu_do_editor_temp_save_load();">(' + load_lang('load_temp_save_load') + ')</a> '
+    monaco_editor_top += '<a href="javascript:opennamu_edit_turn_off_monaco();">(' + load_lang('turn_off_monaco') + ')</a>'
+
+    add_get_file = '''
+        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/editor/editor.main.min.css" integrity="sha512-MFDhxgOYIqLdcYTXw7en/n5BshKoduTitYmX8TkQ+iJOGjrWusRi8+KmfZOrgaDrCjZSotH2d1U1e/Z1KT6nWw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/loader.min.js" integrity="sha512-A+6SvPGkIN9Rf0mUXmW4xh7rDvALXf/f0VtOUiHlDUSPknu2kcfz1KzLpOJyL2pO+nZS13hhIjLqVgiQExLJrw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+    '''
+    
+    darkmode = flask.request.cookies.get('main_css_darkmode', '0')
+    monaco_thema = 'vs-dark' if darkmode == '1' else ''
+    
+    add_script = 'do_monaco_init("' + monaco_thema + '");'
+    
     monaco_on = get_main_skin_set(curs, flask.session, 'main_css_monaco', ip)
     if monaco_on == 'use':
         editor_display = 'style="display: none;"'
-        add_get_file = '''
-            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/editor/editor.main.min.css" integrity="sha512-MFDhxgOYIqLdcYTXw7en/n5BshKoduTitYmX8TkQ+iJOGjrWusRi8+KmfZOrgaDrCjZSotH2d1U1e/Z1KT6nWw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
-            <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/loader.min.js" integrity="sha512-A+6SvPGkIN9Rf0mUXmW4xh7rDvALXf/f0VtOUiHlDUSPknu2kcfz1KzLpOJyL2pO+nZS13hhIjLqVgiQExLJrw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
-        '''
-
-        monaco_editor_top = '<a href="javascript:opennamu_edit_turn_off_monaco();">(' + load_lang('turn_off_monaco') + ')</a>'
-        
-        if flask.request.cookies.get('main_css_darkmode', '0') == '1':
-            monaco_thema = 'vs-dark'
-        else:
-            monaco_thema = ''
-        
-        add_script = 'do_monaco_init("' + monaco_thema + '");'
     else:
         monaco_display = 'style="display: none;"'
-        add_script = 'opennamu_edit_turn_off_monaco();'
 
-    if do_type == 'edit':
-        textarea_size = 'opennamu_textarea_500'
-    else:
-        textarea_size = 'opennamu_textarea_100'
+    textarea_size = 'opennamu_textarea_500' if do_type == 'edit' else 'opennamu_textarea_100'
 
     return add_get_file + '''
         <textarea style="display: none;" id="opennamu_edit_origin" name="doc_data_org">''' + html.escape(data_main) + '''</textarea>
-        <div>''' + monaco_editor_top + ' ' + edit_button('opennamu_edit_textarea', 'opennamu_monaco_editor') + '''</div>
+        <div>
+            ''' + monaco_editor_top + '''
+            <hr class="main_hr">
+            ''' + edit_button() + '''
+        </div>
         
         <div id="opennamu_monaco_editor" class="''' + textarea_size + '''" ''' + monaco_display + '''></div>
         <textarea id="opennamu_edit_textarea" ''' + editor_display + ''' class="''' + textarea_size + '''" name="content" placeholder="''' + p_text + '''">''' + html.escape(data_main) + '''</textarea>
         <hr class="main_hr">
+        
+        ''' + captcha_get() + ip_warning() + addon + '''
+        <hr class="main_hr">
+
         <script>
             do_stop_exit();
-            do_paste_image('opennamu_edit_textarea', 'opennamu_monaco_editor');
+            do_paste_image();
             ''' + add_script + '''
         </script>
+                        
+        <button id="opennamu_save_button" type="submit" onclick="do_stop_exit_release();">''' + load_lang('send') + '''</button>
+        <button id="opennamu_preview_button" type="button" onclick="opennamu_do_editor_preview();">''' + load_lang('preview') + '''</button>
+        <hr class="main_hr">
+
+        <div id="opennamu_preview_area"></div>
     '''
 
 def edit(name = 'Test', section = 0, do_type = ''):
@@ -107,7 +117,6 @@ def edit(name = 'Test', section = 0, do_type = ''):
         post_ver = flask.request.form.get('ver', '')
         if flask.request.method == 'POST':
             edit_repeat = 'error' if post_ver != doc_ver else 'post'
-            edit_repeat = 'error' if do_type == 'preview' else 'post'
         else:
             edit_repeat = 'get'
         
@@ -162,6 +171,12 @@ def edit(name = 'Test', section = 0, do_type = ''):
             else:
                 leng = '+' + str(len(content))
 
+            curs.execute(db_change("select data from other where name = 'document_content_max_length'"))
+            db_data_3 = curs.fetchall()
+            if db_data_3 and db_data_3[0][0] != '':
+                if int(number_check(db_data_3[0][0])) < len(content):
+                    return re_error('/error/44')
+
             curs.execute(db_change("select data from other where name = 'edit_timeout'"))
             db_data_2 = curs.fetchall()
             db_data_2 = '' if not db_data_2 else number_check(db_data_2[0][0])
@@ -179,9 +194,6 @@ def edit(name = 'Test', section = 0, do_type = ''):
             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 = ? and type = ''"), [name])
             for scan_user in curs.fetchall():
                 add_alarm(scan_user[0], ip, '<a href="/w/' + url_pas(name) + '">' + html.escape(name) + '</a>')
@@ -195,9 +207,6 @@ def edit(name = 'Test', section = 0, do_type = ''):
                 leng
             )
             
-            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(
                 doc_name = name,
                 doc_data = content,
@@ -215,7 +224,6 @@ def edit(name = 'Test', section = 0, do_type = ''):
             doc_section_edit_apply = 'X'
             data_section = ''
             data_section_where = ''
-            data_preview = ''
 
             if edit_repeat == 'get':
                 if do_type == 'load':
@@ -285,38 +293,24 @@ def edit(name = 'Test', section = 0, do_type = ''):
 
                 doc_ver = flask.request.form.get('ver', '')
 
-                if do_type != 'preview':
-                    warning_edit = load_lang('exp_edit_conflict') + ' '
-        
-                    if flask.request.form.get('ver', '0') == '0':
-                        warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
-                    else:
-                        warning_edit += '' + \
-                            '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
-                                '(r' + doc_ver + ')' + \
-                            '</a>' + \
-                        ''
-        
-                    warning_edit += '<hr class="main_hr">'
-                    editor_top_text = warning_edit + editor_top_text
+                warning_edit = load_lang('exp_edit_conflict') + ' '
+    
+                if flask.request.form.get('ver', '0') == '0':
+                    warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
                 else:
-                    data_preview = render_set(
-                        doc_name = name, 
-                        doc_data = data,
-                        data_type = 'from'
-                    )
+                    warning_edit += '' + \
+                        '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
+                            '(r' + doc_ver + ')' + \
+                        '</a>' + \
+                    ''
+    
+                warning_edit += '<hr class="main_hr">'
+                editor_top_text = warning_edit + editor_top_text
 
             if data_section == '':
                 data_section = data
-
-            if section == '':
-                form_action = 'formaction="/edit/' + url_pas(name) + '"'
-                form_action_preview = 'formaction="/edit_preview/' + url_pas(name) + '"'
-            else:
-                form_action = 'formaction="/edit_section/' + str(section) + '/' + url_pas(name) + '"'
-                form_action_preview = 'formaction="/edit_section_preview/' + str(section) + '/' + url_pas(name) + '"'
     
-            editor_top_text += '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
+            editor_top_text += '<a href="/filter/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
     
             if editor_top_text != '':
                 editor_top_text += '<hr class="main_hr">'
@@ -330,21 +324,14 @@ def edit(name = 'Test', section = 0, do_type = ''):
                         <textarea style="display: none;" name="doc_section_data_where">''' + data_section_where + '''</textarea>
                         <input style="display: none;" name="doc_section_edit_apply" value="''' + doc_section_edit_apply + '''">
 
+                        <input style="display: none;" id="opennamu_editor_doc_name" value="''' + html.escape(name) + '''">
                         <input style="display: none;" name="ver" value="''' + doc_ver + '''">
                         
-                        ''' + edit_editor(curs, ip, data_section) + '''
-
                         <input placeholder="''' + load_lang('why') + '''" name="send">
                         <hr class="main_hr">
                         
-                        ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
-                        
-                        <button id="opennamu_save_button" type="submit" ''' + form_action + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('save') + '''</button>
-                        <button id="opennamu_preview_button" type="submit" ''' + form_action_preview + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
+                        ''' + edit_editor(curs, ip, data_section, addon = get_edit_text_bottom_check_box() + get_edit_text_bottom()) + '''
                     </form>
-                    
-                    <hr class="main_hr">
-                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 ''',
                 menu = [
                     ['w/' + url_pas(name), load_lang('return')],

+ 0 - 3
route/edit_backlink_reset.py

@@ -7,9 +7,6 @@ def edit_backlink_reset(name = 'Test'):
         curs.execute(db_change("select data from data where title = ?"), [name])
         old = curs.fetchall()
         if old:
-            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(
                 doc_name = name,
                 doc_data = old[0][0],

+ 1 - 3
route/edit_delete.py

@@ -53,10 +53,8 @@ def edit_delete(name):
 
                 curs.execute(db_change("delete from back where link = ?"), [name])
                 curs.execute(db_change("delete from data where title = ?"), [name])
-                conn.commit()
 
-            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)])
+                conn.commit()
 
             return redirect('/w/' + url_pas(name))
         else:            

+ 83 - 146
route/edit_move.py

@@ -41,13 +41,12 @@ def edit_move(name):
             if do_edit_text_bottom_check_box_check(agree) == 1:
                 return re_error('/error/29')
 
+            # 역링크 관련 패치 해야할 듯
+
             # 문서 이동 파트 S
             curs.execute(db_change("select title from history where title = ?"), [move_title])
             if curs.fetchall():
-                if (
-                    move_option == 'merge' and 
-                    admin_check(None, 'merge documents (' + name + ') (' + move_title + ')') == 1
-                ):
+                if move_option == 'merge' and admin_check(None, 'merge documents (' + name + ') (' + move_title + ')') == 1:
                     curs.execute(db_change("select data from data where title = ?"), [move_title])
                     data = curs.fetchall()
                     if data:
@@ -56,151 +55,114 @@ def edit_move(name):
 
                     curs.execute(db_change("select data from data where title = ?"), [name])
                     data = curs.fetchall()
-                    if data:
-                        curs.execute(db_change("update data set title = ? where title = ?"), [move_title, name])
-                        curs.execute(db_change("update back set link = ? where link = ?"), [move_title, name])
+                    data_in = data[0][0] if data else ''
 
-                        data_in = data[0][0]
-                    else:
-                        data_in = ''
-
-                    history_plus(
-                        name,
-                        data_in,
-                        time,
-                        ip,
-                        send,
-                        '0',
-                        t_check = 'merge <a>' + name + '</a> - <a>' + move_title + '</a> move',
-                        mode = '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'"), [move_title])
+                    curs.execute(db_change("update data set title = ? where title = ?"), [move_title, name])
+                    curs.execute(db_change("update back set link = ? where link = ?"), [move_title, name])
 
-                    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)])
+                    # 역링크 S
+                    # 문서 합치기이므로 기존 문서 쪽은 no 역링크 생성, 이동하는 곳에는 no 역링크 제거
+                    curs.execute(db_change("select distinct link from back where title = ?"), [name])
+                    backlink = [[for_a[0], name, 'no', ''] for for_a in curs.fetchall()]
+                    curs.executemany(db_change("insert into back (link, title, type, data) values (?, ?, ?, ?)"), backlink)
+                    curs.execute(db_change("delete from back where title = ? and type = 'no'"), [move_title])
+                    # 역링크 E
 
                     curs.execute(db_change("select id from history where title = ? order by id + 0 desc limit 1"), [move_title])
-                    data = curs.fetchall()
-
-                    num = data[0][0]
+                    num = curs.fetchall()[0][0]
 
                     curs.execute(db_change("select id from history where title = ? order by id + 0 asc"), [name])
                     data = curs.fetchall()
                     for move in data:
-                        curs.execute(db_change("update rc set title = ?, id = ? where title = ? and id = ?"), [
-                            move_title, 
-                            str(int(num) + int(move[0])), 
-                            name, 
-                            move[0]
-                        ])
-                        curs.execute(db_change("update history set title = ?, id = ? where title = ? and id = ?"), [
-                            move_title, 
-                            str(int(num) + int(move[0])), 
-                            name, 
-                            move[0]
-                        ])
+                        curs.execute(db_change("update rc set title = ?, id = ? where title = ? and id = ?"), [move_title, str(int(num) + int(move[0])), name, move[0]])
+                        curs.execute(db_change("update history set title = ?, id = ? where title = ? and id = ?"), [move_title, str(int(num) + int(move[0])), name, move[0]])
+
+                    history_plus(move_title, data_in, time, ip, send, '0',
+                        t_check = 'merge <a>' + name + '</a> - <a>' + move_title + '</a> move',
+                        mode = 'move'
+                    )
                 elif move_option == 'reverse':
+                    # 전체적인 구조 변경 필요
+                    # 중간 문서 거치지 않고 불러와서 바로 변경하도록
+                    # 문서 이동 말고 나머지도 그렇게 변경 필요함
                     i = 0
                     var_name = ''
                     while var_name == '':
-                        curs.execute(db_change("select title from history where title = ?"), ['test ' + str(i)])
+                        temp_title = 'test ' + load_random_key() + ' ' + str(i)
+                        curs.execute(db_change("select title from history where title = ? limit 1"), [temp_title])
                         if not curs.fetchall():
-                            var_name = 'test ' + str(i)
+                            var_name = temp_title
                         else:
                             i += 1
 
-                    curs.execute(db_change("select data from data where title = ?"), [name])
-                    data = curs.fetchall()
-                    if data:
-                        curs.execute(db_change("update data set title = ? where title = ?"), [var_name, name])
-                        curs.execute(db_change("update back set link = ? where link = ?"), [var_name, name])
+                    for title_name in [[name, var_name], [move_title, name], [var_name, move_title]]:
+                        curs.execute(db_change("update data set title = ? where title = ?"), [title_name[1], title_name[0]])
+                        curs.execute(db_change("update back set link = ? where link = ?"), [title_name[1], title_name[0]])
 
-                    curs.execute(db_change("update history set title = ? where title = ?"), [var_name, name])
-                    curs.execute(db_change("update rc set title = ? where title = ?"), [var_name, name])
+                        curs.execute(db_change("update history set title = ? where title = ?"), [title_name[1], title_name[0]])
+                        curs.execute(db_change("update rc set title = ? where title = ?"), [title_name[1], title_name[0]])
 
-                    for title_name in [[move_title, name], [var_name, move_title]]:
-                        curs.execute(db_change("select data from data where title = ?"), [title_name[0]])
+                    for title_name in [[name, move_title], [move_title, name]]:
+                        curs.execute(db_change("select data from data where title = ?"), [name])
                         data = curs.fetchall()
-                        if data:
-                            curs.execute(db_change("update data set title = ? where title = ?"), [title_name[1], title_name[0]])
-                            curs.execute(db_change("update back set link = ? where link = ?"), [title_name[1], title_name[0]])
+                        data_in = data[0][0] if data else ''
 
-                            data_in = data[0][0]
-                        else:
-                            data_in = ''
-
-                        history_plus(
-                            title_name[0],
-                            data_in,
-                            time,
-                            ip,
-                            send,
-                            '0',
-                            t_check = '<a>' + (title_name[0] if title_name[0] != var_name else name) + '</a> - <a>' + title_name[1] + '</a> move',
+                        history_plus(title_name[0], data_in, time, ip, send, '0',
+                            t_check = '<a>' + title_name[0] + '</a> - <a>' + title_name[1] + '</a> move',
                             mode = 'move'
                         )
-
-                        curs.execute(db_change("update history set title = ? where title = ?"), [title_name[1], title_name[0]])
-                        curs.execute(db_change("update rc set title = ? where title = ?"), [title_name[1], title_name[0]])
                 elif move_option != 'none':
                     has_error = 1
-            elif move_option != 'none':                
+            elif move_option != 'none':
                 curs.execute(db_change("select data from data where title = ?"), [name])
                 data = curs.fetchall()
-                if data:
-                    curs.execute(db_change("update data set title = ? where title = ?"), [move_title, name])
-                    curs.execute(db_change("update back set link = ? where link = ?"), [move_title, name])
+                data_in = data[0][0] if data else ''
 
-                    data_in = data[0][0]
-                else:
-                    data_in = ''
-
-                history_plus(
-                    name,
-                    data_in,
-                    time,
-                    ip,
-                    send,
-                    '0',
-                    t_check = '<a>' + name + '</a> - <a>' + move_title + '</a> move',
-                    mode = 'move'
-                )
+                curs.execute(db_change("update data set title = ? where title = ?"), [move_title, name])
+                curs.execute(db_change("update back set link = ? where link = ?"), [move_title, name])
 
-                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'"), [move_title])
+                # 역링크 S
+                # 문서 합치기 쪽 역링크와 동일하게
+                curs.execute(db_change("select distinct link from back where title = ?"), [name])
+                backlink = [[for_a[0], name, 'no', ''] for for_a in curs.fetchall()]
+                curs.executemany(db_change("insert into back (link, title, type, data) values (?, ?, ?, ?)"), backlink)
+                curs.execute(db_change("delete from back where title = ? and type = 'no'"), [move_title])
+                # 역링크 E
 
+                # 역사와 최근 변경 이동 S
                 curs.execute(db_change("update history set title = ? where title = ?"), [move_title, name])
                 curs.execute(db_change("update rc set title = ? where title = ?"), [move_title, name])
-                
+                # 역사와 최근 변경 이동 E
+
+                history_plus(move_title, data_in, time, ip, send, '0',
+                    t_check = '<a>' + name + '</a> - <a>' + move_title + '</a> move',
+                    mode = 'move'
+                )
+
             # 문서 이동 파트 E
             
             # 토론 이동 파트 S
-            if (
-                move_option_topic == 'merge' and
-                admin_check(None, 'merge document\'s topics (' + name + ') (' + move_title + ')') == 1
-            ):
-                curs.execute(db_change("update rd set title = ? where title = ?"), [move_title, name])
-            elif move_option_topic == 'reverse':
-                i = 0
-                var_name = ''
-                while var_name == '':
-                    curs.execute(db_change("select title from rd where title = ?"), ['test ' + str(i)])
-                    if not curs.fetchall():
-                        var_name = 'test ' + str(i)
-                    else:
-                        i += 1
-                
-                curs.execute(db_change("update rd set title = ? where title = ?"), [var_name, move_title])
-                curs.execute(db_change("update rd set title = ? where title = ?"), [move_title, name])
-                curs.execute(db_change("update rd set title = ? where title = ?"), [name, var_name])
-            elif move_option_topic == 'normal':
-                curs.execute(db_change("select title from rd where title = ?"), [move_title])
-                if curs.fetchall():
-                    has_error = 1
-                else:
+            curs.execute(db_change("select title from rd where title = ?"), [move_title])
+            if curs.fetchall():
+                if move_option_topic == 'merge' and admin_check(None, 'merge document\'s topics (' + name + ') (' + move_title + ')') == 1:
                     curs.execute(db_change("update rd set title = ? where title = ?"), [move_title, name])
+                elif move_option_topic == 'reverse':
+                    i = 0
+                    var_name = ''
+                    while var_name == '':
+                        temp_title = 'test ' + load_random_key() + ' ' + str(i)
+                        curs.execute(db_change("select title from rd where title = ? limit 1"), [temp_title])
+                        if not curs.fetchall():
+                            var_name = temp_title
+                        else:
+                            i += 1
+                    
+                    for title_name in [[name, var_name], [move_title, name], [var_name, move_title]]:
+                        curs.execute(db_change("update rd set title = ? where title = ?"), [title_name[1], title_name[0]])
+                else:
+                    has_error = 1
+            elif move_option_topic != 'none':
+                curs.execute(db_change("update rd set title = ? where title = ?"), [move_title, name])
 
             # 토론 이동 파트 E
 
@@ -209,46 +171,21 @@ def edit_move(name):
                 i = 0
                 var_name = ''
                 while var_name == '':
-                    curs.execute(db_change("select title from rd where title = ?"), ['test ' + str(i)])
+                    temp_title = 'test ' + load_random_key() + ' ' + str(i)
+                    curs.execute(db_change("select title from history where title = ? limit 1"), [temp_title])
                     if not curs.fetchall():
-                        var_name = 'test ' + str(i)
+                        var_name = temp_title
                     else:
                         i += 1
                 
-                # create_data['data_set'] = ['doc_name', 'doc_rev', 'set_name', 'set_data']
-                # create_data['acl'] = ['title', 'data', 'type']
-                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [var_name, move_title])
-                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [move_title, name])
-                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [name, var_name])
-
-                curs.execute(db_change("update acl set title = ? where title = ?"), [var_name, move_title])
-                curs.execute(db_change("update acl set title = ? where title = ?"), [move_title, name])
-                curs.execute(db_change("update acl set title = ? where title = ?"), [name, var_name])
+                for title_name in [[name, var_name], [move_title, name], [var_name, move_title]]:
+                    curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [title_name[1], title_name[0]])
             elif document_set_option == 'normal':
                 curs.execute(db_change("delete from data_set where doc_name = ?"), [move_title])
-                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [move_title, name])
-
                 curs.execute(db_change("delete from acl where title = ?"), [move_title])
-                curs.execute(db_change("update acl set title = ? where title = ?"), [move_title, name])
-
-            if document_set_option != 'reverse':
-                curs.execute(db_change("select data from data where title = ?"), [name])
-                db_data = curs.fetchall()
-                if db_data:
-                    render_set(
-                        doc_name = name,
-                        doc_data = db_data[0][0],
-                        data_type = 'backlink'
-                    )
 
-                curs.execute(db_change("select data from data where title = ?"), [move_title])
-                db_data = curs.fetchall()
-                if db_data:
-                    render_set(
-                        doc_name = move_title,
-                        doc_data = db_data[0][0],
-                        data_type = 'backlink'
-                    )
+                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [move_title, name])
+                curs.execute(db_change("update acl set title = ? where title = ?"), [move_title, name])
 
             # data_set 이동 파트 E
                 

+ 38 - 35
route/edit_revert.py

@@ -36,54 +36,57 @@ def edit_revert(name, num):
 
             if do_edit_filter(data[0][0]) == 1:
                 return re_error('/error/21')
+            
+            curs.execute(db_change("select data from other where name = 'document_content_max_length'"))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                if int(number_check(db_data[0][0])) < len(data[0][0]):
+                    return re_error('/error/44')
 
-            curs.execute(db_change("delete from back where link = ?"), [name])
-
-            if data:
-                curs.execute(db_change("select data from data where title = ?"), [name])
-                data_old = curs.fetchall()
-                if data_old:
-                    leng = leng_check(len(data_old[0][0]), len(data[0][0]))
-                    curs.execute(db_change("update data set data = ? where title = ?"), [data[0][0], name])
-                else:
-                    leng = '+' + str(len(data[0][0]))
-                    curs.execute(db_change("insert into data (title, data) values (?, ?)"), [name, data[0][0]])
+            curs.execute(db_change("select data from data where title = ?"), [name])
+            data_old = curs.fetchall()
+            if data_old:
+                leng = leng_check(len(data_old[0][0]), len(data[0][0]))
+                curs.execute(db_change("update data set data = ? where title = ?"), [data[0][0], 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', ''),
-                    leng,
-                    t_check = 'r' + str(num),
-                    mode = 'revert'
-                )
+            history_plus(
+                name,
+                data[0][0],
+                get_time(),
+                ip_check(),
+                flask.request.form.get('send', ''),
+                leng,
+                t_check = 'r' + str(num),
+                mode = 'revert'
+            )
 
-                render_set(
-                    doc_name = name,
-                    doc_data = data[0][0],
-                    data_type = 'backlink'
-                )
+            render_set(
+                doc_name = name,
+                doc_data = data[0][0],
+                data_type = 'backlink'
+            )
 
             conn.commit()
 
             return redirect('/w/' + url_pas(name))
         else:
             if data:
-                preview = '<pre>' + html.escape(data[0][0]) + '</pre>'
+                preview = '<hr class="main_hr"><pre>' + html.escape(data[0][0]) + '</pre>'
             else:
                 preview = ''
             
             return easy_minify(flask.render_template(skin_check(),
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(r' + str(num) + ') (' + load_lang('revert') + ')', 0])],
-                data =  '''
-                        <form method="post">
-                            <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
-                            <hr class="main_hr">
-                            ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
-                            <button type="submit">''' + load_lang('revert') + '''</button>
-                        </form>
-                        ''' + preview,
+                data = '''
+                    <form method="post">
+                        <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
+                        <hr class="main_hr">
+                        ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
+                        <button type="submit">''' + load_lang('revert') + '''</button>
+                    </form>
+                ''' + preview,
                 menu = [['history/' + url_pas(name), load_lang('history')], ['recent_changes', load_lang('recent_change')]]
             ))

+ 4 - 7
route/edit_upload.py

@@ -24,7 +24,7 @@ def edit_upload():
             if (file_max * 1000 * 1000 * file_len) < flask.request.content_length:
                 return re_error('/error/17')
 
-            if file_len == 1:    
+            if file_len == 1:
                 file_num = None
             else:
                 if acl_check(None, 'many_upload') == 1:
@@ -49,7 +49,7 @@ def edit_upload():
                     name = data.filename
 
                 piece = os.path.splitext(name)
-                if re.search(r'[^ㄱ-힣0-9a-zA-Z_\- ]', piece[0]):
+                if re.search(r'\.', piece[0]):
                     return re_error('/error/22')
 
                 e_data = sha224_replace(piece[0]) + piece[1]
@@ -63,7 +63,7 @@ def edit_upload():
                 for i in db_data:
                     t_re = re.compile(i[0])
                     if t_re.search(name):
-                        return redirect('/file_filter')
+                        return redirect('/filter/file_filter')
 
                 data_url_image = load_image_url()
                 if os.path.exists(os.path.join(data_url_image, e_data)):
@@ -92,9 +92,6 @@ def edit_upload():
 
                 curs.execute(db_change("insert into data (title, data) values (?, ?)"), ['file:' + name, file_d])
 
-                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)])
-
                 render_set(
                     doc_name = 'file:' + name,
                     doc_data = file_d,
@@ -137,7 +134,7 @@ def edit_upload():
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('upload'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    <a href="/file_filter">(''' + load_lang('file_filter_list') + ''')</a> <a href="/extension_filter">(''' + load_lang('extension_filter_list') + ''')</a>
+                    <a href="/filter/file_filter">(''' + load_lang('file_filter_list') + ''')</a> <a href="/filter/extension_filter">(''' + load_lang('extension_filter_list') + ''')</a>
                     ''' + upload_help + '''
                     <hr class="main_hr">
                     ''' + load_lang('max_file_size') + ''' : ''' + str(file_max) + '''MB

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

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

+ 283 - 0
route/filter_all_add.py

@@ -0,0 +1,283 @@
+from .tool.func import *
+
+def filter_all_add(tool, name = None):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if not name and tool == 'edit_filter':
+            return redirect('/manager/9')
+
+        if flask.request.method == 'POST':
+            if admin_check() != 1:
+                return re_error('/error/3')
+
+            title = flask.request.form.get('title', 'test')
+            if tool in ('inter_wiki', 'outer_link'):
+                link = flask.request.form.get('link', 'test')
+                icon = flask.request.form.get('icon', '')
+                inter_type = flask.request.form.get('inter_type', '')
+
+                curs.execute(db_change("delete from html_filter where html = ? and kind = ?"), [title, tool])
+                curs.execute(db_change('insert into html_filter (html, plus, plus_t, kind) values (?, ?, ?, ?)'), [title, link, icon, tool])
+                if tool == 'inter_wiki':
+                    curs.execute(db_change("delete from html_filter where html = ? and kind = 'inter_wiki_sub'"), [title])
+                    curs.execute(db_change('insert into html_filter (html, plus, plus_t, kind) values (?, "inter_wiki_type", ?, "inter_wiki_sub")'), [title, inter_type])
+                
+                admin_check(None, tool + ' edit')
+            elif tool == 'edit_filter':
+                sec = flask.request.form.get('second', '0')
+                end = 'X' if sec == '0' else sec
+
+                content = flask.request.form.get('content', 'test')
+                try:
+                    re.compile(content)
+                except:
+                    return re_error('/error/23')
+                
+                curs.execute(db_change("delete from html_filter where html = ? and kind = 'regex_filter'"), [name])
+                curs.execute(db_change("insert into html_filter (html, plus, plus_t, kind) values (?, ?, ?, 'regex_filter')"), [name, content, end])
+                admin_check(None, 'edit_filter edit')
+            elif tool == 'document':
+                post_name = flask.request.form.get('name', '')
+                if post_name == '':
+                    return redirect('/filter/document')
+            
+                post_acl = flask.request.form.get('acl', '')
+                post_regex = flask.request.form.get('regex', '')
+                try:
+                    re.compile(post_regex)
+                except:
+                    return re_error('/error/23')
+                
+                curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, "document", ?, ?)'), [post_name, post_regex, post_acl])
+                admin_check(None, 'document_filter edit')
+            else:
+                plus_d = ''
+                if tool == 'name_filter':
+                    try:
+                        re.compile(title)
+                    except:
+                        return re_error('/error/23')
+
+                    admin_check(None, 'name_filter edit')
+                    type_d = 'name'
+                elif tool == 'file_filter':
+                    try:
+                        re.compile(title)
+                    except:
+                        return re_error('/error/23')
+
+                    admin_check(None, 'file_filter edit')
+                    type_d = 'file'
+                elif tool == 'email_filter':
+                    admin_check(None, 'email_filter edit')
+                    type_d = 'email'
+                elif tool == 'image_license':
+                    admin_check(None, 'image_license edit')
+                    type_d = 'image_license'
+                elif tool == 'extension_filter':
+                    admin_check(None, 'extension_filter edit')
+                    type_d = 'extension'
+                elif tool == 'template':
+                    admin_check(None, 'template_document edit')
+                    type_d = 'template'
+                    plus_d = flask.request.form.get('exp', 'test')
+                else:
+                    admin_check(None, 'edit_top edit')
+                    type_d = 'edit_top'
+                    plus_d = flask.request.form.get('markup', 'test')
+
+                if name:
+                    curs.execute(db_change("delete from html_filter where html = ? and kind = ?"), [name, type_d])
+
+                curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, ?, ?, ?)'), [title, type_d, plus_d, ''])
+
+            conn.commit()
+
+            return redirect('/filter/' + tool)
+        else:
+            get_sub = 0
+            stat = 'disabled' if admin_check() != 1 else ''
+            name = name if name else ''
+
+            if tool in ('inter_wiki', 'outer_link'):
+                value = ['', '', '']
+                if name != '':
+                    curs.execute(db_change("select html, plus, plus_t from html_filter where html = ? and kind = ?"), [name, tool])
+                    exist = curs.fetchall()
+                    value = exist[0] if exist else value
+
+                select = ''
+                if tool == 'inter_wiki':
+                    ex = 'https://namu.wiki/w/'
+
+                    select = ['', '']
+                    curs.execute(db_change("select plus_t from html_filter where kind = 'inter_wiki_sub' and html = ?"), [name])
+                    db_data = curs.fetchall()
+                    if db_data and db_data[0][0] == 'under_bar':
+                        select = ['', 'selected']
+
+                    select = '''
+                        <hr class="main_hr">
+                        ''' + load_lang('inter_wiki_space_change') + '''
+                        <hr class="main_hr">
+                        <select name="inter_type">
+                            <option ''' + select[0] + ''' value="url_encode">%20</option>
+                            <option ''' + select[1] + ''' value="under_bar">_</option>
+                        </select>
+                    '''
+                else:
+                    ex = 'youtube.com'
+
+                title = load_lang('interwiki_add') if tool == 'inter_wiki' else load_lang('outer_link_add')
+                form_data = '''
+                    ''' + load_lang('name') + '''
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(value[0]) + '''" type="text" name="title">
+                    <hr class="main_hr">
+                    ''' + load_lang('link') + ''' (EX : ''' + ex + ''')
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(value[1]) + '''" type="text" name="link">
+                    <hr class="main_hr">
+                    ''' + load_lang('icon') + ''' (''' + ('HTML' if tool == 'inter_wiki' else load_lang('html_or_link')) + ''') (''' + load_lang('link') + ' - EX' + ''' : /image/Test.svg)
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(value[2]) + '''" type="text" name="icon">
+                    ''' + select + '''
+                '''
+            elif tool == 'edit_filter':            
+                curs.execute(db_change("select plus, plus_t from html_filter where html = ? and kind = 'regex_filter'"), [name])
+                exist = curs.fetchall()
+                if exist:
+                    textarea = exist[0][0]
+                    time_data = '' if exist[0][1] == 'X' else exist[0][1]
+                else:
+                    textarea = ''
+                    time_data = ''
+
+                insert_data = ''
+                if stat == '':
+                    t_data = [
+                        ['86400', load_lang('1_day')],
+                        ['432000', load_lang('5_day')],
+                        ['2592000', load_lang('30_day')],
+                        ['15552000', load_lang('180_day')],
+                        ['31104000', load_lang('360_day')],
+                        ['0', load_lang('limitless')]
+                    ]
+                    insert_data += ''.join(['<a href="javascript:opennamu_insert_v(\'second\', \'' + for_a[0] + '\')">(' + for_a[1] + ')</a> ' for for_a in t_data])
+
+                title = load_lang('edit_filter_add')
+                form_data = '''
+                    ''' + insert_data + '''
+                    <hr class="main_hr">
+                    <input placeholder="''' + load_lang('second') + '''" id="second" name="second" type="text" value="''' + html.escape(time_data) + '''">
+                    <hr class="main_hr">
+                    <input placeholder="''' + load_lang('regex') + '''" name="content" value="''' + html.escape(textarea) + '''" type="text">
+                '''
+            elif tool == 'name_filter':
+                title = load_lang('id_filter_add')
+                form_data = '' + \
+                    load_lang('regex') + \
+                    '<hr class="main_hr">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
+                ''
+            elif tool == 'file_filter':
+                title = load_lang('file_filter_add')
+                form_data = '' + \
+                    load_lang('regex') + \
+                    '<hr class="main_hr">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
+                ''
+            elif tool == 'email_filter':
+                title = load_lang('email_filter_add')
+                form_data = '' + \
+                    load_lang('email') + \
+                    '<hr class="main_hr">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
+                ''
+            elif tool == 'image_license':
+                title = load_lang('image_license_add')
+                form_data = '' + \
+                    load_lang('license') + \
+                    '<hr class="main_hr">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
+                ''
+            elif tool == 'extension_filter':
+                title = load_lang('extension_filter_add')
+                form_data = '' + \
+                    load_lang('extension') + \
+                    '<hr class="main_hr">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
+                ''
+            elif tool == 'document':
+                acl_list = get_acl_list()
+                
+                curs.execute(db_change("select plus, plus_t from html_filter where html = ? and kind = 'document'"), [name])
+                db_data = curs.fetchall()
+                acl_list = [['selected' if db_data and db_data[0][1] == for_a else '', for_a] for for_a in acl_list]
+
+                title = load_lang('document_filter_add')
+                form_data = '''
+                    ''' + load_lang('name') + '''
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(name) + '''" type="text" name="name">
+                    <hr class="main_hr">
+                    ''' + load_lang('regex') + '''
+                    <hr class="main_hr">
+                    <input value="''' + (html.escape(db_data[0][0]) if db_data else '') + '''" type="text" name="regex">
+                    <hr class="main_hr">
+                    <a href="/acl/Test#exp">''' + load_lang('acl') + '''</a>
+                    <hr class="main_hr">
+                    <select name="acl">
+                        ''' + ''.join(['<option ' + for_a[0] + ' value=' + for_a[1] + '>' + ('normal' if for_a[1] == '' else for_a[1]) + '</option>' for for_a in acl_list]) + '''
+                    </select>
+                '''
+            elif tool == 'template':
+                title = load_lang('template_document_add')
+
+                value = ''
+                if name:
+                    curs.execute(db_change("select plus from html_filter where html = ? and kind = 'template'"), [name])
+                    exist = curs.fetchall()
+                    value = exist[0][0] if exist else '' 
+
+                form_data = '' + \
+                    load_lang('template') + \
+                    '<hr class="main_hr">' + \
+                    '<input value="' + html.escape(name) + '" type="text" name="title">' + \
+                    '<hr class="main_hr">' + \
+                    load_lang('explanation') + \
+                    '<hr class="main_hr">' + \
+                    '<input value="' + html.escape(value) + '" type="text" name="exp">' + \
+                    '<hr class="main_hr">' + \
+                ''
+            else:
+                title = load_lang('edit_tool_add')
+                
+                value = ''
+                if name:
+                    curs.execute(db_change("select plus from html_filter where html = ? and kind = 'edit_top'"), [name])
+                    exist = curs.fetchall()
+                    value = exist[0][0] if exist else ''    
+
+                form_data = '''
+                    ''' + load_lang('title') + '''
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(name) + '''" type="text" name="title">
+                    <hr class="main_hr">
+                    ''' + load_lang('markup') + '''
+                    <hr class="main_hr">
+                    <input value="''' + html.escape(value) + '''" type="text" name="markup">
+                '''
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [title, wiki_set(), wiki_custom(), wiki_css([get_sub, 0])],
+                data =  '''
+                        <form method="post">
+                            ''' + form_data + '''
+                            <hr class="main_hr">
+                            <button ''' + stat + ''' type="submit">''' + load_lang('add') + '''</button>
+                        </form>
+                        ''',
+                menu = [['filter/' + tool, load_lang('return')]]
+            ))

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

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

+ 0 - 41
route/filter_document.py

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

+ 0 - 62
route/filter_document_add.py

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

+ 0 - 13
route/filter_document_delete.py

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

+ 0 - 239
route/filter_inter_wiki_add.py

@@ -1,239 +0,0 @@
-from .tool.func import *
-
-def filter_inter_wiki_add(tool, name = None):
-    with get_db_connect() as conn:
-        curs = conn.cursor()
-
-        if not name and tool == 'plus_edit_filter':
-            return redirect('/manager/9')
-
-        if flask.request.method == 'POST':
-            if admin_check() != 1:
-                return re_error('/error/3')
-
-            if tool == 'plus_inter_wiki':
-                if name:
-                    curs.execute(db_change("delete from html_filter where html = ? and kind = 'inter_wiki'"), [name])
-
-                curs.execute(db_change("delete from html_filter where html = ? and kind = 'inter_wiki'"), [
-                    flask.request.form.get('title', 'test')
-                ])
-                curs.execute(db_change('insert into html_filter (html, plus, plus_t, kind) values (?, ?, ?, "inter_wiki")'), [
-                    flask.request.form.get('title', 'test'),
-                    flask.request.form.get('link', 'test'),
-                    flask.request.form.get('icon', '')
-                ])
-
-                admin_check(None, 'inter_wiki_plus')
-            elif tool == 'plus_edit_filter':
-                if admin_check(None, 'edit_filter edit') != 1:
-                    return re_error('/error/3')
-
-                if flask.request.form.get('second', '0') == '0':
-                    end = 'X'
-                else:
-                    end = flask.request.form.get('second', 'X')
-
-                try:
-                    re.compile(flask.request.form.get('content', 'test'))
-
-                    curs.execute(db_change("delete from html_filter where html = ? and kind = 'regex_filter'"), [name])
-                    curs.execute(db_change("insert into html_filter (html, plus, plus_t, kind) values (?, ?, ?, 'regex_filter')"), [
-                        name,
-                        flask.request.form.get('content', 'test'),
-                        end
-                    ])
-                except:
-                    return re_error('/error/23')
-            else:
-                plus_d = ''
-
-                if tool == 'plus_name_filter':
-                    try:
-                        re.compile(flask.request.form.get('title', 'test'))
-                    except:
-                        return re_error('/error/23')
-
-                    admin_check(None, 'name_filter edit')
-
-                    type_d = 'name'
-                elif tool == 'plus_file_filter':
-                    try:
-                        re.compile(flask.request.form.get('title', 'test'))
-                    except:
-                        return re_error('/error/23')
-
-                    admin_check(None, 'file_filter edit')
-
-                    type_d = 'file'
-                elif tool == 'plus_email_filter':
-                    admin_check(None, 'email_filter edit')
-
-                    type_d = 'email'
-                elif tool == 'plus_image_license':
-                    admin_check(None, 'image_license edit')
-
-                    type_d = 'image_license'
-                elif tool == 'plus_extension_filter':
-                    admin_check(None, 'extension_filter edit')
-
-                    type_d = 'extension'
-                else:
-                    admin_check(None, 'edit_top edit')
-
-                    type_d = 'edit_top'
-                    plus_d = flask.request.form.get('markup', 'test')
-
-                if name:
-                    curs.execute(db_change("delete from html_filter where html = ? and kind = ?"), [
-                        name,
-                        type_d
-                    ])
-
-                curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, ?, ?, ?)'), [
-                    flask.request.form.get('title', 'test'),
-                    type_d,
-                    plus_d,
-                    ''
-                ])
-
-            conn.commit()
-
-            return redirect('/' + re.sub(r'^plus_', '', tool))
-        else:
-            # 추가 편집 구분 필요
-            # 각 파일 별로 분리 필요
-            get_sub = 0
-            stat = 'disabled' if admin_check() != 1 else ''
-
-            if tool == 'plus_inter_wiki':
-                if name:
-                    curs.execute(db_change("select html, plus, plus_t from html_filter where html = ? and kind = 'inter_wiki'"), [name])
-                    exist = curs.fetchall()
-                    if exist:
-                        value = exist[0]
-                    else:
-                        value = ['', '', '']
-                else:
-                    value = ['', '', '']
-
-                title = load_lang('interwiki_add')
-                form_data = '''
-                    ''' + load_lang('name') + '''
-                    <hr class="main_hr">
-                    <input value="''' + html.escape(value[0]) + '''" type="text" name="title">
-                    <hr class="main_hr">
-                    ''' + load_lang('link') + '''
-                    <hr class="main_hr">
-                    <input value="''' + html.escape(value[1]) + '''" type="text" name="link">
-                    <hr class="main_hr">
-                    ''' + load_lang('icon') + ''' (HTML)
-                    <hr class="main_hr">
-                    <input value="''' + html.escape(value[2]) + '''" type="text" name="icon">
-                '''
-            elif tool == 'plus_edit_filter':            
-                curs.execute(db_change("select plus, plus_t from html_filter where html = ? and kind = 'regex_filter'"), [name])
-                exist = curs.fetchall()
-                if exist:
-                    textarea = exist[0][0]
-
-                    if exist[0][1] == 'X':
-                        time_check = 'checked="checked"'
-                        time_data = ''
-                    else:
-                        time_check = ''
-                        time_data = exist[0][1]
-                else:
-                    textarea = ''
-                    time_check = ''
-                    time_data = ''
-
-                insert_data = ''
-                if stat == '':
-                    t_data = [
-                        ['86400', load_lang('1_day')],
-                        ['432000', load_lang('5_day')],
-                        ['2592000', load_lang('30_day')],
-                        ['15552000', load_lang('180_day')],
-                        ['31104000', load_lang('360_day')],
-                        ['0', load_lang('limitless')]
-                    ]
-                    for i in t_data:
-                        insert_data += '<a href="javascript:insert_v(\'second\', \'' + i[0] + '\')">(' + i[1] + ')</a> '
-
-                title = load_lang('edit_filter_add')
-                form_data = '''
-                    <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''
-                    <hr class="main_hr">
-                    <input placeholder="''' + load_lang('second') + '''" id="second" name="second" type="text" value="''' + html.escape(time_data) + '''">
-                    <hr class="main_hr">
-                    <input placeholder="''' + load_lang('regex') + '''" name="content" value="''' + html.escape(textarea) + '''" type="text">
-                '''
-            elif tool == 'plus_name_filter':
-                title = load_lang('id_filter_add')
-                form_data = '' + \
-                    load_lang('regex') + \
-                    '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
-                ''
-            elif tool == 'plus_file_filter':
-                title = load_lang('file_filter_add')
-                form_data = '' + \
-                    load_lang('regex') + \
-                    '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
-                ''
-            elif tool == 'plus_email_filter':
-                title = load_lang('email_filter_add')
-                form_data = '' + \
-                    load_lang('email') + \
-                    '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
-                ''
-            elif tool == 'plus_image_license':
-                title = load_lang('image_license_add')
-                form_data = '' + \
-                    load_lang('license') + \
-                    '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
-                ''
-            elif tool == 'plus_extension_filter':
-                title = load_lang('extension_filter_add')
-                form_data = '' + \
-                    load_lang('extension') + \
-                    '<hr class="main_hr">' + \
-                    '<input value="' + html.escape(name if name else '') + '" type="text" name="title">' + \
-                ''
-            else:
-                title = load_lang('edit_tool_add')
-                if name:
-                    curs.execute(db_change("select plus from html_filter where html = ? and kind = 'edit_top'"), [name])
-                    exist = curs.fetchall()
-                    if exist:
-                        value = exist[0][0]
-                    else:
-                        value = ''
-                else:
-                    value = ''
-
-                form_data = '''
-                    ''' + load_lang('title') + '''
-                    <hr class="main_hr">
-                    <input value="''' + html.escape(name if name else '') + '''" type="text" name="title">
-                    <hr class="main_hr">
-                    ''' + load_lang('markup') + '''
-                    <hr class="main_hr">
-                    <input value="''' + html.escape(value) + '''" type="text" name="markup">
-                '''
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [title, wiki_set(), wiki_custom(), wiki_css([get_sub, 0])],
-                data =  '''
-                        <form method="post">
-                            ''' + form_data + '''
-                            <hr class="main_hr">
-                            <button ''' + stat + ''' type="submit">''' + load_lang('add') + '''</button>
-                        </form>
-                        ''',
-                menu = [[re.sub('^plus_', '', tool), load_lang('return')]]
-            ))

+ 4 - 4
route/give_admin_groups.py

@@ -1,13 +1,13 @@
 from .tool.func import *
 
-def give_admin_groups_2(name = None):
+def give_admin_groups_2(name = 'test'):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
         acl_name_list = ['ban', 'nothing', 'toron', 'check', 'acl', 'hidel', 'give', 'owner']
 
         if flask.request.method == 'POST':
-            if admin_check(None, 'admin_plus (' + name + ')') != 1:
+            if admin_check(None, 'auth list add (' + name + ')') != 1:
                 return re_error('/error/3')
             elif name in get_default_admin_group():
                 return re_error('/error/3')
@@ -19,7 +19,7 @@ def give_admin_groups_2(name = None):
 
             conn.commit()
 
-            return redirect('/admin_plus/' + url_pas(name))
+            return redirect('/auth/list/add/' + url_pas(name))
         else:
             data = ''
             exist_list = ['', '', '', '', '', '', '', '']
@@ -63,5 +63,5 @@ def give_admin_groups_2(name = None):
                         <button ''' + state +  ''' type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
-                menu = [['admin_group', load_lang('return')]]
+                menu = [['auth/list', load_lang('return')]]
             ))

+ 26 - 13
route/give_auth.py

@@ -26,19 +26,20 @@ def give_auth(name):
             if admin_check(7, 'admin (' + name + ')') != 1:
                 return re_error('/error/3')
 
-            if flask.request.form.get('select', 'X') == 'X':
+            select_data = flask.request.form.get('select', 'X')
+            if select_data == 'X':
                 select_data = 'user'
-            else:
-                select_data = flask.request.form.get('select', 'X')
 
             curs.execute(db_change('select name from alist where name = ? and acl = "owner"'), [select_data])
             if owner_auth != 1 and curs.fetchall():
                 return re_error('/error/3')
 
-            curs.execute(db_change("update user_set set data = ? where id = ? and name = 'acl'"), [
-                select_data, 
-                name
-            ])
+            curs.execute(db_change("update user_set set data = ? where id = ? and name = 'acl'"), [select_data, name])
+            curs.execute(db_change('delete from user_set where name = "auth_date" and id = ?'), [name])
+
+            time_limit = flask.request.form.get('date', '')
+            if re.search(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$', time_limit):
+                curs.execute(db_change("insert into user_set (id, name, data) values (?, 'auth_date', ?)"), [name, time_limit])
 
             conn.commit()
 
@@ -48,6 +49,7 @@ def give_auth(name):
                 return re_error('/error/3')
 
             div = '<option value="X">' + load_lang('normal') + '</option>'
+            div += '<option value="ban">' + load_lang('ban') + '</option>'
 
             curs.execute(db_change('select distinct name from alist order by name asc'))
             for data in curs.fetchall():
@@ -55,15 +57,26 @@ def give_auth(name):
                     div = '<option value="' + data[0] + '">' + data[0] + '</option>' + div
                 else:
                     div += '<option value="' + data[0] + '">' + data[0] + '</option>'
+                    
+            date_value = ''
+            
+            curs.execute(db_change('select data from user_set where name = "auth_date" and id = ?'), [name])
+            db_data = curs.fetchall()
+            if db_data:
+                date_value = db_data[0][0]
 
             return easy_minify(flask.render_template(skin_check(),
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('authorize') + ')', 0])],
                 data =  '''
-                        <form method="post">
-                            <select name="select">''' + div + '''</select>
-                            <hr class="main_hr">
-                            <button type="submit">''' + load_lang('save') + '''</button>
-                        </form>
-                        ''',
+                    <form method="post">
+                        <div id="opennamu_get_user_info">''' + html.escape(name) + '''</div>
+                        <hr class="main_hr">
+                        <select name="select">''' + div + '''</select>
+                        <hr class="main_hr">
+                        <input type="date" value="''' + date_value + '''" name="date" pattern="\\d{4}-\\d{2}-\\d{2}">
+                        <hr class="main_hr">
+                        <button type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
                 menu = [['manager', load_lang('return')]]
             ))

+ 5 - 5
route/give_delete_admin_group.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def give_delete_admin_group_2(name = None):
+def give_delete_admin_group_2(name = 'test'):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -8,21 +8,21 @@ def give_delete_admin_group_2(name = None):
             return re_error('/error/3')
 
         if flask.request.method == 'POST':
-            admin_check(None, 'alist del ' + name)
+            admin_check(None, 'auth list delete (' + name + ')')
 
             curs.execute(db_change("delete from alist where name = ?"), [name])
             curs.execute(db_change("update user_set set data = 'user' where name = 'acl' and data = ?"), [name])
 
             conn.commit()
 
-            return redirect('/admin_group')
+            return redirect('/auth/list')
         else:
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang("delete_admin_group"), wiki_set(), wiki_custom(), wiki_css(['(' + name + ')', 0])],
                 data = '''
                     <form method=post>
-                        <button type=submit>''' + load_lang('start') + '''</button>
+                        <button type=submit>''' + load_lang('delete') + '''</button>
                     </form>
                 ''',
-                menu = [['admin_group', load_lang('return')]]
+                menu = [['auth/list', load_lang('return')]]
             ))

+ 43 - 65
route/give_user_ban.py

@@ -14,13 +14,18 @@ def give_user_ban(name = None, ban_type = ''):
                 return re_error('/error/3')
 
         if flask.request.method == 'POST':
-            end = flask.request.form.get('second', '0')
-            end = end if end else '0'
+            time_limit = flask.request.form.get('date', '')
+            if re.search(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$', time_limit):
+                end = time_limit + ' 00:00:00'
+            else:
+                end = '0'
             
             regex_get = flask.request.form.get('regex', None)
             login = flask.request.form.get('login', '')
             why = flask.request.form.get('why', '')
 
+            release = flask.request.form.get('release', '')
+
             if ban_type == 'multiple':
                 all_user = re.findall(r'([^\n]+)\n', flask.request.form.get('name', 'test').replace('\r', '') + '\n')
             else:
@@ -57,82 +62,55 @@ def give_user_ban(name = None, ban_type = ''):
                     why,
                     login,
                     ip_check(),
-                    type_d
+                    type_d,
+                    1 if release != '' else 0
                 )
 
             return redirect('/block_log')
         else:
-            curs.execute(db_change("select end, why from rb where block = ? and ongoing = '1' and band = ?"), [name, ban_type])
-            end = curs.fetchall()
-            if end:
-                main_name = name
-                b_now = load_lang('release')
-                now = '(' + b_now + ')'
-                
-                if ban_type == 'regex':
-                    action = 'action="/auth/give/ban_regex/' + url_pas(name) + '"'
-                else:
-                    action = 'action="/auth/give/ban/' + url_pas(name) + '"'
-
-                if end[0][0] == '':
-                    data = '<ul class="opennamu_ul"><li>' + load_lang('limitless') + '</li>'
-                else:
-                    data = '<ul class="opennamu_ul"><li>' + load_lang('period') + ' : ' + end[0][0] + '</li>'
-
-                curs.execute(db_change("select block from rb where block = ? and login = 'O' and ongoing = '1'"), [name])
-                if curs.fetchall():
-                    data += '<li>' + load_lang('login_able') + '</li>'
+            if ban_type == 'multiple':
+                main_name = load_lang('multiple_ban')
+                n_name = '<textarea class="opennamu_textarea_500" placeholder="' + load_lang('name_or_ip_or_regex_multiple') + '" name="name"></textarea><hr class="main_hr">'
+            else:
+                main_name = load_lang('ban')
+                n_name = '<input placeholder="' + load_lang('name_or_ip_or_regex') + '" value="' + (name if name else '') + '" name="name"><hr class="main_hr">'
 
-                if end[0][1] != '':
-                    data += '<li>' + load_lang('why') + ' : ' + end[0][1] + '</li></ul><hr class="main_hr">'
-                else:
-                    data += '</ul><hr class="main_hr">'
+            now = 0
+            
+            if ban_type == 'multiple':
+                action = 'action="/auth/give/ban_multiple"'
             else:
-                if ban_type == 'multiple':
-                    main_name = load_lang('multiple_ban')
-                    n_name = '<textarea class="opennamu_textarea_500" placeholder="' + load_lang('name_or_ip_or_regex_multiple') + '" name="name"></textarea><hr class="main_hr">'
-                else:
-                    main_name = load_lang('ban')
-                    n_name = '<input placeholder="' + load_lang('name_or_ip_or_regex') + '" value="' + (name if name else '') + '" name="name"><hr class="main_hr">'
-                
-                regex = '<input type="checkbox" name="regex" ' + ('checked' if ban_type == 'regex' else '') + '> ' + load_lang('regex') + '<hr class="main_hr">'
-                plus = '<input type="checkbox" name="login"> ' + load_lang('login_able') + '<hr class="main_hr">'
-                now = 0
-                b_now = load_lang('ban')
+                action = 'action="/auth/give/ban"'
                 
-                if ban_type == 'multiple':
-                    action = 'action="/auth/give/ban_multiple"'
-                else:
-                    action = 'action="/auth/give/ban"'
-
-                time_data = [
-                    ['86400', load_lang('1_day')],
-                    ['432000', load_lang('5_day')],
-                    ['2592000', load_lang('30_day')],
-                    ['15552000', load_lang('180_day')],
-                    ['31104000', load_lang('360_day')],
-                    ['0', load_lang('limitless')]
-                ]
-                insert_data = ''
-                for i in time_data:
-                    insert_data += '<a href="javascript:insert_v(\'second\', \'' + i[0] + '\')">(' + i[1] + ')</a> '
+            date_value = ''
+            info_data = ''
+            if name:
+                curs.execute(db_change("select end from rb where block = ? and ongoing = '1'"), [name])
+                db_data = curs.fetchall()
+                if db_data and db_data[0][0] != '':
+                    date_value = db_data[0][0].split()[0]
 
-                data = n_name + '''
-                    ''' + regex + '''
-                    <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">
-                    <input placeholder="''' + load_lang('why') + '''" name="why" type="text">
+                info_data = '''
+                    <div id="opennamu_get_user_info">''' + html.escape(name) + '''</div>
                     <hr class="main_hr">
-                ''' + plus
+                '''
 
             return easy_minify(flask.render_template(skin_check(),
                 imp = [main_name, wiki_set(), wiki_custom(), wiki_css([now, 0])],
-                data = '''
+                data = info_data + '''
                     <form method="post" ''' + action + '''>
-                        ''' + data + '''
-                        <button type="submit">''' + b_now + '''</button>
+                        ''' + n_name + '''
+                        <input type="checkbox" name="regex" ''' + ('checked' if ban_type == 'regex' else '') + '> ' + load_lang('regex') + '''
+                        <hr class="main_hr">
+                        <input type="date" value="''' + date_value + '''" name="date" pattern="\\d{4}-\\d{2}-\\d{2}">
+                        <hr class="main_hr">
+                        <input placeholder="''' + load_lang('why') + '''" name="why" type="text">
+                        <hr class="main_hr">
+                        <input type="checkbox" name="login"> ''' + load_lang('login_able') + '''
+                        <hr class="main_hr">
+                        <input type="checkbox" name="release"> ''' + load_lang('release') + '''
+                        <hr class="main_hr">
+                        <button type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
                 menu = [['manager', load_lang('return')]]

+ 1 - 1
route/list_admin.py

@@ -12,7 +12,7 @@ def list_admin():
         for data in curs.fetchall():
             name = '' + \
                 ip_pas(data[0]) + ' ' + \
-                '<a href="/admin_plus/' + url_pas(data[1]) + '">(' + data[1] + ')</a>' + \
+                '<a href="/auth/list/add/' + url_pas(data[1]) + '">(' + data[1] + ')</a>' + \
             ''
 
             div += '<li>' + name + '</li>'

+ 6 - 7
route/list_admin_auth_use.py

@@ -7,15 +7,14 @@ def list_admin_auth_use(arg_num = 1, arg_search = 'normal'):
         sql_num = (arg_num * 50 - 50) if arg_num * 50 > 0 else 0
 
         if flask.request.method == 'POST':
-            return redirect('/list/admin/auth_use/' + url_pas(flask.request.form.get('search', 'normal')) + '/1')
+            return redirect('/list/admin/auth_use_page/1/' + url_pas(flask.request.form.get('search', 'normal')))
         else:
+            arg_search = 'normal' if arg_search == '' else arg_search
+            
             if arg_search == 'normal':
                 curs.execute(db_change("select who, what, time from re_admin order by time desc limit ?, 50"), [sql_num])
             else:
-                curs.execute(
-                    db_change("select who, what, time from re_admin where what like ? order by time desc limit ?, 50"),
-                    [arg_search + "%", sql_num]
-                )
+                curs.execute(db_change("select who, what, time from re_admin where what like ? order by time desc limit ?, 50"), [arg_search + "%", sql_num])
 
             list_data = '<ul class="opennamu_ul">'
 
@@ -33,7 +32,7 @@ def list_admin_auth_use(arg_num = 1, arg_search = 'normal'):
                 list_data += '<li>' + ip_pas(data[0]) + ' | ' + html.escape(do_data) + ' | ' + data[2] + '</li>'
 
             list_data += '</ul>'
-            list_data += next_fix('/list/admin/auth_use/' + url_pas(arg_search) + '/', arg_num, get_list)
+            list_data += get_next_page_bottom('/list/admin/auth_use_page/{}/' + url_pas(arg_search), arg_num, get_list)
 
             arg_search = html.escape(arg_search) if arg_search != 'normal' else ''
 
@@ -41,7 +40,7 @@ def list_admin_auth_use(arg_num = 1, arg_search = 'normal'):
                 imp = [load_lang('authority_use_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <form method="post">
-                        <input class="opennamu_width_200" name="search" value="''' + arg_search + '''">
+                        <input class="opennamu_width_200" name="search" placeholder="''' + load_lang('start_with_search') + '''" value="''' + arg_search + '''">
                         <button type="submit">''' + load_lang('search') + '''</button>
                     </form>
                     <hr class="main_hr">

+ 2 - 2
route/list_admin_group.py

@@ -11,13 +11,13 @@ def list_admin_group_2():
         for data in curs.fetchall():            
             if  admin_check() == 1 and \
                 not data[0] in org_acl_list:
-                delete_admin_group = ' <a href="/delete_admin_group/' + url_pas(data[0]) + '">(' + load_lang("delete") + ')</a>'
+                delete_admin_group = ' <a href="/auth/list/delete/' + url_pas(data[0]) + '">(' + load_lang("delete") + ')</a>'
             else:
                 delete_admin_group = ''
 
             list_data += '' + \
                 '<li>' + \
-                    '<a href="/admin_plus/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a>' + \
+                    '<a href="/auth/list/add/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a>' + \
                     delete_admin_group + \
                 '</li>' + \
             ''

+ 50 - 7
route/list_image_file.py

@@ -1,19 +1,62 @@
 from .tool.func import *
 
-def list_image_file(arg_num = 1):
+def list_image_file(arg_num = 1, do_type = 0):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
         sql_num = (arg_num * 50 - 50) if arg_num * 50 > 0 else 0
 
-        list_data = '<ul class="opennamu_ul">'
+        list_data = ''
+        if do_type == 0:
+            list_data += '<a href="/list/image">(' + load_lang('image') + ')</a>'
+        else:
+            list_data += '<a href="/list/file">(' + load_lang('normal') + ')</a>'
+        
+        list_data += '<hr class="main_hr">'
 
-        curs.execute(db_change("select title from data where title like 'file:%' limit ?, 50"), [sql_num])
-        data_list = curs.fetchall()
-        for data in data_list:
-            list_data += '<li><a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
+        if do_type == 1:
+            render_data = ''
+            sub_data = ''
+            count = 0
 
-        list_data += next_fix('/list/file/', arg_num, data_list)
+            curs.execute(db_change("select title from data where title like 'file:%' limit ?, 50"), [sql_num])
+            data_list = curs.fetchall()
+            for data in data_list:
+                if count != 0 and count % 4 == 0:
+                    render_data += '||\n'
+                    render_data += sub_data + '||\n'
+                    
+                    sub_data = ''
+
+                render_data += '|| [[' + data[0] + ']] '
+                sub_data += '|| [[:' + data[0] + ']] '
+                count += 1
+
+            if render_data != '':
+                render_data += '||\n'
+                render_data += sub_data + '||'
+
+            end_data = render_set(
+                doc_name = '',
+                doc_data = render_data,
+                data_type = 'view',
+                markup = 'namumark'
+            )
+            list_data += end_data
+        else:
+            list_data += '<ul class="opennamu_ul">'
+
+            curs.execute(db_change("select title from data where title like 'file:%' limit ?, 50"), [sql_num])
+            data_list = curs.fetchall()
+            for data in data_list:
+                list_data += '<li><a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
+
+            list_data += '</ul>'
+
+        if do_type == 0:
+            list_data += next_fix('/list/file/', arg_num, data_list)
+        else:
+            list_data += next_fix('/list/image/', arg_num, data_list)
 
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('image_file_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],

+ 13 - 9
route/list_long_page.py

@@ -6,20 +6,24 @@ def list_long_page(tool = 'long_page', arg_num = 1):
 
         sql_num = (arg_num * 50 - 50) if arg_num * 50 > 0 else 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 class="opennamu_ul">'
         select_data = 'desc' if tool == 'long_page' else 'asc'
         title = 'long_page' if tool == 'long_page' else 'short_page'
 
-        curs.execute(db_change("select title, length(data) from data order by length(data) " + select_data + " limit ?, 50"), [sql_num])
-        db_data = curs.fetchall()
-        for data in db_data:
-            div += '<li>' + str(data[1]) + ' | <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
+        curs.execute(db_change("select doc_name, set_data from data_set where set_name = 'length' and doc_rev = '' order by set_data + 0 " + select_data + " limit ?, 50"), [sql_num])
+        n_list = curs.fetchall()
+        for data in n_list:
+            div += '<li>'
+            div += data[1] + ' | <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a>'
+            
+            curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'doc_type'"), [data[0]])
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                div += ' | ' + db_data[0][0]
+
+            div += '</li>'
 
-        div += '</ul>' + next_fix('/list/document/' + ('long' if title == 'long_page' else 'short') + '/', arg_num, db_data)
+        div += '</ul>' + next_fix('/list/document/' + ('long' if title == 'long_page' else 'short') + '/', arg_num, n_list)
 
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang(title), wiki_set(), wiki_custom(), wiki_css([0, 0])],

+ 30 - 0
route/list_no_link.py

@@ -0,0 +1,30 @@
+from .tool.func import *
+
+def list_no_link(num = 1):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+        
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
+        
+        div = '<ul class="opennamu_ul">'
+        
+        curs.execute(db_change("select doc_name, set_data from data_set where set_name = 'link_count' and doc_rev = '' and set_data = '0' limit ?, 50"), [sql_num])
+        n_list = curs.fetchall()
+        for data in n_list:
+            div += '<li>'
+            div += data[1] + ' | <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a>'
+            
+            curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'doc_type'"), [data[0]])
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                div += ' | ' + db_data[0][0]
+
+            div += '</li>'
+        
+        div += '</ul>' + next_fix('/list/document/no_link/', num, n_list)
+        
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('no_link_document_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = div,
+            menu = [['other', load_lang('return')]]
+        ))

+ 9 - 7
route/list_old_page.py

@@ -4,20 +4,22 @@ def list_old_page(num = 1):
     with get_db_connect() as conn:
         curs = conn.cursor()
         
-        # 리다이렉트 구분도 넣을 예정
-        # 그 전에 로직 개편하고
         sql_num = (num * 50 - 50) if num * 50 > 0 else 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 class="opennamu_ul">'
         
         curs.execute(db_change("select doc_name, set_data from data_set where set_name = 'last_edit' and doc_rev = '' order by set_data asc limit ?, 50"), [sql_num])
         n_list = curs.fetchall()
         for data in n_list:
-            div += '<li>' + data[1] + ' | <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
+            div += '<li>'
+            div += data[1] + ' | <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a>'
+            
+            curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'doc_type'"), [data[0]])
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                div += ' | ' + db_data[0][0]
+
+            div += '</li>'
         
         div += '</ul>' + next_fix('/list/document/old/', num, n_list)
         

+ 1 - 5
route/list_please.py

@@ -6,13 +6,9 @@ def list_please(arg_num = 1):
 
         sql_num = (arg_num * 50 - 50) if arg_num * 50 > 0 else 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 class="opennamu_ul">'
 
-        curs.execute(db_change("select distinct title, link from back where type = 'no' order by title asc limit ?, 50"), [sql_num])
+        curs.execute(db_change("select distinct title, link from back where type = 'no' limit ?, 50"), [sql_num])
         data_list = curs.fetchall()
         for data in data_list:
             div += '' + \

+ 2 - 2
route/login_find_email.py

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

+ 21 - 53
route/login_find_email_check.py

@@ -5,28 +5,24 @@ def login_find_email_check(tool):
     with get_db_connect() as conn:
         curs = conn.cursor()
         
-        if  flask.request.method == 'POST' or \
-            ('c_key' in flask.session and flask.session['c_key'] == 'email_pass'):
+        if flask.request.method == 'POST' or ('c_key' in flask.session and flask.session['c_key'] == 'email_pass'):
             re_set_list = ['c_id', 'c_pw', 'c_ans', 'c_que', 'c_key', 'c_type', 'c_email']
+
             ip = ip_check()
+            
             input_key = flask.request.form.get('key', '')
             user_agent = flask.request.headers.get('User-Agent', '')
         
-            if  'c_type' in flask.session and \
-                flask.session['c_type'] == 'pass_find' and \
-                flask.session['c_key'] == input_key:
-                curs.execute(db_change("update user_set set data = ? where name = 'pw' and id = ?"), [
-                    pw_encode(flask.session['c_key']), 
-                    flask.session['c_id']
-                ])
+            if 'c_type' in flask.session and flask.session['c_type'] == 'pass_find' and flask.session['c_key'] == input_key:
+                user_id = flask.session['c_id']
+                user_pw = flask.session['c_key']
+            
+                curs.execute(db_change("update user_set set data = ? where name = 'pw' and id = ?"), [pw_encode(user_pw), user_id])
                 
                 curs.execute(db_change('select data from user_set where name = "2fa" and id = ?'), [user_id])
                 if curs.fetchall():
                     curs.execute(db_change("update user_set set data = '' where name = '2fa' and id = ?"), [user_id])
         
-                user_id = flask.session['c_id']
-                user_pw = flask.session['c_key']
-        
                 for i in re_set_list:
                     flask.session.pop(i, None)
         
@@ -46,8 +42,7 @@ def login_find_email_check(tool):
                     '',
                     menu = [['user', load_lang('return')]]
                 ))
-            elif    'c_type' in flask.session and \
-                    (flask.session['c_key'] == input_key or flask.session['c_key'] == 'email_pass'):
+            elif 'c_type' in flask.session and (flask.session['c_key'] == input_key or flask.session['c_key'] == 'email_pass'):
                 curs.execute(db_change('select data from other where name = "encode"'))
                 db_data = curs.fetchall()
         
@@ -58,27 +53,21 @@ def login_find_email_check(tool):
                     curs.execute(db_change("select id from user_set limit 1"))
                     first = 1 if not curs.fetchall() else 0
         
-                    curs.execute(db_change("select id from user_set where id = ?"), [
-                        flask.session['c_id']
-                    ])
+                    curs.execute(db_change("select id from user_set where id = ?"), [flask.session['c_id']])
                     if curs.fetchall():
                         for i in re_set_list:
                             flask.session.pop(i, None)
         
-                        return re_error('/error/6')
+                        return re_error('/error/8')
                 
-                    curs.execute(db_change("select id from user_set where id = ? and name = 'application'"), [
-                        flask.session['c_id']
-                    ])
+                    curs.execute(db_change("select id from user_set where id = ? and name = 'application'"), [flask.session['c_id']])
                     if curs.fetchall():
                         for i in re_set_list:
                             flask.session.pop(i, None)
         
-                        return re_error('/error/6')
+                        return re_error('/error/8')
         
-                    curs.execute(db_change(
-                        'select data from other where name = "requires_approval"'
-                    ))
+                    curs.execute(db_change('select data from other where name = "requires_approval"'))
                     requires_approval = curs.fetchall()
                     if requires_approval and requires_approval[0][0] == 'on':
                         user_app_data = {}
@@ -92,13 +81,7 @@ def login_find_email_check(tool):
                         user_app_data['ua'] = user_agent
                         user_app_data['email'] = flask.session['c_email']
                         
-                        curs.execute(db_change(
-                            "insert into user_set (id, name, data) values (?, ?, ?)"
-                        ), [
-                            flask.session['c_id'],
-                            'application',
-                            json.dumps(user_app_data)
-                        ])
+                        curs.execute(db_change("insert into user_set (id, name, data) values (?, ?, ?)"), [flask.session['c_id'], 'application', json.dumps(user_app_data)])
                         conn.commit()
         
                         for i in re_set_list:
@@ -111,27 +94,12 @@ def login_find_email_check(tool):
                         else:
                             user_auth = 'owner'
                         
-                        curs.execute(db_change("insert into user_set (id, name, data) values (?, 'pw', ?)"), [
-                            flask.session['c_id'],
-                            flask.session['c_pw']
-                        ])
-                        curs.execute(db_change("insert into user_set (id, name, data) values (?, 'acl', ?)"), [
-                            flask.session['c_id'],
-                            user_auth
-                        ])
-                        curs.execute(db_change("insert into user_set (id, name, data) values (?, 'date', ?)"), [
-                            flask.session['c_id'],
-                            get_time()
-                        ])
-                        curs.execute(db_change("insert into user_set (id, name, data) values (?, 'encode', ?)"), [
-                            flask.session['c_id'],
-                            db_data[0][0]
-                        ])
-        
-                    curs.execute(db_change("insert into user_set (name, id, data) values ('email', ?, ?)"), [
-                        flask.session['c_id'],
-                        flask.session['c_email']
-                    ])
+                        curs.execute(db_change("insert into user_set (id, name, data) values (?, 'pw', ?)"), [flask.session['c_id'], flask.session['c_pw']])
+                        curs.execute(db_change("insert into user_set (id, name, data) values (?, 'acl', ?)"), [flask.session['c_id'], user_auth])
+                        curs.execute(db_change("insert into user_set (id, name, data) values (?, 'date', ?)"), [flask.session['c_id'], get_time()])
+                        curs.execute(db_change("insert into user_set (id, name, data) values (?, 'encode', ?)"), [flask.session['c_id'], db_data[0][0]])
+        
+                    curs.execute(db_change("insert into user_set (name, id, data) values ('email', ?, ?)"), [flask.session['c_id'], flask.session['c_email']])
                     ua_plus(flask.session['c_id'], ip, user_agent, get_time())
         
                     flask.session['id'] = flask.session['c_id']

+ 13 - 17
route/login_login.py

@@ -22,27 +22,23 @@ def login_login_2():
 
             user_agent = flask.request.headers.get('User-Agent', '')
             user_id = flask.request.form.get('id', '')
-            user_data = {}
+            user_pw = flask.request.form.get('pw', '')
 
-            curs.execute(db_change(
-                'select name, data from user_set where id = ? and name = "pw" or name = "encode"'
-            ), [user_id])
-            sql_data = curs.fetchall()
-            if not sql_data:
+            curs.execute(db_change("select data from user_set where id = ? and name = 'pw'"), [user_id])
+            db_data = curs.fetchall()
+            if not db_data:
                 return re_error('/error/2')
-
-            for i in sql_data:
-                user_data[i[0]] = i[1]
-
-            if len(user_data) < 2:
+            else:
+                db_user_pw = db_data[0][0]
+                
+            curs.execute(db_change("select data from user_set where id = ? and name = 'encode'"), [user_id])
+            db_data = curs.fetchall()
+            if not db_data:
                 return re_error('/error/2')
+            else:
+                db_user_encode = db_data[0][0]
 
-            if pw_check(
-                flask.request.form.get('pw', ''),
-                user_data['pw'],
-                user_data['encode'],
-                user_id
-            ) != 1:
+            if pw_check(user_pw, db_user_pw, db_user_encode, user_id) != 1:
                 if not 'login_count' in flask.session:
                     flask.session['login_count'] = 1
                 else:

+ 2 - 6
route/login_login_2fa.py

@@ -25,6 +25,7 @@ def login_login_2fa_2():
 
             user_agent = flask.request.headers.get('User-Agent', '')
             user_id = flask.session['login_id']
+            user_pw = flask.request.form.get('pw', '')
 
             curs.execute(db_change('select data from user_set where name = "2fa_pw" and id = ?'), [user_id])
             user_1 = curs.fetchall()
@@ -33,12 +34,7 @@ def login_login_2fa_2():
                 user_1 = user_1[0][0]
                 user_2 = curs.fetchall()[0][0]
 
-                pw_check_d = pw_check(
-                    flask.request.form.get('pw', ''),
-                    user_1,
-                    user_2,
-                    user_id
-                )
+                pw_check_d = pw_check(user_pw, user_1, user_2, user_id)
                 if pw_check_d != 1:
                     return re_error('/error/10')
 

+ 2 - 6
route/login_login_2fa_email.py

@@ -25,6 +25,7 @@ def login_login_2fa_email_2():
 
             user_agent = flask.request.headers.get('User-Agent', '')
             user_id = flask.session['b_id']
+            user_pw = flask.request.form.get('pw', '')
 
             curs.execute(db_change('select data from user_set where name = "2fa_pw" and id = ?'), [user_id])
             user_1 = curs.fetchall()
@@ -33,12 +34,7 @@ def login_login_2fa_email_2():
                 user_1 = user_1[0][0]
                 user_2 = curs.fetchall()[0][0]
 
-                pw_check_d = pw_check(
-                    flask.request.form.get('pw', ''),
-                    user_1,
-                    user_2,
-                    user_id
-                )
+                pw_check_d = pw_check(user_pw, user_1, user_2, user_id)
                 if pw_check_d != 1:
                     return re_error('/error/10')
 

+ 0 - 5
route/login_register.py

@@ -47,11 +47,6 @@ def login_register_2():
             if do_user_name_check(user_id) == 1:
                 return re_error('/error/8')
 
-            # 중복 확인
-            curs.execute(db_change("select id from user_set where id = ?"), [user_id])
-            if curs.fetchall():
-                return re_error('/error/6')
-
             if admin != 1:
                 # 이메일 필요시 /register/email로 발송
                 curs.execute(db_change('select data from other where name = "email_have"'))

+ 2 - 2
route/login_register_email.py

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

+ 21 - 13
route/login_register_submit.py

@@ -4,24 +4,35 @@ def login_register_submit_2():
     with get_db_connect() as conn:
         curs = conn.cursor()
 
+        session_reset_list = ['submit_id', 'submit_pw', 'submit_email']
+
         if not 'submit_id' in flask.session:
+            for for_a in session_reset_list:
+                flask.session.pop(for_a, None)
+
             return redirect('/register')
 
         curs.execute(db_change('select data from other where name = "approval_question"'))
         sql_data = curs.fetchall()
         if not sql_data:
+            for for_a in session_reset_list:
+                flask.session.pop(for_a, None)
+
             return redirect('/register')
 
         data_que = sql_data[0][0]
 
+        if do_user_name_check(flask.session['submit_id']) == 1:
+            for for_a in session_reset_list:
+                flask.session.pop(for_a, None)
+        
+            return redirect('/register')
+
         if flask.request.method == 'POST':
             curs.execute(db_change('select data from other where name = "encode"'))
             data_encode = curs.fetchall()
             data_encode = data_encode[0][0]
 
-            user_ip = ip_check()
-            user_agent = flask.request.headers.get('User-Agent', '')
-
             user_app_data = {}
             user_app_data['id'] = flask.session['submit_id']
             user_app_data['pw'] = pw_encode(flask.session['submit_pw'])
@@ -34,19 +45,16 @@ def login_register_submit_2():
             else:
                 user_app_data['email'] = ''
 
-            curs.execute(db_change(
-                "insert into user_set (id, name, data) values (?, ?, ?)"
-            ), [
-                flask.session['submit_id'],
-                'application',
-                json.dumps(user_app_data)
-            ])
+            for for_a in session_reset_list:
+                flask.session.pop(for_a, None)
+
+            curs.execute(db_change("insert into user_set (id, name, data) values (?, ?, ?)"), [user_app_data['id'], 'application', json.dumps(user_app_data)])
             conn.commit()
-            
+
             for for_a in get_admin_list():
-                add_alarm(for_a, flask.session['submit_id'], '<a href="/app_submit">' + load_lang('new_application') + '</a>')
+                add_alarm(for_a, user_app_data['id'], '<a href="/app_submit">' + load_lang('new_application') + '</a>')
 
-            return redirect('/')
+            return re_error('/error/43')
         else:
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('approval_question'), wiki_set(), wiki_custom(), wiki_css([0, 0])],

+ 16 - 1
route/main_func_easter_egg.py

@@ -11,4 +11,19 @@ def main_func_easter_egg():
                 curs.execute(db_change('insert into user_set (name, id, data) values ("get_🥚", ?, "Y")'), [ip])
                 conn.commit()
     
-        return redirect('/easter_egg_go')
+        if platform.system() == 'Linux':
+            if platform.machine() in ["AMD64", "x86_64"]:
+                data = os.popen(os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".amd64.bin")).read()
+            else:
+                data = os.popen(os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".arm64.bin")).read()
+        else:
+            if platform.machine() in ["AMD64", "x86_64"]:
+                data = os.popen(os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".amd64.exe")).read()
+            else:
+                data = os.popen(os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".arm64.exe")).read()
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = ['Easter Egg', wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = data,
+            menu = 0
+        ))

+ 1 - 1
route/main_func_error_404.py

@@ -11,4 +11,4 @@ def main_func_error_404(e = ''):
             db_data = curs.fetchall()
             db_data = db_data[0][0] if db_data and db_data[0][0] != '' else 'FrontPage'
             
-            return redirect('/w/' + db_data)
+            return redirect('/w/' + url_pas(db_data))

+ 1 - 1
route/main_setting.py

@@ -10,7 +10,7 @@ def main_setting():
             ['head', load_lang('main_head')],
             ['body/top', load_lang('main_body')],
             ['body/bottom', load_lang('main_bottom_body')],
-            ['sitemap', load_lang('sitemap_management')],
+            ['sitemap_set', load_lang('sitemap_management')],
             ['top_menu', load_lang('top_menu_setting')],
             ['skin_set', load_lang('main_skin_set_default')],
             ['acl', load_lang('main_acl_setting')]

+ 26 - 31
route/main_setting_acl.py

@@ -15,54 +15,43 @@ def main_setting_acl():
             8 : 'document_move_acl',
             9 : 'document_delete_acl',
             10 : 'slow_edit_acl',
-            11 : 'edit_bottom_compulsion_acl'
+            11 : 'edit_bottom_compulsion_acl',
+            12 : 'recaptcha_pass_acl',
+            13 : 'recaptcha_one_check_five_pass_acl'
+        }
+        default_list = {
+            12 : 'user'
         }
 
         if flask.request.method == 'POST':
             if admin_check(None, 'edit_set (acl)') != 1:
                 return re_error('/ban')
             else:
-                for i in i_list:
-                    curs.execute(db_change("update other set data = ? where name = ?"), [
-                        flask.request.form.get(i_list[i], 'normal'),
-                        i_list[i]
-                    ])
-
+                curs.executemany(db_change("update other set data = ? where name = ?"), [[flask.request.form.get(i_list[for_a], 'normal'), i_list[for_a]] for for_a in i_list])
                 conn.commit()
 
                 return redirect('/setting/acl')
         else:
             d_list = {}
+            disable = 'disabled' if admin_check() != 1 else ''
+            acl_div = ['' for _ in range(0, len(i_list))]
 
-            if admin_check() != 1:
-                disable = 'disabled'
-            else:
-                disable = ''
-
-            for i in i_list:
-                curs.execute(db_change('select data from other where name = ?'), [i_list[i]])
+            for for_a in i_list:
+                curs.execute(db_change('select data from other where name = ?'), [i_list[for_a]])
                 sql_d = curs.fetchall()
                 if sql_d:
-                    d_list[i] = sql_d[0][0]
+                    d_list[for_a] = sql_d[0][0]
                 else:
-                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i_list[i], 'normal'])
-                    d_list[i] = 'normal'
+                    default_data = 'normal' if not for_a in default_list else default_list[for_a]
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i_list[for_a], default_data])
+                    d_list[for_a] = default_data
 
             conn.commit()
 
-            acl_div = []
-            for i in range(0, len(i_list)):
-                acl_div += ['']
-
             acl_list = get_acl_list()
-            for i in range(0, len(i_list)):
+            for for_a in range(0, len(i_list)):
                 for data_list in acl_list:
-                    if data_list == d_list[i + 1]:
-                        check = 'selected="selected"'
-                    else:
-                        check = ''
-
-                    acl_div[i] += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
+                    acl_div[for_a] += '<option value="' + data_list + '" ' + ('selected="selected"' if data_list == d_list[for_a + 1] else '') + '>' + (data_list if data_list != '' else 'normal') + '</option>'
 
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('main_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
@@ -89,12 +78,12 @@ def main_setting_acl():
                         <h2>''' + load_lang('upload_acl') + '''</h2>
                         <select ''' + disable + ''' name="upload_acl">''' + acl_div[2] + '''</select>
                         
+                        <h3>''' + load_lang('many_upload_acl') + '''</h3>
+                        <select ''' + disable + ''' name="many_upload_acl">''' + acl_div[4] + '''</select>
+                        
                         <h2>''' + load_lang('view_acl') + '''</h2>
                         <select ''' + disable + ''' name="all_view_acl">''' + acl_div[3] + '''</select>
                         
-                        <h2>''' + load_lang('many_upload_acl') + '''</h2>
-                        <select ''' + disable + ''' name="many_upload_acl">''' + acl_div[4] + '''</select>
-                        
                         <h2>''' + load_lang('vote_acl') + '''</h2>
                         <select ''' + disable + ''' name="vote_acl">''' + acl_div[5] + '''</select>
 
@@ -103,6 +92,12 @@ def main_setting_acl():
 
                         <h2>''' + load_lang('edit_bottom_compulsion_acl') + '''</h2>
                         <select ''' + disable + ''' name="edit_bottom_compulsion_acl">''' + acl_div[10] + '''</select>
+
+                        <h2>''' + load_lang('recaptcha_pass_acl') + '''</h2>
+                        <select ''' + disable + ''' name="recaptcha_pass_acl">''' + acl_div[11] + '''</select>
+
+                        <h3>''' + load_lang('recaptcha_one_check_five_pass_acl') + '''</h3>
+                        <select ''' + disable + ''' name="recaptcha_one_check_five_pass_acl">''' + acl_div[12] + '''</select>
                         
                         <hr class="main_hr">
                         <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>

+ 6 - 4
route/main_setting_head.py

@@ -39,10 +39,15 @@ def main_setting_head(num, skin_name = '', set_preview = 0):
             else:
                 return redirect('/setting/' + end_r + '/' + skin_name)
         else:
+            title = ''
+            start = ''
+            form_action = ''
+            data_preview = ''
+            plus = ''
+
             if num == 4:
                 curs.execute(db_change("select data from other where name = 'body'"))
                 title = '_body'
-                start = ''
                 form_action = 'formaction="/setting/body/top"'
                 data_preview = flask.request.form.get('content', '') if set_preview == 1 else ''
                 plus = '''
@@ -53,7 +58,6 @@ def main_setting_head(num, skin_name = '', set_preview = 0):
             elif num == 7:
                 curs.execute(db_change("select data from other where name = 'bottom_body'"))
                 title = '_bottom_body'
-                start = ''
                 data_preview = flask.request.form.get('content', '') if set_preview == 1 else ''
                 form_action = 'formaction="/setting/body/bottom"'
                 plus = '''
@@ -75,8 +79,6 @@ def main_setting_head(num, skin_name = '', set_preview = 0):
                     </span>
                     <hr class="main_hr">
                 '''
-                form_action = ''
-                plus = ''
 
             if set_preview == 1:
                 data = data_preview

+ 67 - 27
route/main_setting_main.py

@@ -23,7 +23,7 @@ def main_setting_main(db_set):
             19 : ['slow_edit', ''],
             20 : ['requires_approval', ''],
             21 : ['backup_where', ''],
-            22 : ['domain', flask.request.host],
+            22 : ['domain', ''],
             23 : ['ua_get', ''],
             24 : ['enable_comment', ''],
             25 : ['enable_challenge', ''],
@@ -41,6 +41,12 @@ def main_setting_main(db_set):
             37 : ['move_with_redirect', ''],
             38 : ['slow_thread', ''],
             39 : ['edit_timeout', '5'],
+            40 : ['document_content_max_length', ''],
+            41 : ['backup_count', ''],
+            42 : ['ua_expiration_date', ''],
+            43 : ['auth_history_expiration_date', ''],
+            44 : ['auth_history_off', ''],
+            45 : ['user_name_level', '']
         }
 
         if flask.request.method == 'POST':
@@ -61,10 +67,7 @@ def main_setting_main(db_set):
                 curs.execute(db_change('select data from other where name = ?'), [setting_list[i][0]])
                 db_data = curs.fetchall()
                 if not db_data:
-                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [
-                        setting_list[i][0],
-                        setting_list[i][1]
-                    ])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [setting_list[i][0], setting_list[i][1]])
 
                 d_list[i] = db_data[0][0] if db_data else setting_list[i][1]
             else:
@@ -90,7 +93,7 @@ def main_setting_main(db_set):
                 else:
                     tls_select += '<option value="' + tls_select_one + '">' + tls_select_one + '</option>'
 
-            check_box_div = [7, 8, '', 20, 23, 24, 25, 26, 31, 33, 34, 35, 36, 37]
+            check_box_div = [7, 8, '', 20, 23, 24, 25, 26, 31, 33, 34, 35, 36, 37, 44, 45]
             for i in range(0, len(check_box_div)):
                 acl_num = check_box_div[i]
                 if acl_num != '' and d_list[acl_num]:
@@ -113,6 +116,7 @@ def main_setting_main(db_set):
                 data = render_simple_set('''
                     <form method="post">
                         <h2>''' + load_lang('basic_set') + '''</h2>
+                        
                         <span>''' + load_lang('wiki_name') + '''</span>
                         <hr class="main_hr">
                         <input name="name" value="''' + html.escape(d_list[0]) + '''">
@@ -131,7 +135,7 @@ def main_setting_main(db_set):
                         <select name="http_select">''' + tls_select + '''</select>
                         <hr class="main_hr">
 
-                        <span>''' + load_lang('domain') + '''</span> (EX : 2du.pythonanywhere.com)
+                        <span>''' + load_lang('domain') + '''</span> (EX : 2du.pythonanywhere.com) (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="domain" value="''' + html.escape(d_list[22]) + '''">
                         <hr class="main_hr">
@@ -156,25 +160,42 @@ def main_setting_main(db_set):
                         <select name="encode">''' + encode_select + '''</select>
                         <hr class="main_hr">
                         
-                        <input type="checkbox" name="wiki_access_password_need" ''' + check_box_div[8] + '''> ''' + load_lang('set_wiki_access_password_need') + ''' (''' + load_lang('restart_required') + ''') (''' + load_lang('beta') + ''')
+                        <input type="checkbox" name="wiki_access_password_need" ''' + check_box_div[8] + '''> ''' + load_lang('set_wiki_access_password_need') + ''' (''' + load_lang('restart_required') + ''')
                         <hr class="main_hr">
-                        <span>''' + load_lang('set_wiki_access_password') + ''' (''' + load_lang('restart_required') + ''') (''' + load_lang('beta') + ''')</span>
+                        
+                        <span>''' + load_lang('set_wiki_access_password') + '''</span> (''' + load_lang('restart_required') + ''')
                         <hr class="main_hr">
                         <input type="password" name="wiki_access_password" value="''' + html.escape(d_list[32]) + '''">
+                        
+                        <h3>''' + load_lang('authority_use_list') + '''</h3>
+                        
+                        <input type="checkbox" name="auth_history_off" ''' + check_box_div[14] + '''> ''' + load_lang('authority_use_list_off') + '''
+                        <hr class="main_hr">
+                        
+                        <span>''' + load_lang('authority_use_list_expiration_date') + '''</span> (''' + load_lang('day') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
+                        <hr class="main_hr">
+                        <input name="auth_history_expiration_date" value="''' + html.escape(d_list[43]) + '''">
+                        <hr class="main_hr">
 
                         <h3>''' + load_lang('communication_set') + '''</h3>
+                        
                         <input type="checkbox" name="enable_comment" ''' + check_box_div[5] + '''> ''' + load_lang('enable_comment_function') + ''' (''' + load_lang('not_working') + ''')
                         <hr class="main_hr">
 
                         <input type="checkbox" name="enable_challenge" ''' + check_box_div[6] + '''> ''' + load_lang('enable_challenge_function') + ''' (''' + load_lang('not_working') + ''')
                         <hr class="main_hr">
 
+                        <input type="checkbox" name="user_name_level" ''' + check_box_div[15] + '''> ''' + load_lang('display_level_in_user_name') + '''
+                        <hr class="main_hr">
+
                         <h2>''' + load_lang('design_set') + '''</h2>
+                        
                         <span>''' + load_lang('wiki_skin') + '''</span>
                         <hr class="main_hr">
                         <select name="skin">''' + load_skin(d_list[5] if d_list[5] != '' else 'ringo') + '''</select>
 
                         <h2>''' + load_lang('render_set') + '''</h2>
+                        
                         <input type="checkbox" name="namumark_compatible" ''' + check_box_div[10] + '''> ''' + load_lang('namumark_fully_compatible_mode') + '''
                         <hr class="main_hr">
                         
@@ -182,6 +203,7 @@ def main_setting_main(db_set):
                         <hr class="main_hr">
 
                         <h2>''' + load_lang('login_set') + '''</h2>
+                        
                         <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
                         <hr class="main_hr">
 
@@ -194,12 +216,19 @@ def main_setting_main(db_set):
                         <input type="checkbox" name="requires_approval" ''' + check_box_div[3] + '''> ''' + load_lang('requires_approval') + '''
                         <hr class="main_hr">
 
+                        <span>''' + load_lang('password_min_length') + '''</span> (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
+                        <hr class="main_hr">
+                        <input name="password_min_length" value="''' + html.escape(d_list[30]) + '''">
+
+                        <h3>''' + load_lang('ua') + '''</h3>
+                        
                         <input type="checkbox" name="ua_get" ''' + check_box_div[4] + '''> ''' + load_lang('ua_get_off') + '''
                         <hr class="main_hr">
                         
-                        <span>''' + load_lang('password_min_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('ua_expiration_date') + '''</span> (''' + load_lang('day') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
+                        <hr class="main_hr">
+                        <input name="ua_expiration_date" value="''' + html.escape(d_list[42]) + '''">
                         <hr class="main_hr">
-                        <input name="password_min_length" value="''' + html.escape(d_list[30]) + '''">
                         
                         <h2>''' + load_lang('server_set') + '''</h2>
 
@@ -208,38 +237,44 @@ def main_setting_main(db_set):
                         <select name="update">''' + branch_div + '''</select>
 
                         <span ''' + sqlite_only + '''>
-                            <h3>''' + load_lang('sqlite_only') + '''</h3>
-                            <span>
-                                ''' + load_lang('backup_interval') + ''' (''' + load_lang('hour') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''') ''' + \
-                                '''(''' + load_lang('restart_required') + ''')</span>
+                            <h3>''' + load_lang('backup') + ''' (''' + load_lang('sqlite_only') + ''')</h3>
+                            
+                            <span>''' + load_lang('backup_warning') + ''' (EX : data_YYYYMMDDHHMMSS.db)</span>
+                            <hr class="main_hr">
+                            <hr class="main_hr">
+                            
+                            <span>''' + load_lang('backup_interval') + '''</span> (''' + load_lang('hour') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                             <hr class="main_hr">
                             <input name="back_up" value="''' + html.escape(d_list[9]) + '''">
                             <hr class="main_hr">
-
-                            <span>
-                                ''' + load_lang('backup_where') + ''' (''' + load_lang('default') + ''' : ''' + load_lang('empty') + ''') ''' + \
-                                '''(''' + load_lang('restart_required') + ''') (''' + load_lang('example') + ''' : ./data/backup.db)
-                            </span>
+                            
+                            <span>''' + load_lang('backup_where') + '''</span> (''' + load_lang('default') + ''' : ''' + load_lang('empty') + ''') (''' + load_lang('example') + ''' : ./data/backup.db)
                             <hr class="main_hr">
                             <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
                             <hr class="main_hr">
+
+                            <span>''' + load_lang('backup_count') + '''</span> (''' + load_lang('default') + ''' : ''' + load_lang('empty') + ''')
+                            <hr class="main_hr">
+                            <input name="backup_count" value="''' + html.escape(d_list[41]) + '''">
+                            <hr class="main_hr">
                         </span>
 
                         <h2>''' + load_lang('edit_set') + '''</h2>
-                        <span>''' + load_lang('slow_edit') + ''' (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        
+                        <span>''' + load_lang('slow_edit') + '''</span> (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="slow_edit" value="''' + html.escape(d_list[19]) + '''">
                         <hr class="main_hr">
                         
-                        <input type="checkbox" name="edit_bottom_compulsion" ''' + check_box_div[7] + '''> ''' + load_lang('edit_bottom_compulsion') + ''' (''' + load_lang('beta') + ''')
+                        <input type="checkbox" name="edit_bottom_compulsion" ''' + check_box_div[7] + '''> ''' + load_lang('edit_bottom_compulsion') + '''
                         <hr class="main_hr">
                         
-                        <span>''' + load_lang('title_max_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('title_max_length') + '''</span> (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="title_max_length" value="''' + html.escape(d_list[28]) + '''">
                         <hr class="main_hr">
                         
-                        <span>''' + load_lang('title_topic_max_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('title_topic_max_length') + '''</span> (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="title_topic_max_length" value="''' + html.escape(d_list[29]) + '''">
                         <hr class="main_hr">
@@ -249,22 +284,27 @@ def main_setting_main(db_set):
                         <input name="upload" value="''' + html.escape(d_list[4]) + '''">
                         <hr class="main_hr">
                         
-                        <input type="checkbox" name="history_recording_off" ''' + check_box_div[9] + '''> ''' + load_lang('set_history_recording_off') + ''' (''' + load_lang('beta') + ''')
+                        <input type="checkbox" name="history_recording_off" ''' + check_box_div[9] + '''> ''' + load_lang('set_history_recording_off') + '''
                         <hr class="main_hr">
 
                         <input type="checkbox" name="move_with_redirect" ''' + check_box_div[13] + '''> ''' + load_lang('move_with_redirect') + ''' (''' + load_lang('not_working') + ''')
                         <hr class="main_hr">
 
-                        <span>''' + load_lang('slow_thread') + ''' (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
+                        <span>''' + load_lang('slow_thread') + '''</span> (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
                         <hr class="main_hr">
                         <input name="slow_thread" value="''' + html.escape(d_list[38]) + '''">
                         <hr class="main_hr">
 
-                        <span>''' + load_lang('edit_timeout') + ''' (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''') (''' + load_lang('linux_only') + ''')</span>
+                        <span>''' + load_lang('edit_timeout') + '''</span> (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''') (''' + load_lang('linux_only') + ''')
                         <hr class="main_hr">
                         <input name="edit_timeout" value="''' + html.escape(d_list[39]) + '''">
                         <hr class="main_hr">
 
+                        <span>''' + load_lang('document_content_max_length') + '''</span> (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
+                        <hr class="main_hr">
+                        <input name="document_content_max_length" value="''' + html.escape(d_list[40]) + '''">
+                        <hr class="main_hr">
+
                         <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 '''),

+ 23 - 10
route/main_setting_phrase.py

@@ -28,17 +28,16 @@ def main_setting_phrase():
             'topic_text',
             'phrase_user_page_admin',
             'phrase_user_page_owner',
-            'phrase_old_page_warring',
+            'phrase_old_page_warning',
             'bbs_help',
-            'bbs_comment_help'
+            'bbs_comment_help',
+            'outdated_doc_warning',
+            'outdated_doc_warning_date',
+            'category_text',
+            'redirect_text'
         ]
         if flask.request.method == 'POST':
-            for i in i_list:
-                curs.execute(db_change("update other set data = ? where name = ?"), [
-                    flask.request.form.get(i, ''),
-                    i
-                ])
-
+            curs.executemany(db_change("update other set data = ? where name = ?"), [[flask.request.form.get(for_a, ''), for_a] for for_a in i_list])
             conn.commit()
 
             admin_check(None, 'edit_set (phrase)')
@@ -46,7 +45,6 @@ def main_setting_phrase():
             return redirect('/setting/phrase')
         else:
             d_list = []
-
             for i in i_list:
                 curs.execute(db_change('select data from other where name = ?'), [i])
                 sql_d = curs.fetchall()
@@ -124,7 +122,7 @@ def main_setting_phrase():
                         <h2>''' + load_lang('phrase_user_page_owner') + ''' (HTML)</h2>
                         <textarea class="opennamu_textarea_100" name="''' + i_list[19] + '''">''' + html.escape(d_list[19]) + '''</textarea>
 
-                        <h2>''' + load_lang('phrase_old_page_warring') + ''' (''' + load_lang('beta') + ''') (HTML)</h2>
+                        <h2>''' + load_lang('phrase_old_page_warning') + ''' (''' + load_lang('beta') + ''') (HTML)</h2>
                         <textarea class="opennamu_textarea_100" name="''' + i_list[20] + '''">''' + html.escape(d_list[20]) + '''</textarea>
                         
                         <h2>''' + load_lang('bbs_help') + '''</h2>
@@ -133,6 +131,21 @@ def main_setting_phrase():
                         <h2>''' + load_lang('bbs_comment_help') + '''</h2>
                         <textarea class="opennamu_textarea_100" name="''' + i_list[22] + '''">''' + html.escape(d_list[22]) + '''</textarea>
 
+                        <h2>''' + load_lang('outdated_doc_warning') + '''  (HTML)</h2>
+                        <span>''' + load_lang('period') + '''</span> (''' + load_lang('day') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
+                        <hr class="main_hr">
+                        <input name="''' + i_list[24] + '''" value="''' + html.escape(d_list[24]) + '''">
+                        <hr class="main_hr">
+                        <textarea class="opennamu_textarea_100" name="''' + i_list[23] + '''" placeholder="''' + load_lang('old_page_warning') + '''">''' + html.escape(d_list[23]) + '''</textarea>
+
+                        <h2>''' + load_lang('category') + '''</h2>
+                        <input name="''' + i_list[25] + '''" value="''' + html.escape(d_list[25]) + '''">
+
+                        <h2>''' + load_lang('redirect') + '''</h2>
+                        <span>EX : {0} ➤ {1}</span>
+                        <hr class="main_hr">
+                        <input name="''' + i_list[26] + '''" value="''' + html.escape(d_list[26]) + '''">
+
                         <hr class="main_hr">
                         <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>

+ 26 - 37
route/main_setting_sitemap.py

@@ -1,36 +1,47 @@
 from .tool.func import *
 
-def main_setting_sitemap():
+def main_setting_sitemap(do_type = 0):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
-        if admin_check() != 1:
-            return re_error('/ban')
+        if not do_type == 1:
+            if admin_check() != 1:
+                return re_error('/ban')
         
-        if flask.request.method == 'POST':
-            admin_check(None, 'make sitemap')
+        if do_type == 1 or flask.request.method == 'POST':
+            if not do_type == 1:
+                admin_check(None, 'make sitemap')
 
             data = '' + \
                 '<?xml version="1.0" encoding="UTF-8"?>\n' + \
                 '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + \
             ''
 
-            if flask.request.form.get('exclude_domain', None):
+            curs.execute(db_change('select data from other where name = "sitemap_auto_exclude_domain"'))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
                 domain = ''
             else:
                 domain = load_domain('full')
 
             sql_add = ''
-            if flask.request.form.get('exclude_user_page', None):
+
+            curs.execute(db_change('select data from other where name = "sitemap_auto_exclude_user_page"'))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
                 sql_add += ' title not like "user:%"'
 
-            if flask.request.form.get('exclude_file_page', None):
+            curs.execute(db_change('select data from other where name = "sitemap_auto_exclude_file_page"'))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
                 if sql_add != '':
                     sql_add += ' and'
 
                 sql_add += ' title not like "file:%"'
 
-            if flask.request.form.get('exclude_category_page', None):
+            curs.execute(db_change('select data from other where name = "sitemap_auto_exclude_category_page"'))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
                 if sql_add != '':
                     sql_add += ' and'
 
@@ -39,7 +50,6 @@ def main_setting_sitemap():
             if sql_add != '':
                 sql_add = ' where' + sql_add
 
-            print(sql_add)
             curs.execute(db_change("select title from data" + sql_add))
             all_data = curs.fetchall()
 
@@ -79,38 +89,17 @@ def main_setting_sitemap():
                 f.write(data)
                 f.close()
 
-            return redirect('/setting/sitemap')
+            if not do_type == 1:
+                return redirect('/setting/sitemap')
+            else:
+                return ''
         else:
-            sitemap_list = ''
-            if os.path.exists('sitemap.xml'):
-                sitemap_list += '<a href="/sitemap.xml">(' + load_lang('view') + ')</a>'
-
-                for_a = 0
-                while os.path.exists('sitemap_' + str(for_a) + '.xml'):
-                    sitemap_list += ' <a href="/sitemap_' + str(for_a) + '.xml">(sitemap_' + str(for_a) + '.xml)</a>'
-
-                    for_a += 1
-
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('sitemap_management'), wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('beta') + ')', 0])],
+                imp = [load_lang('sitemap_manual_create'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    ''' + sitemap_list + '''
-                    <hr class="main_hr">
                     <form method="post">
-                        <input type="checkbox" name="exclude_domain"> ''' + load_lang('stiemap_exclude_domain') + '''
-                        <hr class="main_hr">
-
-                        <input type="checkbox" name="exclude_user_page"> ''' + load_lang('stiemap_exclude_user_page') + '''
-                        <hr class="main_hr">
-
-                        <input type="checkbox" name="exclude_file_page"> ''' + load_lang('stiemap_exclude_file_page') + '''
-                        <hr class="main_hr">
-
-                        <input type="checkbox" name="exclude_category_page"> ''' + load_lang('stiemap_exclude_category_page') + '''
-                        <hr class="main_hr">
-
                         <button id="opennamu_save_button" type="submit">''' + load_lang('create') + '''</button>
                     </form>
                 ''',
-                menu = [['setting', load_lang('return')]]
+                menu = [['setting/sitemap_set', load_lang('return')]]
             ))

+ 91 - 0
route/main_setting_sitemap_set.py

@@ -0,0 +1,91 @@
+from .tool.func import *
+
+def main_setting_sitemap_set():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if admin_check() != 1:
+            return re_error('/ban')
+        
+        setting_list = {
+            0 : ['sitemap_auto_exclude_domain', ''],
+            1 : ['sitemap_auto_exclude_user_page', ''],
+            2 : ['sitemap_auto_exclude_file_page', ''],
+            3 : ['sitemap_auto_exclude_category_page', ''],
+            4 : ['sitemap_auto_make', '']
+        }
+
+        if flask.request.method == 'POST':
+            for i in setting_list:
+                curs.execute(db_change("update other set data = ? where name = ?"), [
+                    flask.request.form.get(setting_list[i][0], setting_list[i][1]),
+                    setting_list[i][0]
+                ])
+
+            conn.commit()
+
+            admin_check(None, 'edit_set (sitemap)')
+
+            return redirect('/setting/sitemap_set')
+        else:
+            d_list = {}
+            for i in setting_list:
+                curs.execute(db_change('select data from other where name = ?'), [setting_list[i][0]])
+                db_data = curs.fetchall()
+                if not db_data:
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [
+                        setting_list[i][0],
+                        setting_list[i][1]
+                    ])
+
+                d_list[i] = db_data[0][0] if db_data else setting_list[i][1]
+            else:
+                conn.commit()
+
+            check_box_div = [0, 1, 2, 3, 4, '']
+            for i in range(0, len(check_box_div)):
+                acl_num = check_box_div[i]
+                if acl_num != '' and d_list[acl_num]:
+                    check_box_div[i] = 'checked="checked"'
+                else:
+                    check_box_div[i] = ''
+
+            sitemap_list = ''
+            if os.path.exists('sitemap.xml'):
+                sitemap_list += '<a href="/sitemap.xml">(' + load_lang('view') + ')</a>'
+
+                for_a = 0
+                while os.path.exists('sitemap_' + str(for_a) + '.xml'):
+                    sitemap_list += ' <a href="/sitemap_' + str(for_a) + '.xml">(sitemap_' + str(for_a) + '.xml)</a>'
+
+                    for_a += 1
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('sitemap_management'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                data = '''
+                    ''' + sitemap_list + '''
+                    <hr class="main_hr">
+                    <form method="post">
+                        <a href="/setting/sitemap">(''' + load_lang('sitemap_manual_create') + ''')</a>
+                        <hr class="main_hr">
+
+                        <input type="checkbox" ''' + check_box_div[4] + ''' name="sitemap_auto_make"> ''' + load_lang('sitemap_auto_make') + '''
+                        <hr class="main_hr">
+
+                        <input type="checkbox" ''' + check_box_div[0] + ''' name="sitemap_auto_exclude_domain"> ''' + load_lang('stiemap_exclude_domain') + '''
+                        <hr class="main_hr">
+
+                        <input type="checkbox" ''' + check_box_div[1] + ''' name="sitemap_auto_exclude_user_page"> ''' + load_lang('stiemap_exclude_user_page') + '''
+                        <hr class="main_hr">
+
+                        <input type="checkbox" ''' + check_box_div[2] + ''' name="sitemap_auto_exclude_file_page"> ''' + load_lang('stiemap_exclude_file_page') + '''
+                        <hr class="main_hr">
+
+                        <input type="checkbox" ''' + check_box_div[3] + ''' name="sitemap_auto_exclude_category_page"> ''' + load_lang('stiemap_exclude_category_page') + '''
+                        <hr class="main_hr">
+
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
+                menu = [['setting', load_lang('return')]]
+            ))

+ 55 - 13
route/main_setting_skin_set.py

@@ -6,8 +6,7 @@ def main_setting_skin_set():
     with get_db_connect() as conn:
         curs = conn.cursor()
 
-        ip = ip_check()
-        if ban_check(ip) == 1:
+        if admin_check() != 1:
             return re_error('/ban')
             
         set_list = user_setting_skin_set_main_set_list()
@@ -16,15 +15,9 @@ def main_setting_skin_set():
             for for_b in set_list:
                 curs.execute(db_change('select data from other where name = ?'), [for_b])
                 if curs.fetchall():
-                    curs.execute(db_change("update other set data = ? where name = ?"), [
-                        flask.request.form.get(for_b, set_list[for_b][0][0]),
-                        for_b
-                    ])
+                    curs.execute(db_change("update other set data = ? where name = ?"), [flask.request.form.get(for_b, set_list[for_b][0][0]), for_b])
                 else:
-                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [
-                        for_b, 
-                        flask.request.form.get(for_b, set_list[for_b][0][0])
-                    ])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [for_b, flask.request.form.get(for_b, set_list[for_b][0][0])])
             
             conn.commit()
 
@@ -46,77 +39,126 @@ def main_setting_skin_set():
                     else:
                         set_data[for_b] += '<option value="' + for_a[0] + '">' + for_a[1] + '</option>'
 
+            set_data_main = { for_b : '' for for_b in set_list }
+
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('main_skin_set_default'), wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('beta') + ')', 0])],
                 data = render_simple_set('''
                     <form method="post">
                         <h2>''' + load_lang("render") + '''</h2>
                         <h3>''' + load_lang("strike") + '''</h3>
+                        ''' + set_data_main["main_css_strike"] + '''
                         <select name="main_css_strike">
                             ''' + set_data["main_css_strike"] + '''
                         </select>
                         <h3>''' + load_lang("bold") + '''</h3>
+                        ''' + set_data_main["main_css_bold"] + '''
                         <select name="main_css_bold">
                             ''' + set_data["main_css_bold"] + '''
                         </select>
                         <h3>''' + load_lang("category") + '''</h3>
                         <h4>''' + load_lang("position") + '''</h4>
+                        ''' + set_data_main["main_css_category_set"] + '''
                         <select name="main_css_category_set">
                             ''' + set_data["main_css_category_set"] + '''
                         </select>
                         <h4>''' + load_lang("category_change_title") + '''</h4>
+                        ''' + set_data_main["main_css_category_change_title"] + '''
                         <select name="main_css_category_change_title">
                             ''' + set_data["main_css_category_change_title"] + '''
                         </select>
                         <h3>''' + load_lang("footnote") + ''' (''' + load_lang('beta') + ''')</h3>
                         <h4>''' + load_lang("footnote_render") + '''</h4>
+                        ''' + set_data_main["main_css_footnote_set"] + '''
                         <select name="main_css_footnote_set">
                             ''' + set_data["main_css_footnote_set"] + '''
                         </select>
                         <h4>''' + load_lang("footnote_number") + '''</h4>
+                        ''' + set_data_main["main_css_footnote_number"] + '''
                         <select name="main_css_footnote_number">
                             ''' + set_data["main_css_footnote_number"] + '''
                         </select>
                         <h4>''' + load_lang("footnote_real_num_view") + '''</h4>
+                        ''' + set_data_main["main_css_view_real_footnote_num"] + '''
                         <select name="main_css_view_real_footnote_num">
                             ''' + set_data["main_css_view_real_footnote_num"] + '''
                         </select>
                         <h3>''' + load_lang("include_link") + '''</h3>
+                        ''' + set_data_main["main_css_include_link"] + '''
                         <select name="main_css_include_link">
                             ''' + set_data["main_css_include_link"] + '''
                         </select>
-                        <h3>''' + load_lang("image") + '''</h3>
+                        <h3>''' + load_lang("image") + ''' (''' + load_lang('beta') + ''')</h3>
+                        ''' + set_data_main["main_css_image_set"] + '''
                         <select name="main_css_image_set">
                             ''' + set_data["main_css_image_set"] + '''
                         </select>
                         <h3>''' + load_lang("toc") + '''</h3>
+                        ''' + set_data_main["main_css_toc_set"] + '''
                         <select name="main_css_toc_set">
                             ''' + set_data["main_css_toc_set"] + '''
                         </select>
                         <h3>''' + load_lang("exter_link") + '''</h3>
+                        ''' + set_data_main["main_css_exter_link"] + '''
                         <select name="main_css_exter_link">
                             ''' + set_data["main_css_exter_link"] + '''
                         </select>
                         <h3>''' + load_lang("link_delimiter") + '''</h3>
+                        ''' + set_data_main["main_css_link_delimiter"] + '''
                         <select name="main_css_link_delimiter">
                             ''' + set_data["main_css_link_delimiter"] + '''
                         </select>
-                        <h3>''' + load_lang("force_darkmode") + ''' (''' + load_lang("not_working") + ''')</h3>
+                        <h3>''' + load_lang("force_darkmode") + '''</h3>
+                        ''' + set_data_main["main_css_darkmode"] + '''
                         <select name="main_css_darkmode">
                             ''' + set_data["main_css_darkmode"] + '''
                         </select>
-                        <h3>''' + load_lang("table_scroll") + '''</h3>
+                        <h3>''' + load_lang("table") + '''</h3>
+                        <h4>''' + load_lang("table_scroll") + '''</h4>
+                        ''' + set_data_main["main_css_table_scroll"] + '''
                         <select name="main_css_table_scroll">
                             ''' + set_data["main_css_table_scroll"] + '''
                         </select>
+                        <h4>''' + load_lang("table_transparent") + '''</h4>
+                        ''' + set_data_main["main_css_table_transparent"] + '''
+                        <select name="main_css_table_transparent">
+                            ''' + set_data["main_css_table_transparent"] + '''
+                        </select>
+                        <h3>''' + load_lang("list_view_change") + '''</h3>
+                        ''' + set_data_main["main_css_list_view_change"] + '''
+                        <select name="main_css_list_view_change">
+                            ''' + set_data["main_css_list_view_change"] + '''
+                        </select>
+                        <h3>''' + load_lang("view_joke") + '''</h3>
+                        ''' + set_data_main["main_css_view_joke"] + '''
+                        <select name="main_css_view_joke">
+                            ''' + set_data["main_css_view_joke"] + '''
+                        </select>
+                        <h3>''' + load_lang("math_scroll") + '''</h3>
+                        ''' + set_data_main["main_css_math_scroll"] + '''
+                        <select name="main_css_math_scroll">
+                            ''' + set_data["main_css_math_scroll"] + '''
+                        </select>
+                        <h3>''' + load_lang("view_history") + '''</h3>
+                        ''' + set_data_main["main_css_view_history"] + '''
+                        <select name="main_css_view_history">
+                            ''' + set_data["main_css_view_history"] + '''
+                        </select>
+                        <h3>''' + load_lang("font_size") + '''</h3>
+                        ''' + set_data_main["main_css_font_size"] + '''
+                        <select name="main_css_font_size">
+                            ''' + set_data["main_css_font_size"] + '''
+                        </select>
                         <h2>''' + load_lang("edit") + '''</h2>
                         <h3>''' + load_lang("image_paste") + '''</h3>
                         <sup>''' + load_lang('only_korean') + '''</sup> <sup>''' + load_lang('unavailable_in_monaco') + '''</sup>
                         <hr class="main_hr">
+                        ''' + set_data_main["main_css_image_paste"] + '''
                         <select name="main_css_image_paste">
                             ''' + set_data["main_css_image_paste"] + '''
                         </select>
                         <h3>''' + load_lang("monaco_editor") + '''</h3>
+                        ''' + set_data_main["main_css_monaco"] + '''
                         <select name="main_css_monaco">
                             ''' + set_data["main_css_monaco"] + '''
                         </select>

+ 0 - 1
route/main_sys_restart.py

@@ -8,7 +8,6 @@ def main_sys_restart():
         if flask.request.method == 'POST':
             admin_check(None, 'restart')
 
-            print('----')
             print('Restart')
 
             python_ver = ''

+ 0 - 1
route/main_sys_shutdown.py

@@ -10,7 +10,6 @@ def main_sys_shutdown():
 
             conn.commit()
 
-            print('----')
             print('Shutdown')
 
             os._exit(0)

+ 1 - 2
route/main_sys_update.py

@@ -17,9 +17,8 @@ def main_sys_update():
             up_data = curs.fetchall()
             up_data = up_data[0][0] if up_data and up_data[0][0] in ['stable', 'beta', 'dev'] else 'stable'
 
-            print('----')
             print('Update')
-            print('----')
+            
             if platform.system() == 'Linux':
                 ok = []
 

+ 12 - 10
route/main_tool_admin.py

@@ -16,7 +16,7 @@ def main_tool_admin():
                 </ul>
                 <h2>''' + load_lang('owner') + '''</h2>
                 <ul class="opennamu_ul">
-                    <li><a href="/admin_group">''' + load_lang('admin_group_list') + '''</a></li>
+                    <li><a href="/auth/list">''' + load_lang('admin_group_list') + '''</a></li>
                     <li><a href="/delete_multiple">''' + load_lang('many_delete') + '''</a></li>
                     <li><a href="/app_submit">''' + load_lang('application_list') + '''</a></li>
                     <li><a href="/register">''' + load_lang('add_user') + '''</a></li>
@@ -25,15 +25,17 @@ def main_tool_admin():
                 </ul>
                 <h3>''' + load_lang('filter') + '''</h3>
                 <ul class="opennamu_ul">
-                    <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
-                    <li><a href="/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
-                    <li><a href="/edit_top">''' + load_lang('edit_tool_list') + '''</a></li>
-                    <li><a href="/image_license">''' + load_lang('image_license_list') + '''</a></li>
-                    <li><a href="/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
-                    <li><a href="/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
-                    <li><a href="/file_filter">''' + load_lang('file_filter_list') + '''</a></li>
-                    <li><a href="/extension_filter">''' + load_lang('extension_filter_list') + '''</a></li>
-                    <li><a href="/filter/document/list">''' + load_lang('document_filter_list') + ''' (''' + load_lang('beta') + ''')</a></li>
+                    <li><a href="/filter/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
+                    <li><a href="/filter/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
+                    <li><a href="/filter/edit_top">''' + load_lang('edit_tool_list') + '''</a></li>
+                    <li><a href="/filter/image_license">''' + load_lang('image_license_list') + '''</a></li>
+                    <li><a href="/filter/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
+                    <li><a href="/filter/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
+                    <li><a href="/filter/file_filter">''' + load_lang('file_filter_list') + '''</a></li>
+                    <li><a href="/filter/extension_filter">''' + load_lang('extension_filter_list') + '''</a></li>
+                    <li><a href="/filter/document">''' + load_lang('document_filter_list') + '''</a></li>
+                    <li><a href="/filter/outer_link">''' + load_lang('outer_link_filter_list') + '''</a> (''' + load_lang('beta') + ''')
+                    <li><a href="/filter/template">''' + load_lang('template_document_list') + '''</a> (''' + load_lang('beta') + ''')
                 </ul>
                 <h3>''' + load_lang('server') + '''</h2>
                 <ul class="opennamu_ul">

+ 3 - 3
route/main_tool_other.py

@@ -5,10 +5,9 @@ def main_tool_other():
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('other_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = render_simple_set('''
-                <h2>''' + load_lang('record') + '''</h2>
+                <h2>''' + load_lang('user_tool') + '''</h2>
                 <ul class="opennamu_ul">
-                    <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
-                    <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
+                    <li><a href="/manager/6">''' + load_lang('user_tool') + '''</a></li>
                 </ul>
                 <h2>''' + load_lang('list') + '''</h2>
                 <h3>''' + load_lang('admin') + '''</h3>
@@ -29,6 +28,7 @@ def main_tool_other():
                     <li><a href="/list/document/long">''' + load_lang('long_page') + '''</a></li>
                     <li><a href="/list/document/short">''' + load_lang('short_page') + '''</a></li>
                     <li><a href="/list/document/old">''' + load_lang('old_page') + '''</a></li>
+                    <li><a href="/list/document/no_link">''' + load_lang('no_link_document_list') + '''</a></li>
                 </ul>
                 <h3>''' + load_lang('user') + '''</h3>
                 <ul class="opennamu_ul">

+ 18 - 6
route/main_tool_redirect.py

@@ -2,15 +2,16 @@ from .tool.func import *
 
 def main_tool_redirect(num = 1, add_2 = ''):
     with get_db_connect() as conn:
+        curs = conn.cursor()
+
         title_list = {
             0 : [load_lang('document_name'), '/acl', load_lang('acl')],
             1 : [0, '/list/user/check', load_lang('check')],
-            2 : [load_lang('file_name'), '/file_filter/add', load_lang('file_filter_add')],
+            2 : [load_lang('file_name'), '/filter/file_filter/add', load_lang('file_filter_add')],
             3 : [0, '/auth/give', load_lang('authorize')],
-            4 : [0, '/record', load_lang('edit_record')],
-            5 : [0, '/record/topic', load_lang('discussion_record')],
-            6 : [load_lang('name'), '/admin_plus', load_lang('add_admin_group')],
-            7 : [load_lang('name'), '/edit_filter/add', load_lang('edit_filter_add')],
+            4 : [0, '/user', load_lang('user_tool')],
+            6 : [load_lang('name'), '/auth/list/add', load_lang('add_admin_group')],
+            7 : [load_lang('name'), '/filter/edit_filter/add', load_lang('edit_filter_add')],
             8 : [load_lang('document_name'), '/search', load_lang('search')],
             9 : [0, '/block_log/user', load_lang('blocked_user')],
             10 : [0, '/block_log/admin', load_lang('blocked_admin')],
@@ -49,11 +50,22 @@ def main_tool_redirect(num = 1, add_2 = ''):
                 if num == 15:
                     plus = '<input type="checkbox" name="regex"> ' + load_lang('regex') + '<hr class="main_hr">'
 
+                top_plus = ''
+                if num == 13:
+                    curs.execute(db_change("select html, plus from html_filter where kind = 'template'"))
+                    db_data = curs.fetchall()
+                    for for_a in db_data:
+                        top_plus += '' + \
+                            '<a href="javascript:opennamu_insert_v(\'data_field\', \'' + get_tool_js_safe(for_a[0]) + '\')">' + html.escape(for_a[0]) + '</a> : ' + html.escape(for_a[1]) + \
+                            '<hr class="main_hr">' + \
+                        ''
+
                 return easy_minify(flask.render_template(skin_check(),
                     imp = [title_list[num][2], wiki_set(), wiki_custom(), wiki_css([0, 0])],
                     data = '''
                         <form method="post">
-                            <input placeholder="''' + placeholder + '''" name="name" type="text">
+                            ''' + top_plus + '''
+                            <input placeholder="''' + placeholder + '''" id="data_field" name="name" type="text">
                             <hr class="main_hr">
                             ''' + plus + '''
                             <button type="submit">''' + load_lang('go') + '''</button>

+ 3 - 1
route/main_view.py

@@ -8,7 +8,9 @@ def main_view(name = ''):
             return main_func_error_404()
         else:
             file_name = file_name.group(1)
-            dir_name = './views/' + re.sub(r'\.{2,}', '', re.sub(r'([^/]+)$', '', name))
+            dir_name = './views/' + re.sub(r'\.{2,}', '', name[:-len(file_name)])
+
+            file_name = re.sub(r'\.cache_v(?:[0-9]+)$', '', file_name)
 
             mime_type = file_name.split('.')
             if len(mime_type) < 2:

+ 1 - 0
route/main_view_image.py

@@ -3,6 +3,7 @@ from .main_func_error_404 import main_func_error_404
 
 def main_view_image(name = ''):
     with get_db_connect() as conn:
+        name = re.sub(r'\.cache_v(?:[0-9]+)$', '', name)
         mime_type = re.search(r'([^.]+)$', name)
         if mime_type:
             mime_type = mime_type.group(1).lower()

+ 9 - 38
route/recent_app_submit.py

@@ -12,9 +12,7 @@ def recent_app_submit_2():
             div += load_lang('approval_requirement_disabled')
 
         if flask.request.method == 'GET':
-            curs.execute(db_change(
-                'select data from user_set where name = "application"'
-            ))
+            curs.execute(db_change('select data from user_set where name = "application"'))
             db_data = curs.fetchall()
             if db_data:
                 div += '' + \
@@ -98,49 +96,22 @@ def recent_app_submit_2():
                 return re_error('/ban')
 
             if flask.request.form.get('approve', '') != '':
-                curs.execute(db_change(
-                    'select data from user_set where id = ? and name = "application"'
-                ), [
-                    flask.request.form.get('approve', '')
-                ])
+                curs.execute(db_change('select data from user_set where id = ? and name = "application"'), [flask.request.form.get('approve', '')])
                 application = curs.fetchall()
                 if not application:
                     return re_error('/error/26')
                 else:
                     application = json.loads(application[0][0])
 
-                add_user(
-                    application['id'], 
-                    application['pw'],
-                    application['email'],
-                    application['encode']
-                )
-
-                curs.execute(db_change(
-                    "insert into user_set (name, id, data) values ('approval_question', ?, ?)"
-                ), [
-                    application['id'], 
-                    application['question']
-                ])
-                curs.execute(db_change(
-                    "insert into user_set (name, id, data) values ('approval_question_answer', ?, ?)"
-                ), [
-                    application['id'], 
-                    application['answer']
-                ])
-
-                curs.execute(db_change(
-                    'delete from user_set where id = ? and name = "application"'
-                ), [
-                    application['id']
-                ])
+                add_user(application['id'], application['pw'], application['email'], application['encode'])
+
+                curs.execute(db_change("insert into user_set (name, id, data) values ('approval_question', ?, ?)"), [application['id'], application['question']])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('approval_question_answer', ?, ?)"), [application['id'], application['answer']])
+
+                curs.execute(db_change('delete from user_set where id = ? and name = "application"'), [application['id']])
                 conn.commit()
             elif flask.request.form.get('decline', '') != '':
-                curs.execute(db_change(
-                    'delete from user_set where id = ? and name = "application"'
-                ), [
-                    flask.request.form.get('decline', '')
-                ])
+                curs.execute(db_change('delete from user_set where id = ? and name = "application"'), [flask.request.form.get('decline', '')])
                 conn.commit()
 
             return redirect('/app_submit')

+ 0 - 3
route/recent_block.py

@@ -17,9 +17,6 @@ def recent_block_2(name = 'Test', tool = 'all'):
                     </tr>
         '''
 
-        curs.execute(db_change("update rb set ongoing = '' where end < ? and end != '' and ongoing = '1'"), [get_time()])
-        conn.commit()
-
         get_type = flask.request.args.get('type', '')
         sub_type = flask.request.args.get('s_type', '')
         if tool == 'all':

+ 104 - 93
route/recent_change.py

@@ -6,81 +6,85 @@ def recent_change_send_render(data):
         data_unescape = html.unescape(match)
 
         return '<a href="/w/' + url_pas(data_unescape) + '">' + match + '</a>'
+    
+    def send_render_link(match):
+        link_main = match[2]
+        link_main = link_main.replace('"', '&quot;')
+
+        return match[1] + '<a href="' + link_main + '">' + link_main + '</a>'
 
     if data == '&lt;br&gt;' or data == '' or re.search(r'^ +$', data):
         data = '<br>'
     else:
         data = data.replace('javascript:', '')
+
+        data = re.sub(r'( |^)(https?:\/\/(?:[^ ]+))', send_render_link, data)
         data = re.sub(r'&lt;a(?:(?:(?!&gt;).)*)&gt;((?:(?!&lt;\/a&gt;).)+)&lt;\/a&gt;', send_render_href_replace, data)
 
     return data
 
-def recent_change(name = None, tool = ''):
+def recent_change(name = '', tool = '', num = 1, set_type = 'normal'):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
+        ip = ip_check()
+        all_admin = admin_check('all', None, ip)
+        owner = admin_check(None, None, ip)
+
+        option_list = [
+            ['normal', load_lang('normal')],
+            ['edit', load_lang('edit')],
+            ['move', load_lang('move')],
+            ['delete', load_lang('delete')],
+            ['revert', load_lang('revert')],
+            ['r1', load_lang('new_doc')]
+        ]
+
         if flask.request.method == 'POST':
-            return redirect(
-                '/diff' + 
-                '/' + flask.request.form.get('b', '1') +
-                '/' + flask.request.form.get('a', '1') +
-                '/' + url_pas(name)
-            )
+            return redirect('/diff/' + flask.request.form.get('b', '1') + '/' + flask.request.form.get('a', '1') + '/' + url_pas(name))
         else:
             ban = ''
             select = ''
             sub = ''
-            admin = admin_check()
+            admin = owner
             div = '''
                 <table id="main_table_set">
                     <tbody>
                         <tr id="main_table_top_tr">
             '''
 
-            num = int(number_check(flask.request.args.get('num', '1')))
             sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
-            if name:
-                if tool == 'history':
-                    sub += ' (' + load_lang('history') + ')'
-
-                    div += '''
-                        <td id="main_table_width">''' + load_lang('version') + '''</td>
-                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                        <td id="main_table_width">''' + load_lang('time') + '''</td>
-                    '''
+            if tool == 'history':
+                div += '''
+                    <td id="main_table_width">''' + load_lang('version') + '''</td>
+                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                    <td id="main_table_width">''' + load_lang('time') + '''</td>
+                '''
+                sub = '(' + load_lang('history') + ')'
 
-                    set_type = flask.request.args.get('set', 'normal')
-                    set_type = '' if set_type == 'edit' else set_type
+                set_type = '' if set_type == 'edit' else set_type
+                if set_type != 'normal':
+                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where title = ? and type = ? order by id + 0 desc limit ?, 50'), [name, set_type, sql_num])
+                else:
+                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where title = ? order by id + 0 desc limit ?, 50'), [name, sql_num])
 
-                    if set_type != 'normal':
-                        curs.execute(db_change('' + \
-                            'select id, title, date, ip, send, leng, hide from history ' + \
-                            'where title = ? and type = ? ' + \
-                            'order by id + 0 desc ' + \
-                            "limit ?, 50" + \
-                        ''), [name, set_type, sql_num])
-                    else:
-                        curs.execute(db_change('' + \
-                            'select id, title, date, ip, send, leng, hide from history ' + \
-                            'where title = ? ' + \
-                            'order by id + 0 desc ' + \
-                            "limit ?, 50" + \
-                        ''), [name, sql_num])
+                data_list = curs.fetchall()
+            elif tool == 'record':
+                div +=  '''
+                    <td id="main_table_width">''' + load_lang('document_name') + '''</td>
+                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                    <td id="main_table_width">''' + load_lang('time') + '''</td>
+                '''
+                sub = '(' + load_lang('edit_record') + ')'
+                set_type = '' if set_type == 'edit' else set_type
 
-                    data_list = curs.fetchall()
+                if set_type != 'normal':
+                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where ip = ? and type = ? order by date desc limit ?, 50'), [name, set_type, sql_num])
                 else:
-                    div +=  '''
-                        <td id="main_table_width">''' + load_lang('document_name') + '''</td>
-                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                        <td id="main_table_width">''' + load_lang('time') + '''</td>
-                    '''
-
-                    curs.execute(db_change('' + \
-                        'select id, title, date, ip, send, leng, hide from history ' + \
-                        "where ip = ? order by date desc limit ?, 50" + \
-                    ''), [name, sql_num])
-                    data_list = curs.fetchall()
+                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where ip = ? order by date desc limit ?, 50'), [name, sql_num])
+                
+                data_list = curs.fetchall()
             else:
                 div +=  '''
                     <td id="main_table_width">''' + load_lang('document_name') + '''</td>
@@ -88,14 +92,22 @@ def recent_change(name = None, tool = ''):
                     <td id="main_table_width">''' + load_lang('time') + '''</td>
                 '''
                 sub = ''
-                set_type = flask.request.args.get('set', 'normal')
                 set_type = '' if set_type == 'edit' else set_type
 
                 data_list = []
-                curs.execute(db_change('select title, id from rc where type = ? order by date desc limit 50'), [set_type])
-                for i in curs.fetchall():
-                    curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where title = ? and id = ?'), i)
-                    data_list += curs.fetchall()
+
+                if num == 1 or all_admin != 1:
+                    curs.execute(db_change('select title, id from rc where type = ? order by date desc limit 50'), [set_type])
+                    for for_a in curs.fetchall():
+                        curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where title = ? and id = ?'), for_a)
+                        data_list += curs.fetchall()
+                else:
+                    if set_type != 'normal':
+                        curs.execute(db_change('select id, title, date, ip, send, leng, hide from history where type = ? order by date desc limit ?, 50'), [set_type, sql_num])
+                    else:
+                        curs.execute(db_change('select id, title, date, ip, send, leng, hide from history order by date desc limit ?, 50'), [sql_num])
+
+                    data_list = curs.fetchall()
 
             div += '</tr>'
 
@@ -155,57 +167,56 @@ def recent_change(name = None, tool = ''):
                 </table>
             '''
 
-            if name:
-                if tool == 'history':
-                    div = '' + \
-                        '<a href="?set=normal">(' + load_lang('normal') + ')</a> ' + \
-                        '<a href="?set=edit">(' + load_lang('edit') + ')</a> ' + \
-                        '<a href="?set=move">(' + load_lang('move') + ')</a> ' + \
-                        '<a href="?set=delete">(' + load_lang('delete') + ')</a> ' + \
-                        '<a href="?set=revert">(' + load_lang('revert') + ')</a>' + \
-                        '<hr class="main_hr">' + div + \
-                    ''
-                    menu = [['w/' + url_pas(name), load_lang('return')]]
-
-                    if set_type == 'normal':
-                        div = '''
-                            <form method="post">
-                                <select name="a">''' + select + '''</select> <select name="b">''' + select + '''</select>
-                                <button type="submit">''' + load_lang('compare') + '''</button>
-                            </form>
-                            <hr class="main_hr">
-                        ''' + div
-
-                        if admin == 1:
-                            menu += [
-                                ['history_add/' + url_pas(name), load_lang('history_add')],
-                                ['history_reset/' + url_pas(name), load_lang('history_reset')]
-                            ]
-
-                    title = name
-                    div += next_fix('/history/' + url_pas(name) + '?tool=' + set_type + '&num=', num, data_list)
-                else:
-                    title = load_lang('edit_record')
-                    menu = [
-                        ['other', load_lang('other')], 
-                        ['user', load_lang('user')],
-                        ['record/reset/' + url_pas(name), load_lang('record_reset')]
+            set_type = 'edit' if set_type == '' else set_type
+            if tool == 'history':
+                div = '' + \
+                    ' '.join(['<a href="/history_page/1/' + for_a[0] + '/' + url_pas(name) + '">(' + for_a[1] + ')</a> ' for for_a in option_list]) + \
+                    '<hr class="main_hr">' + div + \
+                ''
+                menu = [['w/' + url_pas(name), load_lang('return')]]
+
+                if set_type == 'normal':
+                    div = '''
+                        <form method="post">
+                            <select name="a">''' + select + '''</select> <select name="b">''' + select + '''</select>
+                            <button type="submit">''' + load_lang('compare') + '''</button>
+                        </form>
+                        <hr class="main_hr">
+                    ''' + div
+
+                if admin == 1:
+                    menu += [
+                        ['history_add/' + url_pas(name), load_lang('history_add')],
+                        ['history_reset/' + url_pas(name), load_lang('history_reset')]
                     ]
-                    div += next_fix('/record/' + url_pas(name) + '?num=', num, data_list)
+
+                title = name
+                div += get_next_page_bottom('/history_page/{}/' + set_type + '/' + url_pas(name), num, data_list)
+            elif tool == 'record':
+                div = '' + \
+                    ' '.join(['<a href="/record/1/' + for_a[0] + '/' + url_pas(name) + '">(' + for_a[1] + ')</a> ' for for_a in option_list]) + \
+                    '<hr class="main_hr">' + div + \
+                ''
+
+                title = name
+                menu = [['user/' + url_pas(name), load_lang('user_tool')]]
+                if admin == 1:
+                    menu += [['record/reset/' + url_pas(name), load_lang('record_reset')]]
+
+                div += get_next_page_bottom('/record/{}/' + url_pas(name), num, data_list)
             else:
                 div = '' + \
-                    '<a href="?set=normal">(' + load_lang('normal') + ')</a> ' + \
-                    '<a href="?set=edit">(' + load_lang('edit') + ')</a> ' + \
-                    '<a href="?set=user">(' + load_lang('user_document') + ')</a> ' + \
-                    '<a href="?set=move">(' + load_lang('move') + ')</a> ' + \
-                    '<a href="?set=delete">(' + load_lang('delete') + ')</a> ' + \
-                    '<a href="?set=revert">(' + load_lang('revert') + ')</a>' + \
+                    ' '.join(['<a href="/recent_change/1/' + for_a[0] + '">(' + for_a[1] + ')</a> ' for for_a in option_list]) + \
+                    '<a href="/recent_change/1/user">(' + load_lang('user_document') + ')</a> ' + \
                     '<hr class="main_hr">' + div + \
                 ''
 
                 menu = [['other', load_lang('return')]]
                 title = load_lang('recent_change')
 
+                if all_admin == 1:
+                    div += get_next_page_bottom('/recent_change/{}/' + set_type, num, data_list)
+
             if sub == '':
                 sub = 0
 

+ 9 - 36
route/recent_history_add.py

@@ -1,5 +1,7 @@
 from .tool.func import *
 
+from .edit import edit_editor
+
 def recent_history_add(name = 'Test', do_type = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
@@ -8,7 +10,7 @@ def recent_history_add(name = 'Test', do_type = ''):
         if admin_check() != 1:
             return re_error('/ban')
 
-        if flask.request.method == 'POST' and do_type == '':
+        if flask.request.method == 'POST':
             admin_check(None, 'history_add (' + name + ')')
 
             today = get_time()
@@ -29,48 +31,19 @@ def recent_history_add(name = 'Test', do_type = ''):
             conn.commit()
 
             return redirect('/history/' + url_pas(name))
-        else:
-            curs.execute(db_change('select data from other where name = "edit_help"'))
-            sql_d = curs.fetchall()
-            p_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('default_edit_help')
-
-            send = ''
-            get_ip = ''
-            data = ''
-            data_preview = ''
-            if do_type == 'preview':
-                data = flask.request.form.get('content', '')
-                data = data.replace('\r', '')
-
-                send = flask.request.form.get('send', '')
-                get_ip = flask.request.form.get('get_ip', '')
-
-                data_preview = render_set(
-                    doc_name = name, 
-                    doc_data = data
-                )
-            
+        else:            
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('history_add'), wiki_set(), wiki_custom(), wiki_css(['(' + name + ')', 0])],
                 data = '''
-                    <form method="post">                        
-                        <div>''' + edit_button('opennamu_edit_textarea') + '''</div>
-                        
-                        <textarea id="opennamu_edit_textarea" class="opennamu_textarea_500" name="content" placeholder="''' + p_text + '''">''' + html.escape(data) + '''</textarea>
+                    <form method="post">
+                        <input placeholder="''' + load_lang('why') + '''" name="send">
                         <hr class="main_hr">
                         
-                        <input placeholder="''' + load_lang('why') + '''" name="send" value="''' + html.escape(send) + '''">
+                        <input placeholder="''' + load_lang('name') + '''" name="get_ip">
                         <hr class="main_hr">
-                        
-                        <input placeholder="''' + load_lang('name') + '''" name="get_ip" value="''' + html.escape(get_ip) + '''">
-                        <hr class="main_hr">
-                        
-                        <button id="opennamu_save_button" formaction="/history_add/''' + url_pas(name) + '''" type="submit">''' + load_lang('save') + '''</button>
-                        <button id="opennamu_preview_button" formaction="/history_add_preview/''' + url_pas(name) + '''" type="submit">''' + load_lang('preview') + '''</button>
+
+                        ''' + edit_editor(curs, ip) + '''
                     </form>
-                    
-                    <hr class="main_hr">
-                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 ''',
                 menu = [['history/' + url_pas(name), load_lang('return')]]
             ))

+ 1 - 1
route/recent_history_delete.py

@@ -21,7 +21,7 @@ def recent_history_delete(name = 'Test', rev = 1):
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('history_delete') + ') (r' + num + ')', 0])],
                 data = '''
                     <form method="post">
-                        <span>''' + load_lang('history_delete_warning') + '''</span>
+                        <span>''' + load_lang('delete_warning') + '''</span>
                         <hr class="main_hr">
                         <button type="submit">''' + load_lang('delete') + '''</button>
                     </form>

+ 1 - 1
route/recent_history_reset.py

@@ -19,7 +19,7 @@ def recent_history_reset(name = 'Test'):
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('history_reset') + ')', 0])],
                 data = '''
                     <form method="post">
-                        <span>''' + load_lang('history_delete_warning') + '''</span>
+                        <span>''' + load_lang('delete_warning') + '''</span>
                         <hr class="main_hr">
                         <button type="submit">''' + load_lang('reset') + '''</button>
                     </form>

+ 1 - 1
route/recent_history_send.py

@@ -33,7 +33,7 @@ def recent_history_send(name = 'Test', rev = 1):
                     imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('send_edit') + ') (r' + num + ')', 0])],
                     data = '''
                         <form method="post">
-                            <span>''' + load_lang('history_delete_warning') + '''</span>
+                            <span>''' + load_lang('delete_warning') + '''</span>
                             <hr class="main_hr">
                             <input value="''' + html.escape(send) + '''" name="send">
                             <hr class="main_hr">

+ 1 - 1
route/recent_record_reset.py

@@ -19,7 +19,7 @@ def recent_record_reset(name = 'Test'):
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('record_reset') + ')', 0])],
                 data = '''
                     <form method="post">
-                        <span>''' + load_lang('history_delete_warning') + '''</span>
+                        <span>''' + load_lang('delete_warning') + '''</span>
                         <hr class="main_hr">
                         <button type="submit">''' + load_lang('reset') + '''</button>
                     </form>

+ 1 - 4
route/recent_record_topic.py

@@ -42,8 +42,5 @@ def recent_record_topic(name = 'Test'):
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('discussion_record'), wiki_set(), wiki_custom(), wiki_css([sub, 0])],
             data = div,
-            menu = [
-                ['other', load_lang('other')], 
-                ['user', load_lang('user')]
-            ]
+            menu = [['other', load_lang('other')], ['user/' + url_pas(name), load_lang('user_tool')]]
         ))

Разлика између датотеке није приказан због своје велике величине
+ 309 - 307
route/tool/func.py


+ 29 - 41
route/tool/func_render.py

@@ -5,7 +5,7 @@ from .func_render_namumark import class_do_render_namumark
 # 커스텀 마크 언젠간 다시 추가 예정
 
 class class_do_render:
-    def __init__(self, conn, lang_data = {}):
+    def __init__(self, conn, lang_data = {}, markup = ''):
         self.conn = conn
 
         if lang_data == '{}':
@@ -15,6 +15,7 @@ class class_do_render:
             }
 
         self.lang_data = lang_data
+        self.markup = markup
 
     def do_render(self, doc_name, doc_data, data_type, data_in):
         curs = self.conn.cursor()
@@ -26,7 +27,7 @@ class class_do_render:
         
         data_in = (data_in + '_') if data_in != '' else ''
         doc_set['doc_include'] = data_in
-        rep_data = ''
+        rep_data = self.markup
 
         if rep_data == '' and doc_name != '':
             curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'document_markup'"), [doc_name])
@@ -40,25 +41,11 @@ class class_do_render:
             rep_data = db_data[0][0] if db_data else 'namumark'
 
         if rep_data == 'namumark' or rep_data == 'namumark_beta':
-            data_end = class_do_render_namumark(
-                curs,
-                doc_name,
-                doc_data,
-                doc_set,
-                self.lang_data
-            )()
+            data_end = class_do_render_namumark(curs, doc_name, doc_data, doc_set, self.lang_data)()
         elif rep_data == 'raw':
-            data_end = [
-                html.escape(doc_data).replace('\n', '<br>'), 
-                '', 
-                {}
-            ]
+            data_end = [html.escape(doc_data).replace('\n', '<br>'), '', {}]
         else:
-            data_end = [
-                doc_data, 
-                '', 
-                {}
-            ]
+            data_end = [doc_data, '', {}]
 
         if data_type == 'thread' or data_type == 'api_thread':
             def do_thread_a_change(match):
@@ -73,31 +60,32 @@ class class_do_render:
                 else:
                     return ''
 
-            data_end[0] = re.sub(
-                r'&lt;(topic_a(?:_post|_thread)?)&gt;((?:(?!&lt;\/topic_a(?:_post|_thread)?&gt;).)+)&lt;\/topic_a(?:_post|_thread)?&gt;',
-                do_thread_a_change,
-                data_end[0]
-            )
-            data_end[0] = re.sub(
-                r'&lt;topic_call&gt;@(?P<in>(?:(?!&lt;\/topic_call&gt;).)+)&lt;\/topic_call&gt;',
-                '<a href="/w/user:\\g<in>">@\\g<in></a>',
-                data_end[0]
-            )
-
-        if data_type == 'backlink':
-            if 'backlink' in data_end[2]:
-                backlink = data_end[2]['backlink']
-            else:
-                backlink = []
+            data_end[0] = re.sub(r'&lt;(topic_a(?:_post|_thread)?)&gt;((?:(?!&lt;\/topic_a(?:_post|_thread)?&gt;).)+)&lt;\/topic_a(?:_post|_thread)?&gt;', do_thread_a_change, data_end[0])
+            data_end[0] = re.sub(r'&lt;topic_call&gt;@(?P<in>(?:(?!&lt;\/topic_call&gt;).)+)&lt;\/topic_call&gt;', '<a href="/w/user:\\g<in>">@\\g<in></a>', data_end[0])
+
+        if data_type == 'backlink' and data_in == '':
+            curs.execute(db_change("delete from back where link = ?"), [doc_name])
+            curs.execute(db_change("delete from back where title = ? and type = 'no'"), [doc_name])
+
+            curs.execute(db_change("delete from data_set where doc_name = ? and set_name = 'link_count'"), [doc_name])
+            curs.execute(db_change("delete from data_set where doc_name = ? and set_name = 'doc_type'"), [doc_name])
 
+            backlink = data_end[2]['backlink'] if 'backlink' in data_end[2] else []
             if backlink != []:
-                curs.executemany(db_change("insert into back (link, title, type, data) values (?, ?, ?, ?)"), data_end[2]['backlink'])
+                curs.executemany(db_change("insert into back (link, title, type, data) values (?, ?, ?, ?)"), backlink)
                 curs.execute(db_change("delete from back where title = ? and type = 'no'"), [doc_name])
 
+            link_count = 0
+            if 'link_count' in data_end[2]:
+                link_count = data_end[2]['link_count']
+
+            curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, '', 'link_count', ?)"), [doc_name, link_count])
+
+            if 'redirect' in data_end[2] and data_end[2]['redirect'] == 1:
+                curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, '', 'doc_type', 'redirect')"), [doc_name])
+            else:
+                curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, '', 'doc_type', '')"), [doc_name])
+            
             self.conn.commit()
 
-        return [
-            data_end[0], 
-            data_end[1],
-            data_end[2]
-        ]
+        return [data_end[0], data_end[1], data_end[2]]

Разлика између датотеке није приказан због своје велике величине
+ 348 - 134
route/tool/func_render_namumark.py


+ 1 - 2
route/tool/func_tool.py

@@ -8,7 +8,6 @@ import re
 import os
 import html
 import json
-import sqlite3
 import threading
 
 set_data = ''
@@ -76,7 +75,7 @@ def get_main_skin_set(curs, flask_session, set_name, ip):
     if ip_or_user(ip) == 0:
         curs.execute(db_change('select data from user_set where name = ? and id = ?'), [set_name, ip])
         db_data = curs.fetchall()
-        set_data = db_data[0][0] if db_data else 'default'
+        set_data = db_data[0][0] if db_data and db_data[0][0] != '' else 'default'
     else:
         set_data = flask_session[set_name] if set_name in flask_session and flask_session[set_name] != '' else 'default'
 

+ 10 - 29
route/topic.py

@@ -100,18 +100,13 @@ def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
             return redirect('/thread/' + topic_num + '#' + num)
         else:
             thread_data = ''
-            thread_data_preview = ''
 
             if topic_num == '0':
                 name = load_lang('make_new_topic')
                 sub = load_lang('make_new_topic')
 
-                if do_type == 'preview':
-                    name_value = flask.request.form.get('topic', '')
-                    sub_value = flask.request.form.get('title', '')
-                else:
-                    name_value = doc_name
-                    sub_value = ''
+                name_value = doc_name
+                sub_value = ''
             else:
                 curs.execute(db_change("select title, sub from rd where code = ?"), [topic_num])
                 name = curs.fetchall()
@@ -124,21 +119,11 @@ def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
                 else:
                     return redirect('/')
 
-            if do_type == 'preview':
-                thread_data = flask.request.form.get('content', 'Test')
-                thread_data = thread_data.replace('\r', '')
-
-                thread_data_preview = render_set(
-                    doc_data = thread_data
-                )
-
             acl_display = 'display: none;' if topic_acl == 1 else ''
             name_display = 'display: none;' if topic_num != '0' else ''
 
             shortcut = '<div class="opennamu_thread_shortcut" id="thread_shortcut">'
-            curs.execute(db_change(
-                "select id from topic where code = ? order by id + 0 asc"
-            ), [topic_num])
+            curs.execute(db_change("select id from topic where code = ? order by id + 0 asc"), [topic_num])
             db_data = curs.fetchall()
             for for_a in db_data:
                 shortcut += '<a href="#' + for_a[0] + '">#' + for_a[0] + '</a> '
@@ -156,6 +141,13 @@ def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
             return easy_minify(flask.render_template(skin_check(),
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('discussion') + ')', 0])],
                 data = '''
+                    <style id="opennamu_remove_blind">
+                        .opennamu_comment_blind_js {
+                            display: none;
+                        }
+                    </style>
+                    <input type="checkbox" onclick="opennamu_do_remove_blind_thread();" checked> ''' + load_lang('remove_blind_thread') + '''
+
                     ''' + shortcut + '''
                     <h2 id="topic_top_title">''' + html.escape(sub) + '''</h2>
                     
@@ -175,18 +167,7 @@ def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
                         </div>
                         
                         ''' + edit_editor(curs, ip, thread_data, 'thread') + '''
-                        <hr class="main_hr">
-                        
-                        ''' + captcha_get() + ip_warning() + '''
-                        
-                        <button id="opennamu_save_button" formaction="/thread/''' + topic_num + '''" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('send') + '''</button>
-                        <button id="opennamu_preview_button" formaction="/thread_preview/''' + topic_num + '''#opennamu_edit_textarea" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
                     </form>
-                    <hr class="main_hr">
-                    
-                    <div id="opennamu_preview_area">''' + thread_data_preview + '''</div>
-                    
-                    <!-- JS : opennamu_do_thread_make -->
                 ''',
                 menu = [['topic/' + url_pas(name), load_lang('list')]]
             ))

+ 2 - 9
route/topic_comment_tool.py

@@ -30,22 +30,15 @@ def topic_comment_tool(topic_num = 1, num = 1):
         '''
 
         if admin_check(3) == 1:
-            curs.execute(db_change(
-                "select id from topic where code = ? and id = ? and top = 'O'"
-            ), [topic_num, num])
+            curs.execute(db_change("select id from topic where code = ? and id = ? and top = 'O'"), [topic_num, num])
             top_topic_d = curs.fetchall()
 
-            curs.execute(db_change(
-                "select end from rb where block = ? and ongoing = '1'"
-            ), [data[0][1]])
-            user_ban_d = curs.fetchall()
-
             ban += '''
                 <h2>''' + load_lang('admin_tool') + '''</h2>
                 <ul class="opennamu_ul">
                     <li>
                         <a href="/auth/give/ban/''' + url_pas(data[0][1]) + '''">
-                            ''' + (load_lang('release') if user_ban_d else load_lang('ban')) + '''
+                            ''' + (load_lang('release') if ban_check(data[0][1]) == 1 else load_lang('ban')) + '''
                         </a>
                     </li>
                     <li>

+ 3 - 2
route/topic_tool_delete.py

@@ -19,9 +19,10 @@ def topic_tool_delete(topic_num = 1):
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('topic_delete'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    <hr class="main_hr">
                     <form method="post">
-                        <button type="submit">''' + load_lang('start') + '''</button>
+                        <span>''' + load_lang('delete_warning') + '''</span>
+                        <hr class="main_hr">
+                        <button type="submit">''' + load_lang('delete') + '''</button>
                     </form>
                 ''',
                 menu = [['thread/' + topic_num + '/tool', load_lang('return')]]

+ 16 - 2
route/user_alarm.py

@@ -8,8 +8,10 @@ def user_alarm():
         sql_num = (num * 50 - 50) if num * 50 > 0 else 0
     
         data = '<ul class="opennamu_ul">'
+
+        ip = ip_check()
     
-        curs.execute(db_change("select data, date from alarm where name = ? order by date desc limit ?, 50"), [ip_check(), sql_num])
+        curs.execute(db_change("select data, date, readme, id from user_notice where name = ? order by date desc limit ?, 50"), [ip, sql_num])
         data_list = curs.fetchall()
         if data_list:
             data = '' + \
@@ -20,8 +22,20 @@ def user_alarm():
     
             for data_one in data_list:
                 data_split = data_one[0].split(' | ')
+                data_style = ''
+                if data_one[2] == '1':
+                    data_style = 'opacity: 0.75;'
                 
-                data += '<li>' + ip_pas(data_split[0]) + (' | ' + ' | '.join(data_split[1:]) if len(data_split) > 1 else '') + ' (' + data_one[1] + ')</li>'
+                data += '' + \
+                    '<li style="' + data_style + '">' + \
+                        ip_pas(data_split[0]) + (' | ' + ' | '.join(data_split[1:]) if len(data_split) > 1 else '') + \
+                        ' | ' + data_one[1] + \
+                        ' <a href="/alarm/delete/' + url_pas(data_one[3]) + '">(' + load_lang('delete') + ')</a>' + \
+                    '</li>' + \
+                ''
+
+        curs.execute(db_change("update user_notice set readme = '1' where name = ?"), [ip])
+        conn.commit()
     
         data += '' + \
             '</ul>' + \

+ 6 - 2
route/user_alarm_delete.py

@@ -1,10 +1,14 @@
 from .tool.func import *
 
-def user_alarm_delete():
+def user_alarm_delete(id = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
     
-        curs.execute(db_change("delete from alarm where name = ?"), [ip_check()])
+        if id != '':
+            curs.execute(db_change("delete from user_notice where name = ? and id = ?"), [ip_check(), str(id)])
+        else:
+            curs.execute(db_change("delete from user_notice where name = ?"), [ip_check()])
+        
         conn.commit()
 
         return redirect('/alarm')

+ 230 - 141
route/user_challenge.py

@@ -30,146 +30,235 @@ def user_challenge():
         if ip_or_user(ip) == 1:
             return redirect('/user')
 
-        data_html_green = ''
-        data_html_red = ''
-        
-        data_html_green += do_make_challenge_design(
-            '🆕',
-            load_lang('challenge_title_register'), 
-            load_lang('challenge_info_register'),
-            1
-        )
-        
-        curs.execute(db_change('select count(*) from history where ip = ?'), [ip])
-        db_data = curs.fetchall()
-        
-        disable = 1 if db_data[0][0] >= 1 else 0
-        data_html = do_make_challenge_design(
-            '✏',
-            load_lang('challenge_title_first_contribute'), 
-            load_lang('challenge_info_first_contribute'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        disable = 1 if db_data[0][0] >= 10 else 0
-        data_html = do_make_challenge_design(
-            '🗊',
-            load_lang('challenge_title_tenth_contribute'), 
-            load_lang('challenge_info_tenth_contribute'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        disable = 1 if db_data[0][0] >= 100 else 0
-        data_html = do_make_challenge_design(
-            '🗀',
-            load_lang('challenge_title_hundredth_contribute'), 
-            load_lang('challenge_info_hundredth_contribute'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        disable = 1 if db_data[0][0] >= 1000 else 0
-        data_html = do_make_challenge_design(
-            '🖪',
-            load_lang('challenge_title_thousandth_contribute'), 
-            load_lang('challenge_info_thousandth_contribute'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        disable = 1 if db_data[0][0] >= 10000 else 0
-        data_html = do_make_challenge_design(
-            '🖴',
-            load_lang('challenge_title_tenthousandth_contribute'), 
-            load_lang('challenge_info_tenthousandth_contribute'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        curs.execute(db_change("select count(*) from topic where ip = ?"), [ip])
-        db_data = curs.fetchall()
-        
-        disable = 1 if db_data[0][0] >= 1 else 0
-        data_html = do_make_challenge_design(
-            '🗨',
-            load_lang('challenge_title_first_discussion'), 
-            load_lang('challenge_info_first_discussion'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        disable = 1 if db_data[0][0] >= 10 else 0
-        data_html = do_make_challenge_design(
-            '🗪',
-            load_lang('challenge_title_tenth_discussion'), 
-            load_lang('challenge_info_tenth_discussion'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        disable = 1 if db_data[0][0] >= 100 else 0
-        data_html = do_make_challenge_design(
-            '🖅',
-            load_lang('challenge_title_hundredth_discussion'), 
-            load_lang('challenge_info_hundredth_discussion'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        disable = 1 if db_data[0][0] >= 1000 else 0
-        data_html = do_make_challenge_design(
-            '☏',
-            load_lang('challenge_title_thousandth_discussion'), 
-            load_lang('challenge_info_thousandth_discussion'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
-        else:
-            data_html_red += data_html
-        
-        disable = 1 if db_data[0][0] >= 10000 else 0
-        data_html = do_make_challenge_design(
-            '🖧',
-            load_lang('challenge_title_tenthousandth_discussion'), 
-            load_lang('challenge_info_tenthousandth_discussion'),
-            disable
-        )
-        if disable == 1:
-            data_html_green += data_html
+        if flask.request.method == 'POST':
+            user_exp = 0
+
+            curs.execute(db_change('select count(*) from history where ip = ?'), [ip])
+            db_data = curs.fetchall()
+            if not db_data:
+                db_data = [[0]]
+
+            user_exp += 5 * db_data[0][0]
+
+            if db_data[0][0] >= 1:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_first_contribute'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_first_contribute', ?, '1')"), [ip])
+                user_exp += 500
+
+            if db_data[0][0] >= 10:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_tenth_contribute'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_tenth_contribute', ?, '1')"), [ip])
+                user_exp += 1000
+
+            if db_data[0][0] >= 100:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_hundredth_contribute'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_hundredth_contribute', ?, '1')"), [ip])
+                user_exp += 3000        
+
+            if db_data[0][0] >= 1000:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_thousandth_contribute'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_thousandth_contribute', ?, '1')"), [ip])
+                user_exp += 10000
+
+            curs.execute(db_change("select count(*) from topic where ip = ?"), [ip])
+            db_data = curs.fetchall()
+            if not db_data:
+                db_data = [[0]]
+
+            user_exp += 5 * db_data[0][0]
+
+            if db_data[0][0] >= 1:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_first_discussion'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_first_discussion', ?, '1')"), [ip])
+                user_exp += 500    
+
+            if db_data[0][0] >= 10:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_tenth_discussion'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_tenth_discussion', ?, '1')"), [ip])
+                user_exp += 1000
+
+            if db_data[0][0] >= 100:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_hundredth_discussion'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_hundredth_discussion', ?, '1')"), [ip])
+                user_exp += 3000
+
+            if db_data[0][0] >= 1000:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_thousandth_discussion'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_thousandth_discussion', ?, '1')"), [ip])
+                user_exp += 10000        
+
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_admin', ip])
+            db_data = curs.fetchall()
+            if admin_check('all') == 1 or db_data:
+                curs.execute(db_change("delete from user_set where id = ? and name = 'challenge_admin'"), [ip])
+                curs.execute(db_change("insert into user_set (name, id, data) values ('challenge_admin', ?, '1')"), [ip])
+                user_exp += 10000
+
+            exp = user_exp
+            level = 0
+            while 1:
+                if exp >= (500 + level * 50):
+                    exp -= (500 + level * 50)
+                    level += 1
+                else:
+                    break
+
+            curs.execute(db_change("delete from user_set where id = ? and name = 'level'"), [ip])
+            curs.execute(db_change("insert into user_set (name, id, data) values ('level', ?, ?)"), [ip, level])
+
+            curs.execute(db_change("delete from user_set where id = ? and name = 'experience'"), [ip])
+            curs.execute(db_change("insert into user_set (name, id, data) values ('experience', ?, ?)"), [ip, exp])
+
+            return redirect('/challenge')
         else:
-            data_html_red += data_html
+            data_html_green = ''
+            data_html_red = ''
             
-        data_html = data_html_green + data_html_red
-        
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('challenge'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = data_html,
-            menu = [['user', load_lang('return')]]
-        ))
+            data_html_green += do_make_challenge_design(
+                '🌳',
+                load_lang('challenge_title_register'), 
+                load_lang('challenge_info_register', 1),
+                1
+            )
+            
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_first_contribute', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '🔰',
+                load_lang('challenge_title_first_contribute'), 
+                load_lang('challenge_info_first_contribute', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+            
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_tenth_contribute', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '📝',
+                load_lang('challenge_title_tenth_contribute'), 
+                load_lang('challenge_info_tenth_contribute', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+            
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_hundredth_contribute', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '🖊️',
+                load_lang('challenge_title_hundredth_contribute'), 
+                load_lang('challenge_info_hundredth_contribute', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+            
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_thousandth_contribute', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '🏅',
+                load_lang('challenge_title_thousandth_contribute'), 
+                load_lang('challenge_info_thousandth_contribute', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+            
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_first_discussion', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '💬',
+                load_lang('challenge_title_first_discussion'), 
+                load_lang('challenge_info_first_discussion', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+            
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_tenth_discussion', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '💡',
+                load_lang('challenge_title_tenth_discussion'), 
+                load_lang('challenge_info_tenth_discussion', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+            
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_hundredth_discussion', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '📢',
+                load_lang('challenge_title_hundredth_discussion'), 
+                load_lang('challenge_info_hundredth_discussion', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+            
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_thousandth_discussion', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '📜',
+                load_lang('challenge_title_thousandth_discussion'), 
+                load_lang('challenge_info_thousandth_discussion', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+                
+            data_html = data_html_green + data_html_red
+
+            curs.execute(db_change('select data from user_set where name = ? and id = ?'), ['challenge_admin', ip])
+            db_data = curs.fetchall()
+            disable = 1 if db_data else 0
+            data_html = do_make_challenge_design(
+                '✅',
+                load_lang('challenge_title_admin'), 
+                load_lang('challenge_info_admin', 1),
+                disable
+            )
+            if disable == 1:
+                data_html_green += data_html
+            else:
+                data_html_red += data_html
+                
+            data_html = data_html_green + data_html_red
+            
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('challenge_and_level_manage'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                data = data_html + '''
+                    <form method="post">
+                        <div id="opennamu_get_user_info">''' + html.escape(ip) + '''</div>
+                        <hr class="main_hr">
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('reload') + '''</button>
+                    </form>
+                ''',
+                menu = [['user', load_lang('return')]]
+            ))

+ 7 - 5
route/user_info.py

@@ -13,7 +13,7 @@ def user_info(name = ''):
         tool_menu = ''
         
         if name == '':
-            curs.execute(db_change("select count(*) from alarm where name = ?"), [ip])
+            curs.execute(db_change("select count(*) from user_notice where name = ? and readme = ''"), [ip])
             count = curs.fetchall()
             if count and count[0][0] != 0:
                 tool_menu += '<li><a class="opennamu_not_exist_link" href="/alarm">' + load_lang('alarm') + ' (' + str(count[0][0]) + ')</a></li>'
@@ -28,7 +28,7 @@ def user_info(name = ''):
     
                 tool_menu += '<li><a href="/watch_list">' + load_lang('watchlist') + '</a></li>'
                 tool_menu += '<li><a href="/star_doc">' + load_lang('star_doc') + '</a></li>'
-                tool_menu += '<li><a href="/challenge">' + load_lang('challenge') + '</a></li>'
+                tool_menu += '<li><a href="/challenge">' + load_lang('challenge_and_level_manage') + '</a></li>'
                 tool_menu += '<li><a href="/acl/user:' + url_pas(ip) + '">' + load_lang('user_document_acl') + '</a></li>'
             else:
                 login_menu += '''
@@ -59,17 +59,19 @@ def user_info(name = ''):
             imp = [load_lang('user_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <h2>''' + load_lang('state') + '''</h2>
-                <div id="opennamu_get_user_info">''' + ip + '''</div>
+                <div id="opennamu_get_user_info">''' + html.escape(ip) + '''</div>
                 ''' + login_menu + '''
                 ''' + tool_menu + '''
                 <h2>''' + load_lang('other') + '''</h2>
                 <ul class="opennamu_ul">
-                    <li><a href="/record/''' + url_pas(ip) + '''">''' + load_lang('record') + '''</a></li>
+                    <li><a href="/record/''' + url_pas(ip) + '''">''' + load_lang('edit_record') + '''</a></li>
                     <li><a href="/record/topic/''' + url_pas(ip) + '''">''' + load_lang('discussion_record') + '''</a></li>
+                    <li><a href="/record/bbs/''' + url_pas(ip) + '''">''' + load_lang('bbs_record') + '''</a></li>
+                    <li><a href="/record/bbs_comment/''' + url_pas(ip) + '''">''' + load_lang('bbs_comment_record') + '''</a></li>
                     <li><a href="/topic/user:''' + url_pas(ip) + '''">''' + load_lang('user_discussion') + '''</a></li>
                     <li><a href="/count/''' + url_pas(ip) + '''">''' + load_lang('count') + '''</a></li>
                 </ul>
                 ''' + admin_menu + '''
             ''',
-            menu = 0
+            menu = [['other', load_lang('other_tool')]]
         ))

+ 5 - 4
route/user_setting.py

@@ -16,6 +16,8 @@ def user_setting():
                     ['user_title', flask.request.form.get('user_title', '')],
                     ['sub_user_name' , flask.request.form.get('sub_user_name', '')]
                 ]
+                if not auto_list[2][1] in get_user_title_list(ip):
+                    auto_list[2][1] = ''
 
                 twofa_on = flask.request.form.get('2fa', '')
                 if twofa_on != '':
@@ -67,11 +69,10 @@ def user_setting():
                     else:
                         div3 += '<option value="' + lang_data + '">' + see_data + '</option>'
 
-                # 여기 잘못 짬
                 curs.execute(db_change('select data from user_set where name = "user_title" and id = ?'), [ip])
                 data = curs.fetchall()
                 data = [['']] if not data else data
-                user_title_list = get_user_title_list()
+                user_title_list = get_user_title_list(ip)
                 div4 = ''
                 for user_title in user_title_list:                
                     if data and data[0][0] == user_title:
@@ -107,7 +108,7 @@ def user_setting():
                     imp = [load_lang('user_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                     data = '''
                         <form method="post">
-                            <div id="opennamu_get_user_info">''' + ip + '''</div>
+                            <div id="opennamu_get_user_info">''' + html.escape(ip) + '''</div>
                             <hr class="main_hr">
                             <a href="/change/pw">(''' + load_lang('password_change') + ''')</a>
                             <hr class="main_hr">
@@ -174,7 +175,7 @@ def user_setting():
                     imp = [load_lang('user_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                     data = '''
                         <form method="post">
-                            <div id="opennamu_get_user_info">''' + ip + '''</div>
+                            <div id="opennamu_get_user_info">''' + html.escape(ip) + '''</div>
                             <hr class="main_hr">
                             <h2>''' + load_lang('main') + '''</h2>
                             <span>''' + load_lang('skin') + '''</span>

+ 2 - 2
route/user_setting_email.py

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

Неке датотеке нису приказане због велике количине промена