Explorar o código

Merge pull request #1154 from openNAMU/dev

아 문제 없겠지
잉여개발기 (SPDV) %!s(int64=4) %!d(string=hai) anos
pai
achega
1410dd4f4a
Modificáronse 100 ficheiros con 2632 adicións e 3208 borrados
  1. 1 0
      .gitignore
  2. 425 399
      app.py
  3. 106 88
      emergency_tool.py
  4. 33 22
      lang/en-US.json
  5. 0 0
      lang/help_tool.py
  6. 19 16
      lang/ko-KR.json
  7. 8 16
      readme-en.md
  8. 7 7
      readme.md
  9. 6 2
      requirements.txt
  10. 18 4
      route/api_image_view.py
  11. 8 1
      route/api_raw.py
  12. 14 1
      route/api_sha224.py
  13. 6 2
      route/api_topic_sub.py
  14. 1 1
      route/api_user_info.py
  15. 1 1
      route/api_version.py
  16. 88 47
      route/api_w.py
  17. 0 10
      route/application_submitted.py
  18. 0 106
      route/applications.py
  19. 66 83
      route/edit.py
  20. 3 3
      route/edit_backlink_reset.py
  21. 4 4
      route/edit_delete.py
  22. 4 4
      route/edit_delete_many.py
  23. 2 2
      route/edit_move.py
  24. 5 5
      route/edit_revert.py
  25. 4 2
      route/give_acl.py
  26. 28 27
      route/give_admin.py
  27. 6 2
      route/give_admin_groups.py
  28. 5 5
      route/give_delete_admin_group.py
  29. 1 1
      route/give_user_ban.py
  30. 2 2
      route/give_user_check.py
  31. 1 1
      route/give_user_check_delete.py
  32. 2 2
      route/inter_wiki.py
  33. 4 1
      route/inter_wiki_plus.py
  34. 1 1
      route/list_acl.py
  35. 8 6
      route/list_admin.py
  36. 34 0
      route/list_admin_group.py
  37. 2 5
      route/list_admin_use.py
  38. 0 27
      route/list_give.py
  39. 1 1
      route/list_image_file.py
  40. 1 1
      route/list_long_page.py
  41. 1 1
      route/list_not_close_topic.py
  42. 1 1
      route/list_old_page.py
  43. 1 1
      route/list_please.py
  44. 1 1
      route/list_title_index.py
  45. 7 3
      route/list_user.py
  46. 48 23
      route/login_check_key.py
  47. 18 13
      route/login_login.py
  48. 70 0
      route/login_login_2fa.py
  49. 7 4
      route/login_login_2fa_email.py
  50. 2 2
      route/login_need_email.py
  51. 52 59
      route/login_register.py
  52. 66 0
      route/login_register_email.py
  53. 47 0
      route/login_register_email_check.py
  54. 61 0
      route/login_register_submit.py
  55. 10 0
      route/main_easter_egg.py
  56. 1 1
      route/main_error_404.py
  57. 7 14
      route/main_file.py
  58. 2 2
      route/main_image_view.py
  59. 9 8
      route/main_manager.py
  60. 2 2
      route/main_other.py
  61. 8 6
      route/main_restart.py
  62. 161 132
      route/main_setting.py
  63. 25 0
      route/main_shutdown.py
  64. 12 0
      route/main_test_func.py
  65. 1 1
      route/main_title_random.py
  66. 6 6
      route/main_update.py
  67. 13 12
      route/main_upload.py
  68. 145 0
      route/recent_app_submit.py
  69. 30 26
      route/recent_block.py
  70. 16 17
      route/recent_change.py
  71. 3 3
      route/recent_discuss.py
  72. 2 2
      route/recent_history_add.py
  73. 7 5
      route/recent_history_delete.py
  74. 3 3
      route/recent_history_hidden.py
  75. 27 0
      route/recent_history_reset.py
  76. 45 0
      route/recent_history_send.py
  77. 27 17
      route/recent_history_tool.py
  78. 27 0
      route/recent_record_reset.py
  79. 11 20
      route/recent_record_topic.py
  80. 1 1
      route/search_deep.py
  81. 508 386
      route/tool/func.py
  82. 150 0
      route/tool/func_mark.py
  83. 5 0
      route/tool/func_tool.py
  84. 0 68
      route/tool/init.py
  85. 0 82
      route/tool/mark.py
  86. 0 1334
      route/tool/namumark.py
  87. 3 3
      route/topic.py
  88. 1 1
      route/topic_acl.py
  89. 7 3
      route/topic_admin.py
  90. 1 1
      route/topic_change.py
  91. 2 2
      route/topic_close_list.py
  92. 1 1
      route/topic_delete.py
  93. 1 1
      route/topic_stop.py
  94. 1 1
      route/topic_tool.py
  95. 3 6
      route/user_alarm.py
  96. 0 0
      route/user_alarm_del.py
  97. 2 2
      route/user_count_edit.py
  98. 2 2
      route/user_custom_head_view.py
  99. 1 1
      route/user_info.py
  100. 36 20
      route/user_setting.py

+ 1 - 0
.gitignore

@@ -4,6 +4,7 @@ __pycache__
 data/set.json
 data/mysql.json
 data/oauthsettings.json
+data/version.json
 
 route/tool/set_mark/custom.py
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 425 - 399
app.py


+ 106 - 88
emergency_tool.py

@@ -9,96 +9,95 @@ while 1:
         break
 
 if data_db_load == 'Y':
-    # DB
-    while 1:
-        try:
-            set_data = json.loads(open('data/set.json', encoding = 'utf8').read())
-            if not 'db_type' in set_data:
-                try:
-                    os.remove('data/set.json')
-                except:
-                    print('Please delete set.json')
-                    print('----')
-                    raise
-            else:
-                print('DB name : ' + set_data['db'])
-                print('DB type : ' + set_data['db_type'])
-
-                break
-        except:
-            if os.getenv('NAMU_DB') != None or os.getenv('NAMU_DB_TYPE') != None:
-                set_data = {
-                    "db" : os.getenv('NAMU_DB') if os.getenv('NAMU_DB') else 'data',
-                    "db_type" : os.getenv('NAMU_DB_TYPE') if os.getenv('NAMU_DB_TYPE') else 'sqlite'
-                }
-
-                print('DB name : ' + set_data['db'])
-                print('DB type : ' + set_data['db_type'])
-
-                break
-            else:
-                new_json = ['', '']
-                normal_db_type = ['sqlite', 'mysql']
+    # Init-DB
+    if os.path.exists(os.path.join('data', 'set.json')):
+        db_set_list = ['db', 'db_type']
+        set_data = json.loads(open(os.path.join('data', 'set.json'), encoding = 'utf8').read())
+        for i in db_set_list:
+            if not i in set_data:
+                print('Please delete set.json')
+                print('----')
+                raise
+
+        print('DB name : ' + set_data['db'])
+        print('DB type : ' + set_data['db_type'])
+    elif os.getenv('NAMU_DB') or os.getenv('NAMU_DB_TYPE'):
+        set_data = {}
+
+        if os.getenv('NAMU_DB'):
+            set_data['db'] = os.getenv('NAMU_DB')
+        else:
+            set_data['db'] = 'data'
 
-                print('DB type (sqlite) [sqlite, mysql] : ', end = '')
-                new_json[0] = str(input())
-                if new_json[0] == '' or not new_json[0] in normal_db_type:
-                    new_json[0] = 'sqlite'
+        if os.getenv('NAMU_DB_TYPE'):
+            set_data['db'] = os.getenv('NAMU_DB_TYPE')
+        else:
+            set_data['db'] = 'sqlite'
 
-                all_src = []
-                for i_data in os.listdir("."):
-                    f_src = re.search(r"(.+)\.db$", i_data)
-                    if f_src:
-                        all_src += [f_src.group(1)]
+        print('DB name : ' + set_data['db'])
+        print('DB type : ' + set_data['db_type'])
+    else:
+        set_data = {}
+        normal_db_type = ['sqlite', 'mysql']
 
-                if all_src != [] and new_json[0] != 'mysql':
-                    print('DB name (data) [' + ', '.join(all_src) + '] : ', end = '')
-                else:
-                    print('DB name (data) : ', end = '')
+        print('DB type (' + normal_db_type[0] + ') [' + ', '.join(normal_db_type) + '] : ', end = '')
+        data_get = str(input())
+        if data_get == '' or not data_get in normal_db_type:
+            set_data['db_type'] = 'sqlite'
+        else:
+            set_data['db_type'] = data_get
 
-                new_json[1] = str(input())
-                if new_json[1] == '':
-                    new_json[1] = 'data'
+        all_src = []
+        if set_data['db_type'] == 'sqlite':
+            for i_data in os.listdir("."):
+                f_src = re.search(r"(.+)\.db$", i_data)
+                if f_src:
+                    all_src += [f_src.group(1)]
 
-                with open('data/set.json', 'w', encoding = 'utf8') as f:
-                    f.write('{ "db" : "' + new_json[1] + '", "db_type" : "' + new_json[0] + '" }')
+        print('DB name (data) [' + ', '.join(all_src) + '] : ', end = '')
 
-                set_data = json.loads(open('data/set.json', encoding = 'utf8').read())
+        data_get = str(input())
+        if data_get == '':
+            set_data['db'] = 'data'
+        else:
+            set_data['db'] = data_get
 
-                break
+        with open(os.path.join('data', 'set.json'), 'w', encoding = 'utf8') as f:
+            f.write(json.dumps(set_data))
 
     db_data_get(set_data['db_type'])
 
     if set_data['db_type'] == 'mysql':
-        try:
-            set_data_mysql = json.loads(open('data/mysql.json', encoding = 'utf8').read())
-        except:
-            new_json = {}
+        if not os.path.exists(os.path.join('data', 'mysql.json')):
+            db_set_list = ['user', 'password', 'host', 'port']
+            set_data = json.loads(open(
+                os.path.join('data', 'mysql.json'), 
+                encoding = 'utf8'
+            ).read())
+            for i in db_set_list:
+                if not i in set_data:
+                    print('Please delete mysql.json')
+                    print('----')
+                    raise
 
-            while 1:
-                print('DB user ID : ', end = '')
-                new_json['user'] = str(input())
-                if new_json['user'] != '':
-                    break
+            print('DB user ID : ', end = '')
+            set_data_mysql['user'] = str(input())
 
-            while 1:
-                print('DB password : ', end = '')
-                new_json['password'] = str(input())
-                if new_json['password'] != '':
-                    break
+            print('DB password : ', end = '')
+            set_data_mysql['password'] = str(input())
 
             print('DB host (localhost) : ', end = '')
-            new_json['host'] = str(input())
-            new_json['host'] = 'localhost' if new_json['host'] == '' else new_json['host']
+            set_data_mysql['host'] = str(input())
+            if set_data_mysql['host'] == '':
+                set_data_mysql['host'] = 'localhost'
 
             print('DB port (3306) : ', end = '')
-            new_json['port'] = str(input())
-            new_json['port'] = '3306' if new_json['port'] == '' else new_json['port']
+            set_data_mysql['port'] = str(input())
+            if set_data_mysql['port'] == '':
+                set_data_mysql['port'] = '3306'
 
-            with open('data/mysql.json', 'w', encoding = 'utf8') as f:
-                f.write(json.dumps(new_json))
-
-            set_data_mysql = new_json
+            with open(os.path.join('data', 'mysql.json'), 'w', encoding = 'utf8') as f:
+                f.write(json.dumps(set_data_mysql))
 
         conn = pymysql.connect(
             host = set_data_mysql['host'] if 'host' in set_data_mysql else 'localhost',
@@ -142,6 +141,7 @@ print('13. Cache data reset')
 print('14. Delete Main <HEAD>')
 print('15. Give owner')
 print('16. Delete 2FA password')
+print('17. Change markup')
 
 print('----')
 print('Select : ', end = '')
@@ -167,7 +167,12 @@ if what_i_do == '1':
     print('----')
     print('Load...')
 
-    curs.execute(db_change("select title from data d where not exists (select title from back where link = d.title)"))
+    curs.execute(db_change("" + \
+        "select title from data d " + \
+        "where not exists (" + \
+            "select title from back where link = d.title limit 1" + \
+        ")" + \
+    ""))
     title = curs.fetchall()
 
     print('----')
@@ -195,8 +200,11 @@ elif what_i_do == '3':
     print('IP or Name : ', end = '')
     user_data = input()
 
-    curs.execute(db_change("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)"),
-        [user_data,
+    curs.execute(db_change("" + \
+        "insert into rb (block, end, today, blocker, why, band) " + \
+        "values (?, ?, ?, ?, ?, ?)"
+    ), [
+        user_data,
         'release',
         get_time(),
         'tool:emergency',
@@ -248,7 +256,10 @@ elif what_i_do == '7':
         else:
             hashed = hashlib.sha3_256(bytes(user_pw, 'utf-8')).hexdigest()
 
-    curs.execute(db_change("update user set pw = ? where id = ?"), [hashed, user_name])
+    curs.execute(db_change("update user_set set data = ? where id = ? and name = 'pw'"), [
+        hashed, 
+        user_name
+    ])
 elif what_i_do == '8':
     print('----')
     print('Insert version (0000000) : ', end = '')
@@ -259,10 +270,8 @@ elif what_i_do == '8':
 
     curs.execute(db_change("update other set data = ? where name = 'ver'"), [new_ver])
 elif what_i_do == '9':
-    try:
-        os.remove('data/set.json')
-    except:
-        pass
+    if os.path.exists(os.path.join('data', 'set.json')):
+        os.remove(os.path.join('data', 'set.json'))
 elif what_i_do == '10':
     print('----')
     print('User name : ', end = '')
@@ -272,12 +281,13 @@ elif what_i_do == '10':
     print('New name : ', end = '')
     new_name = input()
 
-    curs.execute(db_change("update user set id = ? where id = ?"), [new_name, user_name])
+    curs.execute(db_change("update user_set set id = ? where id = ?"), [
+        new_name, 
+        user_name
+    ])
 elif what_i_do == '11':
-    try:
-        os.remove('data/mysql.json')
-    except:
-        pass
+    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()
@@ -287,7 +297,9 @@ elif what_i_do == '12':
         count_data = 0
 
     curs.execute(db_change('delete from other where name = "count_all_title"'))
-    curs.execute(db_change('insert into other (name, data) values ("count_all_title", ?)'), [str(count_data)])
+    curs.execute(db_change('insert into other (name, data) values ("count_all_title", ?)'), [
+        str(count_data)
+    ])
 elif what_i_do == '13':
     curs.execute(db_change('delete from cache_data'))
 elif what_i_do == '14':
@@ -297,8 +309,8 @@ elif what_i_do == '15':
     print('User name : ', end = '')
     user_name = input()
 
-    curs.execute(db_change("update user set acl = 'owner' where id = ?"), [user_name])
-else:
+    curs.execute(db_change("update user_set set data = 'owner' where id = ? and name = 'acl'"), [user_name])
+elif what_i_do == '16':
     print('----')
     print('User name : ', end = '')
     user_name = input()
@@ -306,6 +318,12 @@ else:
     curs.execute(db_change('select data from user_set where name = "2fa" and id = ?'), [user_name])
     if curs.fetchall():
         curs.execute(db_change("update user_set set data = '' where name = '2fa' and id = ?"), [user_name])
+else:
+    print('----')
+    print('Markup name : ', end = '')
+    markup = input()
+
+    curs.execute(db_change("update other set data = ? where name = 'markup'"), [markup])
 
 if data_db_load == 'Y':
     conn.commit()

+ 33 - 22
language/en-US.json → lang/en-US.json

@@ -20,6 +20,7 @@
         "host" : "Host",
         "port" : "Port",
         "restart" : "Restart",
+        "shutdown" : "Shutdown",
         "document_name" : "Document[s] name",
         "discussion_name" : "Discussion[s] topic",
         "user_name" : "Username",
@@ -122,6 +123,7 @@
             "release" : "Unblock",
     "_comment_2_" : "Func",
         "wiki_restart" : "Restart wiki engine",
+        "wiki_shutdown" : "Shutdown wiki engine",
         "update" : "Update",
         "need_document" : "Required Document(s)",
         "close_discussion" : "Closed discussion(s)",
@@ -143,17 +145,12 @@
         "pinned_release" : "Unpinned",
         "discussion_tool" : "Discussion tools",
         "discussion_raw" : "Discussion raw",
-        "oauth_signin_facebook" : "Sign-in with Facebook",
-        "oauth_signin_naver" : "Sign-in with NAVER",
-        "oauth_signin_discord" : "Sign-in with Discord",
-        "oauth_signin_kakao" : "Sign-in with Kakao",
         "connection" : "Connection",
         "new_connection" : "Connect...",
         "user_setting" : "User settings",
         "now_password" : "Current password",
         "new_password" : "New password",
         "password_confirm" : "Confirm password",
-        "oauth_connection" : "OAuth Connection",
         "password_search" : "Password finder",
         "login_able" : "Loginable",
         "band_ban" : "Range block",
@@ -214,6 +211,8 @@
         "2fa" : "2FA",
         "2fa_password" : "2FA password",
         "2fa_password_change" : "Change 2FA password",
+        "history_reset" : "Document history reset",
+        "record_reset" : "User edit log reset",
         "_comment_2.1_" : "Filter",
             "_comment_2.1.1_" : "List",
                 "interwiki_list" : "Interwiki(s) list",
@@ -236,7 +235,6 @@
         "_comment_2.2_" : "Setting",
             "setting" : "Setting",
             "restart_required" : "Restart required",
-            "oauth_setting" : "OAuth settings",
             "adsense_setting" : "Adsense settings",
             "adsense_enable" : "Adsense enable",
             "skin_setting" : "Skin settings",
@@ -247,11 +245,18 @@
                 "main_head" : "Global <HEAD>",
                 "main_body" : "Top of body",
                 "main_bottom_body" : "Bottom of body",
+                "ext_api_req_set" : "External API required setting",
             "_comment_2.2.2_" : "Main",
+                "basic_set" : "Basic settings",
+                "design_set" : "Design-related settings",
+                "login_set" : "Login-related settings",
+                "server_set" : "Server-related settings",
+                "edit_set" : "Edit-related settings",
+    
                 "wiki_name" : "Wiki[s] name",
                 "wiki_logo" : "Wiki[s] logo",
                 "main_page" : "Main page",
-                "bottom_text" : "Bottom text",
+                "bottom_text" : "License text",
                 "max_file_size" : "Max file size",
                 "backup_interval" : "Backup Cycles",
                 "wiki_skin" : "Wiki[s] default Skin",
@@ -260,7 +265,7 @@
                 "wiki_host" : "Wiki host address",
                 "wiki_port" : "Wiki port number",
                 "wiki_secret_key" : "Wiki secret key",
-                "email_required" : "Email required",
+                "email_required" : "Enable email",
                 "smtp_setting_required" : "Email SMTP setting required",
                 "update_branch" : "Branch to import updates",
                 "slow_edit" : "Continuous edit limit",
@@ -284,14 +289,21 @@
                 "edit_help" : "Editing textarea phrase",
                 "upload_help" : "File upload phrase",
                 "upload_default" : "File upload other Default",
-            "_comment_2.2.4_" : "Google",
+            "_comment_2.2.4_" : "Ext_API",
                 "recaptcha" : "reCAPTCHA",
-                "smtp_setting" : "Email SMTP setting",
-                "smtp_server" : "SMTP Server address",
-                "smtp_security": "SMTP Connection security",
-                "smtp_port" : "SMTP Server port",
-                "smtp_username" : "SMTP Username",
-                "smtp_password" : "SMTP Password",
+                
+                "email_setting" : "Email settings",
+                "_comment_2.2.4.1_" : "SMTP",
+                    "smtp_setting" : "Email SMTP settings",
+                    "smtp_server" : "SMTP Server address",
+                    "smtp_security": "SMTP Connection security",
+                    "smtp_port" : "SMTP Server port",
+                    "smtp_username" : "SMTP Username",
+                    "smtp_password" : "SMTP Password",
+                
+                "oauth" : "OAuth",
+                "_comment_2.2.4.2_" : "OAuth",
+                    "oauth_client_id" : "OAuth client ID",
         "_comment_2.3_" : "List",
             "open_discussion_list" : "Open discussion(s) list",
             "discussion_list" : "Discussion(s) list",
@@ -373,19 +385,12 @@
         "application_submitted": "Applicatied successfully for registration",
         "waiting_for_approval": "Application for registration has been made successfully. Please wait for approval by administrators.",
         "ie_no_data_required" : "Operation cannot continue because all required data has not been collected.",
-        "oauth_settings_not_found" : "The administrator has not provided any data about using this feature.",
-        "oauth_disabled" : "The administrator has disabled this feature.",
-        "http_warring" : "Warning: If you are not on HTTPS connection, Your information can be leaked. We won't response to that.",
-        "user_head_warring" : "User data will be deleted if you close the browser or when you sign in.",
-        "no_login_warring" : "You are not logged in. The IP address will be logged when editing or discussing with non-login.",
         "user_reset_sign" : "Your account information has changed like this.",
-        "update_warring" : "Manual updates are recommended if your version is 0.2 or lower than the latest version. For Windows, the contents of the route folder disappear.",
         "default_edit_help" : "Describe it here",
         "markup_enabled" : "Markup enabled",
         "many_delete_help" : "Please write down the document[s] name one by one on the line.",
         "sqlite_only" : "SQLite only",
         "approval_question_visible_only_when_approval_on" : "Approval questions are visible only when approval requirement is on",
-        "oauth_explain" : "To use the OAuth login feature, you must set the 'publish_url' value to a domain address that includes the HTTPS protocol, and actually support HTTPS connections.",
         "msg_whatchlist_lmt": "You can add as many as",
         "enter_html" : "Please enter HTML",
         "exp_edit_conflict" : "Editing conflict occurred",
@@ -426,4 +431,10 @@
             "restart_fail_error" : "Restart failed. Please use manual restart.",
             "same_email_error" : "There are users using the same email.",
             "input_email_error" : "There is a problem with the input value."
+        "_comment_3.2_" : "Warning",
+            "http_warning" : "Warning: If you are not on HTTPS connection, Your information can be leaked. We won't response to that.",
+            "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. The IP address will be logged when editing or discussing with non-login.",
+            "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 disappear.",
+            "history_delete_warning" : "If you erase history, it's hard to restore it, so make a careful decision."
 }

+ 0 - 0
language/help_tool.py → lang/help_tool.py


+ 19 - 16
language/ko-KR.json → lang/ko-KR.json

@@ -74,7 +74,6 @@
     "wiki_name": "위키 이름",
     "acl_document_list": "ACL 문서 목록",
     "connection": "연결",
-    "oauth_disabled": "관리자가 이 기능을 비활성화시켰습니다.",
     "random": "무작위",
     "filter": "필터",
     "band_blocked": "대역 차단됨",
@@ -91,13 +90,11 @@
     "setting": "설정",
     "end": "끝",
     "error": "오류",
-    "oauth_signin_discord": "디스코드 아이디로 로그인",
     "ban": "차단",
     "email_insert_text": "이메일 입력란 문구",
     "check_key_text": "인증키 검사 문구",
     "other_tool": "기타 도구",
     "recent_discussion": "최근 토론",
-    "oauth_signin_naver": "네이버 아이디로 로그인",
     "record": "기록",
     "owner_authority": "소유자 권한",
     "wiki_port": "위키 포트",
@@ -108,12 +105,11 @@
     "under_category": "하위 분류",
     "range": "대역",
     "edit_filter_rule": "편집 필터 규칙",
-    "oauth_connection": "Oauth 연결",
     "hide_ip": "IP 주소 숨기기",
     "topic_tool": "토론 관리 도구",
     "user_document": "사용자 문서",
     "id": "아이디",
-    "no_login_warring": "비로그인 상태입니다. 편집 시 지금 접속한 IP가 기록됩니다.",
+    "no_login_warning": "비로그인 상태입니다. 편집 시 지금 접속한 IP가 기록됩니다.",
     "decument_404_error": "이 문서는 존재하지 않습니다.",
     "key": "키",
     "lastest": "최신",
@@ -132,7 +128,6 @@
     "regex": "정규표현식",
     "file_filter_add": "파일명 필터 추가",
     "wiki_restart": "위키 엔진 재시작",
-    "oauth_settings_not_found": "관리자가 해당 기능을 수행하기 위해 필요한 데이터를 제공하지 않았습니다.",
     "discussion_raw": "토론 댓글 원본",
     "main_setting": "메인 설정",
     "password": "비밀번호",
@@ -170,7 +165,6 @@
     "recaptcha": "reCAPTCHA",
     "create": "생성",
     "restart": "재시작",
-    "oauth_setting": "OAuth 설정",
     "edit_bottom_text": "편집창 하단 문구",
     "copyright_checkbox_text": "저작권 동의 문구(체크박스 형태)",
     "authority": "권한",
@@ -193,8 +187,8 @@
     "editor": "편집자",
     "wiki_secret_key": "위키 비밀 키",
     "band_ban": "대역 차단",
-    "http_warring": "경고: HTTPS 연결을 사용하지 않는다면 개인정보가 유출될 수 있습니다. 이 사항에 의해 입는 피해는 사용자에게 책임이 있음을 알려드립니다.",
-    "update_warring": "최신 버전보다 0.2 버전 이상 낮은 경우 수동 업데이트를 권장합니다. 윈도우의 경우 route 폴더의 내용이 사라집니다.",
+    "http_warning": "경고: HTTPS 연결을 사용하지 않는다면 개인정보가 유출될 수 있습니다. 이 사항에 의해 입는 피해는 사용자에게 책임이 있음을 알려드립니다.",
+    "update_warning": "최신 버전보다 0.2 버전 이상 낮은 경우 수동 업데이트를 권장합니다. 윈도우의 경우 route 폴더의 내용이 사라집니다.",
     "discussion_name": "토론 제목",
     "discussion": "토론",
     "main": "메인",
@@ -203,7 +197,7 @@
     "interwiki_add": "인터위키 추가",
     "return": "돌아가기",
     "logout": "로그아웃",
-    "bottom_text": "하단 내용",
+    "bottom_text": "라이선스 내용",
     "30_day": "30일",
     "topic_long_error": "토론 제목은 256자를 넘을 수 없습니다.",
     "error_401": "ACL 읽기 제한 문서 문구",
@@ -216,7 +210,6 @@
     "name": "이름",
     "period": "기간",
     "writer": "작성자",
-    "oauth_signin_facebook": "페이스북 아이디로 로그인",
     "long_id_error": "ID는 20자보다 짧아야 합니다.",
     "edit_record_error": "사유는 500자를 넘을 수 없습니다.",
     "revert": "복원",
@@ -232,7 +225,6 @@
     "ban_period": "차단 기간",
     "use_push_alarm": "푸쉬 알림 사용",
     "email_filter_add": "이메일 필터 추가",
-    "oauth_signin_kakao": "카카오톡 아이디로 로그인",
     "authority_error": "권한이 없습니다.",
     "type": "유형",
     "acl_change": "문서 ACL 변경",
@@ -271,8 +263,8 @@
     "other": "기타",
     "edit": "편집",
     "open_discussion_list": "열린 토론 목록",
-    "user_head_warring": "비로그인시 브라우저를 닫거나 로그인시 사용자가 지정한 정보는 삭제됩니다.",
-    "email_required": "이메일 필요",
+    "user_head_warning": "비로그인시 브라우저를 닫거나 로그인시 사용자가 지정한 정보는 삭제됩니다.",
+    "email_required": "이메일 사용",
     "1_day": "1일",
     "regex_error": "정규표현식에 오류가 있습니다.",
     "backup_interval": "백업 주기",
@@ -337,7 +329,6 @@
     "all_register_num": "모든 가입 신청자의 수",
     "replace_move": "문서 바꾸기",
     "merge_move": "문서 병합",
-    "oauth_explain": "OAuth 로그인 기능을 사용하려면 'publish_url' 값을 HTTPS 프로토콜을 포함한 도메인 주소로 설정하고, 실제로 HTTPS 연결을 지원해야 합니다.",
     "add_admin_group": "관리자 그룹 추가",
     "add_watchlist": "주시 문서 추가",
     "blocked_user": "차단된 사용자",
@@ -400,5 +391,17 @@
     "input_email_error" : "입력 값에 문제가 있습니다.",
     "short_page" : "짧은 문서 목록",
     "long_page" : "긴 문서 목록",
-    "ua_get_off" : "가입자 정보 수집 끄기"
+    "ua_get_off" : "가입자 정보 수집 끄기",
+    "ext_api_req_set" : "외부 API 필요 설정",
+    "oauth" : "OAuth",
+    "basic_set" : "기본 설정",
+    "design_set" : "디자인 관련 설정",
+    "login_set" : "로그인 관련 설정",
+    "server_set" : "서버 관련 설정",
+    "edit_set" : "편집 관련 설정",
+    "wiki_shutdown" : "위키 엔진 종료",
+    "shutdown" : "종료",
+    "history_delete_warning" : "역사를 지울 경우 복구하기 어려우니 신중하게 결정하세요.",
+    "history_reset" : "문서 역사 초기화",
+    "record_reset" : "사용자 편집 기록 초기화"
 }

+ 8 - 16
readme-en.md

@@ -3,9 +3,9 @@
 [![Up to Python 3.5](https://img.shields.io/badge/python->=%203.5-blue.svg)](https://python.org)
 [![LICENSE](https://img.shields.io/badge/license-BSD%203--Clause-lightgrey.svg)](./LICENSE)
 
-![](https://raw.githubusercontent.com/2du/openNAMU/beta/.github/logo.png)
+![](https://raw.githubusercontent.com/openNAMU/openNAMU/beta/.github/logo.png)
 
-openNAMU is a Python-based wiki engine. You can use openNAMU by installing Python and its dependency modules, and you can modify the code yourself to create more specialized wikis.
+openNAMU is a Python-based wiki engine. 
 
 ### Index
  * [Getting Started](#getting-started)
@@ -21,14 +21,14 @@ openNAMU is based upon Python, and it requires a Python environment.
 
 ## Clone
 You can clone this repository by entering the following command at the terminal (command prompt):
- * `git clone -b stable https://github.com/2du/openNAMU.git`
- * `git clone -b beta https://github.com/2du/openNAMU.git`
- * `git clone -b dev https://github.com/2du/openNAMU.git`
+ * `git clone -b stable https://github.com/openNAMU/openNAMU.git`
+ * `git clone -b beta https://github.com/openNAMU/openNAMU.git`
+ * `git clone -b dev https://github.com/openNAMU/openNAMU.git`
 
 ## Contribute
-openNAMU may have some untested bugs. Your use of openNAMU and bug discovery will help develop openNAMU. [(Create Issues)](https://github.com/2du/openNAMU/issues/new)
+openNAMU may have some untested bugs. Your use of openNAMU and bug discovery will help develop openNAMU. [(Create Issues)](https://github.com/openNAMU/openNAMU/issues/new)
 
-openNAMU is a complete open source project. Add new features and create pull requests. [(Create Pull Requests)](https://github.com/2du/openNAMU/compare)
+openNAMU is a complete open source project. Add new features and create pull requests. [(Create Pull Requests)](https://github.com/openNAMU/openNAMU/compare)
 
 ## Lisence
 openNAMU is protected by [BSD 3-Clause License](./LICNESE). Please refer to the documentation for details.
@@ -39,15 +39,7 @@ openNAMU is protected by [BSD 3-Clause License](./LICNESE). Please refer to the
  * Numerical expression [MathJax](https://www.mathjax.org/)
  * Handling Keyboard Shortcuts [shortcut.js](http://www.openjs.com/scripts/events/keyboard_shortcuts/)
 
-### Authors
- * [Reference](https://github.com/2DU/openNAMU/graphs/contributors)
-
-### Special Thanks
- * [Team Croatia](https://github.com/TeamCroatia)
- * Basix
- * Efrit
- * Other chat rooms
-
 ## Etc.
  * Owner rights are granted to the first registor.
  * [Test Server](http://2du.pythonanywhere.com)
+ * [Contributors](https://github.com/openNAMU/openNAMU/graphs/contributors)

+ 7 - 7
readme.md

@@ -3,7 +3,7 @@
 [![Python 3.5 이상](https://img.shields.io/badge/python->=%203.5-blue.svg)](https://python.org)
 [![라이선스](https://img.shields.io/badge/license-BSD%203--Clause-lightgrey.svg)](./LICENSE)
 
-![](https://raw.githubusercontent.com/2du/openNAMU/beta/.github/logo.png)
+![](https://raw.githubusercontent.com/openNAMU/openNAMU/beta/.github/logo.png)
 
 오픈나무는 파이썬 기반의 위키 엔진입니다.
 
@@ -22,14 +22,14 @@
 
 ### 클론
 아래 명령을 터미널(명령 프롬프트)에 입력하여 본 리포지토리를 클론할 수 있습니다.
- * 일반: `git clone -b stable https://github.com/2du/openNAMU.git`
- * 베타: `git clone -b beta https://github.com/2du/openNAMU.git`
- * 개발: `git clone -b dev https://github.com/2du/openNAMU.git`
+ * 일반: `git clone -b stable https://github.com/openNAMU/openNAMU.git`
+ * 베타: `git clone -b beta https://github.com/openNAMU/openNAMU.git`
+ * 개발: `git clone -b dev https://github.com/openNAMU/openNAMU.git`
 
 ## 기여
-오픈나무에는 확인되지 않은 버그가 존재할 수 있습니다. 이를 보고해주시면 오픈나무의 발전을 도울 수 있습니다. [여기](https://github.com/2du/openNAMU/issues/new)를 눌러 버그를 보고해주세요.
+오픈나무에는 확인되지 않은 버그가 존재할 수 있습니다. 이를 보고해주시면 오픈나무의 발전을 도울 수 있습니다. [여기](https://github.com/openNAMU/openNAMU/issues/new)를 눌러 버그를 보고해주세요.
 
-오픈나무는 오픈소스 프로젝트입니다. 원한다면 직접 코드를 수정하고 Pull Request를 보낼 수 있습니다.
+오픈나무는 오픈소스 프로젝트입니다. 원한다면 직접 코드를 수정하고 [Pull Request](https://github.com/openNAMU/openNAMU/compare)를 보낼 수 있습니다.
 
 ## 라이선스
 오픈나무 프로젝트는 [BSD 3-Clause License](./LICENSE)의 보호를 받고 있으며, 오픈나무 프로젝트를 사용하고자 한다면 라이선스를 준수해야 합니다. 본 라이선스를 위반할 경우 법적인 조치가 취해질 수 있습니다. 자세한 내용은 문서를 참고하세요.
@@ -53,4 +53,4 @@
 ## 기타
  * 첫 가입자에게 소유자 권한이 부여됩니다.
  * [테스트 서버](http://2du.pythonanywhere.com)
- * [기여자 목록](https://github.com/2DU/openNAMU/graphs/contributors)
+ * [기여자 목록](https://github.com/openNAMU/openNAMU/graphs/contributors)

+ 6 - 2
requirements.txt

@@ -1,8 +1,12 @@
 flask
-flask-Reggie
-tornado
+gevent
+
 requests
+
 pymysql
+
 Pillow
+
 diff-match-patch
+
 pysha3; python_version < "3.6"

+ 18 - 4
route/api_image_view.py

@@ -1,9 +1,23 @@
 from .tool.func import *
 
-def api_image_view_2(conn, name, app_var):
+def api_image_view_2(conn, name):
     curs = conn.cursor()
 
-    if os.path.exists(os.path.join(app_var['path_data_image'], name)):
-        return flask.jsonify({ "exist" : "1" })
+    if flask.request.method == 'POST':
+        try:
+            title_list = json.loads(flask.request.form.get('title_list', ''))
+            title_list = list(set(title_list))
+        except:
+            title_list = []
+        
+        data_list = {}
+        for i in title_list:
+            if os.path.exists(os.path.join(load_image_url(), i)):
+                data_list[i] = '1'
+        
+        return flask.jsonify(data_list)
     else:
-        return flask.jsonify({})
+        if os.path.exists(os.path.join(load_image_url(), name)):
+            return flask.jsonify({ "exist" : "1" })
+        else:
+            return flask.jsonify({})

+ 8 - 1
route/api_raw.py

@@ -11,7 +11,14 @@ def api_raw_2(conn, name):
             curs.execute(db_change("select data from data where title = ?"), [name])
         data = curs.fetchall()
         if data:
-            json_data = { "title" : name, "data" : render_set(title = name, data = data[0][0], s_data = 1) }
+            json_data = {
+                "title" : name, 
+                "data" : render_set(
+                    doc_name = name, 
+                    doc_data = data[0][0],
+                    data_type = 'raw'
+                )
+            }
 
             return flask.jsonify(json_data)
         

+ 14 - 1
route/api_sha224.py

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

+ 6 - 2
route/api_topic_sub.py

@@ -4,7 +4,6 @@ def api_topic_sub_2(conn, topic_num):
     curs = conn.cursor()
 
     topic_num = str(topic_num)
-    get_acl = acl_check('', 'render')
 
     if flask.request.args.get('num', None):
         curs.execute(db_change("select id, data, date, ip, block, top from topic where code = ? and id + 0 = ? + 0 order by id + 0 asc"), [
@@ -56,7 +55,12 @@ def api_topic_sub_2(conn, topic_num):
                 "blind" : i[4],
                 
                 "ip_pas" : ip_a[i[3]],
-                "data_pas" : [data_r_html, data_r_js]
+                "data_pas" : render_set(
+                    doc_data = data_v, 
+                    data_type = 'api_view',
+                    data_in = i[0],
+                    doc_acl = 0
+                )
             }
 
         return flask.jsonify(data_a)

+ 1 - 1
route/api_user_info.py

@@ -29,7 +29,7 @@ def api_user_info_2(conn, name):
             </table>
         '''
 
-        curs.execute(db_change("select acl from user where id = ?"), [name])
+        curs.execute(db_change("select data from user_set where id = ? and name = 'acl'"), [name])
         data = curs.fetchall()
         if data:
             if data[0][0] != 'user':

+ 1 - 1
route/api_version.py

@@ -11,7 +11,7 @@ def api_version_2(conn, r_ver, c_ver):
     up_data = up_data[0][0] if up_data and up_data[0][0] in ['stable', 'beta', 'dev'] else 'stable'
 
     try:
-        data = urllib.request.urlopen('https://raw.githubusercontent.com/2du/openNAMU/' + up_data + '/version.json')
+        data = urllib.request.urlopen('https://raw.githubusercontent.com/openNAMU/openNAMU/' + up_data + '/version.json')
     except:
         data = None
 

+ 88 - 47
route/api_w.py

@@ -3,70 +3,111 @@ from .tool.func import *
 def api_w_2(conn, name):
     curs = conn.cursor()
 
-    data_arg_exist = flask.request.args.get('exist', '')
-    if data_arg_exist != '':
-        curs.execute(db_change("select title from data where title = ?"), [name])
-        if curs.fetchall():
-            return flask.jsonify({ "exist" : "1" })
-    else:
-        if acl_check(name, 'render') != 1:
-            if flask.request.method == 'POST':
-                data_org = flask.request.form.get('data', '')
+    data_arg_v = flask.request.args.get('v', '')
+    if flask.request.method == 'POST':
+        print(data_arg_v)
+        if data_arg_v == '' or data_arg_v == 'preview':
+            data_org = flask.request.form.get('data', '')
+            data_pas = render_set(
+                doc_name = name, 
+                doc_data = data_org, 
+                data_type = 'api_view'
+            )
+
+            return flask.jsonify({
+                "data" : data_pas[0], 
+                "js_data" : data_pas[1]
+            })
+        elif data_arg_v == 'include':
+            name_org = flask.request.args.get('name_org', '')
+            name_org = name if name_org == '' else name_org
+            
+            include_data = flask.request.args.get('include', '')
+                
+            try:
+                include_list = json.loads(flask.request.form.get('include_list', ''))
+            except:
+                include_list = []
+
+            curs.execute(db_change("select data from data where title = ?"), [name])
+            sql_data = curs.fetchall()
+            if not sql_data:
+                return flask.jsonify({})
+            else:
+                json_data = sql_data[0][0]
+
+                get_all_change_1 = []
+                find_replace_moment = re.findall(r'(@([^=@]+)=([^=@]+)@|@([^=@]+)@)', json_data)
+                for i in find_replace_moment:
+                    if i[1] != '':
+                        get_all_change_1 += [['@' + i[1] + '@', i[2]]]
+
+                        json_data = json_data.replace(i[0], '@' + i[1] + '@', 1)
+                    else:
+                        json_data = json_data.replace(i[0], '@' + i[3] + '@', 1)
+
+                get_all_change_2 = include_list + get_all_change_1
+                print(get_all_change_2)
+                for i in get_all_change_2:
+                    json_data = json_data.replace('@' + i[0] + '@', i[1])
+
                 data_pas = render_set(
-                    title = name, 
-                    data = data_org, 
-                    num = 2
+                    doc_name = name_org, 
+                    doc_data = json_data, 
+                    data_type = 'api_view',
+                    data_in = include_data
                 )
 
                 return flask.jsonify({
                     "data" : data_pas[0], 
                     "js_data" : data_pas[1]
                 })
+        elif data_arg_v == 'exist':
+            try:
+                title_list = json.loads(flask.request.form.get('title_list', ''))
+                title_list = list(set(title_list))
+            except:
+                title_list = []
+            
+            data_exist = {}
+            for i in title_list:
+                curs.execute(db_change("select title from data where title = ?"), [i])
+                if curs.fetchall():
+                    data_exist[i] = '1'
+                    
+            return flask.jsonify(data_exist)
+        else:
+            return flask.jsonify({})
+    else:
+        data_arg_exist = flask.request.args.get('exist', '')
+        if data_arg_v == 'exist' or data_arg_exist != '':
+            curs.execute(db_change("select title from data where title = ?"), [name])
+            if curs.fetchall():
+                return flask.jsonify({ "exist" : "1" })
+            else:
+                return flask.jsonify({})
+        else:
+            data_arg_include = flask.request.args.get('include', '')
+            if acl_check(name, 'render') == 1:
+                return flask.jsonify({})
             else:
                 data_arg_rev = flask.request.args.get('num', '')
                 if data_arg_rev != '':
                     curs.execute(db_change("select data from history where title = ? and id = ?"), [name, rev])
                 else:
                     curs.execute(db_change("select data from data where title = ?"), [name])
-                
-                data = curs.fetchall()
-                if data:
-                    name_org = flask.request.args.get('name_org', '')
-                    if name_org == '':
-                        name_org = name
-                        
-                    json_data = data[0][0]
-                    
-                    include_data = flask.request.args.get('include', '')
-                    if include_data != '':
-                        get_all_change_1 = []
-                        find_replace_moment = re.findall(r'(@([^=@]+)=([^=@]+)@|@([^=@]+)@)', json_data)
-                        for i in find_replace_moment:
-                            if i[1] != '':
-                                get_all_change_1 += [['@' + i[1] + '@', i[2]]]
-
-                                json_data = json_data.replace(i[0], '@' + i[1] + '@', 1)
-                            else:
-                                json_data = json_data.replace(i[0], '@' + i[3] + '@', 1)
 
-                        get_all_change_2 = re.findall(r'(@(?:[^@]*)@),([^,]*),', flask.request.args.get('change', '')) + get_all_change_1
-                        for i in get_all_change_2:
-                            json_data = json_data.replace(
-                                i[0].replace('<amp>', '&'), 
-                                i[1].replace('<amp>', '&').replace('<comma>', ','), 
-                                1
-                            )
-                        
+                sql_data = curs.fetchall()
+                if not sql_data:
+                    return flask.jsonify({})
+                else:
                     data_pas = render_set(
-                        title = name_org, 
-                        data = json_data, 
-                        num = 2, 
-                        include = include_data
+                        doc_name = name, 
+                        doc_data = sql_data[0][0], 
+                        data_type = 'api_view'
                     )
 
                     return flask.jsonify({
                         "data" : data_pas[0], 
                         "js_data" : data_pas[1]
-                    })
-
-    return flask.jsonify({})
+                    })

+ 0 - 10
route/application_submitted.py

@@ -1,10 +0,0 @@
-from .tool.func import *
-
-def application_submitted_2(conn):
-    curs = conn.cursor()
-
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('application_submitted'), wiki_set(), custom(), other2([0, 0])],
-        data = '<p>' + load_lang('waiting_for_approval') + '</p>',
-        menu = [['user', load_lang('return')]]
-    ))

+ 0 - 106
route/applications.py

@@ -1,106 +0,0 @@
-from .tool.func import *
-
-def applications_2(conn):
-    curs = conn.cursor()
-
-    div = ''
-
-    if admin_check() != 1:
-        return re_error('/ban')
-
-    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':
-        div += '<p>' + load_lang('approval_requirement_disabled') + '</p>'
-
-    if flask.request.method == 'GET':
-        curs.execute(db_change('select id, date, question, answer, token, email from user_application'))
-        db_data = curs.fetchall()
-        if db_data:
-            div += '<p>' + load_lang('all_register_num') + ' : ' + str(len(db_data)) + '</p><br>'
-
-            for application in db_data:
-                question = application[2]
-                answer = application[3]
-                email = application[5]
-                if not question:
-                    question = ''
-
-                if not answer:
-                    answer = ''
-                
-                if not email:
-                    email = ''
-                
-                div += '''
-                    <form method=\"post\">
-                        <table>
-                            <tbody>
-                                <tr>
-                                    <td>''' + load_lang('id') + '''</td><td>''' + application[0] + '''</td>
-                                </tr>
-                                <tr>
-                                    <td>''' + load_lang('application_time') + '''</td><td>''' + application[1] + '''</td>
-                                </tr>
-                                <tr>
-                                    <td>''' + load_lang('approval_question') + '''</td><td>''' + html.escape(question) + '''</td>
-                                </tr>
-                                <tr>
-                                    <td>''' + load_lang('answer') + '''</td><td>''' + html.escape(answer) + '''</td>
-                                </tr>
-                                <tr>
-                                    <td>''' + load_lang('email') + '''</td><td>''' + html.escape(email) + '''</td>
-                                </tr>
-                                <tr>
-                                    <td colspan=\"2\" style=\"text-align: center;\">
-                                        <button type=\"submit\" name=\"approve\" value=\"''' + application[4] + '''\">''' + load_lang('approve') + '''</button>
-                                        <button type=\"submit\" name=\"decline\" value=\"''' + application[4] + '''\">''' + load_lang('decline') + '''</button>
-                                    </td>
-                                </tr>
-                            </tbody>
-                        </table>
-                    </form>
-                    <br>
-                '''
-        else:
-            div += load_lang('no_applications_now')
-
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('application_list'), wiki_set(), custom(), other2([0, 0])],
-            data = div,
-            menu = [['other', load_lang('return')]]
-        ))
-    else:
-        if flask.request.form.get('approve', '') != '':
-            curs.execute(db_change('select id, pw, date, encode, question, answer, ip, ua, email from user_application where token = ?'), [
-                flask.request.form.get('approve', '')
-            ])
-            application = curs.fetchall()
-            if not application:
-                return re_error('/error/26')
-            
-            application = application[0]
-
-            curs.execute(db_change("select id from user where id = ?"), [application[0]])
-            if curs.fetchall():
-                return re_error('/error/6')
-            
-            curs.execute(db_change("insert into user (id, pw, acl, date, encode) values (?, ?, 'user', ?, ?)"), [
-                application[0], 
-                application[1], 
-                application[2], 
-                application[3]
-            ])
-            curs.execute(db_change("insert into user_set (name, id, data) values ('approval_question', ?, ?)"), [application[0], application[4]])
-            curs.execute(db_change("insert into user_set (name, id, data) values ('approval_question_answer', ?, ?)"), [application[0], application[5]])
-            ua_plus(application[0], application[6], application[7], application[2])
-            if application[8] and application[8] != '':
-                curs.execute(db_change("insert into user_set (name, id, data) values ('email', ?, ?)"), [application[0], application[8]])
-            
-            curs.execute(db_change('delete from user_application where token = ?'), [flask.request.form.get('approve', '')])
-            conn.commit()
-        elif flask.request.form.get('decline', '') != '':
-            curs.execute(db_change('delete from user_application where token = ?'), [flask.request.form.get('decline', '')])
-            conn.commit()
-
-        return redirect('/applications')

+ 66 - 83
route/edit.py

@@ -1,45 +1,24 @@
 from .tool.func import *
 
-class run_count_section:
-    def __init__(self, key, change):
-        self.counter = key
-        self.change = change
-
-    def __call__(self, match):
-        self.counter -= 1
-
-        if self.counter == 0:
-            return '\n' + self.change + '\n'
-        else:
-            return '\n' + match[1]
-
 def edit_2(conn, name):
     curs = conn.cursor()
 
     ip = ip_check()
-    section = flask.request.args.get('section', None)
-    if section:
-        curs.execute(db_change("select data from other where name = 'markup'"))
-        markup = curs.fetchall()
-        if markup[0][0] == 'namumark':
-            section = int(number_check(section))
-        else:
-            return redirect('/edit/' + url_pas(name))
-
     if acl_check(name) == 1:
         return re_error('/ban')
     
     curs.execute(db_change("select id from history where title = ? order by id + 0 desc"), [name])
     doc_ver = curs.fetchall()
     doc_ver = doc_ver[0][0] if doc_ver else '0'
-
-    edit_repeat = 0
+    
+    section = flask.request.args.get('section', '')
+    post_ver = flask.request.form.get('ver', '')
     if flask.request.method == 'POST':
-        edit_repeat = 1
-        if flask.request.form.get('ver', '') != doc_ver:
-            edit_repeat = 2
+        edit_repeat = 'error' if post_ver != doc_ver else 'post'
+    else:
+        edit_repeat = 'get'
     
-    if edit_repeat == 1:
+    if edit_repeat == 'post':
         if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
             return re_error('/error/13')
         else:
@@ -64,17 +43,6 @@ def edit_2(conn, name):
         if old:  
             o_data = old[0][0].replace('\r\n', '\n')
 
-            if section:
-                run_count = run_count_section(section, content)
-
-                c_data = html.escape('\n' + o_data)
-                c_data = re.sub(r'\n(?P<in>={1,6})', '<br>\g<in>', c_data)
-                c_data = re.sub(r'<br>((?:(?:(?!<br>).)*\n*)*)', run_count, c_data)
-                c_data = re.sub(r'^\n', '', c_data)
-                c_data = html.unescape(c_data)
-
-                content = c_data
-
             leng = leng_check(len(o_data), len(content))
             
             curs.execute(db_change("update data set data = ? where title = ?"), [content, name])
@@ -103,51 +71,44 @@ def edit_2(conn, name):
         curs.execute(db_change("delete from back where title = ? and type = 'no'"), [name])
         
         render_set(
-            title = name,
-            data = content,
-            num = 1
+            doc_name = name,
+            doc_data = content,
+            data_type = 'backlink'
         )
         
         conn.commit()
         
-        return redirect('/w/' + url_pas(name) + (('#edit_load_' + str(section)) if section else ''))
+        section = (('#edit_load_' + str(section)) if section != '' else '')
+        
+        return redirect('/w/' + url_pas(name) + section)
     else:
         editor_top_text = ''
-        if edit_repeat != 2:
-            load_title = flask.request.args.get('plus', None)
-            if load_title:
-                curs.execute(db_change("select data from data where title = ?"), [load_title])
-                get_data = curs.fetchall()
-                data = get_data[0][0] if get_data else ''
-            else:
-                curs.execute(db_change("select data, id from history where title = ? order by id + 0 desc"), [name])
-                old = curs.fetchall()
-                old = old if old else [['']]
-                if section:
-                    data = html.escape('\n' + old[0][0].replace('\r\n', '\n'))
-                    data = re.sub(r'\n(?P<in>={1,6})', '<br>\g<in>', data)
-
-                    section_data = re.findall(r'<br>((?:(?:(?!<br>).)*\n*)*)', data)
-                    if len(section_data) >= section:
-                        data = html.unescape(section_data[section - 1])
-                    else:
-                        return redirect('/edit/' + url_pas(name))
-                else:
-                    data = old[0][0].replace('\r\n', '\n')
-                    editor_top_text += '<a href="/manager/15?plus=' + url_pas(name) + '">(' + load_lang('load') + ')</a> '
+        if edit_repeat == 'get':
+            load_title = flask.request.args.get('plus', '')
+            if load_title == '':
+                load_title = name
+                editor_top_text += '<a href="/manager/15?plus=' + url_pas(name) + '">(' + load_lang('load') + ')</a> '
+                
+            curs.execute(db_change("select data from data where title = ?"), [load_title])
+            sql_d = curs.fetchall()
+            data = sql_d[0][0] if sql_d else ''
+            data = data.replace('\r\n', '\n')
+                    
         else:
             data = flask.request.form.get('content', '')
-            warring_edit = load_lang('exp_edit_conflict') + ' '
+            warning_edit = load_lang('exp_edit_conflict') + ' '
 
             if flask.request.form.get('ver', '0') == '0':
-                warring_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
+                warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
             else:
-                warring_edit += '' + \
-                    '<a href="/diff/' + url_pas(name) + '?first=' + flask.request.form.get('ver', '1') + '&second=' + doc_ver + '">(r' + doc_ver + ')</a>' + \
+                warning_edit += '' + \
+                    '<a href="/diff/' + url_pas(name) + '?first=' + flask.request.form.get('ver', '1') + '&second=' + doc_ver + '">' + \
+                        '(r' + doc_ver + ')' + \
+                    '</a>' + \
                 ''
 
-            warring_edit += '<hr class="main_hr">'
-            editor_top_text = warring_edit + editor_top_text
+            warning_edit += '<hr class="main_hr">'
+            editor_top_text = warning_edit + editor_top_text
 
         editor_top_text += '' + \
             '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>' + \
@@ -205,16 +166,21 @@ def edit_2(conn, name):
             monaco_display = 'style="display: none;"'
             add_get_file = ''
             add_script = ''
+            
+        curs.execute(db_change("select data from other where name = 'markup'"))
+        markup = curs.fetchall()[0][0]
+        
+        server_set = {
+            'section' : section,
+            'markup' : markup
+         }
 
         return easy_minify(flask.render_template(skin_check(), 
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('edit') + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('edit') + ')', 0])],
             data =  editor_top_text + add_get_file + '''
+                <span   id="server_set"
+                        style="display: none;">''' + json.dumps(server_set) + '''</span>
                 <form method="post">
-                    <script>
-                        do_paste_image();
-                        do_not_out();
-                        ''' + add_script + '''
-                    </script>
                     <div ''' + editor_display + '''>''' + edit_button() + '''</div>
                     <div    id="monaco_editor"
                             class="content" 
@@ -225,21 +191,38 @@ def edit_2(conn, name):
                                 placeholder="''' + p_text + '''" 
                                 name="content">''' + html.escape(data) + '''</textarea>
                     <hr class="main_hr">
-                    <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
-                    <textarea style="display: none;" id="origin">''' + html.escape(data) + '''</textarea>
-                    <input style="display: none;" name="ver" value="''' + doc_ver + '''">
+                    <input  placeholder="''' + load_lang('why') + '''" 
+                            name="send">
+                    <textarea   style="display: none;" 
+                                id="origin">''' + html.escape(data) + '''</textarea>
+                    <input  style="display: none;" 
+                            name="ver" 
+                            value="''' + doc_ver + '''">
                     <hr class="main_hr">
-                    ''' + captcha_get() + ip_warring() + cccb_text + '''
+                    ''' + captcha_get() + ip_warning() + cccb_text + '''
                     <button id="save"
                             type="submit" 
-                            onclick="monaco_to_content(); save_stop_exit();">''' + load_lang('save') + '''</button>
+                            onclick="
+                                monaco_to_content(); 
+                                save_stop_exit();
+                                section_edit_do();
+                            ">''' + load_lang('save') + '''</button>
                     <button id="preview" 
                             type="button" 
-                            onclick="monaco_to_content(); load_preview(\'''' + url_pas(name) + '\');">' + load_lang('preview') + '''</button>
+                            onclick="
+                                monaco_to_content(); 
+                                load_preview(\'''' + url_pas(name) + '''\');
+                            ">''' + load_lang('preview') + '''</button>
                 </form>
                 ''' + b_text + '''
                 <hr class="main_hr">
                 <div id="see_preview"></div>
+                <script>
+                    section_edit_init();
+                    do_paste_image();
+                    do_not_out();
+                    ''' + add_script + '''
+                </script>
             ''',
             menu = [
                 ['w/' + url_pas(name), load_lang('return')],

+ 3 - 3
route/edit_backlink_reset.py

@@ -10,9 +10,9 @@ def edit_backlink_reset_2(conn, name):
         curs.execute(db_change("delete from back where title = ? and type = 'no'"), [name])
         
         render_set(
-            title = name,
-            data = old[0][0],
-            num = 1
+            doc_name = name,
+            doc_data = old[0][0],
+            data_type = 'backlink'
         )
 
     return redirect('/xref/' + url_pas(name))

+ 4 - 4
route/edit_delete.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def edit_delete_2(conn, name, app_var):
+def edit_delete_2(conn, name):
     curs = conn.cursor()
 
     ip = ip_check()
@@ -49,7 +49,7 @@ def edit_delete_2(conn, name, app_var):
         if file_check:
             file_check = file_check.groups()
             file_directory = os.path.join(
-                app_var['path_data_image'], 
+                load_image_url(), 
                 sha224_replace(file_check[0]) + '.' + file_check[1]
             )
             if os.path.exists(file_directory):
@@ -61,10 +61,10 @@ def edit_delete_2(conn, name, app_var):
         return redirect('/w/' + url_pas(name))
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('delete') + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('delete') + ')', 0])],
             data = '''
                 <form method="post">
-                    ''' + ip_warring() + '''
+                    ''' + ip_warning() + '''
                     <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
                     <hr class="main_hr">
                     ''' + captcha_get() + '''

+ 4 - 4
route/edit_many_delete.py → route/edit_delete_many.py

@@ -1,7 +1,7 @@
 from .tool.func import *
 from . import edit_delete
 
-def edit_many_delete_2(conn, app_var):
+def edit_delete_many_2(conn):
     curs = conn.cursor()
 
     ip = ip_check()
@@ -11,12 +11,12 @@ def edit_many_delete_2(conn, app_var):
     if flask.request.method == 'POST':
         all_title = re.findall(r'([^\n]+)\n', flask.request.form.get('content', '').replace('\r\n', '\n') + '\n')
         for name in all_title:
-            edit_delete.edit_delete_2(conn, name, app_var)
+            edit_delete.edit_delete_2(conn, name)
 
         return redirect('/recent_changes')
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('many_delete'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('many_delete'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <form method="post">
                     <textarea rows="25" placeholder="''' + load_lang('many_delete_help') + '''" name="content"></textarea>
@@ -27,4 +27,4 @@ def edit_many_delete_2(conn, app_var):
                 </form>
             ''',
             menu = [['manager/1', load_lang('return')]]
-        ))     
+        ))

+ 2 - 2
route/edit_move.py

@@ -156,10 +156,10 @@ def edit_move_2(conn, name):
             return redirect('/w/' + url_pas(move_title))
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('move') + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('move') + ')', 0])],
             data = '''
                 <form method="post">
-                    ''' + ip_warring() + '''
+                    ''' + ip_warning() + '''
                     <input placeholder="''' + load_lang('document_name') + '" value="' + name + '''" name="title" type="text">
                     <hr class=\"main_hr\">
                     <input placeholder="''' + load_lang('why') + '''" name="send" type="text">

+ 5 - 5
route/edit_revert.py

@@ -52,9 +52,9 @@ def edit_revert_2(conn, name):
             )
 
             render_set(
-                title = name,
-                data = data[0][0],
-                num = 1
+                doc_name = name,
+                doc_data = data[0][0],
+                data_type = 'backlink'
             )
 
             conn.commit()
@@ -66,12 +66,12 @@ def edit_revert_2(conn, name):
             return redirect('/w/' + url_pas(name))
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('revert') + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('revert') + ')', 0])],
             data =  '''
                     <form method="post">
                         <span>r''' + flask.request.args.get('num', '0') + '''</span>
                         <hr class=\"main_hr\">
-                        ''' + ip_warring() + '''
+                        ''' + ip_warning() + '''
                         <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
                         <hr class=\"main_hr\">
                         ''' + captcha_get() + '''

+ 4 - 2
route/give_acl.py

@@ -69,7 +69,9 @@ def give_acl_2(conn, name):
                 [load_lang('view_acl'), 'view']
             ]
         else:
-            acl_get_list = [load_lang('document_acl'), 'decu']
+            acl_get_list = [
+                [load_lang('document_acl'), 'decu']
+            ]
             
         for i in acl_get_list:
             data += '' + \
@@ -113,7 +115,7 @@ def give_acl_2(conn, name):
         '''
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('acl') + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('acl') + ')', 0])],
             data = '''
                 <form method="post">
                     <a href="/setting/8">(''' + load_lang('main_acl_setting') + ''')</a>

+ 28 - 27
route/give_admin.py

@@ -5,32 +5,38 @@ def give_admin_2(conn, name):
 
     owner = admin_check()
 
-    curs.execute(db_change("select acl from user where id = ?"), [name])
-    user = curs.fetchall()
-    if not user:
+    curs.execute(db_change("select data from user_set where id = ? and name = 'acl'"), [name])
+    user_acl = curs.fetchall()
+    if not user_acl:
         return re_error('/error/2')
     else:
-        if owner != 1:
-            curs.execute(db_change('select name from alist where name = ? and acl = "owner"'), [user[0][0]])
-            if curs.fetchall():
-                return re_error('/error/3')
+        user_acl = user_acl[0][0]
+    
+    if owner != 1:
+        curs.execute(db_change('select name from alist where name = ? and acl = "owner"'), [user_acl])
+        if curs.fetchall():
+            return re_error('/error/3')
 
-            if ip_check() == name:
-                return re_error('/error/3')
+        if ip_check() == name:
+            return re_error('/error/3')
 
     if flask.request.method == 'POST':
         if admin_check(7, 'admin (' + name + ')') != 1:
             return re_error('/error/3')
 
-        if owner != 1:
-            curs.execute(db_change('select name from alist where name = ? and acl = "owner"'), [flask.request.form.get('select', None)])
-            if curs.fetchall():
-                return re_error('/error/3')
-
-        if flask.request.form.get('select', None) == 'X':
-            curs.execute(db_change("update user set acl = 'user' where id = ?"), [name])
+        if flask.request.form.get('select', 'X') == 'X':
+            select_data = 'user'
         else:
-            curs.execute(db_change("update user set acl = ? where id = ?"), [flask.request.form.get('select', None), name])
+            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 != 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
+        ])
 
         conn.commit()
 
@@ -43,22 +49,17 @@ def give_admin_2(conn, name):
 
         curs.execute(db_change('select distinct name from alist order by name asc'))
         for data in curs.fetchall():
-            if user[0][0] == data[0]:
-                div += '<option value="' + data[0] + '" selected="selected">' + data[0] + '</option>'
+            if user_acl == data[0]:
+                div = '<option value="' + data[0] + '">' + data[0] + '</option>' + div
             else:
-                if owner != 1:
-                    curs.execute(db_change('select name from alist where name = ? and acl = "owner"'), [data[0]])
-                    if not curs.fetchall():
-                        div += '<option value="' + data[0] + '">' + data[0] + '</option>'
-                else:
-                    div += '<option value="' + data[0] + '">' + data[0] + '</option>'
+                div += '<option value="' + data[0] + '">' + data[0] + '</option>'
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('authorize') + ')', 0])],
+            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\">
+                        <hr class="main_hr">
                         <button type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     ''',

+ 6 - 2
route/give_admin_groups.py

@@ -8,6 +8,9 @@ def give_admin_groups_2(conn, name):
     if flask.request.method == 'POST':
         if admin_check(None, 'admin_plus (' + name + ')') != 1:
             return re_error('/error/3')
+        else:
+            if name in ['owner', 'ban']:
+                return re_error('/error/3')
 
         curs.execute(db_change("delete from alist where name = ?"), [name])
         for i in acl_name_list:
@@ -21,6 +24,7 @@ def give_admin_groups_2(conn, name):
         data = ''
         exist_list = ['', '', '', '', '', '', '', '']
         state = 'disabled' if admin_check() != 1 else ''
+        state = 'disabled' if name in get_default_admin_group() else ''
 
         curs.execute(db_change('select acl from alist where name = ?'), [name])
         acl_list = curs.fetchall()
@@ -40,7 +44,7 @@ def give_admin_groups_2(conn, name):
         data += ''
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('admin_group') + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('admin_group') + ')', 0])],
             data = '''
                 <form method="post">
                     ''' + data + '''
@@ -59,5 +63,5 @@ def give_admin_groups_2(conn, name):
                     <button ''' + state +  ''' type="submit">''' + load_lang('save') + '''</button>
                 </form>
             ''',
-            menu = [['give_log', load_lang('return')]]
+            menu = [['admin_group', load_lang('return')]]
         ))

+ 5 - 5
route/give_delete_admin_group.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def delete_admin_group_2(conn, name):
+def give_delete_admin_group_2(conn, name):
     curs = conn.cursor()
 
     if admin_check() != 1:
@@ -10,18 +10,18 @@ def delete_admin_group_2(conn, name):
         admin_check(None, 'alist del ' + name)
 
         curs.execute(db_change("delete from alist where name = ?"), [name])
-        curs.execute(db_change("update user set acl = 'user' where acl = ?"), [name])
+        curs.execute(db_change("update user_set set data = 'user' where name = 'acl' and data = ?"), [name])
 
         conn.commit()
 
-        return redirect('/give_log')
+        return redirect('/admin_group')
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang("delete_admin_group"), wiki_set(), custom(), other2(['(' + name + ')', 0])],
+            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>
                 </form>
             ''',
-            menu = [['give_log', load_lang('return')]]
+            menu = [['admin_group', load_lang('return')]]
         ))  

+ 1 - 1
route/give_user_ban.py

@@ -105,7 +105,7 @@ def give_user_ban_2(conn, name):
             ''' + plus
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [main_name, wiki_set(), custom(), other2([now, 0])],
+            imp = [main_name, wiki_set(), wiki_custom(), wiki_css([now, 0])],
             data = '''
                 <form method="post" ''' + action + '''>
                     ''' + data + '''

+ 2 - 2
route/give_user_check.py

@@ -147,7 +147,7 @@ def give_user_check_2(conn, name):
         )
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('check'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('check'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = div,
             menu = [['manager', load_lang('return')]]
         ))
@@ -172,7 +172,7 @@ def give_user_check_2(conn, name):
             )
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('simple_check') + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('simple_check') + ')', 0])],
             data = div,
             menu = [['check/' + url_pas(name), load_lang('return')]]
         ))

+ 1 - 1
route/give_user_check_delete.py

@@ -28,7 +28,7 @@ def give_user_check_delete_2(conn):
             return redirect('/check/' + url_pas(user_id if return_type == '0' else user_ip))
         else:
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('check'), wiki_set(), custom(), other2(['(' + load_lang('delete') + ')', 0])],
+                imp = [load_lang('check'), wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('delete') + ')', 0])],
                 data = '''
                     ''' + load_lang('name') + ''' : ''' + user_id + '''
                     <hr class="main_hr">

+ 2 - 2
route/inter_wiki.py

@@ -29,7 +29,7 @@ def inter_wiki_2(conn, tools):
         curs.execute(db_change("select html from html_filter where kind = 'name'"))
     elif tools == 'edit_filter':
         del_link = 'del_edit_filter'
-        plus_link = 'plus_edit_filter'
+        plus_link = 'manager/9'
         title = load_lang('edit_filter_list')
         div = ''
 
@@ -100,7 +100,7 @@ def inter_wiki_2(conn, tools):
             div += '<a href="/' + plus_link + '">(' + load_lang('add') + ')</a>'
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [title, wiki_set(), custom(), other2([0, 0])],
+        imp = [title, wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = div,
         menu = [['manager/1', load_lang('return')]]
     ))

+ 4 - 1
route/inter_wiki_plus.py

@@ -125,6 +125,9 @@ def inter_wiki_plus_2(conn, tools, name):
                 <input value="''' + html.escape(value[2]) + '''" type="text" name="icon">
             '''
         elif tools == 'plus_edit_filter':
+            if not name:
+                name = 'test'
+            
             curs.execute(db_change("select plus, plus_t from html_filter where html = ? and kind = 'regex_filter'"), [name])
             exist = curs.fetchall()
             if exist:
@@ -220,7 +223,7 @@ def inter_wiki_plus_2(conn, tools, name):
             '''
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [title, wiki_set(), custom(), other2([get_sub, 0])],
+            imp = [title, wiki_set(), wiki_custom(), wiki_css([get_sub, 0])],
             data =  '''
                     <form method="post">
                         ''' + form_data + '''

+ 1 - 1
route/list_acl.py

@@ -31,7 +31,7 @@ def list_acl_2(conn):
     div += next_fix('/acl_list?num=', num, list_data)
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('acl_document_list'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('acl_document_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = div,
         menu = [['other', load_lang('return')]]
     ))

+ 8 - 6
route/list_admin.py

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

+ 34 - 0
route/list_admin_group.py

@@ -0,0 +1,34 @@
+from .tool.func import *
+
+def list_admin_group_2(conn):
+    curs = conn.cursor()
+
+    list_data = '<ul class="inside_ul">'
+    org_acl_list = get_default_admin_group()
+
+    curs.execute(db_change("select distinct name from alist order by name asc"))
+    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>'
+        else:
+            delete_admin_group = ''
+
+        list_data += '' + \
+            '<li>' + \
+                '<a href="/admin_plus/' + url_pas(data[0]) + '">' + data[0] + '</a>' + \
+                delete_admin_group + \
+            '</li>' + \
+        ''
+
+    list_data += '' + \
+        '</ul>' + \
+        '<hr class="main_hr">' + \
+        '<a href="/manager/8">(' + load_lang('add') + ')</a>' + \
+    ''
+
+    return easy_minify(flask.render_template(skin_check(),
+        imp = [load_lang('admin_group_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+        data = list_data,
+        menu = [['manager', load_lang('return')]]
+    ))    

+ 2 - 5
route/list_admin_use.py

@@ -4,10 +4,7 @@ def list_admin_use_2(conn):
     curs = conn.cursor()
 
     num = int(number_check(flask.request.args.get('num', '1')))
-    if num * 50 > 0:
-        sql_num = num * 50 - 50
-    else:
-        sql_num = 0
+    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
     if flask.request.method == 'POST':
         return redirect('/admin_log?search=' + flask.request.form.get('search', 'normal'))
@@ -30,7 +27,7 @@ def list_admin_use_2(conn):
         list_data += next_fix('/admin_log?num=', num, get_list)
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('authority_use_list'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('authority_use_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <form method="post">
                     <input name="search" id="admin_log_search"> <button type="submit">''' + load_lang('search') + '''</button>

+ 0 - 27
route/list_give.py

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

+ 1 - 1
route/list_image_file.py

@@ -20,7 +20,7 @@ def list_image_file_2(conn):
     list_data += next_fix('/image_file_list?num=', num, data_list)
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('image_file_list'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('image_file_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = list_data,
         menu = [['other', load_lang('return')]]
     ))    

+ 1 - 1
route/list_long_page.py

@@ -18,7 +18,7 @@ def list_long_page_2(conn, tool):
     div += '</ul>'
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang(title), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang(title), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = div,
         menu = [['other', load_lang('return')]]
     ))

+ 1 - 1
route/list_not_close_topic.py

@@ -13,7 +13,7 @@ def list_not_close_topic_2(conn):
     div += '</ul>'
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('open_discussion_list'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('open_discussion_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = div,
         menu = [['manager', load_lang('return')]]
     ))

+ 1 - 1
route/list_old_page.py

@@ -31,7 +31,7 @@ def list_old_page_2(conn):
     div += '</ul>' + next_fix('/old_page?num=', num, n_list)
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('old_page'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('old_page'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = div,
         menu = [['other', load_lang('return')]]
     ))

+ 1 - 1
route/list_please.py

@@ -20,7 +20,7 @@ def list_please_2(conn):
     div += '</ul>' + next_fix('/please?num=', num, data_list)
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('need_document'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('need_document'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = div,
         menu = [['other', load_lang('return')]]
     ))

+ 1 - 1
route/list_title_index.py

@@ -72,7 +72,7 @@ def list_title_index_2(conn):
     sub = ' (' + str(num) + ')'
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('all_document_list'), wiki_set(), custom(), other2([sub, 0])],
+        imp = [load_lang('all_document_list'), wiki_set(), wiki_custom(), wiki_css([sub, 0])],
         data = data,
         menu = [['other', load_lang('return')]]
     ))

+ 7 - 3
route/list_user.py

@@ -8,15 +8,19 @@ def list_user_2(conn):
 
     list_data = '<ul class="inside_ul">'
 
-    curs.execute(db_change("select id, date from user order by date desc limit ?, 50"), [sql_num])
+    curs.execute(db_change("select id, data from user_set where name = 'date' order by data desc limit ?, 50"), [sql_num])
     user_list = curs.fetchall()
     for data in user_list:
-        list_data += '<li>' + ip_pas(data[0]) + (' (' + data[1] + ')' if data[1] != '' else '') + '</li>'
+        list_data += '' + \
+            '<li>' + \
+                ip_pas(data[0]) + (' (' + data[1] + ')' if data[1] != '' else '') + \
+            '</li>' + \
+        ''
 
     list_data += '</ul>' + next_fix('/user_log?num=', num, user_list)
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('member_list'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('member_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = list_data,
         menu = [['other', load_lang('return')]]
     ))

+ 48 - 23
route/login_check_key.py

@@ -13,7 +13,10 @@ def login_check_key_2(conn, tool):
         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 pw = ? where id = ?"), [pw_encode(flask.session['c_key']), flask.session['c_id']])
+            curs.execute(db_change("update user_set set data = ? where name = 'pw' and id = ?"), [
+                pw_encode(flask.session['c_key']), 
+                flask.session['c_id']
+            ])
             conn.commit()
 
             user_id = flask.session['c_id']
@@ -31,7 +34,7 @@ def login_check_key_2(conn, tool):
                 curs.execute(db_change("update user_set set data = '' where name = '2fa' and id = ?"), [user_id])
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('reset_user_ok'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('reset_user_ok'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = b_text + load_lang('id') + ' : ' + user_id + '<br>' + load_lang('password') + ' : ' + user_pw,
                 menu = [['user', load_lang('return')]]
             ))
@@ -44,41 +47,49 @@ def login_check_key_2(conn, tool):
                 if flask.session['c_key'] == 'email_pass':
                     flask.session['c_email'] = ''
 
-                curs.execute(db_change("select id from user limit 1"))
+                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 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')
             
-                curs.execute(db_change("select id from user_application where id = ?"), [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')
 
-                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':
-                    application_token = load_random_key(32)
+                    user_app_data = {}
+                    user_app_data['id'] = flask.session['c_id']
+                    user_app_data['pw'] = flask.session['c_pw']
+                    user_app_data['date'] = get_time()
+                    user_app_data['encode'] = db_data[0][0]
+                    user_app_data['question'] = flask.session['c_que']
+                    user_app_data['answer'] = flask.session['c_ans']
+                    user_app_data['ip'] = ip
+                    user_app_data['ua'] = user_agent
+                    user_app_data['email'] = flask.session['c_email']
+                    
                     curs.execute(db_change(
-                        "insert into user_application (id, pw, date, encode, question, answer, token, ip, ua, email) " + \
-                        "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+                        "insert into user_set (id, name, data) values (?, ?, ?)"
                     ), [
                         flask.session['c_id'],
-                        flask.session['c_pw'],
-                        get_time(),
-                        db_data[0][0],
-                        flask.session['c_que'],
-                        flask.session['c_ans'],
-                        application_token,
-                        ip,
-                        user_agent,
-                        flask.session['c_email']
+                        'application',
+                        json.dumps(user_app_data)
                     ])
                     conn.commit()
     
@@ -87,11 +98,25 @@ def login_check_key_2(conn, tool):
 
                     return redirect('/application_submitted')
                 else:
-                    curs.execute(db_change("insert into user (id, pw, acl, date, encode) values (?, ?, ?, ?, ?)"), [
+                    if first == 0:
+                        user_auth = 'user'
+                    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'],
-                        flask.session['c_pw'],
-                        'user' if first == 0 else 'owner',
-                        get_time(),
                         db_data[0][0]
                     ])
 
@@ -126,7 +151,7 @@ def login_check_key_2(conn, tool):
         b_text = (sql_d[0][0] + '<hr class="main_hr">') if sql_d and sql_d[0][0] != '' else ''
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('check_key'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('check_key'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <form method="post">
                     ''' + b_text + '''

+ 18 - 13
route/login.py → route/login_login.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def login_2(conn):
+def login_login_2(conn):
     curs = conn.cursor()
 
     ip = ip_check()
@@ -18,27 +18,32 @@ def login_2(conn):
 
         user_agent = flask.request.headers.get('User-Agent', '')
         user_id = flask.request.form.get('id', '')
+        user_data = {}
 
-        curs.execute(db_change("select pw, encode from user where id = ?"), [user_id])
-        user = curs.fetchall()
-        if not user:
+        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:
             return re_error('/error/2')
+        else:
+            for i in sql_data:
+                user_data[i[0]] = i[1]
 
-        pw_check_d = pw_check(
+        if pw_check(
             flask.request.form.get('pw', ''),
-            user[0][0],
-            user[0][1],
+            user_data['pw'],
+            user_data['encode'],
             user_id
-        )
-        if pw_check_d != 1:
+        ) != 1:
             return re_error('/error/10')
 
         curs.execute(db_change('select data from user_set where name = "2fa" and id = ?'), [user_id])
         fa_data = curs.fetchall()
         if fa_data and fa_data[0][0] != '':
-            flask.session['b_id'] = user_id
+            flask.session['login_id'] = user_id
 
-            return redirect('/2fa_login')
+            return redirect('/login/2fa')
         else:
             flask.session['id'] = user_id
 
@@ -48,7 +53,7 @@ def login_2(conn):
             return redirect('/user')
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('login'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('login'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data =  '''
                     <form method="post">
                         <input placeholder="''' + load_lang('id') + '''" name="id" type="text">
@@ -57,7 +62,7 @@ def login_2(conn):
                         <hr class=\"main_hr\">
                         ''' + captcha_get() + '''
                         <button type="submit">''' + load_lang('login') + '''</button>
-                        ''' + http_warring() + '''
+                        ''' + http_warning() + '''
                     </form>
                     ''',
             menu = [['user', load_lang('return')]]

+ 70 - 0
route/login_login_2fa.py

@@ -0,0 +1,70 @@
+from .tool.func import *
+
+def login_login_2fa_2(conn):
+    curs = conn.cursor()
+
+    # email 2fa
+    # pw 2fa
+    # q_a 2fa
+    if not (flask.session and 'login_id' in flask.session):
+        return redirect('/user')
+
+    ip = ip_check()
+    if ip_or_user(ip) == 0:
+        return redirect('/user')
+
+    if ban_check(None, 'login') == 1:
+        return re_error('/ban')
+
+    if flask.request.method == 'POST':
+        if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
+            return re_error('/error/13')
+        else:
+            captcha_post('', 0)
+
+        user_agent = flask.request.headers.get('User-Agent', '')
+        user_id = flask.session['login_id']
+
+        curs.execute(db_change('select data from user_set where name = "2fa_pw" and id = ?'), [user_id])
+        user_1 = curs.fetchall()
+        if user_1:
+            curs.execute(db_change('select data from user_set where name = "2fa_pw_encode" and id = ?'), [user_id])
+            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
+            )
+            if pw_check_d != 1:
+                return re_error('/error/10')
+
+        flask.session['id'] = user_id
+
+        ua_plus(
+            user_id, 
+            ip, 
+            user_agent, 
+            get_time()
+        )
+        conn.commit()
+
+        flask.session.pop('b_id', None)
+
+        return redirect('/user')
+    else:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('login'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data =  '''
+                    <form method="post">
+                        <input placeholder="''' + load_lang('2fa_password') + '''" name="pw" type="password">
+                        <hr class="main_hr">
+                        ''' + captcha_get() + '''
+                        <button type="submit">''' + load_lang('login') + '''</button>
+                        ''' + http_warning() + '''
+                    </form>
+                    ''',
+            menu = [['user', load_lang('return')]]
+        ))

+ 7 - 4
route/login_2fa.py → route/login_login_2fa_email.py

@@ -1,9 +1,12 @@
 from .tool.func import *
 
-def login_2fa_2(conn):
+def login_login_2fa_email_2(conn):
     curs = conn.cursor()
 
-    if not (flask.session and 'b_id' in flask.session):
+    # email 2fa
+    # pw 2fa
+    # q_a 2fa
+    if not (flask.session and 'login_id' in flask.session):
         return redirect('/user')
 
     ip = ip_check()
@@ -48,14 +51,14 @@ def login_2fa_2(conn):
         return redirect('/user')
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('login'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('login'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data =  '''
                     <form method="post">
                         <input placeholder="''' + load_lang('2fa_password') + '''" name="pw" type="password">
                         <hr class=\"main_hr\">
                         ''' + captcha_get() + '''
                         <button type="submit">''' + load_lang('login') + '''</button>
-                        ''' + http_warring() + '''
+                        ''' + http_warning() + '''
                     </form>
                     ''',
             menu = [['user', load_lang('return')]]

+ 2 - 2
route/login_need_email.py

@@ -78,7 +78,7 @@ def login_need_email_2(conn, tool):
             b_text = (sql_d[0][0] + '<hr class="main_hr">') if sql_d and sql_d[0][0] != '' else ''
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('password_search'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('password_search'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = b_text + '''
                     <form method="post">
                         <input placeholder="''' + load_lang('id') + '''" name="id" type="text">
@@ -99,7 +99,7 @@ def login_need_email_2(conn, tool):
             b_text = (sql_d[0][0] + '<hr class="main_hr">') if sql_d and sql_d[0][0] != '' else ''
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('email'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('email'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <a href="/email_filter">(''' + load_lang('email_filter_list') + ''')</a>
                     <hr class="main_hr">

+ 52 - 59
route/login_register.py

@@ -18,11 +18,13 @@ def login_register_2(conn):
             return re_error('/ban')
 
     if flask.request.method == 'POST':
+        # 리캡차
         if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
             return re_error('/error/13')
         else:
             captcha_post('', 0)
 
+        # 아이디 비밀번호 검증 파트
         user_id = flask.request.form.get('id', '')
         user_pw = flask.request.form.get('pw', '')
         user_repeat = flask.request.form.get('pw2', '')
@@ -45,85 +47,76 @@ def login_register_2(conn):
         if len(user_id) > 32:
             return re_error('/error/7')
 
-        curs.execute(db_change("select id from user where id = ?"), [user_id])
+        curs.execute(db_change("select id from user_set where id = ?"), [user_id])
         if curs.fetchall():
             return re_error('/error/6')
-    
-        curs.execute(db_change("select id from user_application where id = ?"), [user_id])
-        if curs.fetchall():
-            return re_error('/error/6')
-
-        hashed = pw_encode(user_pw)
-        ans_q = flask.request.form.get('approval_question_answer', '')
-
-        curs.execute(db_change('select data from other where name = "requires_approval"'))
-        requires_approval = curs.fetchall()
-        requires_approval = requires_approval and requires_approval[0][0] == 'on'
-        requires_approval = None if admin == 1 else requires_approval
-        if requires_approval:
-            curs.execute(db_change('select data from other where name = "approval_question"'))
-            approval_question = curs.fetchall()
-            approval_question = approval_question[0][0] if approval_question and approval_question[0][0] else ''
-        else:
-            approval_question = ''
-
-        # c_id, c_pw, c_ans, c_que, c_key, c_type
-        flask.session['c_id'] = user_id
-        flask.session['c_pw'] = hashed
-        flask.session['c_type'] = 'register'
-        if requires_approval:
-            flask.session['c_ans'] = flask.request.form.get('approval_question_answer', '')
-            flask.session['c_que'] = approval_question
         
-        curs.execute(db_change('select data from other where name = "email_have"'))
-        sql_data = curs.fetchall()
-        if sql_data and sql_data[0][0] != '' and admin != 1:
-            flask.session['c_key'] = load_random_key(32)
-
-            return redirect('/need_email')
-        else:
-            flask.session['c_key'] = 'email_pass'
-
-            return redirect('/check_key')
+        if admin != 1:
+            # 이메일 필요시 /register/email로 발송
+            curs.execute(db_change('select data from other where name = "email_have"'))
+            sql_data = curs.fetchall()
+            if sql_data and sql_data[0][0] != '':
+                # 임시로 세션에 저장
+                flask.session['reg_id'] = user_id
+                flask.session['reg_pw'] = user_pw
+
+                return redirect('/register/email')
+            
+            # 가입 승인 필요시 /register/submit으로 발송
+            curs.execute(db_change('select data from other where name = "requires_approval"'))
+            sql_data = curs.fetchall()
+            if sql_data and sql_data[0][0] != '':
+                flask.session['submit_id'] = user_id
+                flask.session['submit_pw'] = user_pw
+                
+                return redirect('/register/submit')
+        
+        # 전부 아니면 바로 가입 후 /login으로 발송
+        add_user(user_id, user_pw)
+        
+        return redirect('/login')
     else:
         curs.execute(db_change('select data from other where name = "contract"'))
         data = curs.fetchall()
         contract = (data[0][0] + '<hr class="main_hr">') if data and data[0][0] != '' else ''
-
-        approval_question = ''
-        
-        curs.execute(db_change('select data from other where name = "requires_approval"'))
-        requires_approval = curs.fetchall()
-        requires_approval = requires_approval and requires_approval[0][0] == 'on'
-        requires_approval = None if admin == 1 else requires_approval
-        if requires_approval:
-            curs.execute(db_change('select data from other where name = "approval_question"'))
-            data = curs.fetchall()
-            if data and data[0][0] != '':
-                approval_question = '''
-                    <hr class="main_hr">
-                    <span>''' + load_lang('approval_question') + ' : ' + data[0][0] + '''<span>
-                    <hr class="main_hr">
-                    <input placeholder="''' + load_lang('approval_question') + '''" name="approval_question_answer" type="text">
-                    <hr class="main_hr">
-                '''
-
+                
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('register'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('register'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <form method="post">
                     ''' + contract + '''
+                    
                     <input placeholder="''' + load_lang('id') + '''" name="id" type="text">
                     <hr class="main_hr">
+                    
                     <input placeholder="''' + load_lang('password') + '''" name="pw" type="password">
                     <hr class="main_hr">
+                    
                     <input placeholder="''' + load_lang('password_confirm') + '''" name="pw2" type="password">
                     <hr class="main_hr">
-                    ''' + approval_question + '''
+                    
                     ''' + captcha_get() + '''
+                    
+                    <!--
+                    <a href="" id="oauth_google">(Google)</a>     
+                    <hr class="main_hr">
+                    -->
+                    
                     <button type="submit">''' + load_lang('save') + '''</button>
-                    ''' + http_warring() + '''
+                    
+                    ''' + http_warning() + '''
                 </form>
+                <script>
+                    document.getElementById('oauth_google').href = '' +
+                        'https://accounts.google.com/o/oauth2/auth' +
+                        '?client_id=ID' +
+                        '&redirect_uri=' + window.location.origin +
+                        '&response_type=code' +
+                        '&scope=https://www.googleapis.com/auth/userinfo.email' +
+                        '&approval_prompt=force' +
+                        '&access_type=offline' +
+                    '';
+                </script>
             ''',
             menu = [['user', load_lang('return')]]
         ))

+ 66 - 0
route/login_register_email.py

@@ -0,0 +1,66 @@
+from .tool.func import *
+
+def login_register_email_2(conn):
+    curs = conn.cursor()
+    
+    if not 'reg_id' in flask.session:
+        return redirect('/register')
+    
+    if flask.request.method == 'POST':
+        flask.session['reg_key'] = load_random_key(32)
+
+        user_email = flask.request.form.get('email', '')
+        email_data = re.search(r'@([^@]+)$', user_email)
+        if email_data:
+            email_data = email_data.group(1)
+            
+            curs.execute(db_change(
+                "select html from html_filter where html = ? and kind = 'email'"
+            ), [email_data])
+            if not curs.fetchall():                
+                return redirect('/email_filter')
+
+        curs.execute(db_change('select data from other where name = "email_title"'))
+        sql_d = curs.fetchall()
+        if sql_d and sql_d[0][0] != '':
+            t_text = html.escape(sql_d[0][0])
+        else:
+            t_text = wiki_set()[0] + ' key'
+
+        curs.execute(db_change('select data from other where name = "email_text"'))
+        sql_d = curs.fetchall()
+        if sql_d and sql_d[0][0] != '':
+            i_text = html.escape(sql_d[0][0]) + '\n\nKey : ' + flask.session['c_key']
+        else:
+            i_text = 'Key : ' + flask.session['c_key']
+        
+
+        curs.execute(db_change('select id from user_set where name = "email" and data = ?'), [user_email])
+        if curs.fetchall():
+            return re_error('/error/35')
+
+        if send_email(user_email, t_text, i_text) == 0:
+            return re_error('/error/18')
+
+        flask.session['reg_email'] = user_email
+
+        return redirect('/register/email/check')
+    else:
+        curs.execute(db_change('select data from other where name = "email_insert_text"'))
+        sql_d = curs.fetchall()
+        b_text = (sql_d[0][0] + '<hr class="main_hr">') if sql_d and sql_d[0][0] != '' else ''
+
+        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>
+                <hr class="main_hr">
+                ''' + b_text + '''
+                <form method="post">
+                    <input placeholder="''' + load_lang('email') + '''" name="email" type="text">
+                    <hr class="main_hr">
+                    <button type="submit">''' + load_lang('save') + '''</button>
+                </form>
+            ''',
+            menu = [['user', load_lang('return')]]
+        ))

+ 47 - 0
route/login_register_email_check.py

@@ -0,0 +1,47 @@
+from .tool.func import *
+
+def login_register_email_check_2(conn):
+    curs = conn.cursor()
+
+    if not 'reg_email' in flask.session:
+        return redirect('/register')
+    
+    if  flask.request.method == 'POST':
+        input_key = flask.request.form.get('key', '')
+
+        if flask.session['reg_key'] != input_key:
+            return redirect('/register')
+
+        curs.execute(db_change('select data from other where name = "requires_approval"'))
+        sql_data = curs.fetchall()
+        if sql_data and sql_data[0][0] != '':
+            flask.session['submit_id'] = flask.session['reg_id']
+            flask.session['submit_pw'] = flask.session['reg_pw']
+            flask.session['submit_email'] = flask.session['reg_email']
+            
+            return redirect('/register/submit')
+        
+        add_user(
+            flask.session['reg_id'],
+            flask.session['reg_pw'],
+            flask.session['reg_email']
+        )
+
+        return redirect('/login')
+    else:
+        curs.execute(db_change('select data from other where name = "check_key_text"'))
+        sql_d = curs.fetchall()
+        b_text = (sql_d[0][0] + '<hr class="main_hr">') if sql_d and sql_d[0][0] != '' else ''
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('check_key'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = '''
+                <form method="post">
+                    ''' + b_text + '''
+                    <input placeholder="''' + load_lang('key') + '''" name="key" type="text">
+                    <hr class="main_hr">
+                    <button type="submit">''' + load_lang('save') + '''</button>
+                </form>
+            ''',
+            menu = [['user', load_lang('return')]]
+        ))

+ 61 - 0
route/login_register_submit.py

@@ -0,0 +1,61 @@
+from .tool.func import *
+
+from .tool.func import *
+
+def login_register_submit_2(conn):
+    curs = conn.cursor()
+    
+    if not 'submit_id' in flask.session:
+        return redirect('/register')
+    
+    curs.execute(db_change('select data from other where name = "approval_question"'))
+    sql_data = curs.fetchall()
+    if not sql_data:
+        return redirect('/register')
+    
+    data_que = sql_data[0][0]
+    
+    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'])
+        user_app_data['encode'] = data_encode
+        user_app_data['question'] = data_que
+        user_app_data['answer'] = flask.request.form.get('answer', '')
+        
+        if 'submit_email' in flask.session:
+            user_app_data['email'] = flask.session['submit_email']
+        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)
+        ])
+        conn.commit()
+        
+        return redirect('/app_submit')
+    else:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('approval_question'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = '''
+                <form method="post">
+                    ''' + load_lang('approval_question') + ' : ' + data_que + '''
+                    <hr class="main_hr">
+                    <input placeholder="''' + load_lang('approval_question') + '''" name="answer">
+                    <hr class="main_hr">
+                    <button type="submit">''' + load_lang('save') + '''</button>
+                </form>
+            ''',
+            menu = [['user', load_lang('return')]]
+        ))

+ 10 - 0
route/main_easter_egg.py

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

+ 1 - 1
route/main_error_404.py

@@ -6,4 +6,4 @@ def main_error_404_2(conn):
     if os.path.exists('404.html') and flask.request.path != '/':
         return open('404.html', encoding='utf8').read()
     else:
-        return redirect('/w/' + url_pas(wiki_set(2)))
+        return redirect('/w/' + wiki_set(2))

+ 7 - 14
route/main_file.py

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

+ 2 - 2
route/main_image_view.py

@@ -1,7 +1,7 @@
 from .tool.func import *
 from . import main_error_404
 
-def main_image_view_2(conn, name, app_var):
+def main_image_view_2(conn, name):
     curs = conn.cursor()
 
     mime_type = re.search(r'([^.]+)$', name)
@@ -11,7 +11,7 @@ def main_image_view_2(conn, name, app_var):
             mime_type = 'svg+xml'
         
         return flask.send_from_directory(
-            './' + app_var['path_data_image'], name, 
+            './' + load_image_url(), name, 
             mimetype = 'image/' + mime_type
         )
     else:

+ 9 - 8
route/main_manager.py

@@ -9,12 +9,12 @@ def main_manager_2(conn, num, r_ver):
         2 : [load_lang('file_name'), 'plus_file_filter', load_lang('file_filter_add')],
         3 : [0, 'admin', load_lang('authorize')],
         4 : [0, 'record', load_lang('edit_record')],
-        5 : [0, 'topic_record', load_lang('discussion_record')],
+        5 : [0, 'record/topic', load_lang('discussion_record')],
         6 : [load_lang('name'), 'admin_plus', load_lang('add_admin_group')],
         7 : [load_lang('name'), 'plus_edit_filter', load_lang('edit_filter_add')],
         8 : [load_lang('document_name'), 'search', load_lang('search')],
-        9 : [0, 'block_user', load_lang('blocked_user')],
-        10 : [0, 'block_admin', load_lang('blocked_admin')],
+        9 : [0, 'block_log/user', load_lang('blocked_user')],
+        10 : [0, 'block_log/admin', load_lang('blocked_admin')],
         11 : [load_lang('document_name'), 'watch_list', load_lang('add_watchlist')],
         12 : [load_lang('compare_target'), 'check', load_lang('compare_target')],
         13 : [load_lang('document_name'), 'edit', load_lang('load')],
@@ -24,7 +24,7 @@ def main_manager_2(conn, num, r_ver):
 
     if num == 1:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('admin_tool'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('admin_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <h2>''' + load_lang('admin') + '''</h2>
                 <ul class="inside_ul">
@@ -37,9 +37,9 @@ def main_manager_2(conn, num, r_ver):
                 <br>
                 <h2>''' + load_lang('owner') + '''</h2>
                 <ul class="inside_ul">
-                    <li><a href="/give_log">''' + load_lang('admin_group_list') + '''</a></li>
+                    <li><a href="/admin_group">''' + load_lang('admin_group_list') + '''</a></li>
                     <li><a href="/many_delete">''' + load_lang('many_delete') + '''</a></li>
-                    <li><a href="/applications">''' + load_lang('application_list') + '''</a></li>
+                    <li><a href="/app_submit">''' + load_lang('application_list') + '''</a></li>
                     <li><a href="/api/sitemap.xml">''' + load_lang('get_sitemap') + '''</a></li>
                     <li><a href="/register">''' + load_lang('add_user') + '''</a></li>
                     <li><a href="/setting">''' + load_lang('setting') + '''</a></li>
@@ -59,6 +59,7 @@ def main_manager_2(conn, num, r_ver):
                 <h2>''' + load_lang('server') + '''</h2>
                 <ul class="inside_ul">
                     <li><a href="/restart">''' + load_lang('wiki_restart') + '''</a></li>
+                    <li><a href="/shutdown">''' + load_lang('wiki_shutdown') + '''</a></li>
                     <li><a href="/update">''' + load_lang('update') + '''</a></li>
                 </ul>
                 <br>
@@ -79,7 +80,7 @@ def main_manager_2(conn, num, r_ver):
         if flask.request.method == 'POST':
             if flask.request.args.get('plus', None):
                 return redirect(
-                    '/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.args.get('plus', 'test')) + '?plus=' + flask.request.form.get('name', 'test')
+                    '/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.args.get('plus', 'test')) + '?plus=' + url_pas(flask.request.form.get('name', 'test'))
                 )
             elif flask.request.form.get('regex', None):
                 return redirect('/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.form.get('name', 'test')) + '?type=regex')
@@ -96,7 +97,7 @@ def main_manager_2(conn, num, r_ver):
                 plus = '<input type="checkbox" name="regex"> ' + load_lang('regex') + '<hr class="main_hr">'
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [title_list[(num - 2)][2], wiki_set(), custom(), other2([0, 0])],
+                imp = [title_list[(num - 2)][2], wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <form method="post">
                         <input placeholder="''' + placeholder + '''" name="name" type="text">

+ 2 - 2
route/main_other.py

@@ -4,7 +4,7 @@ def main_other_2(conn):
     curs = conn.cursor()
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('other_tool'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('other_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = '''
             <h2>''' + load_lang('record') + '''</h2>
             <ul class="inside_ul">
@@ -28,7 +28,7 @@ def main_other_2(conn):
                 <li><a href="/image_file_list">''' + load_lang('image_file_list') + '''</a></li>
                 <li><a href="/vote">''' + load_lang('vote_list') + '''</a></li>
                 <li><a href="/long_page">''' + load_lang('long_page') + '''</a></li>
-                <!-- <li><a href="/short_page">''' + load_lang('short_page') + '''</a></li> -->
+                <li><a href="/short_page">''' + load_lang('short_page') + '''</a></li>
             </ul>
             <br>
             <h2>''' + load_lang('other') + '''</h2>

+ 8 - 6
route/server_restart.py → route/main_restart.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def server_restart_2(conn):
+def main_restart_2(conn):
     curs = conn.cursor()
 
     if admin_check() != 1:
@@ -15,13 +15,15 @@ def server_restart_2(conn):
         try:
             os.execl(sys.executable, sys.executable, *sys.argv)
         except:
-            try:
-                os.execl(sys.executable, '"' + sys.executable + '"', *sys.argv)
-            except:
-                return re_error('/error/33')
+            pass
+        
+        try:
+            os.execl(sys.executable, '"' + sys.executable + '"', *sys.argv)
+        except:
+            return re_error('/error/33')
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('wiki_restart'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('wiki_restart'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <form method="post">
                     <button type="submit">''' + load_lang('restart') + '''</button>

+ 161 - 132
route/setting.py → route/main_setting.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def setting_2(conn, num, db_set):
+def main_setting_2(conn, num, db_set):
     curs = conn.cursor()
 
     if not (num == 0 or num == 8) and admin_check() != 1:
@@ -8,26 +8,19 @@ def setting_2(conn, num, db_set):
 
     if num == 0:
         li_list = [
-            load_lang('main_setting'),
-            load_lang('text_setting'),
-            load_lang('main_head'),
-            load_lang('main_body'),
-            'robots.txt',
-            'Google',
-            load_lang('main_bottom_body'),
-            load_lang('main_acl_setting'),
-            load_lang('wiki_logo')
+            [1, load_lang('main_setting')],
+            [2, load_lang('text_setting')],
+            [5, 'robots.txt'],
+            [6, load_lang('ext_api_req_set')],
+            [3, load_lang('main_head')],
+            [4, load_lang('main_body')],
+            [7, load_lang('main_bottom_body')]
         ]
 
-        x = 0
-        li_data = ''
-
-        for li in li_list:
-            x += 1
-            li_data += '<li><a href="/setting/' + str(x) + '">' + li + '</a></li>'
-
+        li_data = ''.join(['<li><a href="/setting/' + str(li[0]) + '">' + li[1] + '</a></li>' for li in li_list])
+        
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('setting'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '<h2>' + load_lang('list') + '</h2><ul class="inside_ul">' + li_data + '</ul>',
             menu = [['manager', load_lang('return')]]
         ))
@@ -35,7 +28,6 @@ def setting_2(conn, num, db_set):
         i_list = {
             0 : 'name',
             2 : 'frontpage',
-            3 : 'license',
             4 : 'upload',
             5 : 'skin',
             7 : 'reg',
@@ -44,7 +36,6 @@ def setting_2(conn, num, db_set):
             10 : 'port',
             11 : 'key',
             12 : 'update',
-            13 : 'email_have',
             15 : 'encode',
             16 : 'host',
             19 : 'slow_edit',
@@ -56,7 +47,6 @@ def setting_2(conn, num, db_set):
         n_list = {
             0 : 'Wiki',
             2 : 'FrontPage',
-            3 : 'ARR',
             4 : '2',
             5 : '',
             7 : '',
@@ -65,7 +55,6 @@ def setting_2(conn, num, db_set):
             10 : '3000',
             11 : 'test',
             12 : 'stable',
-            13 : '',
             15 : 'sha3',
             16 : '0.0.0.0',
             19 : '0',
@@ -116,8 +105,6 @@ def setting_2(conn, num, db_set):
                     acl_num = 7
                 elif i == 1:
                     acl_num = 8
-                elif i == 2:
-                    acl_num = 13
                 elif i == 3:
                     acl_num = 20
                 else:
@@ -137,88 +124,110 @@ def setting_2(conn, num, db_set):
             sqlite_only = 'style="display:none;"' if db_set != 'sqlite' else ''
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('main_setting'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('main_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    <form method="post">
+                    <form method="post" id="main_set_data">
+                        <h2>1. ''' + load_lang('basic_set') + '''</h2>
                         <span>''' + load_lang('wiki_name') + '''</span>
                         <hr class="main_hr">
                         <input name="name" value="''' + html.escape(d_list[0]) + '''">
                         <hr class="main_hr">
-                        <span><a href="/setting/10">(''' + load_lang('wiki_logo') + ''')</a></span>
+                        
+                        <span><a href="/setting/9">(''' + load_lang('wiki_logo') + ''')</a></span>
                         <hr class="main_hr">
+                        
                         <span>''' + load_lang('main_page') + '''</span>
                         <hr class="main_hr">
                         <input name="frontpage" value="''' + html.escape(d_list[2]) + '''">
                         <hr class="main_hr">
-                        <span>''' + load_lang('bottom_text') + ''' (HTML)</span>
-                        <hr class="main_hr">
-                        <input name="license" value="''' + html.escape(d_list[3]) + '''">
-                        <hr class="main_hr">
-                        <span>''' + load_lang('max_file_size') + ''' (MB)</span>
+                        
+                        <span>''' + load_lang('domain') + '''</span> (EX : http://2du.pythonanywhere.com/)
                         <hr class="main_hr">
-                        <input name="upload" value="''' + html.escape(d_list[4]) + '''">
+                        <input name="''' + i_list[22] + '''" value="''' + html.escape(d_list[22]) + '''">
                         <hr class="main_hr">
-                        <span ''' + sqlite_only + '''>
-                            <span>''' + load_lang('backup_interval') + ' (' + load_lang('hour') + ') (' + load_lang('off') + ' : 0) (' + load_lang('restart_required') + ''')</span>
-                            <hr class="main_hr">
-                            <input name="back_up" value="''' + html.escape(d_list[9]) + '''">
-                            <hr class="main_hr">
-                            <span>''' + load_lang('backup_where') + ' (' + load_lang('empty') + ' : ' + load_lang('default') + ') (' + load_lang('restart_required') + ''') (EX : ./data/backup.db)</span>
-                            <hr class="main_hr">
-                            <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
-                            <hr class="main_hr">
-                        </span>
-                        <span>''' + load_lang('wiki_skin') + '''</span>
+                        
+                        <span>''' + load_lang('wiki_host') + '''</span>
                         <hr class="main_hr">
-                        <select name="skin">''' + load_skin(d_list[5] if d_list[5] != '' else 'marisa') + '''</select>
+                        <input name="host" value="''' + html.escape(d_list[16]) + '''">
                         <hr class="main_hr">
-                        <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
+                        
+                        <span>''' + load_lang('wiki_port') + '''</span>
                         <hr class="main_hr">
-                        <input type="checkbox" name="ip_view" ''' + check_box_div[1] + '''> ''' + load_lang('hide_ip') + '''
+                        <input name="port" value="''' + html.escape(d_list[10]) + '''">
                         <hr class="main_hr">
-                        <input type="checkbox" name="email_have" ''' + check_box_div[2] + '''> ''' + load_lang('email_required') + ' <a href="/setting/6">(' + load_lang('smtp_setting_required') + ''')</a>
+                        
+                        <span>''' + load_lang('wiki_secret_key') + '''</span>
                         <hr class="main_hr">
-                        <input type="checkbox" name="requires_approval" ''' + check_box_div[3] + '''> ''' + load_lang('requires_approval') + '''
+                        <input type="password" name="key" value="''' + html.escape(d_list[11]) + '''">
                         <hr class="main_hr">
-                        <input type="checkbox" name="ua_get" ''' + check_box_div[4] + '''> ''' + load_lang('ua_get_off') + '''
+                        
+                        <span>''' + load_lang('encryption_method') + '''</span>
                         <hr class="main_hr">
-                        <span>''' + load_lang('wiki_host') + '''</span>
+                        <select name="encode">''' + acl_div[0] + '''</select>
+                        
+                        <h2>2. ''' + load_lang('design_set') + '''</h2>
+                        <span>''' + load_lang('wiki_skin') + '''</span>
                         <hr class="main_hr">
-                        <input name="host" value="''' + html.escape(d_list[16]) + '''">
+                        <select name="skin">''' + load_skin(d_list[5] if d_list[5] != '' else 'tenshi') + '''</select>
+                        
+                        <h2>3. ''' + load_lang('login_set') + '''</h2>
+                        <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
                         <hr class="main_hr">
-                        <span>''' + load_lang('wiki_port') + '''</span>
+                        
+                        <input type="checkbox" name="ip_view" ''' + check_box_div[1] + '''> ''' + load_lang('hide_ip') + '''
                         <hr class="main_hr">
-                        <input name="port" value="''' + html.escape(d_list[10]) + '''">
+                        
+                        <input type="checkbox" name="requires_approval" ''' + check_box_div[3] + '''> ''' + load_lang('requires_approval') + '''
                         <hr class="main_hr">
-                        <span>''' + load_lang('wiki_secret_key') + '''</span>
+                        
+                        <input type="checkbox" name="ua_get" ''' + check_box_div[4] + '''> ''' + load_lang('ua_get_off') + '''
+                        
+                        <h2>4. ''' + load_lang('server_set') + '''</h2>
+                        <span>''' + load_lang('max_file_size') + ''' (MB)</span>
                         <hr class="main_hr">
-                        <input type="password" name="key" value="''' + html.escape(d_list[11]) + '''">
+                        <input name="upload" value="''' + html.escape(d_list[4]) + '''">
                         <hr class="main_hr">
+                        
+                        <span ''' + sqlite_only + '''>
+                            <span>
+                                ''' + load_lang('backup_interval') + ' (' + load_lang('hour') + ') (' + load_lang('off') + ' : 0) ' + \
+                                '(' + load_lang('restart_required') + ''')</span>
+                            <hr class="main_hr">
+                            <input name="back_up" value="''' + html.escape(d_list[9]) + '''">
+                            <hr class="main_hr">
+                            
+                            <span>
+                                ''' + load_lang('backup_where') + ' (' + load_lang('empty') + ' : ' + load_lang('default') + ') ' + \
+                                '(' + load_lang('restart_required') + ''') (EX : ./data/backup.db)
+                            </span>
+                            <hr class="main_hr">
+                            <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
+                            <hr class="main_hr">
+                        </span>
+                        
                         <span>''' + load_lang('update_branch') + '''</span>
                         <hr class="main_hr">
                         <select name="update">''' + branch_div + '''</select>
+                        
+                        <h2>5. ''' + load_lang('edit_set') + '''</h2>
+                        <span><a href="/setting/8">(''' + load_lang('main_acl_setting') + ''')</a></span>
                         <hr class="main_hr">
-                        <span>''' + load_lang('encryption_method') + '''</span>
-                        <hr class="main_hr">
-                        <select name="encode">''' + acl_div[0] + '''</select>
-                        <hr class="main_hr">
+                        
                         <span>''' + load_lang('slow_edit') + ' (' + load_lang('second') + ') (' + load_lang('off') + ''' : 0)</span>
                         <hr class="main_hr">
                         <input name="''' + i_list[19] + '''" value="''' + html.escape(d_list[19]) + '''">
-                        <hr class="main_hr">
-                        <span>''' + load_lang('domain') + '''</span> (EX : http://2du.pythonanywhere.com/)
-                        <hr class="main_hr">
-                        <input name="''' + i_list[22] + '''" value="''' + html.escape(d_list[22]) + '''">
+                        
                         <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
                     </form>
+                    <script>simple_render('main_set_data');</script>
                 ''',
                 menu = [['setting', load_lang('return')]]
             ))
     elif num == 2:
         i_list = [
             'contract',
-            'no_login_warring',
+            'no_login_warning',
             'edit_bottom_text',
             'copyright_checkbox_text',
             'check_key_text',
@@ -232,7 +241,8 @@ def setting_2(conn, num, db_set):
             'approval_question',
             'edit_help',
             'upload_help',
-            'upload_default'
+            'upload_default',
+            'license'
         ]
         if flask.request.method == 'POST':
             for i in i_list:
@@ -262,79 +272,69 @@ def setting_2(conn, num, db_set):
             conn.commit()
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('text_setting'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('text_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    <form method="post">
-                        <span>''' + load_lang('register_text') + ''' (HTML)</span>
-                        <hr class="main_hr">
+                    <form method="post" id="main_set_data">
+                        <h2>1. ''' + load_lang('register_text') + ''' (HTML)</h2>
                         <textarea rows="3" name="''' + i_list[0] + '''">''' + html.escape(d_list[0]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('non_login_alert') + ''' (HTML)</span>
-                        <hr class="main_hr">
+                        
+                        <h2>2. ''' + load_lang('non_login_alert') + ''' (HTML)</h2>
                         <textarea rows="3" name="''' + i_list[1] + '''">''' + html.escape(d_list[1]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('edit_bottom_text') + ''' (HTML)</span>
-                        <hr class="main_hr">
+                        
+                        <h2>3. ''' + load_lang('edit_bottom_text') + ''' (HTML)</h2>
                         <textarea rows="3" name="''' + i_list[2] + '''">''' + html.escape(d_list[2]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('copyright_checkbox_text') + ''' (HTML)</span>
-                        <hr class="main_hr">
+                        
+                        <h2>4. ''' + load_lang('copyright_checkbox_text') + ''' (HTML)</h2>
                         <textarea rows="3" name="''' + i_list[3] + '''">''' + html.escape(d_list[3]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('check_key_text') + ''' (HTML)</span>
-                        <hr class="main_hr">
+                        
+                        <h2>5. ''' + load_lang('check_key_text') + ''' (HTML)</h2>
                         <textarea rows="3" name="''' + i_list[4] + '''">''' + html.escape(d_list[4]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('email_title') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>6. ''' + load_lang('email_title') + '''</h2>
                         <textarea rows="3" name="''' + i_list[5] + '''">''' + html.escape(d_list[5]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('email_text') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>7. ''' + load_lang('email_text') + '''</h2>
                         <textarea rows="3" name="''' + i_list[6] + '''">''' + html.escape(d_list[6]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('email_insert_text') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>8. ''' + load_lang('email_insert_text') + '''</h2>
                         <textarea rows="3" name="''' + i_list[7] + '''">''' + html.escape(d_list[7]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('password_search_text') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>9. ''' + load_lang('password_search_text') + '''</h2>
                         <textarea rows="3" name="''' + i_list[8] + '''">''' + html.escape(d_list[8]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('reset_user_text') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>10. ''' + load_lang('reset_user_text') + '''</h2>
                         <textarea rows="3" name="''' + i_list[9] + '''">''' + html.escape(d_list[9]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('error_401') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>11. ''' + load_lang('error_401') + '''</h2>
                         <textarea rows="3" name="''' + i_list[10] + '''">''' + html.escape(d_list[10]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('error_404') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>12. ''' + load_lang('error_404') + '''</h2>
                         <textarea rows="3" name="''' + i_list[11] + '''">''' + html.escape(d_list[11]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('approval_question') + '''</span><sup><a href="#note_1_end" id="note_1">(1)</a></sup>
+                        
+                        <h2>13. ''' + load_lang('approval_question') + '''</h2>
+                        <sup>(1)</sup>
                         <hr class="main_hr">
                         <textarea rows="3" name="''' + i_list[12] + '''">''' + html.escape(d_list[12]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('edit_help') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>14. ''' + load_lang('edit_help') + '''</h2>
                         <textarea rows="3" name="''' + i_list[13] + '''">''' + html.escape(d_list[13]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('upload_help') + ''' (HTML)</span>
-                        <hr class="main_hr">
+                        
+                        <h2>15. ''' + load_lang('upload_help') + ''' (HTML)</h2>
                         <textarea rows="3" name="''' + i_list[14] + '''">''' + html.escape(d_list[14]) + '''</textarea>
-                        <hr class="main_hr">
-                        <span>''' + load_lang('upload_default') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>16. ''' + load_lang('upload_default') + '''</h2>
                         <textarea rows="3" name="''' + i_list[15] + '''">''' + html.escape(d_list[15]) + '''</textarea>
+                        
+                        <h2>17. ''' + load_lang('bottom_text') + ''' (HTML)</h2>
+                        <textarea rows="3" name="''' + i_list[16] + '''">''' + html.escape(d_list[16]) + '''</textarea>
+                        
                         <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                        <hr class="main_hr">
-                        <ul id="footnote_data">
-                            <li><a href="#note_1" id="note_1_end">(1)</a> <span>''' + load_lang('approval_question_visible_only_when_approval_on') + '''</span></li>
-                        </ul>
                     </form>
+                    <ul id="footnote_data">
+                        <li><a href="#note_1" id="note_1_end">(1)</a> ''' + load_lang('approval_question_visible_only_when_approval_on') + '''</li>
+                    </ul>
+                    <script>simple_render('main_set_data');</script>
                 ''',
                 menu = [['setting', load_lang('return')]]
             ))
@@ -414,7 +414,7 @@ def setting_2(conn, num, db_set):
                 sub_plus = ''
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang(data = 'main' + title, safe = 1), wiki_set(), custom(), other2(['(HTML)' + sub_plus, 0])],
+                imp = [load_lang(data = 'main' + title, safe = 1), wiki_set(), wiki_custom(), wiki_css(['(HTML)' + sub_plus, 0])],
                 data = '''
                     <form method="post">
                         ''' + start + '''
@@ -473,7 +473,7 @@ def setting_2(conn, num, db_set):
                 data = ''.join(lines)
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = ['robots.txt', wiki_set(), custom(), other2([0, 0])],
+                imp = ['robots.txt', wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <a href="/robots.txt">(''' + load_lang('view') + ''')</a>
                     <hr class="main_hr">
@@ -494,7 +494,9 @@ def setting_2(conn, num, db_set):
             'smtp_security',
             'smtp_email',
             'smtp_pass',
-            'recaptcha_ver'
+            'recaptcha_ver',
+            'oauth_client_id',
+            'email_have'
         ]
 
         if flask.request.method == 'POST':
@@ -538,45 +540,72 @@ def setting_2(conn, num, db_set):
                 re_ver += '<option value="v3">v3</option><option value="">v2</option>'
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = ['Google', wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('ext_api_req_set'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
-                    <form method="post">
-                        <h2><a href="https://www.google.com/recaptcha/admin">''' + load_lang('recaptcha') + '''</a></h2>
+                    <form method="post" id="main_set_data">
+                        <h2>1. ''' + load_lang('recaptcha') + '''</h2>
+                        <a href="https://www.google.com/recaptcha/admin">(Google)</a>
+                        <hr class="main_hr">
+                        
                         <span>''' + load_lang('public_key') + '''</span>
                         <hr class="main_hr">
                         <input name="recaptcha" value="''' + html.escape(d_list[0]) + '''">
                         <hr class="main_hr">
+                        
                         <span>''' + load_lang('secret_key') + '''</span>
                         <hr class="main_hr">
                         <input name="sec_re" value="''' + html.escape(d_list[1]) + '''">
                         <hr class="main_hr">
+                        
                         <select name="recaptcha_ver">
                             ''' + re_ver + '''
                         </select>
-                        <hr class="main_hr">
-                        <h2>''' + load_lang('smtp_setting') + ' (' + load_lang('restart_required') + ''')</h1>
+                        
+                        <h2>2. ''' + load_lang('email_setting') + '''</h1>
+                        <input type="checkbox" name="email_have" ''' + ('checked' if d_list[9] != '' else '')  + '''> ''' + \
+                             load_lang('email_required') + '''
+                        
+                        <h2>2.1. ''' + load_lang('smtp_setting') + '''</h1>
+                        <a href="https://support.google.com/mail/answer/7126229">(Google)</a>
+                        <hr class="main_hr">
+                        
                         <span>''' + load_lang('smtp_server') + '''</span>
                         <hr class="main_hr">
                         <input name="smtp_server" value="''' + html.escape(d_list[2]) + '''">
                         <hr class="main_hr">
+                        
                         <span>''' + load_lang('smtp_port') + '''</span>
                         <hr class="main_hr">
                         <input name="smtp_port" value="''' + html.escape(d_list[3]) + '''">
                         <hr class="main_hr">
+                        
                         <span>''' + load_lang('smtp_security') + '''</span>
-                        <hr class="main_hr">'''
-                        + security_radios +
-                        '''<hr class="main_hr">
+                        <hr class="main_hr">
+                        ''' + security_radios + '''
+                        <hr class="main_hr">
+                        
                         <span>''' + load_lang('smtp_username') + '''</span>
                         <hr class="main_hr">
                         <input name="smtp_email" value="''' + html.escape(d_list[5]) + '''">
                         <hr class="main_hr">
+                        
                         <span>''' + load_lang('smtp_password') + '''</span>
                         <hr class="main_hr">
                         <input type="password" name="smtp_pass" value="''' + html.escape(d_list[6]) + '''">
+                        
+                        <h2>3. ''' + load_lang('oauth') + '''</h2>
+                        <a href="https://developers.google.com/identity/protocols/oauth2">(Google)</a>
+                        <hr class="main_hr">
+                        
+                        <span>''' + load_lang('oauth_client_id') + '''</span>
+                        <hr class="main_hr">
+                        <input name="oauth_client_id" value="''' + html.escape(d_list[8]) + '''">
+                        <hr class="main_hr">
+                        
                         <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
                     </form>
+                    <script>simple_render('main_set_data');</script>
                 ''',
                 menu = [['setting', load_lang('return')]]
             ))
@@ -638,7 +667,7 @@ def setting_2(conn, num, db_set):
                     acl_div[i] += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('main_acl_setting'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('main_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <form method="post">
                         <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
@@ -690,7 +719,7 @@ def setting_2(conn, num, db_set):
 
             admin_check(None, 'edit_set (' + str(num) + ')')
 
-            return redirect('/setting/10')
+            return redirect('/setting/9')
         else:
             d_list = []
             for i in i_list:
@@ -713,7 +742,7 @@ def setting_2(conn, num, db_set):
                 ''
             
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('wiki_logo'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('wiki_logo'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <form method="post">
                         ''' + end_data + '''

+ 25 - 0
route/main_shutdown.py

@@ -0,0 +1,25 @@
+from .tool.func import *
+
+def main_shutdown_2(conn):
+    curs = conn.cursor()
+    
+    if admin_check() != 1:
+        return re_error('/error/3')
+
+    if flask.request.method == 'POST':
+        admin_check(None, 'shutdown')
+
+        print('----')
+        print('shutdown')
+
+        os._exit(os.EX_OK)
+    else:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('wiki_shutdown'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = '''
+                <form method="post">
+                    <button type="submit">''' + load_lang('shutdown') + '''</button>
+                </form>
+            ''',
+            menu = [['manager', load_lang('return')]]
+        ))

+ 12 - 0
route/main_test_func.py

@@ -0,0 +1,12 @@
+import time
+from .tool.func import *
+
+def main_test_func_2(conn):
+    test_start = time.time()
+
+    for _ in range(0, 10000):
+        load_lang('edit')
+        
+    end_time = "time :" + str(time.time() - test_start) + '\n'
+
+    return end_time

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

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def func_title_random_2(conn):
+def main_title_random_2(conn):
     curs = conn.cursor()
 
     curs.execute(db_change("" + \

+ 6 - 6
route/server_now_update.py → route/main_update.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def server_now_update_2(conn, r_ver):
+def main_update_2(conn, r_ver):
     curs = conn.cursor()
 
     if admin_check() != 1:
@@ -20,7 +20,7 @@ def server_now_update_2(conn, r_ver):
             ok = []
 
             ok += [os.system('git remote rm origin')]
-            ok += [os.system('git remote add origin https://github.com/2DU/opennamu.git')]
+            ok += [os.system('git remote add origin https://github.com/opennamu/opennamu.git')]
             ok += [os.system('git fetch origin ' + up_data)]
             ok += [os.system('git reset --hard origin/' + up_data)]
             if (ok[0] and ok[1] and ok[2] and ok[3]) == 0:
@@ -29,7 +29,7 @@ def server_now_update_2(conn, r_ver):
                 print('Error : update failed')
         elif platform.system() == 'Windows':
             os.system('rd /s /q route')
-            urllib.request.urlretrieve('https://github.com/2DU/opennamu/archive/' + up_data + '.zip', 'update.zip')
+            urllib.request.urlretrieve('https://github.com/opennamu/opennamu/archive/' + up_data + '.zip', 'update.zip')
             zipfile.ZipFile('update.zip').extractall('')
             ok = os.system('xcopy /y /s /r opennamu-' + up_data + ' .')
             if ok == 0:
@@ -43,14 +43,14 @@ def server_now_update_2(conn, r_ver):
         return re_error('/error/34')
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('update'), wiki_set(), custom(), other2([0, 0])],
-            data = load_lang('update_warring') + '''
+            imp = [load_lang('update'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = load_lang('update_warning') + '''
                 <hr class=\"main_hr\">
                 <ul class="inside_ul">
                     <li>''' + load_lang('version') + ' : ' + r_ver + '''</li>
                     <li id="ver_send" style="display: none;">''' + load_lang('lastest') + ''' : </li>
                 </ul>
-                <a href="https://github.com/2du/openNAMU">(Beta)</a> <a href="https://github.com/2du/openNAMU/tree/stable">(Stable)</a>
+                <a href="https://github.com/openNAMU/openNAMU">(Beta)</a> <a href="https://github.com/openNAMU/openNAMU/tree/stable">(Stable)</a>
                 <hr class=\"main_hr\">
                 <form method="post">
                     <button type="submit">''' + load_lang('update') + '''</button>

+ 13 - 12
route/func_upload.py → route/main_upload.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def func_upload_2(conn, app_var):
+def main_upload_2(conn):
     curs = conn.cursor()
 
     if acl_check(None, 'upload') == 1:
@@ -59,15 +59,16 @@ def func_upload_2(conn, app_var):
                 if t_re.search(name):
                     return redirect('/file_filter')
 
-            if os.path.exists(os.path.join(app_var['path_data_image'], e_data)):
-                os.remove(os.path.join(app_var['path_data_image'], e_data))
-                data.save(os.path.join(app_var['path_data_image'], e_data))
+            data_url_image = load_image_url()
+            if os.path.exists(os.path.join(data_url_image, e_data)):
+                os.remove(os.path.join(data_url_image, e_data))
+                data.save(os.path.join(data_url_image, e_data))
             else:
-                data.save(os.path.join(app_var['path_data_image'], e_data))
+                data.save(os.path.join(data_url_image, e_data))
 
             ip = ip_check()
             g_lice = flask.request.form.get('f_lice', '')
-            file_size = os.stat(os.path.join(app_var['path_data_image'], e_data)).st_size
+            file_size = os.stat(os.path.join(data_url_image, e_data)).st_size
 
             curs.execute(db_change("select data from other where name = 'markup'"))
             db_data = curs.fetchall()
@@ -95,9 +96,9 @@ def func_upload_2(conn, app_var):
             curs.execute(db_change("insert into acl (title, data, type) values (?, 'admin', 'decu')"), ['file:' + name])
 
             render_set(
-                title = 'file:' + name,
-                data = file_d,
-                num = 1
+                doc_name = 'file:' + name,
+                doc_data = file_d,
+                data_type = 'backlink'
             )
 
             history_plus(
@@ -105,7 +106,7 @@ def func_upload_2(conn, app_var):
                 file_d,
                 get_time(),
                 ip,
-                ip,
+                '',
                 '0',
                 t_check = 'upload',
                 mode = 'upload'
@@ -134,9 +135,9 @@ def func_upload_2(conn, app_var):
         upload_default = html.escape(db_data[0][0]) if db_data and db_data[0][0] != '' else ''
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('upload'), wiki_set(), custom(), other2([0, 0])],
+            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="/file_filter">(''' + load_lang('file_filter_list') + ''')</a> <a href="/extension_filter">(''' + load_lang('extension_filter_list') + ''')</a>
                 ''' + upload_help + '''
                 <hr class="main_hr">
                 ''' + load_lang('max_file_size') + ''' : ''' + wiki_set(3) + '''MB

+ 145 - 0
route/recent_app_submit.py

@@ -0,0 +1,145 @@
+from .tool.func import *
+
+def recent_app_submit_2(conn):
+    curs = conn.cursor()
+
+    div = ''
+
+    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':
+        div += load_lang('approval_requirement_disabled')
+
+    if flask.request.method == 'GET':
+        curs.execute(db_change(
+            'select data from user_set where name = "application"'
+        ))
+        db_data = curs.fetchall()
+        if db_data:
+            div += '' + \
+                load_lang('all_register_num') + ' : ' + str(len(db_data)) + \
+                '<hr class="main_hr">' + \
+            ''
+            
+            div += '''
+                <table id="main_table_set">
+                    <tr id="main_table_top_tr">
+                        <td id="main_table_width_half">''' + load_lang('id') + '''</td>
+                        <td id="main_table_width_half">''' + load_lang('email') + '''</td>
+                    </tr>
+                    <tr id="main_table_top_tr">
+                        <td>''' + load_lang('approval_question') + '''</td>
+                        <td>''' + load_lang('answer') + '''</td>
+                    </tr>                        
+            '''
+
+            for application in db_data:
+                application = json.loads(application[0])
+                
+                if 'question' in application:
+                    question = html.escape(application['question'])
+                    question = question if question != '' else '<br>'
+                else:
+                    question = '<br>'
+                    
+                if 'answer' in application:
+                    answer = html.escape(application['answer'])
+                    answer = answer if answer != '' else '<br>'
+                else:
+                    answer = '<br>'
+                    
+                    
+                if 'email' in application:
+                    email = html.escape(application['email'])
+                    email = email if email != '' else '<br>'
+                else:
+                    email = '<br>'
+                
+                div += '''
+                    <form method="post">
+                        <tr>
+                            <td>''' + application['id'] + '''</td>
+                            <td>''' + email + '''</td>
+                        </tr>
+                        <tr>
+                            <td>''' + question + '''</td>
+                            <td>''' + answer + '''</td>
+                        </tr>
+                        <tr>
+                            <td colspan="3">
+                                <button type="submit" 
+                                        id="save"
+                                        name="approve" 
+                                        value="''' + application['id'] + '''">
+                                    ''' + load_lang('approve') + '''
+                                </button>
+                                <button type="submit" 
+                                        name="decline" 
+                                        value="''' + application['id'] + '''">
+                                    ''' + load_lang('decline') + '''
+                                </button>
+                            </td>
+                        </tr>
+                    </form>
+                '''
+                
+            div += '</table>'
+        else:
+            div += load_lang('no_applications_now')
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('application_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = div,
+            menu = [['other', load_lang('return')]]
+        ))
+    else:
+        if admin_check(None, 'app submit') != 1:
+            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', '')
+            ])
+            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']
+            ])
+            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', '')
+            ])
+            conn.commit()
+
+        return redirect('/app_submit')

+ 30 - 26
route/recent_block.py

@@ -9,7 +9,7 @@ def recent_block_2(conn, name, tool):
     div = '''
         <table id="main_table_set">
             <tbody>
-                <tr>
+                <tr id="main_table_top_tr">
                     <td id="main_table_width">''' + load_lang('blocked') + '''</td>
                     <td id="main_table_width">''' + load_lang('admin') + '''</td>
                     <td id="main_table_width">''' + load_lang('period') + '''</td>
@@ -21,10 +21,10 @@ def recent_block_2(conn, name, tool):
 
     get_type = flask.request.args.get('type', '')
     sub_type = flask.request.args.get('s_type', '')
-    if not name:
+    if tool == 'all':
         if get_type == 'ongoing':
             sub = ' (' + load_lang('in_progress') + ')'
-           
+
             if sub_type == '':
                 div = '' + \
                     '<a href="?type=ongoing&s_type=regex">(' + load_lang('regex') + ')</a> ' + \
@@ -66,29 +66,28 @@ def recent_block_2(conn, name, tool):
                 "select why, block, blocker, end, today, band, ongoing " + \
                 "from rb order by today desc limit ?, 50" + \
             ""), [sql_num])
-    else:
+    elif tool == 'user':
+        sub = ' (' + load_lang('blocked') + ')'
         menu = [['block_log', load_lang('normal')]]
 
-        if tool == 'block_user':
-            sub = ' (' + load_lang('blocked') + ')'
-
-            curs.execute(db_change("" + \
-                "select why, block, blocker, end, today, band, ongoing " + \
-                "from rb where block = ? order by today desc limit ?, 50" + \
-            ""), [
-                name, 
-                sql_num
-            ])
-        else:
-            sub = ' (' + load_lang('admin') + ')'
+        curs.execute(db_change("" + \
+            "select why, block, blocker, end, today, band, ongoing " + \
+            "from rb where block = ? order by today desc limit ?, 50" + \
+        ""), [
+            name, 
+            sql_num
+        ])
+    else:
+        sub = ' (' + load_lang('admin') + ')'
+        menu = [['block_log', load_lang('normal')]]
 
-            curs.execute(db_change("" + \
-                "select why, block, blocker, end, today, band, ongoing " + \
-                "from rb where blocker = ? order by today desc limit ?, 50" + \
-            ""), [
-                name, 
-                sql_num
-            ])
+        curs.execute(db_change("" + \
+            "select why, block, blocker, end, today, band, ongoing " + \
+            "from rb where blocker = ? order by today desc limit ?, 50" + \
+        ""), [
+            name, 
+            sql_num
+        ])
 
     data_list = curs.fetchall()
     all_ip = ip_pas([i[1] for i in data_list] + [i[2] for i in data_list])
@@ -136,11 +135,16 @@ def recent_block_2(conn, name, tool):
             </tr>
         '''
 
-    div += '</tbody></table>'
-    div += next_fix('/block_log?num=', num, data_list) if not name else next_fix('/' + url_pas(tool) + '/' + url_pas(name) + '?num=', num, data_list)
+    div += '</tbody>'
+    div += '</table>'
+    
+    if tool == 'all':
+        div += next_fix('/block_log?num=', num, data_list)
+    else:
+        div += next_fix('/block_log/' + url_pas(tool) + '/' + url_pas(name) + '?num=', num, data_list)
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('recent_ban'), wiki_set(), custom(), other2([sub, 0])],
+        imp = [load_lang('recent_ban'), wiki_set(), wiki_custom(), wiki_css([sub, 0])],
         data = div,
         menu = menu
     ))

+ 16 - 17
route/recent_changes.py → route/recent_change.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def recent_changes_2(conn, name, tool):
+def recent_change_2(conn, name, tool):
     curs = conn.cursor()
 
     if flask.request.method == 'POST':
@@ -18,7 +18,7 @@ def recent_changes_2(conn, name, tool):
         div = '''
             <table id="main_table_set">
                 <tbody>
-                    <tr>
+                    <tr id="main_table_top_tr">
         '''
 
         num = int(number_check(flask.request.args.get('num', '1')))
@@ -60,8 +60,6 @@ def recent_changes_2(conn, name, tool):
                     <td id="main_table_width">''' + load_lang('time') + '''</td>
                 '''
 
-                div = '<a href="/topic_record/' + url_pas(name) + '">(' + load_lang('discussion') + ')</a><hr class=\"main_hr\">' + div
-
                 curs.execute(db_change('' + \
                     'select id, title, date, ip, send, leng, hide from history ' + \
                     "where ip = ? order by date desc limit ?, 50" + \
@@ -91,7 +89,7 @@ def recent_changes_2(conn, name, tool):
             send = '<br>'
 
             if data[4]:
-                if not re.search(r"^(?: *)$", data[4]):
+                if not re.search(r"^(?: +)$", data[4]):
                     send = data[4]
 
             if re.search(r"\+", data[5]):
@@ -102,10 +100,7 @@ def recent_changes_2(conn, name, tool):
                 leng = '<span style="color:gray;">(' + data[5] + ')</span>'
 
             ip = all_ip[data[3]]
-            if tool == 'history':
-                m_tool = '<a href="/history_tool/' + url_pas(data[1]) + '?num=' + data[0] + '&type=history">(' + load_lang('tool') + ')</a>'
-            else:
-                m_tool = '<a href="/history_tool/' + url_pas(data[1]) + '?num=' + data[0] + '">(' + load_lang('tool') + ')</a>'
+            m_tool = '<a href="/history/tool/' + data[0] + '/' + url_pas(data[1]) + '">(' + load_lang('tool') + ')</a>'
 
             style = ['', '']
             date = data[2]
@@ -114,15 +109,11 @@ def recent_changes_2(conn, name, tool):
                 if admin == 1:
                     style[0] = 'id="toron_color_grey"'
                     style[1] = 'id="toron_color_grey"'
-
-                    send += ' (' + load_lang('hide') + ')'
                 else:
                     ip = ''
                     ban = ''
                     date = ''
 
-                    send = '(' + load_lang('hide') + ')'
-
                     style[0] = 'style="display: none;"'
                     style[1] = 'id="toron_color_grey"'
 
@@ -142,13 +133,14 @@ def recent_changes_2(conn, name, tool):
                     <td>''' + date + '''</td>
                 </tr>
                 <tr ''' + style[1] + '''>
-                    <td colspan="3">''' + send_parser(send) + '''</td>
+                    <td class="send_content" colspan="3">''' + html.escape(send) + '''</td>
                 </tr>
             '''
 
         div += '''
                 </tbody>
             </table>
+            <script>send_render();</script>
         '''
 
         if name:
@@ -173,13 +165,20 @@ def recent_changes_2(conn, name, tool):
                     ''' + div
 
                     if admin == 1:
-                        menu += [['add_history/' + url_pas(name), load_lang('history_add')]]
+                        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')], ['count/' + url_pas(name), load_lang('count')]]
+                menu = [
+                    ['other', load_lang('other')], 
+                    ['user', load_lang('user')],
+                    ['record/reset/' + url_pas(name), load_lang('record_reset')]
+                ]
                 div += next_fix('/record/' + url_pas(name) + '?num=', num, data_list)
         else:
             div = '' + \
@@ -199,7 +198,7 @@ def recent_changes_2(conn, name, tool):
             sub = 0
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [title, wiki_set(), custom(), other2([sub, 0])],
+            imp = [title, wiki_set(), wiki_custom(), wiki_css([sub, 0])],
             data = div,
             menu = menu
         ))

+ 3 - 3
route/recent_discuss.py

@@ -15,10 +15,10 @@ def recent_discuss_2(conn):
         m_sub = ' (' + load_lang('closed') + ')'
 
     div +=  '''
-            <hr class=\"main_hr\">
+            <hr class="main_hr">
             <table id="main_table_set">
                 <tbody>
-                    <tr>
+                    <tr id="main_table_top_tr">
                         <td id="main_table_width_half">''' + load_lang('discussion_name') + '''</td>
                         <td id="main_table_width_half">''' + load_lang('time') + '''</td>
                     </tr>
@@ -38,7 +38,7 @@ def recent_discuss_2(conn):
     div += '</tbody></table>'
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('recent_discussion'), wiki_set(), custom(), other2([m_sub, 0])],
+        imp = [load_lang('recent_discussion'), wiki_set(), wiki_custom(), wiki_css([m_sub, 0])],
         data = div,
         menu = 0
     ))

+ 2 - 2
route/give_history_add.py → route/recent_history_add.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def give_history_add_2(conn, name):
+def recent_history_add_2(conn, name):
     curs = conn.cursor()
 
     ip = ip_check()
@@ -30,7 +30,7 @@ def give_history_add_2(conn, name):
         return redirect('/history/' + url_pas(name))
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('history_add'), wiki_set(), custom(), other2(['(' + name + ')', 0])],
+            imp = [load_lang('history_add'), wiki_set(), wiki_custom(), wiki_css(['(' + name + ')', 0])],
             data = '''
                 <form method="post">
                     <script>do_stop_exit();</script>

+ 7 - 5
route/recent_history_delete.py

@@ -1,15 +1,15 @@
 from .tool.func import *
 
-def recent_history_delete_2(conn, name):
+def recent_history_delete_2(conn, name, rev):
     curs = conn.cursor()
 
-    num = str(int(number_check(flask.request.args.get('num', '1'))))
+    num = str(rev)
 
     if admin_check() != 1:
         return re_error('/error/3')
 
     if flask.request.method == 'POST':
-        admin_check(None, 'history delete r' + num)
+        admin_check(None, 'history delete ' + name + ' r' + num)
 
         curs.execute(db_change("delete from history where id = ? and title = ?"), [num, name])
         conn.commit()
@@ -17,10 +17,12 @@ def recent_history_delete_2(conn, name):
         return redirect('/history/' + url_pas(name))
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(r' + num + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('history_delete') + ') (r' + num + ')', 0])],
             data = '''
                 <form method="post">
-                    <button type="submit">''' + load_lang('history_delete') + '''</button>
+                    <span>''' + load_lang('history_delete_warning') + '''</span>
+                    <hr class="main_hr">
+                    <button type="submit">''' + load_lang('delete') + '''</button>
                 </form>
             ''',
             menu = [['history/' + url_pas(name), load_lang('return')]]

+ 3 - 3
route/give_history_hidden.py → route/recent_history_hidden.py

@@ -1,9 +1,9 @@
 from .tool.func import *
 
-def give_history_hidden_2(conn, name):
+def recent_history_hidden_2(conn, name, rev):
     curs = conn.cursor()
-
-    num = number_check(flask.request.args.get('num', '1'))
+    
+    num = str(rev)
 
     if admin_check(6, 'history_hidden (' + name + '#' + num + ')') == 1:
         curs.execute(db_change("select title from history where title = ? and id = ? and hide = 'O'"), [name, num])

+ 27 - 0
route/recent_history_reset.py

@@ -0,0 +1,27 @@
+from .tool.func import *
+
+def recent_history_reset_2(conn, name):
+    curs = conn.cursor()
+
+    if admin_check() != 1:
+        return re_error('/error/3')
+
+    if flask.request.method == 'POST':
+        admin_check(None, 'history reset ' + name)
+
+        curs.execute(db_change("delete from history where title = ?"), [name])
+        conn.commit()
+
+        return redirect('/history/' + url_pas(name))
+    else:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('history_reset') + ')', 0])],
+            data = '''
+                <form method="post">
+                    <span>''' + load_lang('history_delete_warning') + '''</span>
+                    <hr class="main_hr">
+                    <button type="submit">''' + load_lang('reset') + '''</button>
+                </form>
+            ''',
+            menu = [['history/' + url_pas(name), load_lang('return')]]
+        ))

+ 45 - 0
route/recent_history_send.py

@@ -0,0 +1,45 @@
+from .tool.func import *
+
+def recent_history_send_2(conn, name, rev):
+    curs = conn.cursor()
+
+    num = str(rev)
+    
+    if admin_check() != 1:
+        return re_error('/error/3')
+
+    if flask.request.method == 'POST':
+        admin_check(None, 'send edit ' + name + ' r' + num)
+
+        curs.execute(db_change("select send from history where title = ? and id = ?"), [name, num])
+        if curs.fetchall():
+            curs.execute(db_change("update history set send = ? where title = ? and id = ?"), [
+                flask.request.form.get('send', ''),
+                name, 
+                num
+            ])
+
+        conn.commit()
+
+        return redirect('/history/' + url_pas(name))
+    else:
+        curs.execute(db_change("select send from history where title = ? and id = ?"), [name, num])
+        send = curs.fetchall()
+        if send:
+            send = send[0][0]
+        
+            return easy_minify(flask.render_template(skin_check(),
+                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>
+                        <hr class="main_hr">
+                        <input value="''' + html.escape(send) + '''" name="send">
+                        <hr class="main_hr">
+                        <button type="submit">''' + load_lang('edit') + '''</button>
+                    </form>
+                ''',
+                menu = [['history/' + url_pas(name), load_lang('return')]]
+            ))
+        else:
+            return redirect('/history/' + url_pas(name))

+ 27 - 17
route/recent_history_tool.py

@@ -1,9 +1,9 @@
 from .tool.func import *
 
-def recent_history_tool_2(conn, name):
+def recent_history_tool_2(conn, name, rev):
     curs = conn.cursor()
 
-    num = str(int(number_check(flask.request.args.get('num', '1'))))
+    num = str(rev)
 
     data = '' + \
         '<h2>' + load_lang('tool') + '</h2>' + \
@@ -11,31 +11,41 @@ def recent_history_tool_2(conn, name):
             '<li><a href="/raw/' + url_pas(name) + '?num=' + num + '">' + load_lang('raw') + '</a></li>' + \
     ''
 
-    if flask.request.args.get('type', '') == 'history':
-        data += '<li><a href="/revert/' + url_pas(name) + '?num=' + num + '">' + load_lang('revert') + '</a></li>'
-        if (int(num) - 1) > 0:
-            data += '<li><a href="/diff/' + url_pas(name) + '?first=' + str(int(num) - 1) + '&second=' + num + '">' + load_lang('compare') + '</a></li>'
-    elif (int(num) - 1) > 0:
-        data += '<li><a href="/revert/' + url_pas(name) + '?num=' + str(int(num) - 1) + '">' + load_lang('revert') + '</a></li>'
-
-    if flask.request.args.get('type', '') != 'history':
-        data += '<li><a href="/history/' + url_pas(name) + '">' + load_lang('history') + '</a></li>'
+    data += '<li><a href="/revert/' + url_pas(name) + '?num=' + num + '">' + load_lang('revert') + ' | r' + num + '</a></li>'
+    if rev - 1 > 0:
+        data += '<li><a href="/revert/' + url_pas(name) + '?num=' + str(rev - 1) + '">' + load_lang('revert') + ' | r' + str(rev - 1) + '</a></li>'
+    
+    if rev - 1 > 0:
+        data += '<li><a href="/diff/' + url_pas(name) + '?first=' + str(rev - 1) + '&second=' + num + '">' + load_lang('compare') + '</a></li>'
 
+    data += '<li><a href="/history/' + url_pas(name) + '">' + load_lang('history') + '</a></li>'
+    data += '</ul>'
+    
     if admin_check(6) == 1:
+        data += '<h3>admin</h3>'
+        data += '<ul class="inside_ul">'
         curs.execute(db_change('' + \
             'select title from history ' + \
             'where title = ? and id = ? and hide = "O"' + \
         ''), [name, num])
-        hide = curs.fetchall()
-        data += '<li><a href="/hidden/' + url_pas(name) + '?num=' + num + '">' + (load_lang('hide_release') if hide else load_lang('hide')) + '</li>'
+        data += '<li><a href="/history/hidden/' + num + '/' + url_pas(name) + '">'
+        if curs.fetchall():
+            data += load_lang('hide_release') 
+        else:
+            data += load_lang('hide')
+            
+        data += '</li>'
+        data += '</ul>'
 
     if admin_check() == 1:
-        data += '<li><a href="/history_delete/' + url_pas(name) + '?num=' + num + '">' + load_lang('history_delete') + '</li>'
-
-    data += '</ul>'
+        data += '<h3>owner</h3>'
+        data += '<ul class="inside_ul">'
+        data += '<li><a href="/history/delete/' + num + '/' + url_pas(name) + '">' + load_lang('history_delete') + '</li>'
+        data += '<li><a href="/history/send/' + num + '/' + url_pas(name) + '">' + load_lang('send_edit') + '</li>'
+        data += '</ul>'
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [name, wiki_set(), custom(), other2(['(r' + num + ')', 0])],
+        imp = [name, wiki_set(), wiki_custom(), wiki_css(['(r' + num + ')', 0])],
         data = data,
         menu = [['history/' + url_pas(name), load_lang('return')]]
     ))

+ 27 - 0
route/recent_record_reset.py

@@ -0,0 +1,27 @@
+from .tool.func import *
+
+def recent_record_reset_2(conn, name):
+    curs = conn.cursor()
+
+    if admin_check() != 1:
+        return re_error('/error/3')
+
+    if flask.request.method == 'POST':
+        admin_check(None, 'record reset ' + name)
+
+        curs.execute(db_change("delete from history where ip = ?"), [name])
+        conn.commit()
+
+        return redirect('/record/' + url_pas(name))
+    else:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('record_reset') + ')', 0])],
+            data = '''
+                <form method="post">
+                    <span>''' + load_lang('history_delete_warning') + '''</span>
+                    <hr class="main_hr">
+                    <button type="submit">''' + load_lang('reset') + '''</button>
+                </form>
+            ''',
+            menu = [['record/' + url_pas(name), load_lang('return')]]
+        ))

+ 11 - 20
route/list_user_topic.py → route/recent_record_topic.py

@@ -1,22 +1,18 @@
 from .tool.func import *
 
-def list_user_topic_2(conn, name):
+def recent_record_topic_2(conn, name):
     curs = conn.cursor()
 
     num = int(number_check(flask.request.args.get('num', '1')))
-    if num * 50 > 0:
-        sql_num = num * 50 - 50
-    else:
-        sql_num = 0
+    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
     div = '''
         <table id="main_table_set">
-            <tbody>
-                <tr>
-                    <td id="main_table_width">''' + load_lang('discussion_name') + '''</td>
-                    <td id="main_table_width">''' + load_lang('writer') + '''</td>
-                    <td id="main_table_width">''' + load_lang('time') + '''</td>
-                </tr>
+            <tr id="main_table_top_tr">
+                <td id="main_table_width">''' + load_lang('discussion_name') + '''</td>
+                <td id="main_table_width">''' + load_lang('writer') + '''</td>
+                <td id="main_table_width">''' + load_lang('time') + '''</td>
+            </tr>
     '''
     sub = '(' + html.escape(name) + ')'
     pas_name = ip_pas(name)
@@ -39,19 +35,14 @@ def list_user_topic_2(conn, name):
             '</tr>' + \
         ''
 
-    div += '' + \
-            '</tbody>' + \
-        '</table>' + \
-    ''
-    div += next_fix('/topic_record/' + url_pas(name) + '?num=', num, data_list)
+    div += '</table>'
+    div += next_fix('/record/topic/' + url_pas(name) + '?num=', num, data_list)
     
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('discussion_record'), wiki_set(), custom(), other2([sub, 0])],
+        imp = [load_lang('discussion_record'), wiki_set(), wiki_custom(), wiki_css([sub, 0])],
         data = div,
         menu = [
             ['other', load_lang('other')], 
-            ['user', load_lang('user')], 
-            ['count/' + url_pas(name), load_lang('count')], 
-            ['record/' + url_pas(name), load_lang('record')]
+            ['user', load_lang('user')]
         ]
     ))

+ 1 - 1
route/search_deep.py

@@ -59,7 +59,7 @@ def search_deep_2(conn, name):
     div += next_fix('/search/' + url_pas(name) + '?num=', num, all_list)
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [name, wiki_set(), custom(), other2(['(' + load_lang('search') + ')', 0])],
+        imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('search') + ')', 0])],
         data = div,
         menu = 0
     ))

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 508 - 386
route/tool/func.py


+ 150 - 0
route/tool/func_mark.py

@@ -0,0 +1,150 @@
+from .func_tool import *
+
+# 커스텀 마크 언젠간 다시 추가 예정
+
+conn = ''
+curs = ''
+
+def load_conn2(data):
+    global conn
+    global curs
+
+    conn = data
+    curs = conn.cursor()
+    
+def backlink_generate(data_markup, doc_data, doc_name):
+    if data_markup == 'namumark':
+        # Link
+        link_re = re.compile(r'\[\[(?!https?:\/\/)((?:(?!\[\[|\]\]|\|).)+)(?:\]\]|\|)', re.I)
+        
+        data_link = link_re.findall(doc_data)
+        data_link = list(set(data_link))
+        
+        data_link_end = {}
+        data_link_end['cat'] = []
+        data_link_end['file'] = []
+        data_link_end['link'] = []
+        
+        data_link_end_all = []
+        
+        for i in data_link:
+            data_link_in = i
+            if data_link_in[0] == '#':
+                continue
+            elif re.search(r'^(?:분류|category):', data_link_in):
+                data_link_in = re.sub(r'\\(.)', r'\1', data_link_in)
+                data_link_end['cat'] += [re.sub(r'^분류:', 'category:', data_link_in)]
+            elif re.search(r'^(?:파일|file):', data_link_in):
+                data_link_in = re.sub(r'\\(.)', r'\1', data_link_in)
+                data_link_end['file'] += [re.sub(r'^파일:', 'file:', data_link_in)]
+            else:
+                data_link_in = re.sub(r'([^\\])#(?:[^#]*)$', r'\1', data_link_in)
+                
+                if data_link_in[0] == ':':
+                    data_link_in = re.sub(r'^:', '', data_link_in)
+                elif data_link_in[0] == '/':
+                    data_link_in = doc_name + data_link_in
+                elif len(data_link_in) >= 3 and data_link_in[0:3] == '../':
+                    data_link_in = data_link_in[3:len(data_link_in)]
+                    data_link_in = '' + \
+                        re.sub('\/[^/]+$', '', doc_name) + \
+                        (('/' + data_link_in) if data_link_in != '' else '') + \
+                    ''
+
+                data_link_in = re.sub(r'\\(.)', r'\1', data_link_in)
+                data_link_end['link'] += [data_link_in]
+                
+        if data_link_end != {}:
+            data_link_end['cat'] = list(set(data_link_end['cat']))
+            data_link_end['file'] = list(set(data_link_end['file']))
+            data_link_end['link'] = list(set(data_link_end['link']))
+
+            data_link_end_all += [[doc_name, i, 'cat'] for i in data_link_end['cat']]
+            data_link_end_all += [[doc_name, i, 'file'] for i in data_link_end['file']]
+            data_link_end_all += [[doc_name, i, ''] for i in data_link_end['link']]
+            
+            data_link_no = []
+            for i in data_link_end['link']:
+                curs.execute(db_change("select title from data where title = ?"), [i])
+                if not curs.fetchall():
+                    data_link_no += [[doc_name, i, 'no']]
+                    
+            data_link_end_all += data_link_no
+            
+        # Include
+        include_re = re.compile(r'\[include\(((?:(?!\)\]).)+)\)\]', re.I)
+        
+        data_include = include_re.findall(doc_data)
+        data_include = list(set(data_include))
+        
+        for i in data_include:
+            data_include_in = i
+            data_include_in = re.sub(r'([^\\]),.*$', r'\1', data_include_in)
+            
+            data_link_end_all += [[doc_name, data_include_in, 'include']]
+        
+        # Redirect
+        redirect_re = re.compile(r'^#(?:redirect|넘겨주기) ([^\n]+)', re.I)
+        
+        data_redirect = redirect_re.search(doc_data)
+        if data_redirect:
+            data_redirect = data_redirect.group(1)
+            
+            data_redirect = re.sub(r'([^\\])#(?:[^#]*)$', r'\1', data_redirect)
+            
+            data_link_end_all += [[doc_name, data_redirect, 'redirect']]
+    else:
+        # markup == null
+        data_link_end_all = []
+            
+    return data_link_end_all
+
+def render_do(doc_name, doc_data, data_type, data_in):
+    data_in = None if data_in == '' else data_in
+    
+    curs.execute(db_change('select data from other where name = "markup"'))
+    rep_data = curs.fetchall()
+    rep_data = rep_data[0][0] if rep_data else 'namumark'
+    
+    if data_type != 'backlink':
+        if rep_data == 'namumark':
+            data_in = (data_in + '_') if data_in else ''
+            data_end = [
+                '<pre style="display: none;" id="' + data_in + 'render_content_load">' + html.escape(doc_data) + '</pre>'
+                '<div class="render_content" id="' + data_in + 'render_content"></div>', 
+                '''
+                    do_onmark_render(
+                        test_mode = "normal", 
+                        name_id = "''' + data_in + '''render_content",
+                        name_include = "''' + data_in + '''",
+                        name_doc = "''' + doc_name.replace('"', '//"') + '''"
+                    );
+                ''',
+                []
+            ]
+        else:
+            data_end = [
+                doc_data, 
+                '', 
+                []
+            ]
+
+        if data_type == 'api_view':
+            return [
+                data_end[0], 
+                data_end[1]
+            ]
+        else:
+            return data_end[0] + '<script>' + data_end[1] + '</script>'
+    else:
+        backlink = backlink_generate(
+            rep_data, 
+            html.escape(doc_data), 
+            doc_name
+        )
+        
+        if backlink != []:
+            curs.executemany(db_change("insert into back (link, title, type) values (?, ?, ?)"), backlink)
+            curs.execute(db_change("delete from back where title = ? and type = 'no'"), [doc_name])
+
+        conn.commit()

+ 5 - 0
route/tool/tool.py → route/tool/func_tool.py

@@ -4,6 +4,11 @@ import hashlib
 import flask
 import re
 
+import os
+import html
+import sqlite3
+import threading
+
 set_data = ''
 
 def get_time():

+ 0 - 68
route/tool/init.py

@@ -1,68 +0,0 @@
-import os
-
-env_dict = {
-    'host' : os.getenv('NAMU_HOST'),
-    'port' : os.getenv('NAMU_PORT'),
-    'language' : os.getenv('NAMU_LANG'),
-    'markup' : os.getenv('NAMU_MARKUP'),
-    'encode' : os.getenv('NAMU_ENCRYPT')
-}
-
-server_set_var = {
-    'host' : {
-        'display' : 'Host',
-        'require' : 'conv',
-        'default' : '0.0.0.0'
-    },
-    'port' : {
-        'display' : 'Port',
-        'require' : 'conv',
-        'default' : '3000'
-    },
-    'language' : {
-        'display' : 'Language',
-        'require' : 'select',
-        'default' : 'ko-KR',
-        'list' : ['ko-KR', 'en-US']
-    },
-    'markup' : {
-        'display' : 'Markup',
-        'require' : 'select',
-        'default' : 'namumark',
-        'list' : ['namumark', 'custom', 'js_onmark']
-    },
-    'encode' : {
-        'display' : 'Encryption method',
-        'require' : 'select',
-        'default' : 'sha3',
-        'list' : ['sha3', 'sha256']
-    }
-}
-
-def init(key):
-    if env_dict[key] != None:
-        return env_dict[key]
-    else:
-        while 1:
-            if server_set_var[key]['require'] == 'select':
-                list_ = '[' + ', '.join(server_set_var[key]['list']) + ']'
-            else:
-                list_ = ''
-
-            print('{} ({}) {} : '.format(
-                server_set_var[key]['display'],
-                server_set_var[key]['default'],
-                list_
-            ), end = '')
-
-            server_set_val = input()
-            if server_set_val:
-                if server_set_var[key]['require'] == 'select':
-                    if server_set_val not in server_set_var[key]['list']:
-                        pass
-                    else:
-                        return server_set_val
-                else:
-                    return server_set_val
-            else:
-                return server_set_var[key]['default']

+ 0 - 82
route/tool/mark.py

@@ -1,82 +0,0 @@
-from .namumark import namumark
-from .tool import *
-
-import re
-import os
-import html
-import sqlite3
-import asyncio
-import threading
-import urllib.parse
-
-conn = ''
-curs = ''
-
-if os.path.exists('route/tool/custom.py'):
-    from .custom import custom_mark
-else:
-    def custom_mark(conn, data, title, num, include):
-        return [data, '', []]
-
-def load_conn2(data):
-    global conn
-    global curs
-
-    conn = data
-    curs = conn.cursor()
-
-def send_parser(data):
-    if not re.search(r'^<br>$', data):
-        data = html.escape(data)
-
-        data = re.sub(r'javascript:', '', data, flags = re.I)
-        data = data.replace('&lt;br&gt;', '')
-
-    link_re = re.compile(r'&lt;a(?: (?:(?:(?!&gt;).)*))?&gt;(?P<in>(?:(?!&lt;).)*)&lt;\/a&gt;')
-    link_data = link_re.findall(data)
-    for i in link_data:
-        data = link_re.sub('<a href="/w/' + urllib.parse.quote(i).replace('/','%2F') + '">' + i + '</a>', data, 1)
-
-    return data
-
-def render_do(title, data, num, include):
-    # num == 1 -> commit O | html
-    # num == 2 -> commit X | list
-    # num == 3 -> commit X 
-    curs.execute(db_change('select data from other where name = "markup"'))
-    rep_data = curs.fetchall()
-    if rep_data[0][0] == 'namumark':
-        data = namumark(conn, data, title, include)
-    elif rep_data[0][0] == 'custom':
-        data = custom_mark(conn, data, title, include)
-    elif rep_data[0][0] == 'js_onmark':
-        include = (include + '_') if include else ''
-        data = [
-            '<div id="' + include + 'render_content">' + html.escape(data) + '</div>', 
-            '''
-                do_onmark_render(
-                    test_mode = 0, 
-                    name_id = "''' + include + '''render_content",
-                    name_include = "''' + include + '''",
-                    name_doc = "''' + title.replace('"', '//"') + '''",
-                );
-            ''',
-            []
-        ]
-    else:
-        data = [data, '', []]
-
-    if num in [1, 3]:
-        if data[2] == []:
-            curs.execute(db_change("insert into back (title, link, type) values ('test', ?, 'nothing')"), [title])
-        else:
-            curs.executemany(db_change("insert into back (link, title, type) values (?, ?, ?)"), data[2])
-            curs.execute(db_change("delete from back where title = ? and type = 'no'"), [title])
-
-        if num != 3:
-            conn.commit()
-
-    if num == 2:
-        return [data[0], data[1]]
-    else:
-        return data[0] + '<script>' + data[1] + '</script>'

+ 0 - 1334
route/tool/namumark.py

@@ -1,1334 +0,0 @@
-from . import tool
-
-import datetime
-import html
-import re
-
-end_data = ''
-plus_data = ''
-nowiki_num = ''
-include_name = ''
-
-def nowiki_js(data):
-    data = data.replace('\\', '\\\\')
-    data = data.replace('"', '\\"')
-    data = data.replace('\r', '')
-    
-    data = re.sub(r'^\n', '', data)
-
-    data = data.replace('\n', '<br>')
-
-    return data
-
-def link_fix(main_link, no_change = 0):
-    global end_data
-
-    main_link = main_link.replace('&#x27;', "<link_comma>")
-    
-    if re.search(r'^:', main_link):
-        main_link = re.sub(r'^:', '', main_link)
-
-    if no_change == 0:
-        main_link = re.sub(r'^사용자:', 'user:', main_link)
-        main_link = re.sub(r'^파일:', 'file:', main_link)
-        main_link = re.sub(r'^분류:', 'category:', main_link)
-
-    other_link = re.search(r'[^\\]?(#[^#]+)$', main_link)
-    if other_link:
-        other_link = other_link.group(1)
-
-        main_link = re.sub(r'(#[^#]+)$', '', main_link)
-    else:
-        other_link = ''
-
-    main_link = main_link.replace("<link_comma>", "&#x27;")
-    main_link = main_link.replace('\\#', '%23')
-
-    find_data = re.findall(r'<span id="((?:include_(?:[0-9]+)_)?(?:nowiki_[0-9]+))">', main_link)
-    for i in find_data:
-        main_link = main_link.replace('<span id="' + i + '"></span>', end_data[i])
-
-    find_data = re.findall(r'<span id="((?:include_(?:[0-9]+)_)?(?:nowiki_[0-9]+))">', other_link)
-    for i in find_data:
-        other_link = other_link.replace('<span id="' + i + '"></span>', end_data[i])
-
-    return [main_link, other_link]
-
-def table_parser(data, cel_data, cel_num, start_data, num = 0, cel_color = {}):
-    table_class = 'class="'
-    div_style = 'style="'
-    all_table = 'style="'
-    cel_style = 'style="'
-    row_style = 'style="'
-    row = ''
-    cel = 'colspan="' + str(round(len(start_data) / 2)) + '"'
-
-    if not cel_num in cel_color:
-        cel_color[cel_num] = ''
-
-    cel_style += cel_color[cel_num]
-
-    if num == 0:
-        if re.search(r'^ ', cel_data) and re.search(r' $', cel_data):
-            cel_style += 'text-align: center;'
-        elif re.search(r'^ ', cel_data):
-            cel_style += 'text-align: right;'
-        elif re.search(r' $', cel_data):
-            cel_style += 'text-align: left;'
-
-    table_state = re.findall(r'&lt;((?:(?!&gt;).)+)&gt;', data)
-    for in_state in table_state:
-        table_state_data = re.search(r'^([^=]+)=([^=]+)$', in_state)
-        if not table_state_data:
-            if re.search(r'^(#(?:[0-9a-f-A-F]{3}){1,2}|\w+)$', in_state):
-                table_state_data = ['bgcolor', in_state]
-            else:
-                table_state_data = re.search(r'([^0-9]+)([0-9]+)$', in_state)
-                if table_state_data:
-                    table_state_data = table_state_data.groups()
-                else:
-                    table_state_data = [in_state, '']
-        else:
-            table_state_data = table_state_data.groups()
-            table_state_data = [
-                table_state_data[0].replace(' ', ''),
-                re.sub(r',([^,]+)$', '', table_state_data[1])
-            ]
-
-        if table_state_data[0] == 'tablewidth':
-            table_data = table_state_data[1]
-            div_style += 'width: ' + ((table_data + 'px') if re.search(r'^[0-9]+$', table_data) else table_data) + ';'
-            all_table += 'width: 100%;'
-        elif table_state_data[0] == 'tableheight':
-            table_data = table_state_data[1]
-            div_style += 'height: ' + ((table_data + 'px') if re.search(r'^[0-9]+$', table_data) else table_data) + ';'
-        elif table_state_data[0] == 'tablealign':
-            table_data = table_state_data[1]
-            if table_data == 'right':
-                div_style += 'float: right;'
-            elif table_data == 'center':
-                div_style += 'margin: auto;'
-                all_table += 'margin: auto;'
-        elif table_state_data[0] == 'tabletextalign':
-            num = 1
-            table_data = table_state_data[1]
-            if table_data == 'right':
-                all_table += 'text-align: right;'
-            elif table_data == 'center':
-                all_table += 'text-align: center;'
-        elif table_state_data[0] == 'rowtextalign':
-            table_data = table_state_data[1]
-            if table_data == 'right':
-                row_style += 'text-align: right;'
-            elif table_data == 'center':
-                row_style += 'text-align: center;'
-            else:
-                row_style += 'text-align: left;'
-        elif table_state_data[0] == '-':
-            cel = 'colspan="' + table_state_data[1] + '"'
-        elif table_state_data[0] == '^|' or table_state_data[0] == 'v|' or table_state_data[0] == '|':
-            if table_state_data[0][0] == '^':
-                cel_style += 'vertical-align: top;'
-            elif table_state_data[0][0] == 'v':
-                cel_style += 'vertical-align: bottom;'
-
-            row = 'rowspan="' + table_state_data[1] + '"'
-        elif table_state_data[0] == 'rowbgcolor':
-            table_data = table_state_data[1]
-            row_style += 'background: ' + table_data + ';'
-        elif table_state_data[0] == 'rowcolor':
-            table_data = table_state_data[1]
-            row_style += 'color: ' + table_data + ';'
-        elif table_state_data[0] == 'tablebordercolor':
-            table_data = table_state_data[1]
-            all_table += 'border: ' + table_data + ' 2px solid;'
-        elif table_state_data[0] == 'tablebgcolor':
-            table_data = table_state_data[1]
-            all_table += 'background: ' + table_data + ';'
-        elif table_state_data[0] == 'tablecolor':
-            table_data = table_state_data[1]
-            all_table += 'color: ' + table_data + ';'
-        elif table_state_data[0] == 'colbgcolor':
-            table_data = table_state_data[1]
-            table_data = table_data
-            cel_color[cel_num] += 'background: ' + table_data + ';'
-            cel_style += 'background: ' + table_data + ';'
-        elif table_state_data[0] == 'colcolor':
-            table_data = table_state_data[1]
-            table_data = table_data
-            cel_color[cel_num] += 'color: ' + table_data + ';'
-            cel_style += 'color: ' + table_data + ';'
-        elif table_state_data[0] == 'bgcolor':
-            table_data = table_state_data[1]
-            cel_style += 'background: ' + table_data + ';'
-        elif table_state_data[0] == 'color':
-            table_data = table_state_data[1]
-            cel_style += 'color: ' + table_data + ';'
-        elif table_state_data[0] == 'width':
-            table_data = table_state_data[1]
-            cel_style += 'width: ' + ((table_data + 'px') if re.search(r'^[0-9]+$', table_data) else table_data) + ';'
-        elif table_state_data[0] == 'height':
-            table_data = table_state_data[1]
-            cel_style += 'height: ' + ((table_data + 'px') if re.search(r'^[0-9]+$', table_data) else table_data) + ';'
-        elif table_state_data[0] == '(' or table_state_data[0] == ':' or table_state_data[0] == ')':
-            if table_state_data[0] == '(':
-                cel_style += 'text-align: right;'
-            elif table_state_data[0] == ':':
-                cel_style += 'text-align: center;'
-            else:
-                cel_style += 'text-align: left;'
-        elif table_state_data[0] == 'tableclass':
-            table_data = table_state_data[1]
-            table_class += table_data
-
-    div_style += '"'
-    all_table += '"'
-    cel_style += '"'
-    row_style += '"'
-    table_class += '"'
-
-    return [all_table, row_style, cel_style, row, cel, table_class, num, div_style, cel_color]
-
-def table_start(data):
-    data = re.sub(r'\n( +)\|\|', '\n||', data)
-    data = re.sub(r'\|\|( +)\n', '||\n', data)
-    data = re.sub(r'(\|\|)+\n', '||\n', data)
-
-    while 1:
-        cel_num = 0
-        table_num = 0
-        table_end = ''
-        cel_color = {}
-
-        table = re.search(r'\n((?:(?:(?:(?:\|\||\|[^|]+\|)+(?:(?:(?!\|\|).\n*)*))+)\|\|(?:\n)?)+)', data)
-        if table:
-            table = re.sub(r'(\|\|)+\n', '||\n', table.group(1))
-            
-            table_caption = re.search(r'^\|([^|]+)\|', table)
-            if table_caption:
-                table_caption = '<caption>' + table_caption.group(1) + '</caption>'
-                
-                table = re.sub(r'^\|([^|]+)\|', '||', table)
-            else:
-                table_caption = ''
-            
-            table = '\n' + table
-            
-            table_cel = re.findall(r'(\n(?:(?:\|\|)+)|\|\|\n(?:(?:\|\|)+)|(?:(?:\|\|)+))((?:(?:(?!\n|\|\|).)+\n*)+)', table)
-            for i in table_cel:
-                cel_plus = re.search(r'^((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)', i[1])
-                cel_plus = cel_plus.group(1) if cel_plus else ''
-                cel_data = re.sub(r'^((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)', '', i[1])
-
-                if re.search(r'^\n', i[0]):
-                    cel_num = 1
-
-                    cel_plus = table_parser(
-                        cel_plus, 
-                        cel_data,
-                        cel_num,
-                        re.sub(r'^\n', '', i[0]),
-                        table_num,
-                        cel_color
-                    )
-                    cel_color = cel_plus[8]
-                    table_num = cel_plus[6]
-
-                    table_end += '' + \
-                        '<div class="table_safe" ' + cel_plus[7] + '>' + \
-                            '<table ' + cel_plus[5] + ' ' + cel_plus[0] + '>' + \
-                                table_caption + \
-                                '<tr ' + cel_plus[1] + '>' + \
-                                    '<td ' + cel_plus[2] + ' ' + cel_plus[3] + ' ' + cel_plus[4] + '>' + \
-                                        cel_data
-                                        
-                elif re.search(r'\n', i[0]):
-                    cel_num = 1
-
-                    cel_plus = table_parser(
-                        cel_plus, 
-                        cel_data,
-                        cel_num,
-                        re.sub(r'^\|\|\n', '', i[0]),
-                        table_num,
-                        cel_color
-                    )
-                    cel_color = cel_plus[8]
-
-                    table_end += '' + \
-                            '</td>' + \
-                        '</tr>' + \
-                        '<tr ' + cel_plus[1] + '>' + \
-                            '<td ' + cel_plus[2] + ' ' + cel_plus[3] + ' ' + cel_plus[4] + '>' + \
-                                cel_data
-                else:
-                    cel_num += 1
-
-                    cel_plus = table_parser(
-                        cel_plus, 
-                        cel_data,
-                        cel_num,
-                        re.sub(r'^\|\|\n', '', i[0]),
-                        table_num,
-                        cel_color
-                    )
-                    cel_color = cel_plus[8]
-
-                    table_end += '' + \
-                        '</td>' + \
-                        '<td ' + cel_plus[2] + ' ' + cel_plus[3] + ' ' + cel_plus[4] + '>' + \
-                            cel_data
-
-            table_end += '' + \
-                            '</td>' + \
-                        '</tr>' + \
-                    '</table>' + \
-                '</div>' + \
-            ''
-
-            data = re.sub(r'\n((?:(?:(?:(?:\|\||\|[^|]+\|)+(?:(?:(?!\|\|).\n*)*))+)\|\|(?:\n)?)+)', '\n' + table_end + '\n', data, 1)
-        else:
-            break
-
-    return data.replace('||', '<no_table>')
-
-def middle_parser(data):
-    global end_data
-    global plus_data
-    global nowiki_num
-    global include_name
-
-    middle_stack = 0
-    middle_list = []
-    middle_num = 0
-
-    html_num = 0
-    syntax_num = 0
-    folding_num = 0
-
-    middle_re = re.compile(r'(?:{{{((?:(?:(?! |{{{|}}}|&lt;).)*) ?)|(}}}))')
-    middle_all_data = middle_re.findall(data)
-    for middle_data in middle_all_data:
-        if not middle_data[1]:
-            if middle_stack > 0:
-                middle_stack += 1
-
-                data = re.sub(r'(?:{{{((?:(?! |{{{|}}}|&lt;).)*)(?P<in> ?)|(}}}))', '<middle_start>' + middle_data[0] + '\g<in>', data, 1)
-            else:
-                if re.search(r'^(#|@|\+|\-)', middle_data[0]) and not re.search(r'^(#|@|\+|\-){2}|(#|@|\+|\-)\\', middle_data[0]):
-                    if re.search(r'^(#(?:[0-9a-f-A-F]{3}){1,2})', middle_data[0]):
-                        middle_search = re.search(r'^(#(?:[0-9a-f-A-F]{3}){1,2})', middle_data[0])
-                        middle_list += ['span']
-
-                        data = middle_re.sub('<span style="color: ' + middle_search.group(1) + ';">', data, 1)
-                    elif re.search(r'^(?:#(\w+))', middle_data[0]):
-                        middle_search = re.search(r'^(?:#(\w+))', middle_data[0])
-                        middle_list += ['span']
-
-                        data = middle_re.sub('<span style="color: ' + middle_search.group(1) + ';">', data, 1)
-                    elif re.search(r'^(?:@((?:[0-9a-f-A-F]{3}){1,2}))', middle_data[0]):
-                        middle_search = re.search(r'^(?:@((?:[0-9a-f-A-F]{3}){1,2}))', middle_data[0])
-                        middle_list += ['span']
-
-                        data = middle_re.sub('<span style="background: #' + middle_search.group(1) + ';">', data, 1)
-                    elif re.search(r'^(?:@(\w+))', middle_data[0]):
-                        middle_search = re.search(r'^(?:@(\w+))', middle_data[0])
-                        middle_list += ['span']
-
-                        data = middle_re.sub('<span style="background: ' + middle_search.group(1) + ';">', data, 1)
-                    elif re.search(r'^(\+|-)([1-5])', middle_data[0]):
-                        middle_search = re.search(r'^(\+|-)([1-5])', middle_data[0])
-                        middle_search = middle_search.groups()
-                        if middle_search[0] == '+':
-                            font_size = str(int(middle_search[1]) * 20 + 100)
-                        else:
-                            font_size = str(100 - int(middle_search[1]) * 10)
-
-                        middle_list += ['span']
-
-                        data = middle_re.sub('<span style="font-size: ' + font_size + '%;">', data, 1)
-                    elif re.search(r'^#!wiki', middle_data[0]):
-                        middle_data_2 = re.search(r'{{{#!wiki(?: style=(?:&quot;|&#x27;)((?:(?!&quot;|&#x27;).)*)(?:&quot;|&#x27;))?(?: *)\n?', data)
-                        if middle_data_2:
-                            middle_data_2 = middle_data_2.groups()
-                        else:
-                            middle_data_2 = ['']
-
-                        middle_list += ['div_1']
-
-                        data = re.sub(
-                            r'{{{#!wiki(?: style=(?:&quot;|&#x27;)((?:(?!&quot;|&#x27;).)*)(?:&quot;|&#x27;))?(?: *)\n?',
-                            '<div_1 style="' + str(middle_data_2[0] if middle_data_2[0] else '') + '">',
-                            data,
-                            1
-                        )
-                    elif re.search(r'^#!syntax', middle_data[0]):
-                        syntax_re = re.compile(r'{{{#!syntax ?((?:(?!\n|{{{|}}}).)*)\n?')
-                        middle_data_2 = syntax_re.search(data)
-                        if middle_data_2:
-                            middle_data_2 = middle_data_2.groups()
-                        else:
-                            middle_data_2 = ['python']
-
-                        if syntax_num == 0:
-                            plus_data += 'hljs.initHighlightingOnLoad();\n'
-
-                            syntax_num = 1
-
-                        middle_list += ['pre']
-
-                        data = syntax_re.sub(
-                            '<pre id="syntax"><code class="' + middle_data_2[0] + '">',
-                            data,
-                            1
-                        )
-                    elif re.search(r'^#!folding', middle_data[0]):
-                        middle_list += ['div_dd']
-
-                        folding_data = re.search(r'{{{#!folding ?((?:(?!\n).)*)\n?', data)
-                        if folding_data:
-                            folding_data = folding_data.groups()
-                        else:
-                            folding_data = ['Test']
-
-                        plus_data += '' + \
-                            'if(document.getElementById("get_' + include_name + 'folding_' + str(folding_num) + '")) { ' + \
-                                'document.getElementById("get_' + include_name + 'folding_' + str(folding_num) + '").innerHTML = ' + \
-                                    '"' + nowiki_js(folding_data[0]) + '"; ' + \
-                                '' + \
-                            '}' + \
-                            '\n' + \
-                        ''
-                        data = re.sub(
-                            r'{{{#!folding ?((?:(?!\n).)*)\n?', '' + \
-                            '<div style="display: inline-block;">' + \
-                                '<b>' + \
-                                    '<a href="javascript:void(0);" ' + \
-                                        'onclick="do_open_folding(\'' + include_name + 'folding_' + str(folding_num) + '\');" ' + \
-                                        'id="get_' + include_name + 'folding_' + str(folding_num) + '">' + \
-                                    '</a>' + \
-                                '</b>' + \
-                            '</div_2>' + \
-                            '<div id="' + include_name + 'folding_' + str(folding_num) + '" style="display: none;">' + \
-                                '<div_1 style="">\n',
-                            data,
-                            1
-                        )
-
-                        folding_num += 1
-                    elif re.search(r'^#!html', middle_data[0]):
-                        middle_list += ['span']
-
-                        html_num += 1
-
-                        data = middle_re.sub('<span id="' + include_name + 'render_contect_' + str(html_num) + '">', data, 1)
-                    else:
-                        middle_list += ['span']
-
-                        data = middle_re.sub('<span>', data, 1)
-                else:
-                    middle_list += ['code']
-
-                    middle_stack += 1
-
-                    data = middle_re.sub('<code>' + middle_data[0].replace('\\', '\\\\'), data, 1)
-
-                middle_num += 1
-        else:
-            if middle_list == []:
-                data = middle_re.sub('<middle_end>', data, 1)
-            else:
-                if middle_stack > 0:
-                    middle_stack -= 1
-
-                if middle_stack > 0:
-                    data = middle_re.sub('<middle_end>', data, 1)
-                else:
-                    if middle_num > 0:
-                        middle_num -= 1
-
-                    if middle_list[middle_num] == 'div_dd':
-                        data = middle_re.sub('</div_1></div_2>', data, 1)
-                    elif middle_list[middle_num] == 'pre':
-                        data = middle_re.sub('</code></pre>', data, 1)
-                    else:
-                        data = middle_re.sub('</' + middle_list[middle_num] + '>', data, 1)
-
-                    del middle_list[middle_num]
-
-    while 1:
-        if middle_list == []:
-            break
-        else:
-            if middle_stack > 0:
-                middle_stack -= 1
-
-            if middle_stack > 0:
-                data += '<middle_end>'
-            else:
-                if middle_num > 0:
-                    middle_num -= 1
-
-                if middle_list[middle_num] == 'div_dd':
-                    data += '</div_1></div_2>'
-                elif middle_list[middle_num] == 'pre':
-                    data += '</code></pre>'
-                else:
-                    data += '</' + middle_list[middle_num] + '>'
-
-                del middle_list[middle_num]
-
-    data = data.replace('<middle_start>', '{{{')
-    data = data.replace('<middle_end>', '}}}')
-
-    while 1:
-        nowiki_data = re.search(r'<code>((?:(?:(?!<\/code>).)*\n*)*)<\/code>', data)
-        if nowiki_data:
-            nowiki_data = nowiki_data.groups()
-
-            nowiki_num += 1
-            end_data[include_name + 'nowiki_' + str(nowiki_num)] = nowiki_data[0]
-            plus_data += '' + \
-                'if(document.getElementById("' + include_name + 'nowiki_' + str(nowiki_num) + '")) {\n' + \
-                    'document.getElementById("' + include_name + 'nowiki_' + str(nowiki_num) + '").innerHTML = "' + nowiki_js(nowiki_data[0]) + '";\n' + \
-                '}\n' + \
-            ''
-
-            data = re.sub(
-                r'<code>((?:(?:(?!<\/code>).)*\n*)*)<\/code>',
-                '<span id="' + include_name + 'nowiki_' + str(nowiki_num) + '"></span>',
-                data,
-                1
-            )
-        else:
-            break
-
-    while 1:
-        syntax_data = re.search(
-            r'<code class="([^"\'>]+)">((?:(?:(?:(?!<\/code>|<span ).)*)\n*)+)<\/code>', 
-            data
-        )
-        if syntax_data:
-            syntax_data = syntax_data.groups()
-
-            nowiki_num += 1
-            end_data[include_name + 'nowiki_' + str(nowiki_num)] = syntax_data[1]
-            plus_data += '' + \
-                'if(document.getElementById("' + include_name + 'nowiki_' + str(nowiki_num) + '")) {\n' + \
-                    'document.getElementById("' + include_name + 'nowiki_' + str(nowiki_num) + '").innerHTML = "' + nowiki_js(syntax_data[1]) + '";\n' + \
-                '}\n' + \
-            ''
-
-            data = re.sub(
-                r'<code class="([^"\'>]+)">((?:(?:(?:(?!<\/code>|<span ).)*)\n*)+)<\/code>', 
-                '<code class="' + syntax_data[0] + '"><span id="' + include_name + 'nowiki_' + str(nowiki_num) + '"></span></code>',
-                data,
-                1
-            )
-        else:
-            break
-
-    return data
-
-def namumark(conn, data, title, include_num):
-    curs = conn.cursor()
-
-    global plus_data
-    global end_data
-    global nowiki_num
-    global include_name
-
-    nowiki_num = 0
-    data = '\n' + data + '\n'
-    include_name = (include_num + '_') if include_num else ''
-    now_time = tool.get_time().split()[0]
-    plus_data = ''
-
-    backlink = []
-    end_data = {}
-
-    data = re.sub(r'@((?:(?!(?:=|{{{|}}}|\[\[|\]\]|@)).)+)=(?P<in>(?:(?!(?:=|{{{|}}}|\[\[|\]\]|@)).)+)@', '\g<in>', data)
-    data = re.sub(r'<math>(?P<in>(?:(?!<\/math>).)+)<\/math>', '[math(\g<in>)]', data)
-
-    data = html.escape(data)
-    data = data.replace('\r\n', '\n')
-
-    # 테이블 앞에 공백 있는 경우 처리 필요
-    # 테이블 col 옵션 적용시 셀 병합 고려 필요
-    data = re.sub(r'\n +\|\|', '\n||', data)
-
-    math_re = re.compile(r'\[math\(((?:(?!\)\]).)+)\)\]', re.I)
-    while 1:
-        math = math_re.search(data)
-        if math:
-            math = math.group(1)
-            math = math.replace('{', '<math_mid_1>')
-            math = math.replace('}', '<math_mid_2>')
-            math = math.replace('\\', '<math_slash>')
-
-            data = math_re.sub('<math>' + math + '</math>', data, 1)
-        else:
-            break
-
-    data = data.replace('\\{', '<break_middle>')
-    data = middle_parser(data)
-    data = data.replace('<break_middle>', '\\{')
-
-    first = 0
-    math_re = re.compile(r'<math>((?:(?!<\/math>).)+)<\/math>', re.I)
-    while 1:
-        math = math_re.search(data)
-        if math:
-            math = math.group(1)
-            math = math.replace('<math_mid_1>', '{')
-            math = math.replace('<math_mid_2>', '}')
-            math = math.replace('<math_slash>', '\\')
-
-            first += 1
-            data = math_re.sub('<span id="math_' + str(first) + '"></span>', data, 1)
-
-            plus_data += '' + \
-                'try {\n' + \
-                    'katex.render("' + nowiki_js(html.unescape(math)) + '", document.getElementById(\"' + include_name + 'math_' + str(first) + '\"));\n' + \
-                '} catch {\n' + \
-                    'document.getElementById(\"' + include_name + 'math_' + str(first) + '\").innerHTML = "<span style=\'color: red;\'>' + nowiki_js(math) + '</span>";\n' + \
-                '}\n' + \
-            ''
-        else:
-            break
-
-    num = 0
-    while 1:
-        one_nowiki = re.search(r'(?:\\)(.)', data)
-        if one_nowiki:
-            one_nowiki = one_nowiki.groups()
-
-            nowiki_num += 1
-            end_data[include_name + 'nowiki_' + str(nowiki_num)] = one_nowiki[0]
-            plus_data += '' + \
-                'if(document.getElementById("' + include_name + 'nowiki_' + str(nowiki_num) + '")) {\n' + \
-                    'document.getElementById("' + include_name + 'nowiki_' + str(nowiki_num) + '").innerHTML = "' + nowiki_js(one_nowiki[0]) + '";\n' + \
-                '}\n' + \
-            ''
-
-            data = re.sub(r'(?:\\)(.)', '<span id="' + include_name + 'nowiki_' + str(nowiki_num) + '"></span>', data, 1)
-        else:
-            break
-
-    include_re = re.compile(r'\[include\(((?:(?!\)\]).)+)\)\]', re.I)
-    if include_name == '':
-        i = 0
-        while 1:
-            i += 1
-
-            include = include_re.search(data)
-            if include:
-                include = include.group(1)
-
-                include_data = re.search(r'^((?:(?!,).)+)', include)
-                if include_data:
-                    include_data = include_data.group(1)
-                else:
-                    include_data = 'Test'
-
-                include_link = include_data
-                backlink += [[title, include_link, 'include']]
-
-                data = include_re.sub('' + \
-                    '<a id="' + include_name + 'include_link" class="include_' + str(i) + '" href="/w/' + tool.url_pas(include_link) + '">(' + include_link + ')</a>' + \
-                    '<div id="' + include_name + 'include_' + str(i) + '"></div>' + \
-                '', data, 1)
-
-                include_plus_data = []
-                while 1:
-                    include_plus = re.search(r', ?((?:(?!=).)+)=((?:(?!,).)+)', include)
-                    if include_plus:
-                        include_plus = include_plus.groups()
-
-                        include_data_set = include_plus[1]
-                        find_data = re.findall(r'<span id="((?:include_(?:[0-9]+)_)?(?:nowiki_[0-9]+))">', include_data_set)
-                        for j in find_data:
-                            include_data_set = include_data_set.replace('<span id="' + j + '"></span>', end_data[j])
-
-                        include_plus_data += [[include_plus[0], include_data_set]]
-
-                        include = re.sub(r', ?((?:(?!=).)+)=((?:(?!,).)+)', '', include, 1)
-                    else:
-                        break
-
-                plus_data += '' + \
-                    'load_include(' + \
-                        '"' + include_link + '", '+ \
-                        '"' + include_name + 'include_' + str(i) + '", ' + \
-                        str(include_plus_data) + ', ' + \
-                        '"' + title + '"' + \
-                    ');\n' + \
-                ''
-            else:
-                break
-    else:
-        data = include_re.sub('', data)
-
-    data = data.replace('&amp;', '&')
-    data = re.sub(r'\n##[^\n]+', '', data)
-
-    div_1_re = re.compile(r'<div_1 ([^>]+)>((?:(?!<div_1|<\/div_1>).|\n*)+)<\/div_1>')
-    while 1:
-        wiki_table_data = div_1_re.search(data)
-        if wiki_table_data:
-            wiki_table_data = wiki_table_data.groups()
-            if re.search(r'\|\|', wiki_table_data[1]):
-                end_parser = table_start('\n' + wiki_table_data[1] + '\n')
-                end_parser = re.sub(r'^\n', '', end_parser)
-                end_parser = re.sub(r'\n$', '', end_parser)
-            else:
-                end_parser = wiki_table_data[1]
-
-            data = div_1_re.sub('<div id="wiki_div" ' + wiki_table_data[0] + '>' + end_parser + '</div_2>', data, 1)
-        else:
-            break
-
-    data = data.replace('</div_2>', '</div>')
-    data = data.replace('</td>', '</td_1>')
-
-    data += '\n'
-    data = data.replace('\\', '&#92;')
-
-    redirect_re = re.compile(r'\n#(?:redirect|넘겨주기) ([^\n]+)', re.I)
-    redirect = redirect_re.search(data)
-    if redirect:
-        redirect = redirect.group(1)
-
-        return_link = link_fix(redirect)
-        main_link = html.unescape(return_link[0])
-        other_link = return_link[1]
-
-        backlink += [[title, main_link, 'redirect']]
-        
-        plus_data += '' + \
-            'var get_link = window.location.search.match(/(?:\?|&)from=([^&]+)/);\n' + \
-            'var get_link_2 = window.location.pathname.match(/^\/w\//);\n' + \
-            'if(!get_link && get_link_2) {\n' + \
-                'window.location.href = "/w/' + tool.url_pas(main_link) + '?from=' + tool.url_pas(title) + other_link + '";\n' + \
-            '}\n' + \
-        ''
-        data = redirect_re.sub('\nredirect to ' + html.escape(main_link) + other_link, data, 1)
-
-    no_toc_re = re.compile(r'\[(?:목차|toc)\(no\)\]', re.I)
-    toc_re = re.compile(r'\[(?:목차|toc)\]', re.I)
-    if not no_toc_re.search(data) and not toc_re.search(data):
-        data = re.sub(r'(?P<in>\n(={1,6})(#)? ?((?:(?!(?: #=| =)).)+) ?#?(?:=+)\n)', '\n[toc]\g<in>', data, 1)
-        auto_toc = 1
-    else:
-        data = no_toc_re.sub('', data)
-        auto_toc = 0
-
-    data = '<div class="all_in_data" id="in_data_0">' + data
-
-    toc_stack = [0, 0, 0, 0, 0, 0]
-    toc_num = 0
-    toc_data = '' + \
-        '<div id="toc">' + \
-            '<span id="toc_title">TOC</span>' + \
-            '<br>' + \
-            '<br>' + \
-    ''
-    edit_num = 0
-    toc_head_re = re.compile(r'\n(={1,6})(#)? ?((?:(?!(?: #=| =)).)+) ?#?(?:=+)\n')
-    while 1:
-        toc = toc_head_re.search(data)
-        if toc:
-            toc = toc.groups()
-            edit_num += 1
-
-            toc_len_num = len(toc[0])
-            toc_len_str = str(toc_len_num)
-            toc_len_num -= 1
-            toc_stack[toc_len_num] += 1
-            for i in range(toc_len_num + 1, 6):
-                toc_stack[i] = 0
-
-            edit_num_str = str(edit_num)
-            toc_level_str = '.'.join([str(i) for i in toc_stack if i != 0])
-            toc_fol = '+' if toc[1] else '-'
-
-            data = toc_head_re.sub(
-                '\n' + \
-                '</div>'
-                '<h' + toc_len_str + ' id="s-' + toc_level_str + '">' + \
-                    '<a href="#toc">' + toc_level_str + '.</a> ' + toc[2] + ' ' + \
-                    '<span style="font-size: 12px">' + \
-                        '<a id="edit_load_' + edit_num_str + '" href="/edit/' + tool.url_pas(title) + '?section=' + edit_num_str + '">(Edit)</a>' + \
-                        ' ' + \
-                        '<a href="javascript:void(0);" onclick="do_open_folding(\'in_data_' + edit_num_str + '\', this);">' + \
-                            '(' + toc_fol + ')' + \
-                        '</a>' + \
-                    '</span>' + \
-                '</h' + toc_len_str + '>' + \
-                '<div class="all_in_data"' + (' style="display: none;"' if toc_fol == '+' else '') + ' id="in_data_' + edit_num_str + '">' + \
-                    '\n',
-                data,
-                1
-            )
-
-            toc_main_data = toc[2]
-            toc_main_data = re.sub(r'\[\*((?:(?! |\]).)*)(?: ((?:(?!(\[\*(?:(?:(?!\]).)+)\]|\])).)+))?\]', '', toc_main_data)
-            toc_main_data = re.sub(r'<span id="math_[0-9]"><\/span>', '(Math)', toc_main_data)
-
-            toc_data += '' + \
-                '<span style="margin-left:' + str(len(re.findall(r'\.', toc_level_str)) * 10) + 'px;">' + \
-                    '<a href="#s-' + toc_level_str + '">' + toc_level_str + '.</a> ' + toc_main_data + \
-                '</span>' + \
-                '<br>' + \
-            ''
-        else:
-            break
-
-    toc_data += '</div>'
-    if auto_toc == 1:
-        data = toc_re.sub('<div id="auto_toc">' + toc_data + '</div>', data, 1)
-    else:
-        data = toc_re.sub(toc_data, data)
-    
-    macro_re = re.compile(r'\[([^[(]+)\(((?:(?!\[|\)]).)+)\)\]')
-    macro_data = macro_re.findall(data)
-    for i in macro_data:
-        macro_name = i[0].lower()
-        if macro_name == 'youtube' or macro_name == 'kakaotv' or macro_name == 'nicovideo':
-            width = re.search(r', ?width=((?:(?!,).)+)', i[1])
-            if width:
-                video_width = width.group(1)
-                if re.search(r'^[0-9]+$', video_width):
-                    video_width += 'px'
-            else:
-                video_width = '560px'
-
-            height = re.search(r', ?height=((?:(?!,).)+)', i[1])
-            if height:
-                video_height = height.group(1)
-                if re.search(r'^[0-9]+$', video_height):
-                    video_height += 'px'
-            else:
-                video_height = '315px'
-
-            code = re.search(r'^((?:(?!,).)+)', i[1])
-            if code:
-                video_code = code.group(1)
-            else:
-                video_code = ''
-
-            video_start = ''
-
-            if macro_name == 'youtube':
-                start = re.search(r', ?(start=(?:(?!,).)+)', i[1])
-                if start:
-                    video_start = '?' + start.group(1)
-
-                video_code = re.sub(r'^https:\/\/www\.youtube\.com\/watch\?v=', '', video_code)
-                video_code = re.sub(r'^https:\/\/youtu\.be\/', '', video_code)
-
-                video_src = 'https://www.youtube.com/embed/' + video_code
-            elif macro_name == 'kakaotv':
-                video_code = re.sub(r'^https:\/\/tv\.kakao\.com\/channel\/9262\/cliplink\/', '', video_code)
-                video_code = re.sub(r'^http:\/\/tv\.kakao\.com\/v\/', '', video_code)
-
-                video_src = 'https://tv.kakao.com/embed/player/cliplink/' + video_code +'?service=kakao_tv'
-            else:
-                video_src = 'https://embed.nicovideo.jp/watch/' + video_code
-
-            data = macro_re.sub(
-                '<iframe style="width: ' + video_width + '; height: ' + video_height + ';" src="' + video_src + video_start + '" frameborder="0" allowfullscreen></iframe>', 
-                data, 
-                1
-            )
-        elif macro_name == 'anchor':
-            data = macro_re.sub('<span id="' + i[1] + '"></span>', data, 1)
-        elif macro_name == 'ruby':
-            ruby_code = re.search(r'^([^,]+)', i[1])
-            if ruby_code:
-                ruby_code = ruby_code.group(1)
-            else:
-                ruby_code = 'Test'
-
-            ruby_top = re.search(r'ruby=([^,]+)', i[1], flags = re.I)
-            if ruby_top:
-                ruby_top = ruby_top.group(1)
-            else:
-                ruby_top = 'Test'
-
-            ruby_color = re.search(r'color=([^,]+)', i[1], flags = re.I)
-            if ruby_color:
-                ruby_color = 'color: ' + ruby_color.group(1) + ';'
-            else:
-                ruby_color = ''
-
-            ruby_data = '' + \
-                '<ruby>' + \
-                    ruby_code \
-                    + '<rp>(</rp>' + \
-                    '<rt style="' + ruby_color + '">' + ruby_top + '</rt>' + \
-                    '<rp>)</rp>' + \
-                '</ruby>' + \
-            ''
-
-            data = macro_re.sub(ruby_data, data, 1)
-        elif macro_name == 'age' or macro_name == 'dday':
-            try:
-                old = datetime.datetime.strptime(now_time, '%Y-%m-%d')
-                will = datetime.datetime.strptime(i[1], '%Y-%m-%d')
-
-                e_data = old - will
-
-                if macro_name == 'age':
-                    data = macro_re.sub(str(int(e_data.days / 365)), data, 1)
-                else:
-                    data = macro_re.sub((str(e_data.days) if re.search(r'^-', str(e_data.days)) else ('+' + str(e_data.days))), data, 1)
-            except:
-                data = macro_re.sub('age-dday-error', data, 1)
-        else:
-            data = macro_re.sub('<macro_start>' + i[0] + '<macro_middle>' + i[1] + '<macro_end>', data, 1)
-            
-    data = data.replace('<macro_start>', '[')
-    data = data.replace('<macro_middle>', '(')
-    data = data.replace('<macro_end>', ')]')
-
-    blockquote_re = re.compile(r'(\n(?:&gt; ?(?:[^\n]*)\n)+)')
-    while 1:
-        blockquote = blockquote_re.search(data)
-        if blockquote:
-            blockquote = re.sub(r'^\n&gt; ?', '', blockquote.group(1))
-            blockquote = re.sub(r'\n&gt; ?', '\n', blockquote)
-            blockquote = re.sub(r'\n$', '', blockquote)
-
-            data = blockquote_re.sub('\n<blockquote>' + blockquote + '</blockquote>\n', data, 1)
-        else:
-            break
-
-    hr_re = re.compile(r'\n-{4,9}\n')
-    while 1:
-        if hr_re.search(data):
-            data = hr_re.sub('\n<hr>\n', data, 1)
-        else:
-            break
-
-    data = re.sub(r'(?P<in>\n +\* ?(?:(?:(?!\|\|).)+))\|\|', '\g<in>\n ||', data)
-    data = re.sub(r'(?P<in><div id="folding_(?:[0-9]+)" style="display: none;"><div style="">|<blockquote>)(?P<out> )?\* ', '\g<in>\n\g<out>* ', data)
-
-    li_re = re.compile(r'(\n(?:(?: *)\* (?:[^\n]+)\n)+)')
-    while 1:
-        li_data = li_re.search(data)
-        if li_data:
-            li_data = li_data.group(1)
-            li_end_data = ''
-
-            sub_li = re.findall(r'( *)\* ([^\n]+)\n', li_data)
-            for i in sub_li:
-                li_end_data += '<li style="margin-left: ' + str(20 if len(i[0]) == 0 else (len(i[0]) * 20)) + 'px;">' + i[1] + '</li>'
-
-            data = li_re.sub('\n\n<ul>' + li_end_data + '</ul>\n', data, 1)
-        else:
-            break
-
-    data = re.sub(r'<\/ul>\n \|\|', '</ul>||', data)
-    data = re.sub(r'\|\|</blockquote>', '</blockquote>||', data)
-
-    while 1:
-        indent = re.search(r'\n( +)', data)
-        if indent:
-            data = re.sub(r'\n( +)', '\n' + ('<span style="margin-left: 20px;"></span>' * len(indent.group(1))), data, 1)
-        else:
-            break
-
-    data = table_start(data)
-
-    category = ''
-    link_re = re.compile('\[\[((?:(?!\[\[|\]\]|<\/td>).)+)\]\]')
-    category_re = re.compile(r'^(?:category|분류):', re.I)
-    e_link_id = 0
-    while 1:
-        link = link_re.search(data)
-        if link:
-            link = link.group(1)
-            str_e_link_id = str(e_link_id)
-            e_link_id += 1
-
-            link_split = re.search(r'((?:(?!\|).)+)(?:\|((?:(?!\|).)+))', link)
-            if link_split:
-                link_split = link_split.groups()
-
-                main_link = link_split[0]
-                see_link = link_split[1]
-                inter_same = 0
-            else:
-                main_link = link
-                see_link = link
-                inter_same = 1
-
-            if re.search(r'^((?:file|파일)|(?:out|외부)):', main_link):
-                file_style = ''
-
-                file_width = re.search(r'width=((?:(?!&).)+)', see_link)
-                if file_width:
-                    file_width = file_width.group(1)
-                    if re.search(r'px$', file_width):
-                        file_style += 'width: ' + file_width + ';'
-                    else:
-                        file_style += 'width: ' + file_width + 'px;'
-
-                file_height = re.search(r'height=((?:(?!&).)+)', see_link)
-                if file_height:
-                    file_height = file_height.group(1)
-                    if re.search(r'px$', file_height):
-                        file_style += 'height: ' + file_height + ';'
-                    else:
-                        file_style += 'height: ' + file_height + 'px;'
-
-                file_align = re.search(r'align=((?:(?!&).)+)', see_link)
-                if file_align:
-                    file_align = file_align.group(1)
-                    if file_align == 'center':
-                        file_align = 'display: block; text-align: center;'
-                    else:
-                        file_align = 'float: ' + file_align + ';'
-                else:
-                    file_align = ''
-
-                file_color = re.search(r'bgcolor=((?:(?!&).)+)', see_link)
-                if file_color:
-                    file_color = 'background: ' + file_color.group(1) + '; display: inline-block;'
-                else:
-                    file_color = ''
-
-                file_alt = re.search(r'alt=((?:(?!&).)+)', see_link)
-                if file_alt:
-                    file_alt = file_alt.group(1)
-                else:
-                    file_alt = ''
-
-                if re.search(r'^(?:out|외부):', main_link):
-                    file_src = re.sub(r'^(?:out|외부):', '', main_link)
-
-                    file_alt = main_link if file_alt == '' else file_alt
-                    exist = 'Yes'
-                else:
-                    file_data = re.search(r'^(?:file|파일):((?:(?!\.).)+)\.(.+)$', main_link)
-                    if file_data:
-                        file_data = file_data.groups()
-                        file_name = file_data[0]
-                        file_end = file_data[1]
-
-                        if main_link != title:
-                            backlink += [[title, main_link, 'file']]
-                    else:
-                        file_name = 'TEST'
-                        file_end = 'jpg'
-
-                    file_src = '/image/' + tool.sha224_replace(file_name) + '.' + file_end
-                    file_alt = ('file:' + file_name + '.' + file_end) if file_alt == '' else file_alt
-                    exist = None
-
-                data = link_re.sub(
-                    '<span style="' + file_align + '">' + \
-                        '<span  style="' + file_color + '" ' + \
-                                'class="' + include_name + 'file_finder" ' + \
-                                'under_style="' + file_style + '" ' + \
-                                'under_alt="' + file_alt + '" ' + \
-                                'under_src="' + file_src + '" ' + \
-                                'under_href="' + ("out_link" if exist else '/upload?name=' + tool.url_pas(file_name)) + '">' + \
-                        '</span>' + \
-                    '</span>',
-                    data,
-                    1
-                )
-            elif category_re.search(main_link):
-                if include_name == '':
-                    if category == '':
-                        category += '<div id="cate_all"><div id="cate">Category : '
-
-                    main_link = category_re.sub('category:', main_link)
-                    link_id = ''
-
-                    if re.search(r'#blur', main_link):
-                        link_id = ' hidden_link'
-                        main_link = main_link.replace('#blur', '')
-                        see_link = see_link.replace('#blur', '')
-
-                    backlink += [[title, main_link, 'cat']]
-                    category += '' + \
-                        '<a class="' + include_name + 'link_finder' + link_id + '" ' + \
-                            'href="/w/' + tool.url_pas(main_link) + '">' + \
-                            category_re.sub('', see_link) + \
-                        '</a> | ' + \
-                    ''
-
-                data = link_re.sub('', data, 1)
-            elif re.search(r'^inter:((?:(?!:).)+):', main_link):
-                inter_data = re.search(r'^inter:((?:(?!:).)+):((?:(?!\]\]).)+)', main_link)
-                inter_data = inter_data.groups()
-
-                curs.execute(tool.db_change('select plus, plus_t from html_filter where html = ? and kind = "inter_wiki"'), [inter_data[0]])
-                inter = curs.fetchall()
-                if inter:
-                    return_link = link_fix(inter_data[1], 1)
-                    main_link = html.unescape(return_link[0])
-                    other_link = return_link[1]
-
-                    inter_view = inter[0][1] if inter[0][1] != '' else (inter_data[0] + ':')
-
-                    data = link_re.sub('' + \
-                        '<a id="inside" ' + \
-                            'name="' + include_name + 'set_link_' + str_e_link_id + '" ' + \
-                            'href="">' + inter_view + see_link + '</a>' + \
-                        '', 
-                        data, 
-                        1
-                    )
-                    plus_data += "" + \
-                        "document.getElementsByName('" + include_name + "set_link_" + str_e_link_id + "')[0].href = '" + \
-                            (inter[0][0] + tool.url_pas(main_link) + other_link).replace('\'', '\\\'') + "';" + \
-                        "\n" + \
-                    ""
-                    if inter_same == 1:
-                        plus_data += "" + \
-                            "document.getElementsByName('" + include_name + "set_link_" + str_e_link_id + "')[0].innerHTML = '" + \
-                                (inter_view + main_link + other_link).replace('\'', '\\\'') + "';" + \
-                            "\n" + \
-                        ""
-                else:
-                    data = link_re.sub('', data, 1)
-            elif re.search(r'^(\/(?:.+))$', main_link):
-                under_title = re.search(r'^(\/(?:.+))$', main_link)
-                under_title = under_title.group(1)
-
-                if see_link != main_link:
-                    data = link_re.sub('[[' + title + under_title + '|' + see_link + ']]', data, 1)
-                else:
-                    data = link_re.sub('[[' + title + under_title + ']]', data, 1)
-            elif re.search(r'^http(s)?:\/\/', main_link):
-                data = link_re.sub('' + \
-                    '<a id="out_link" ' + \
-                        'name="' + include_name + 'set_link_' + str_e_link_id + '" ' + \
-                        'rel="nofollow" ' + \
-                        'href="">' + see_link + '</a>' + \
-                    '', 
-                    data, 
-                    1
-                )
-
-                plus_data += "" + \
-                    "document.getElementsByName('" + include_name + "set_link_" + str_e_link_id + "')[0].href = '" + \
-                        main_link.replace('\'', '\\\'') + "';" + \
-                    "\n" + \
-                ""
-                if inter_same == 1:
-                    plus_data += "" + \
-                        "document.getElementsByName('" + include_name + "set_link_" + str_e_link_id + "')[0].innerHTML = '" + \
-                            main_link.replace('\'', '\\\'') + "';" + \
-                        "\n" + \
-                    ""
-            else:
-                return_link = link_fix(main_link)
-                main_link = html.unescape(return_link[0])
-                other_link = return_link[1]
-
-                if re.search(r'^\/', main_link):
-                    main_link = re.sub(r'^\/', title + '/', main_link)
-                elif re.search(r'\.\.\/\/', main_link):
-                    main_link = re.sub(r'\.\.\/\/', '/', main_link)
-                elif re.search(r'^\.\.\/', main_link):
-                    main_link = re.sub(r'^\.\.\/', re.sub(r'(?P<in>.+)\/.*$', '\g<in>', title), main_link)
-
-                if main_link != title and main_link != '':
-                    backlink += [[title, main_link, '']]
-
-                    curs.execute(tool.db_change("select title from data where title = ?"), [main_link])
-                    if not curs.fetchall():
-                        backlink += [[title, main_link, 'no']]
-
-                    data = link_re.sub('' + \
-                        '<a class="' + include_name + 'link_finder" ' + \
-                            'name="' + include_name + 'set_link_' + str_e_link_id + '" ' + \
-                            'title="" ' + \
-                            'href="">' + see_link + '</a>' + \
-                        '', 
-                        data,
-                        1
-                    )
-
-                    plus_data += "" + \
-                        "document.getElementsByName('" + include_name + "set_link_" + str_e_link_id + "')[0].href = '" + \
-                            ('/w/' + tool.url_pas(main_link) + other_link).replace('\'', '\\\'') + "';" + \
-                        "\n" + \
-                    ""
-                    plus_data += "" + \
-                        "document.getElementsByName('" + include_name + "set_link_" + str_e_link_id + "')[0].title = '" + \
-                            (html.escape(main_link) + other_link).replace('\'', '\\\'') + "';" + \
-                        "\n" + \
-                    ""
-                    if inter_same == 1:
-                        plus_data += "" + \
-                            "document.getElementsByName('" + include_name + "set_link_" + str_e_link_id + "')[0].innerHTML = '" + \
-                                (html.escape(main_link) + other_link).replace('\'', '\\\'') + "';" + \
-                            "\n" + \
-                        ""
-                else:
-                    if re.search(r'^#', other_link):
-                        data = link_re.sub(
-                            '<a title="' + other_link + '" href="' + other_link + '">' + (other_link if see_link == other_link else see_link) + '</a>',
-                            data,
-                            1
-                        )
-                    else:
-                        data = link_re.sub('<b>' + see_link + '</b>', data, 1)
-        else:
-            break
-
-    if re.search(r'\[pagecount(?:\([^()]+\))?\]', data, flags = re.I):
-        plus_data += 'page_count();\n'
-        data = re.sub(r'\[pagecount(?:\([^()]+\))?\]', '<span class="all_page_count"></span>', data, flags = re.I)
-
-    data = re.sub(r'\[date\]', now_time, data, flags = re.I)
-    data = re.sub(r'\[clearfix\]', '<div style="clear:both"></div>', data, flags = re.I)
-    data = re.sub(r'\[br\]', '<br>', data, flags = re.I)
-
-    # 각주 기능
-    footnote_number = 0
-    footnote_all = []
-    footnote_dict = {}
-    footnote_re = {}
-    footdata_all = '<ul id="footnote_data">'
-    re_footnote = re.compile(r'(?:\[\*((?:(?! |\]).)*)(?: ((?:(?!(?:\[\*|\])).)+))?\]|(\[(?:각주|footnote)\]))')
-    while 1:
-        footnote = re_footnote.search(data)
-        if footnote:
-            footnote_data = footnote.groups()
-            if footnote_data[2]:
-                footnote_all.sort()
-
-                for footdata in footnote_all:
-                    if footdata[2] == 0:
-                        footdata_in = ''
-                    else:
-                        footdata_in = footdata[2]
-
-                    footdata_all += '' + \
-                        '<li>' + \
-                            '<a href="javascript:do_open_foot(\'' + include_name + 'fn-' + str(footdata[0]) + '\', 1);" ' + \
-                                'id="' + include_name + 'cfn-' + str(footdata[0]) + '">' + \
-                                '(' + footdata[1] + ')' + \
-                            '</a> <span id="' + include_name + 'fn-' + str(footdata[0]) + '">' + footdata_in + '</span>' + \
-                        '</li>' + \
-                    ''
-
-                data = re_footnote.sub(footdata_all + '</ul>', data, 1)
-
-                footnote_all = []
-                footdata_all = '<ul id="footnote_data">'
-            else:
-                footnote = footnote_data[1]
-                footnote_name = footnote_data[0]
-                if footnote_name and not footnote:
-                    if footnote_name in footnote_dict:
-                        footnote_re[footnote_name] += 1
-
-                        foot_plus_num = str(footnote_re[footnote_name])
-                        footshort = footnote_dict[footnote_name] + '.' + foot_plus_num
-
-                        footnote_all += [[float(footshort), footshort, 0]]
-
-                        data = re_footnote.sub('' + \
-                            '<sup>' + \
-                                '<a href="javascript:do_open_foot(\'' + include_name + 'fn-' + footshort + '\', 0);" ' + \
-                                    'id="' + include_name + 'rfn-' + footshort + '">' + \
-                                    '(' + footnote_name + ')' + \
-                                '</a>' + \
-                            '</sup><span id="' + include_name + 'dfn-' + footshort + '"></span>' + \
-                        '', data, 1)
-                    else:
-                        data = re_footnote.sub('<sup><a href="javascript:void(0);">(' + footnote_name + ')</a></sup>', data, 1)
-                else:
-                    footnote_number += 1
-
-                    if not footnote_name:
-                        footnote_name = str(footnote_number)
-
-                    footnote_dict.update({ footnote_name : str(footnote_number) })
-
-                    if not footnote_name in footnote_re:
-                        footnote_re.update({ footnote_name : 0 })
-                    else:
-                        footnote_re[footnote_name] += 1
-
-                    footnote_all += [[footnote_number, footnote_name, footnote]]
-
-                    data = re_footnote.sub('' + \
-                        '<sup>' + \
-                            '<a href="javascript:do_open_foot(\'' + include_name + 'fn-' + str(footnote_number) + '\', 0);" ' + \
-                                'id="' + include_name + 'rfn-' + str(footnote_number) + '">' + \
-                                '(' + footnote_name + ')' + \
-                            '</a>' + \
-                        '</sup><span id="' + include_name + 'dfn-' + str(footnote_number) + '"></span>' + \
-                    '', data, 1)
-        else:
-            break
-
-    data = re.sub(r'\n+$', '', data)
-
-    footnote_all.sort()
-
-    for footdata in footnote_all:
-        if footdata[2] == 0:
-            footdata_in = ''
-        else:
-            footdata_in = str(footdata[2])
-
-        footdata_all += '' + \
-            '<li>' + \
-                '<a href="javascript:do_open_foot(\'' + include_name + 'fn-' + str(footdata[0]) + '\', 1);" ' + \
-                    'id="' + include_name + 'cfn-' + str(footdata[0]) + '">' + \
-                    '(' + str(footdata[1]) + ')' + \
-                '</a> <span id="' + include_name + 'fn-' + str(footdata[0]) + '">' + footdata_in + '</span>' + \
-            '</li>' + \
-        ''
-
-    footdata_all += '</ul>'
-    footdata_all = '' if footdata_all == '<ul id="footnote_data"></ul>' else footdata_all
-    footdata_all = '</div>' + footdata_all    
-
-    data += footdata_all
-
-    # 기본 꾸미기 문법
-    data = re.sub(r'&#x27;&#x27;&#x27;(?P<in>((?!&#x27;&#x27;&#x27;).)+)&#x27;&#x27;&#x27;', '<b>\g<in></b>', data)
-    data = re.sub(r'&#x27;&#x27;(?P<in>((?!&#x27;&#x27;).)+)&#x27;&#x27;', '<i>\g<in></i>', data)
-    data = re.sub(r'~~(?P<in>(?:(?!~~).)+)~~', '<s>\g<in></s>', data)
-    data = re.sub(r'--(?P<in>(?:(?!--).)+)--', '<s>\g<in></s>', data)
-    data = re.sub(r'__(?P<in>(?:(?!__).)+)__', '<u>\g<in></u>', data)
-    data = re.sub(r'\^\^(?P<in>(?:(?!\^\^).)+)\^\^', '<sup>\g<in></sup>', data)
-    data = re.sub(r',,(?P<in>(?:(?!,,).)+),,', '<sub>\g<in></sub>', data)
-
-    # 최종 처리
-    data += (re.sub(r' \| $', '', category) + '</div></div>') if category != '' else ''
-    data = data.replace('<no_table>', '||')
-    data = data.replace('</td_1>', '</td>')
-    data = re.sub(r'<\/ul>\n?', '</ul>', data)
-    data = re.sub(r'<\/pre>\n?', '</pre>', data)
-    data = re.sub(r'(?P<in><div class="all_in_data"(?:(?:(?!id=).)+)? id="in_data_([^"]+)">)(\n)+', '\g<in>', data)
-    data = data.replace('\n\n<ul>', '\n<ul>')
-    data = data.replace('</ul>\n\n', '</ul>')
-    data = re.sub(r'^(\n)+', '', data)
-    data = re.sub(r'(\n)+<ul id="footnote_data">', '<ul id="footnote_data">', data)
-    data = re.sub(r'(?P<in><td(((?!>).)*)>)\n', '\g<in>', data)
-    data = re.sub(r'(\n)?<hr>(\n)?', '<hr>', data)
-    data = data.replace('</ul>\n\n<ul>', '</ul>\n<ul>')
-    data = data.replace('</ul>\n<ul>', '</ul><ul>')
-    data = data.replace('\n</ul>', '</ul>')
-    data = data.replace('\n', '<br>')
-
-    # 파일, 링크, HTML 작동 JS
-    plus_data += '' + \
-        'get_link_state("' + include_name + '");\n' + \
-        'get_file_state("' + include_name + '");\n' + \
-    ''
-    plus_data = 'render_html("' + include_name + 'render_contect");\n' + plus_data
-
-    return [data, plus_data, backlink]

+ 3 - 3
route/topic.py

@@ -52,7 +52,7 @@ def topic_2(conn, topic_num):
                     if u_data:
                         y_check = 1
             else:
-                curs.execute(db_change("select id from user where id = ?"), [match])
+                curs.execute(db_change("select id from user_set where id = ?"), [match])
                 u_data = curs.fetchall()
                 if u_data:
                     y_check = 1
@@ -96,7 +96,7 @@ def topic_2(conn, topic_num):
     else:
         display = 'display: none;' if ban == 1 else ''
         return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), custom(), other2(['(' + load_lang('discussion') + ')', 0])],
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('discussion') + ')', 0])],
             data = '''
                 <h2 id="topic_top_title">''' + html.escape(sub) + '''</h2>
                 <div id="top_topic"></div>
@@ -108,7 +108,7 @@ def topic_2(conn, topic_num):
                 <form style="''' + display + '''" method="post">
                     <textarea id="content" class="topic_content" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
                     <hr class="main_hr">
-                    ''' + captcha_get() + (ip_warring() if display == '' else '') + '''
+                    ''' + captcha_get() + (ip_warning() if display == '' else '') + '''
                     <input style="display: none;" name="topic" value="''' + name + '''">
                     <input style="display: none;" name="title" value="''' + sub + '''">
                     <button id="save" type="submit">''' + load_lang('send') + '''</button>

+ 1 - 1
route/topic_acl.py

@@ -54,7 +54,7 @@ def topic_acl_2(conn, topic_num):
             acl_html_list += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('topic_acl_setting'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('topic_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <form method="post">
                     <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>

+ 7 - 3
route/topic_admin.py

@@ -27,10 +27,14 @@ def topic_admin_2(conn, topic_num, num):
     '''
 
     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]])
+        curs.execute(db_change(
+            "select end from rb where block = ? and ongoing = '1'"
+        ), [data[0][1]])
         user_ban_d = curs.fetchall()
 
         ban += '''
@@ -56,7 +60,7 @@ def topic_admin_2(conn, topic_num, num):
         '''
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('discussion_tool'), wiki_set(), custom(), other2(['(#' + num + ')', 0])],
+        imp = [load_lang('discussion_tool'), wiki_set(), wiki_custom(), wiki_css(['(#' + num + ')', 0])],
         data = ban,
         menu = [['thread/' + topic_num + '#' + num, load_lang('return')]]
     ))

+ 1 - 1
route/topic_change.py

@@ -43,7 +43,7 @@ def topic_change_2(conn, topic_num):
         return redirect('/thread/' + topic_num)
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('topic_name_change'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('topic_name_change'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <form method="post">
                     ''' + load_lang('document_name') + '''

+ 2 - 2
route/topic_close_list.py

@@ -41,7 +41,7 @@ def topic_close_list_2(conn, name):
                 <hr class="main_hr">
                 <textarea rows="10" id="content" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
                 <hr class="main_hr">
-                ''' + captcha_get() + (ip_warring() if display == '' else '') + '''
+                ''' + captcha_get() + (ip_warning() if display == '' else '') + '''
                 <input style="display: none;" name="topic" value="''' + name + '''">
                 <button type="submit">''' + load_lang('send') + '''</button>
                 <button id="preview" type="button" onclick="load_preview(\'''' + url_pas(name) + '\')">' + load_lang('preview') + '''</button>
@@ -72,7 +72,7 @@ def topic_close_list_2(conn, name):
         plus = re.sub(r'^<br>', '', plus)
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [name, wiki_set(), custom(), other2(['(' + sub + ')', 0])],
+        imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + sub + ')', 0])],
         data = div + plus,
         menu = menu
     ))

+ 1 - 1
route/topic_delete.py

@@ -16,7 +16,7 @@ def topic_delete_2(conn, topic_num):
         return redirect('/')
     else:
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('topic_delete'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('topic_delete'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <hr class=\"main_hr\">
                 <form method="post">

+ 1 - 1
route/topic_stop.py

@@ -67,7 +67,7 @@ def topic_stop_2(conn, topic_num):
         agree_check = 'checked="checked"' if rd_d[0][1] == 'O' else ''
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('topic_setting'), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('topic_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = '''
                 <form method="post">
                     <select name="stop_d">

+ 1 - 1
route/topic_tool.py

@@ -55,7 +55,7 @@ def topic_tool_2(conn, topic_num):
         '''
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('topic_tool'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('topic_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = data,
         menu = [['thread/' + topic_num, load_lang('return')]]
     ))

+ 3 - 6
route/alarm.py → route/user_alarm.py

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

+ 0 - 0
route/alarm_del.py → route/user_alarm_del.py


+ 2 - 2
route/user_count_edit.py

@@ -23,11 +23,11 @@ def user_count_edit_2(conn, name):
         t_data = 0
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('count'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('count'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = '''
             <ul class="inside_ul">
                 <li><a href="/record/''' + url_pas(that) + '''">''' + load_lang('edit_record') + '''</a> : ''' + str(data) + '''</li>
-                <li><a href="/topic_record/''' + url_pas(that) + '''">''' + load_lang('discussion_record') + '''</a> : ''' + str(t_data) + '''</a></li>
+                <li><a href="/record/topic/''' + url_pas(that) + '''">''' + load_lang('discussion_record') + '''</a> : ''' + str(t_data) + '''</a></li>
             </ul>
         ''',
         menu = [['user', load_lang('return')]]

+ 2 - 2
route/user_custom_head_view.py

@@ -28,7 +28,7 @@ def user_custom_head_view_2(conn):
             data = head_data[0][0] if head_data else ''
         else:
             start = '' + \
-                '<span>' + load_lang('user_head_warring') + '</span>' + \
+                '<span>' + load_lang('user_head_warning') + '</span>' + \
                 '<hr class="main_hr">' + \
             ''
             data = flask.session['head'] if 'head' in flask.session else ''
@@ -43,7 +43,7 @@ def user_custom_head_view_2(conn):
         ''
 
         return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang(data = 'user_head', safe = 1), wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang(data = 'user_head', safe = 1), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             data = start + '''
                 <form method="post">
                     <textarea rows="25" cols="100" name="content">''' + data + '''</textarea>

+ 1 - 1
route/user_info.py

@@ -35,7 +35,7 @@ def user_info_2(conn):
             plus += '<li><a href="/pass_find">' + load_lang('password_search') + '</a></li>'
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('user_tool'), wiki_set(), custom(), other2([0, 0])],
+        imp = [load_lang('user_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
         data = '''
             <h2>''' + load_lang('state') + '''</h2>
             <div id="get_user_info"></div>

+ 36 - 20
route/user_setting.py

@@ -3,7 +3,7 @@ from .tool.func import *
 def user_setting_2(conn, server_init):
     curs = conn.cursor()
 
-    support_language = ['default'] + server_init.server_set_var['language']['list']
+    support_language = ['default'] + server_init.server_init()['language']['list']
     ip = ip_check()
 
     if ban_check() == 1:
@@ -23,7 +23,7 @@ def user_setting_2(conn, server_init):
                 twofa_pw = flask.request.form.get('2fa_pw', '')
                 if twofa_pw != '':
                     twofa_pw = pw_encode(twofa_pw)
-                    curs.execute(db_change("select encode from user where id = ?"), [ip])
+                    curs.execute(db_change("select data from user_set where id = ? and name = 'encode'"), [ip])
                     twofa_encode = curs.fetchall()[0][0]
                     auto_list += [['2fa', 'on'], ['2fa_pw', twofa_pw], ['2fa_pw_encode', twofa_encode]]
                 else:
@@ -46,13 +46,14 @@ def user_setting_2(conn, server_init):
             data = curs.fetchall()
             email = data[0][0] if data else '-'
 
-            div2 = load_skin('', 0, 1)
-            div3 = ''
+            curs.execute(db_change('select data from user_set where name = "skin" and id = ?'), [ip])
+            data = curs.fetchall()
+            div2 = load_skin(data[0][0] if data else '', 0, 1)
 
-            curs.execute(db_change('select data from user_set where name = "lang" and id = ?'), [ip_check()])
+            curs.execute(db_change('select data from user_set where name = "lang" and id = ?'), [ip])
             data = curs.fetchall()
             data = [['default']] if not data else data
-
+            div3 = ''
             for lang_data in support_language:
                 see_data = lang_data if lang_data != 'default' else load_lang('default')
                 
@@ -63,21 +64,30 @@ def user_setting_2(conn, server_init):
 
             curs.execute(db_change('select data from user_set where name = "2fa" and id = ?'), [ip])
             fa_data = curs.fetchall()
-            fa_data = 'checked' if fa_data and fa_data[0][0] != '' else ''
+            fa_data = fa_data[0][0] if fa_data and fa_data[0][0] != '' else ''
+            fa_data_select = ''
+            fa_data_sp_list = [['off', ''], ['pw', 'on']]
+            for fa_data_get in fa_data_sp_list:
+                fa_data_selected = ''
+                if fa_data == fa_data_get[1]:
+                    fa_data_selected = 'selected'
+                
+                fa_data_select += '<option ' + fa_data_selected + ' value="' + fa_data_get[1] + '">' + fa_data_get[0] + '</option>'
 
             curs.execute(db_change('select data from user_set where name = "2fa_pw" and id = ?'), [ip])
             fa_data_pw = curs.fetchall()
             fa_data_pw = load_lang('2fa_password_change') if fa_data_pw else load_lang('2fa_password')
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('user_setting'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('user_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <form method="post">
-                        <span>''' + load_lang('id') + ''' : ''' + ip_pas(ip) + '''</span>
+                        <div id="get_user_info"></div>
+                        <script>load_user_info("''' + ip + '''");</script>
                         <hr class="main_hr">
-                        <a href="/pw_change">(''' + load_lang('password_change') + ''')</a>
+                        <a href="/change/pw">(''' + load_lang('password_change') + ''')</a>
                         <hr class="main_hr">
-                        <span>''' + load_lang('email') + ''' : ''' + email + '''</span> <a href="/email_change">(''' + load_lang('email_change') + ''')</a>
+                        <span>''' + load_lang('email') + ''' : ''' + email + '''</span> <a href="/change/email">(''' + load_lang('email_change') + ''')</a>
                         <h2>''' + load_lang('main') + '''</h2>
                         <span>''' + load_lang('skin') + '''</span>
                         <hr class="main_hr">
@@ -87,14 +97,16 @@ def user_setting_2(conn, server_init):
                         <hr class="main_hr">
                         <select name="lang">''' + div3 + '''</select>
                         <h2>''' + load_lang('2fa') + '''</h2>
-                        <input type="checkbox" id="twofa_check_input" onclick="do_twofa_check(0);" name="2fa" value="on" ''' + fa_data + '''> ''' + load_lang('on') + '''
+                        <select name="2fa"
+                                id="twofa_check_input"
+                                onchange="do_twofa_check(0);">''' + fa_data_select + '''</select>
                         <div id="fa_plus_content">
                             <hr class="main_hr">
                             <input type="password" name="2fa_pw" placeholder="''' + fa_data_pw + '''">
                         </div>
                         <hr class="main_hr">
                         <button type="submit">''' + load_lang('save') + '''</button>
-                        ''' + http_warring() + '''
+                        ''' + http_warning() + '''
                         <script>do_twofa_check(1);</script>
                     </form>
                 ''',
@@ -107,11 +119,14 @@ def user_setting_2(conn, server_init):
             
             return redirect('/change')
         else:
-            div2 = load_skin(('' if not 'skin' in flask.session else flask.session['skin']), 0, 1)
-            div3 = ''
+            div2 = load_skin(
+                ('' if not 'skin' in flask.session else flask.session['skin']), 
+                0, 
+                1
+            )
 
             data = [['default']] if not 'lang' in flask.session else [[flask.session['lang']]]
-
+            div3 = ''
             for lang_data in support_language:
                 see_data = lang_data if lang_data != 'default' else load_lang('default')
                 
@@ -121,10 +136,11 @@ def user_setting_2(conn, server_init):
                     div3 += '<option value="' + lang_data + '">' + see_data + '</option>'
             
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('user_setting'), wiki_set(), custom(), other2([0, 0])],
+                imp = [load_lang('user_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <form method="post">
-                        <span>''' + load_lang('id') + ''' : ''' + ip_pas(ip) + '''</span>
+                        <div id="get_user_info"></div>
+                        <script>load_user_info("''' + ip + '''");</script>
                         <hr class="main_hr">
                         <h2>''' + load_lang('main') + '''</h2>
                         <span>''' + load_lang('skin') + '''</span>
@@ -136,9 +152,9 @@ def user_setting_2(conn, server_init):
                         <select name="lang">''' + div3 + '''</select>
                         <hr class="main_hr">
                         <button type="submit">''' + load_lang('save') + '''</button>
-                        ''' + http_warring() + '''
+                        ''' + http_warning() + '''
                         <hr class="main_hr">
-                        <span>''' + load_lang('user_head_warring') + '''</span>
+                        <span>''' + load_lang('user_head_warning') + '''</span>
                     </form>
                 ''',
                 menu = [['user', load_lang('return')]]

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio