Sfoglia il codice sorgente

Merge pull request #1701 from openNAMU/beta

모르겠다
잉여개발기 (SPDV) 3 anni fa
parent
commit
90831b9710
100 ha cambiato i file con 6370 aggiunte e 3192 eliminazioni
  1. 26 10
      .dockerignore
  2. 14 8
      .github/ISSUE_TEMPLATE.md
  3. 5 4
      .gitignore
  4. 3 3
      Docker-Install.md
  5. 2 1
      Dockerfile
  6. 2 1
      Dockerfile.arm64v8
  7. 21 0
      Dockerfile.arm64v8.ko
  8. 21 0
      Dockerfile.ko
  9. 287 192
      app.py
  10. 5 0
      docker_build.bat
  11. 59 11
      emergency_tool.py
  12. 103 17
      lang/en-US.json
  13. 89 14
      lang/ko-KR.json
  14. 1 1
      readme.md
  15. 0 1
      requirements.txt
  16. 18 0
      route/api_func_lang.py
  17. 18 0
      route/api_func_sha224.py
  18. 18 17
      route/api_image_view.py
  19. 0 12
      route/api_markup.py
  20. 0 17
      route/api_sha224.py
  21. 0 56
      route/api_sitemap.py
  22. 76 0
      route/api_topic.py
  23. 0 65
      route/api_topic_sub.py
  24. 54 76
      route/api_user_info.py
  25. 211 89
      route/edit.py
  26. 2 2
      route/edit_delete.py
  27. 4 4
      route/edit_delete_multiple.py
  28. 148 31
      route/edit_move.py
  29. 2 2
      route/edit_revert.py
  30. 18 11
      route/edit_upload.py
  31. 1 1
      route/filter_inter_wiki.py
  32. 2 2
      route/filter_inter_wiki_add.py
  33. 171 113
      route/give_acl.py
  34. 56 55
      route/give_admin.py
  35. 57 57
      route/give_admin_groups.py
  36. 22 21
      route/give_delete_admin_group.py
  37. 124 101
      route/give_user_ban.py
  38. 163 162
      route/give_user_check.py
  39. 44 43
      route/give_user_check_delete.py
  40. 31 30
      route/list_acl.py
  41. 19 18
      route/list_admin.py
  42. 27 26
      route/list_admin_group.py
  43. 44 33
      route/list_admin_use.py
  44. 17 19
      route/list_image_file.py
  45. 18 17
      route/list_long_page.py
  46. 4 8
      route/list_old_page.py
  47. 24 23
      route/list_please.py
  48. 52 65
      route/list_title_index.py
  49. 20 19
      route/list_user.py
  50. 11 10
      route/login_find.py
  51. 62 59
      route/login_login.py
  52. 58 57
      route/login_login_2fa.py
  53. 53 52
      route/login_login_2fa_email.py
  54. 4 3
      route/login_logout.py
  55. 120 113
      route/login_register.py
  56. 56 55
      route/login_register_email.py
  57. 43 42
      route/login_register_email_check.py
  58. 59 57
      route/login_register_submit.py
  59. 11 4
      route/main_error_404.py
  60. 35 0
      route/main_func_easter_egg.py
  61. 18 15
      route/main_func_setting.py
  62. 32 16
      route/main_func_setting_acl.py
  63. 9 10
      route/main_func_setting_external.py
  64. 29 20
      route/main_func_setting_head.py
  65. 65 30
      route/main_func_setting_main.py
  66. 1 1
      route/main_func_setting_main_logo.py
  67. 55 47
      route/main_func_setting_phrase.py
  68. 25 37
      route/main_func_setting_robot.py
  69. 116 0
      route/main_func_setting_sitemap.py
  70. 51 0
      route/main_func_setting_top_menu.py
  71. 2 1
      route/main_search.py
  72. 34 34
      route/main_search_deep.py
  73. 26 25
      route/main_sys_restart.py
  74. 20 17
      route/main_sys_shutdown.py
  75. 6 6
      route/main_sys_update.py
  76. 52 107
      route/main_tool_admin.py
  77. 0 0
      route/main_tool_guide.py
  78. 28 30
      route/main_tool_other.py
  79. 61 0
      route/main_tool_redirect.py
  80. 27 23
      route/main_view.py
  81. 21 8
      route/main_view_file.py
  82. 13 12
      route/main_view_image.py
  83. 138 137
      route/recent_app_submit.py
  84. 128 129
      route/recent_block.py
  85. 19 7
      route/recent_change.py
  86. 27 4
      route/recent_discuss.py
  87. 36 11
      route/recent_history_add.py
  88. 7 7
      route/recent_history_tool.py
  89. 499 192
      route/tool/func.py
  90. 53 163
      route/tool/func_render.py
  91. 1897 80
      route/tool/func_render_namumark.py
  92. 14 0
      route/tool/func_tool.py
  93. 138 60
      route/topic.py
  94. 6 3
      route/topic_comment_blind.py
  95. 7 3
      route/topic_comment_notice.py
  96. 8 5
      route/topic_comment_tool.py
  97. 5 10
      route/topic_list.py
  98. 31 10
      route/topic_tool.py
  99. 42 13
      route/topic_tool_acl.py
  100. 9 9
      route/topic_tool_change.py

+ 26 - 10
.dockerignore

@@ -1,18 +1,34 @@
-.git
-.gitignore
-Dockerfile
-.dockerignore
-*.md
-
-set_mark/__pycache__
-/__pycache__
+__pycache__
 /app_session
 /app_session
+
+data/set.json
+data/mysql.json
+data/oauthsettings.json
+data/version.json
+
+route/tool/set_mark/custom.py
+
+images
+
 .vscode
 .vscode
+goorm.manifest
+.DS_Store
 
 
 *.db
 *.db
+*.db-shm
+*.db-wal
+*.db-journal
+
+robots.txt
+custom.py
+404.html
 
 
 views/liberty
 views/liberty
-views/yousoro
-views/super_lite
 views/buma
 views/buma
 views/before_namu
 views/before_namu
+views/acme
+views/sl_open
+views/nitori
+
+sitemap.xml
+sitemap_0.xml

+ 14 - 8
.github/ISSUE_TEMPLATE.md

@@ -1,13 +1,19 @@
-## Environment (환경)
-* OS :
-* Python version :
-* openNAMU version :
-* Skin : 
-* Skin version : 
+## 환경 (Environment)
+* 운영체제 (OS) :
+* 파이썬 버전 (Python version) :
+* 오픈나무 버전 (openNAMU version) :
+* 사용하는 브랜치 (Branch that you use) :
+* 스킨 (Skin) : 
+* 스킨 버전 (Skin version) : 
 
 
 <!-- 무언가 작동 안할 때는 캐시 초기화를 먼저 해보세요. -->
 <!-- 무언가 작동 안할 때는 캐시 초기화를 먼저 해보세요. -->
 <!-- Try initializing the cache first when something isn't working. -->
 <!-- Try initializing the cache first when something isn't working. -->
 
 
-## Explanation (설명)
+## 설명 (Explanation)
 
 
-## Screenshot (스크린샷)
+## 오류 내용 (Error contents)
+
+## 스크린샷 (Screenshot)
+
+<!-- 다 작성해주시면 오류 해결에 좀 더 빠른 시간이 소요됩니다. -->
+<!-- If you fill it out, it will take faster time to resolve the error. -->

+ 5 - 4
.gitignore

@@ -9,7 +9,11 @@ data/version.json
 route/tool/set_mark/custom.py
 route/tool/set_mark/custom.py
 
 
 images
 images
+
 .vscode
 .vscode
+.vs
+goorm.manifest
+.DS_Store
 
 
 *.db
 *.db
 *.db-shm
 *.db-shm
@@ -20,8 +24,6 @@ robots.txt
 custom.py
 custom.py
 404.html
 404.html
 
 
-goorm.manifest
-
 views/liberty
 views/liberty
 views/buma
 views/buma
 views/before_namu
 views/before_namu
@@ -29,6 +31,5 @@ views/acme
 views/sl_open
 views/sl_open
 views/nitori
 views/nitori
 
 
-.DS_Store
 sitemap.xml
 sitemap.xml
-sitemap_0.xml
+sitemap_0.xml

+ 3 - 3
Docker-Install.md

@@ -1,10 +1,10 @@
 ## Installation
 ## Installation
 ```
 ```
-docker pull opennamu/stable
+docker pull opennamu/opennamu
 ```
 ```
 
 
 ## Start
 ## Start
 ```
 ```
-docker run -p 3000:3000 -v data:/app/data --name opennamu opennamu/stable
-docker run -p <host-port>:3000 -v <host-data_directory>:/app/data --name <docker-containername> opennamu/stable
+docker run -p 3000:3000 -v data:/app/data --name opennamu opennamu/opennamu
+docker run -p <host-port>:3000 -v <host-data_directory>:/app/data --name <docker-containername> opennamu/opennamu
 ```
 ```

+ 2 - 1
Dockerfile

@@ -1,4 +1,4 @@
-FROM python:3.6.8-stretch
+FROM python:3.10.5-alpine
 
 
 MAINTAINER 2du <min08101@naver.com>
 MAINTAINER 2du <min08101@naver.com>
 MAINTAINER hoparkgo9ma <me@ho9.me>
 MAINTAINER hoparkgo9ma <me@ho9.me>
@@ -10,6 +10,7 @@ ENV NAMU_PORT 3000
 ENV NAMU_LANG en-US
 ENV NAMU_LANG en-US
 ENV NAMU_MARKUP namumark
 ENV NAMU_MARKUP namumark
 ENV NAMU_ENCRYPT sha3
 ENV NAMU_ENCRYPT sha3
+ENV NAMU_DOCKER O
 
 
 ADD . /app
 ADD . /app
 WORKDIR /app
 WORKDIR /app

+ 2 - 1
Dockerfile.arm64v8

@@ -1,4 +1,4 @@
-FROM arm64v8/python:3.6.8-stretch
+FROM arm64v8/3.10.5-alpine
 
 
 MAINTAINER 2du <min08101@naver.com>
 MAINTAINER 2du <min08101@naver.com>
 MAINTAINER hoparkgo9ma <me@ho9.me>
 MAINTAINER hoparkgo9ma <me@ho9.me>
@@ -10,6 +10,7 @@ ENV NAMU_PORT 3000
 ENV NAMU_LANG en-US
 ENV NAMU_LANG en-US
 ENV NAMU_MARKUP namumark
 ENV NAMU_MARKUP namumark
 ENV NAMU_ENCRYPT sha3
 ENV NAMU_ENCRYPT sha3
+ENV NAMU_DOCKER O
 
 
 ADD . /app
 ADD . /app
 WORKDIR /app
 WORKDIR /app

+ 21 - 0
Dockerfile.arm64v8.ko

@@ -0,0 +1,21 @@
+FROM arm64v8/3.10.5-alpine
+
+MAINTAINER 2du <min08101@naver.com>
+MAINTAINER hoparkgo9ma <me@ho9.me>
+
+ENV NAMU_DB_TYPE sqlite
+ENV NAMU_DB data
+ENV NAMU_HOST 0.0.0.0
+ENV NAMU_PORT 3000
+ENV NAMU_LANG ko-KR
+ENV NAMU_MARKUP namumark
+ENV NAMU_ENCRYPT sha3
+ENV NAMU_DOCKER O
+
+ADD . /app
+WORKDIR /app
+
+RUN pip install -r requirements.txt
+EXPOSE 3000
+
+CMD [ "python", "./app.py" ]

+ 21 - 0
Dockerfile.ko

@@ -0,0 +1,21 @@
+FROM python:3.10.5-alpine
+
+MAINTAINER 2du <min08101@naver.com>
+MAINTAINER hoparkgo9ma <me@ho9.me>
+
+ENV NAMU_DB_TYPE sqlite
+ENV NAMU_DB data
+ENV NAMU_HOST 0.0.0.0
+ENV NAMU_PORT 3000
+ENV NAMU_LANG ko-KR
+ENV NAMU_MARKUP namumark
+ENV NAMU_ENCRYPT sha3
+ENV NAMU_DOCKER O
+
+ADD . /app
+WORKDIR /app
+
+RUN pip install -r requirements.txt
+EXPOSE 3000
+
+CMD [ "python", "./app.py" ]

+ 287 - 192
app.py

@@ -35,163 +35,236 @@ data_db_set = class_check_json()
 
 
 db_data_get(data_db_set['type'])
 db_data_get(data_db_set['type'])
 do_db_set(data_db_set)
 do_db_set(data_db_set)
-load_db = get_db_connect_old(data_db_set)
-
-conn = load_db.db_load()
-curs = conn.cursor()
-
-setup_tool = ''
-try:
-    curs.execute(db_change('select data from other where name = "ver"'))
-except:
-    setup_tool = 'init'
-
-if setup_tool != 'init':
-    ver_set_data = curs.fetchall()
-    if ver_set_data:
-        if int(version_list['beta']['c_ver']) > int(ver_set_data[0][0]):
-            setup_tool = 'update'
-        else:
-            setup_tool = 'normal'
-    else:
+
+with get_db_connect() as conn:
+    curs = conn.cursor()
+
+    setup_tool = ''
+    try:
+        curs.execute(db_change('select data from other where name = "ver"'))
+    except:
         setup_tool = 'init'
         setup_tool = 'init'
 
 
-if setup_tool != 'normal':
-    create_data = get_db_table_list()
-    for create_table in create_data:
-        for create in ['test'] + create_data[create_table]:
+    if setup_tool != 'init':
+        ver_set_data = curs.fetchall()
+        if ver_set_data:
+            if int(version_list['beta']['c_ver']) > int(ver_set_data[0][0]):
+                setup_tool = 'update'
+            else:
+                setup_tool = 'normal'
+        else:
+            setup_tool = 'init'
+
+    if data_db_set['type'] == 'mysql':
+        try:
+            curs.execute(db_change(
+                'create database ' + data_db_set['name'] + ' ' + \
+                'default character set utf8mb4'
+            ))
+        except:
             try:
             try:
-                curs.execute(db_change('select ' + create + ' from ' + create_table + ' limit 1'))
+                curs.execute(db_change(
+                    'alter database ' + data_db_set['name'] + ' ' + \
+                    'character set utf8mb4'
+                ))
             except:
             except:
+                pass
+
+    if setup_tool != 'normal':
+        create_data = get_db_table_list()
+        for create_table in create_data:
+            for create in ['test'] + create_data[create_table]:
+                db_pass = 0
+
                 try:
                 try:
-                    curs.execute(db_change('create table ' + create_table + '(test longtext default "")'))
+                    curs.execute(db_change('select ' + create + ' from ' + create_table + ' limit 1'))
+
+                    db_pass = 1
                 except:
                 except:
-                    curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext default ''"))
-
-    if setup_tool == 'update':
-        update(int(ver_set_data[0][0]), set_data)
-    else:
-        set_init()
-
-set_init_always(version_list['beta']['c_ver'])
-
-# Init-Route
-class EverythingConverter(werkzeug.routing.PathConverter):
-    regex = r'.*?'
-
-class RegexConverter(werkzeug.routing.BaseConverter):
-    def __init__(self, url_map, *items):
-        super(RegexConverter, self).__init__(url_map)
-        self.regex = items[0]
-
-app = flask.Flask(
-    __name__, 
-    template_folder = './'
-)
-
-app.config['JSON_AS_ASCII'] = False
-app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
-
-log = logging.getLogger('waitress')
-log.setLevel(logging.ERROR)
-
-app.jinja_env.filters['md5_replace'] = md5_replace
-app.jinja_env.filters['load_lang'] = load_lang
-app.jinja_env.filters['cut_100'] = cut_100
-
-app.url_map.converters['everything'] = EverythingConverter
-app.url_map.converters['regex'] = RegexConverter
-
-curs.execute(db_change('select data from other where name = "key"'))
-sql_data = curs.fetchall()
-app.secret_key = sql_data[0][0]
-
-print('----')
-
-# Init-DB_Data
-server_set = {}
-server_set_var = get_init_set_list()
-server_set_env = {
-    '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')
-}
-for i in server_set_var:
-    curs.execute(db_change('select data from other where name = ?'), [i])
-    server_set_val = curs.fetchall()
-    if server_set_val:
-        server_set_val = server_set_val[0][0]
-    elif server_set_env[i] != None:
-        server_set_val = server_set_env[i]
-    else:
-        if 'list' in server_set_var[i]:
-            print(server_set_var[i]['display'] + ' (' + server_set_var[i]['default'] + ') [' + ', '.join(server_set_var[i]['list']) + ']' + ' : ', end = '')
-        else:
-            print(server_set_var[i]['display'] + ' (' + server_set_var[i]['default'] + ') : ', end = '')
+                    pass
 
 
-        server_set_val = input()
-        if server_set_val == '':
-            server_set_val = server_set_var[i]['default']
-        elif server_set_var[i]['require'] == 'select':
-            if not server_set_val in server_set_var[i]['list']:
-                server_set_val = server_set_var[i]['default']
+                if db_pass == 0:
+                    try:
+                        curs.execute(db_change('create table ' + create_table + '(test longtext default (""))'))
 
 
-        curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, server_set_val])
+                        db_pass = 1
+                    except:
+                        pass
 
 
-    print(server_set_var[i]['display'] + ' : ' + server_set_val)
+                if db_pass == 0:
+                    try:
+                        curs.execute(db_change('create table ' + create_table + '(test longtext default "")'))
 
 
-    server_set[i] = server_set_val
+                        db_pass = 1
+                    except:
+                        pass
 
 
-print('----')
+                if db_pass == 0:
+                    try:
+                        curs.execute(db_change('create table ' + create_table + '(test longtext)'))
 
 
-# Init-DB_care
-if data_db_set['type'] == 'sqlite':
-    def back_up(back_time, back_up_where):
-        print('----')
+                        db_pass = 1
+                    except:
+                        pass
 
 
-        try:
-            shutil.copyfile(
-                data_db_set['name'] + '.db', 
-                back_up_where
-            )
+                if db_pass == 0:
+                    try:
+                        curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext default ('')"))
+
+                        db_pass = 1
+                    except:
+                        pass
+
+                if db_pass == 0:
+                    try:
+                        curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext default ''"))
+
+                        db_pass = 1
+                    except:
+                        pass
 
 
-            print('Back up : OK')
+                if db_pass == 0:
+                    try:
+                        curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext"))
+
+                        db_pass = 1
+                    except:
+                        pass
+
+                if db_pass == 0:
+                    raise
+        try:
+            curs.execute(db_change("create index history_index on history (title, ip)"))
         except:
         except:
-            print('Back up : Error')
-
-        threading.Timer(
-            60 * 60 * back_time, 
-            back_up,
-            [back_time, back_up_where]
-        ).start()
-
-    curs.execute(db_change('select data from other where name = "back_up"'))
-    back_time = curs.fetchall()
-    back_time = int(number_check(back_time[0][0])) if back_time else 0
-    if back_time != 0:
-        curs.execute(db_change('select data from other where name = "backup_where"'))
-        back_up_where = curs.fetchall()
-        if back_up_where and back_up_where[0][0] != '':
-            back_up_where = back_up_where[0][0]
+            pass
+
+        if setup_tool == 'update':
+            update(int(ver_set_data[0][0]), set_data)
+        else:
+            set_init()
+
+    set_init_always(version_list['beta']['c_ver'])
+
+    # Init-Route
+    class EverythingConverter(werkzeug.routing.PathConverter):
+        regex = r'.*?'
+
+    class RegexConverter(werkzeug.routing.BaseConverter):
+        def __init__(self, url_map, *items):
+            super(RegexConverter, self).__init__(url_map)
+            self.regex = items[0]
+
+    app = flask.Flask(
+        __name__, 
+        template_folder = './'
+    )
+
+    app.config['JSON_AS_ASCII'] = False
+    app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
+
+    log = logging.getLogger('waitress')
+    log.setLevel(logging.ERROR)
+
+    app.jinja_env.filters['md5_replace'] = md5_replace
+    app.jinja_env.filters['load_lang'] = load_lang
+    app.jinja_env.filters['cut_100'] = cut_100
+
+    app.url_map.converters['everything'] = EverythingConverter
+    app.url_map.converters['regex'] = RegexConverter
+
+    curs.execute(db_change('select data from other where name = "key"'))
+    sql_data = curs.fetchall()
+    app.secret_key = sql_data[0][0]
+
+    print('----')
+
+    # Init-DB_Data
+    server_set = {}
+    server_set_var = get_init_set_list()
+    server_set_env = {
+        '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')
+    }
+    for i in server_set_var:
+        curs.execute(db_change('select data from other where name = ?'), [i])
+        server_set_val = curs.fetchall()
+        if server_set_val:
+            server_set_val = server_set_val[0][0]
+        elif server_set_env[i] != None:
+            server_set_val = server_set_env[i]
+
+            curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i, server_set_env[i]])
         else:
         else:
-            back_up_where = 'back_' + data_db_set['name'] + '.db'
+            if 'list' in server_set_var[i]:
+                print(server_set_var[i]['display'] + ' (' + server_set_var[i]['default'] + ') [' + ', '.join(server_set_var[i]['list']) + ']' + ' : ', end = '')
+            else:
+                print(server_set_var[i]['display'] + ' (' + server_set_var[i]['default'] + ') : ', end = '')
 
 
-        print('Back up state : ' + str(back_time) + ' hours')
+            server_set_val = input()
+            if server_set_val == '':
+                server_set_val = server_set_var[i]['default']
+            elif server_set_var[i]['require'] == 'select':
+                if not server_set_val in server_set_var[i]['list']:
+                    server_set_val = server_set_var[i]['default']
 
 
-        back_up(back_time, back_up_where)
-    else:
-        print('Back up state : Turn off')
+            curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i, server_set_val])
 
 
-print('Now running... http://localhost:' + server_set['port'])
-conn.commit()
+        print(server_set_var[i]['display'] + ' : ' + server_set_val)
+
+        server_set[i] = server_set_val
+
+    print('----')
+
+    # Init-DB_care
+    if data_db_set['type'] == 'sqlite':
+        def back_up(back_time, back_up_where):
+            print('----')
+
+            try:
+                shutil.copyfile(
+                    data_db_set['name'] + '.db', 
+                    back_up_where
+                )
+
+                print('Back up : OK')
+            except:
+                print('Back up : Error')
+
+            threading.Timer(
+                60 * 60 * back_time, 
+                back_up,
+                [back_time, back_up_where]
+            ).start()
+
+        curs.execute(db_change('select data from other where name = "back_up"'))
+        back_time = curs.fetchall()
+        back_time = int(number_check(back_time[0][0])) if back_time and back_time != '' else 0
+        if back_time != 0:
+            curs.execute(db_change('select data from other where name = "backup_where"'))
+            back_up_where = curs.fetchall()
+            if back_up_where and back_up_where[0][0] != '':
+                back_up_where = back_up_where[0][0]
+            else:
+                back_up_where = 'back_' + data_db_set['name'] + '.db'
+
+            print('Back up state : ' + str(back_time) + ' hours')
+
+            back_up(back_time, back_up_where)
+        else:
+            print('Back up state : Turn off')
+
+    print('Now running... http://localhost:' + server_set['port'])
+    
+    conn.commit()
 
 
 # Init-custom
 # Init-custom
 if os.path.exists('custom.py'):
 if os.path.exists('custom.py'):
     from custom import custom_run
     from custom import custom_run
-    custom_run(load_db.db_get(), app)
-    
+    custom_run('error', app)
+
 # Func
 # Func
 # Func-inter_wiki
 # Func-inter_wiki
 app.route('/inter_wiki', defaults = { 'tool' : 'inter_wiki' })(filter_inter_wiki)
 app.route('/inter_wiki', defaults = { 'tool' : 'inter_wiki' })(filter_inter_wiki)
@@ -235,101 +308,100 @@ app.route('/extension_filter/add', methods = ['POST', 'GET'], defaults = { 'tool
 
 
 # Func-list
 # Func-list
 # /list/document/old
 # /list/document/old
-app.route('/old_page')(list_old_page)
+app.route('/list/document/old')(list_old_page)
+app.route('/list/document/old/<int:num>')(list_old_page)
 
 
 # /list/document/acl
 # /list/document/acl
 @app.route('/acl_list')
 @app.route('/acl_list')
 def list_acl():
 def list_acl():
-    return list_acl_2(load_db.db_get())
+    return list_acl_2()
 
 
 # /list/document/acl/add
 # /list/document/acl/add
 @app.route('/acl/<everything:name>', methods = ['POST', 'GET'])
 @app.route('/acl/<everything:name>', methods = ['POST', 'GET'])
 def give_acl(name = None):
 def give_acl(name = None):
-    return give_acl_2(load_db.db_get(), name)
+    return give_acl_2(name)
 
 
 # /list/document/need
 # /list/document/need
 @app.route('/please')
 @app.route('/please')
 def list_please():
 def list_please():
-    return list_please_2(load_db.db_get())
+    return list_please_2()
 
 
 # /list/document/all
 # /list/document/all
-@app.route('/title_index')
-def list_title_index():
-    return list_title_index_2(load_db.db_get())
+app.route('/list/document/all')(list_title_index)
+app.route('/list/document/all/<int:num>')(list_title_index)
 
 
 # /list/document/long
 # /list/document/long
 @app.route('/long_page')
 @app.route('/long_page')
 def list_long_page():
 def list_long_page():
-    return list_long_page_2(load_db.db_get(), 'long_page')
+    return list_long_page_2('long_page')
 
 
 # /list/document/short
 # /list/document/short
 @app.route('/short_page')
 @app.route('/short_page')
 def list_short_page():
 def list_short_page():
-    return list_long_page_2(load_db.db_get(), 'short_page')
+    return list_long_page_2('short_page')
 
 
 # /list/file
 # /list/file
 @app.route('/image_file_list')
 @app.route('/image_file_list')
 def list_image_file():
 def list_image_file():
-    return list_image_file_2(load_db.db_get())
+    return list_image_file_2()
 
 
 # /list/admin
 # /list/admin
 # /list/admin/list
 # /list/admin/list
 @app.route('/admin_list')
 @app.route('/admin_list')
 def list_admin():
 def list_admin():
-    return list_admin_2(load_db.db_get())
+    return list_admin_2()
 
 
 # /list/admin/auth_use
 # /list/admin/auth_use
-@app.route('/admin_log', methods = ['POST', 'GET'])
-def list_admin_use():
-    return list_admin_use_2(load_db.db_get())
+app.route('/list/admin/auth_use', methods = ['POST', 'GET'])(list_admin_use)
+app.route('/list/admin/auth_use/<arg_search>/<int:arg_num>', methods = ['POST', 'GET'])(list_admin_use)
 
 
 # /list/user
 # /list/user
 @app.route('/user_log')
 @app.route('/user_log')
 def list_user():
 def list_user():
-    return list_user_2(load_db.db_get())
+    return list_user_2()
 
 
 # /list/user/check
 # /list/user/check
 @app.route('/check/<name>')
 @app.route('/check/<name>')
 def give_user_check(name = None):
 def give_user_check(name = None):
-    return give_user_check_2(load_db.db_get(), name)
+    return give_user_check_2(name)
     
     
 # /list/user/check/delete
 # /list/user/check/delete
 @app.route('/check_delete', methods = ['POST', 'GET'])
 @app.route('/check_delete', methods = ['POST', 'GET'])
 def give_user_check_delete():
 def give_user_check_delete():
-    return give_user_check_delete_2(load_db.db_get())
+    return give_user_check_delete_2()
 
 
 # Func-auth
 # Func-auth
 # /auth/give
 # /auth/give
 # /auth/give/<name>
 # /auth/give/<name>
 @app.route('/admin/<name>', methods = ['POST', 'GET'])
 @app.route('/admin/<name>', methods = ['POST', 'GET'])
 def give_admin(name = None):
 def give_admin(name = None):
-    return give_admin_2(load_db.db_get(), name)
+    return give_admin_2(name)
 
 
 # /auth/give
 # /auth/give
 # /auth/give/<name>
 # /auth/give/<name>
-@app.route('/ban', methods = ['POST', 'GET'])
-@app.route('/ban/<name>', methods = ['POST', 'GET'])
-def give_user_ban(name = None):
-    return give_user_ban_2(load_db.db_get(), name)
+app.route('/auth/give/ban', methods = ['POST', 'GET'])(give_user_ban)
+app.route('/auth/give/ban/<name>', methods = ['POST', 'GET'])(give_user_ban)
+app.route('/auth/give/ban_regex/<everything:name>', methods = ['POST', 'GET'], defaults = { 'ban_type' : 'regex' })(give_user_ban)
+app.route('/auth/give/ban_multiple', methods = ['POST', 'GET'], defaults = { 'ban_type' : 'multiple' })(give_user_ban)
 
 
 # /auth/list
 # /auth/list
 @app.route('/admin_group')
 @app.route('/admin_group')
 def list_admin_group():
 def list_admin_group():
-    return list_admin_group_2(load_db.db_get())
+    return list_admin_group_2()
 
 
 # /auth/list/add/<name>
 # /auth/list/add/<name>
 @app.route('/admin_plus/<name>', methods = ['POST', 'GET'])
 @app.route('/admin_plus/<name>', methods = ['POST', 'GET'])
 def give_admin_groups(name = None):
 def give_admin_groups(name = None):
-    return give_admin_groups_2(load_db.db_get(), name)
+    return give_admin_groups_2(name)
 
 
 # /auth/list/delete/<name>
 # /auth/list/delete/<name>
 @app.route('/delete_admin_group/<name>', methods = ['POST', 'GET'])
 @app.route('/delete_admin_group/<name>', methods = ['POST', 'GET'])
 def give_delete_admin_group(name = None):
 def give_delete_admin_group(name = None):
-    return give_delete_admin_group_2(load_db.db_get(), name)
+    return give_delete_admin_group_2(name)
 
 
 @app.route('/app_submit', methods = ['POST', 'GET'])
 @app.route('/app_submit', methods = ['POST', 'GET'])
 def recent_app_submit():
 def recent_app_submit():
-    return recent_app_submit_2(load_db.db_get())
+    return recent_app_submit_2()
 
 
 # /auth/history
 # /auth/history
 # ongoing 반영 필요
 # ongoing 반영 필요
@@ -337,7 +409,7 @@ def recent_app_submit():
 @app.route('/block_log/<regex("user"):tool>/<name>')
 @app.route('/block_log/<regex("user"):tool>/<name>')
 @app.route('/block_log/<regex("admin"):tool>/<name>')
 @app.route('/block_log/<regex("admin"):tool>/<name>')
 def recent_block(name = 'Test', tool = 'all'):
 def recent_block(name = 'Test', tool = 'all'):
-    return recent_block_2(load_db.db_get(), name, tool)
+    return recent_block_2(name, tool)
 
 
 # Func-history
 # Func-history
 app.route('/recent_change')(recent_change)
 app.route('/recent_change')(recent_change)
@@ -354,6 +426,7 @@ app.route('/history_hidden/<int(signed = True):rev>/<everything:name>')(recent_h
 app.route('/history_send/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])(recent_history_send)
 app.route('/history_send/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])(recent_history_send)
 app.route('/history_reset/<everything:name>', methods = ['POST', 'GET'])(recent_history_reset)
 app.route('/history_reset/<everything:name>', methods = ['POST', 'GET'])(recent_history_reset)
 app.route('/history_add/<everything:name>', methods = ['POST', 'GET'])(recent_history_add)
 app.route('/history_add/<everything:name>', methods = ['POST', 'GET'])(recent_history_add)
+app.route('/history_add_preview/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(recent_history_add)
 
 
 # Func-view
 # Func-view
 app.route('/xref/<everything:name>')(view_xref)
 app.route('/xref/<everything:name>')(view_xref)
@@ -372,21 +445,23 @@ app.route('/w_rev/<int(signed = True):doc_rev>/<everything:name>')(view_read)
 app.route('/w_from/<everything:name>', defaults = { 'do_type' : 'from' })(view_read)
 app.route('/w_from/<everything:name>', defaults = { 'do_type' : 'from' })(view_read)
 app.route('/w/<everything:name>')(view_read)
 app.route('/w/<everything:name>')(view_read)
 
 
-app.route('/random')(main_func_random)
+app.route('/random')(view_random)
 
 
 # Func-edit
 # Func-edit
 app.route('/edit/<everything:name>', methods = ['POST', 'GET'])(edit)
 app.route('/edit/<everything:name>', methods = ['POST', 'GET'])(edit)
-app.route('/edit/<everything:name>/doc_from/<everything:name_load>', methods = ['POST', 'GET'])(edit)
-app.route('/edit/<everything:name>/doc_section/<int:section>', methods = ['POST', 'GET'])(edit)
+app.route('/edit_preview/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(edit)
+app.route('/edit_from/<everything:name>', defaults = { 'do_type' : 'load' })(edit)
+app.route('/edit_section/<int:section>/<everything:name>', methods = ['POST', 'GET'])(edit)
+app.route('/edit_section_preview/<int:section>/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(edit)
 
 
-app.route('/upload', methods = ['POST', 'GET'])(main_func_upload)
+app.route('/upload', methods = ['POST', 'GET'])(edit_upload)
 
 
 # 개편 예정
 # 개편 예정
 app.route('/xref_reset/<everything:name>')(edit_backlink_reset)
 app.route('/xref_reset/<everything:name>')(edit_backlink_reset)
 
 
 app.route('/delete/<everything:name>', methods = ['POST', 'GET'])(edit_delete)
 app.route('/delete/<everything:name>', methods = ['POST', 'GET'])(edit_delete)
 app.route('/delete_file/<everything:name>', methods = ['POST', 'GET'])(edit_delete_file)
 app.route('/delete_file/<everything:name>', methods = ['POST', 'GET'])(edit_delete_file)
-app.route('/delete_mutiple', methods = ['POST', 'GET'])(edit_delete_mutiple)
+app.route('/delete_multiple', methods = ['POST', 'GET'])(edit_delete_multiple)
 
 
 app.route('/revert/<int:num>/<everything:name>', methods = ['POST', 'GET'])(edit_revert)
 app.route('/revert/<int:num>/<everything:name>', methods = ['POST', 'GET'])(edit_revert)
 
 
@@ -398,6 +473,8 @@ app.route('/recent_discuss/close', defaults = { 'tool' : 'close' })(recent_discu
 app.route('/recent_discuss/open', defaults = { 'tool' : 'open' })(recent_discuss)
 app.route('/recent_discuss/open', defaults = { 'tool' : 'open' })(recent_discuss)
 
 
 app.route('/thread/<int:topic_num>', methods = ['POST', 'GET'])(topic)
 app.route('/thread/<int:topic_num>', methods = ['POST', 'GET'])(topic)
+app.route('/thread/0/<everything:doc_name>', defaults = { 'topic_num' : '0' }, methods = ['POST', 'GET'])(topic)
+app.route('/thread_preview/<int:topic_num>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(topic)
 app.route('/topic/<everything:name>', methods = ['POST', 'GET'])(topic_list)
 app.route('/topic/<everything:name>', methods = ['POST', 'GET'])(topic_list)
 
 
 app.route('/thread/<int:topic_num>/tool')(topic_tool)
 app.route('/thread/<int:topic_num>/tool')(topic_tool)
@@ -417,9 +494,15 @@ app.route('/change', methods = ['POST', 'GET'])(user_setting)
 app.route('/change/key')(user_setting_key)
 app.route('/change/key')(user_setting_key)
 app.route('/change/key/delete')(user_setting_key_delete)
 app.route('/change/key/delete')(user_setting_key_delete)
 app.route('/change/pw', methods = ['POST', 'GET'])(user_setting_pw)
 app.route('/change/pw', methods = ['POST', 'GET'])(user_setting_pw)
-app.route('/change/head', methods=['GET', 'POST'])(user_setting_head)
+app.route('/change/head', methods=['GET', 'POST'], defaults = { 'skin_name' : '' })(user_setting_head)
+app.route('/change/head/<skin_name>', methods=['GET', 'POST'])(user_setting_head)
+app.route('/change/head_reset', methods=['GET', 'POST'])(user_setting_head_reset)
 app.route('/change/skin_set')(user_setting_skin_set)
 app.route('/change/skin_set')(user_setting_skin_set)
-app.route('/change/skin_set/main')(user_setting_skin_set)
+app.route('/change/top_menu', methods=['GET', 'POST'])(user_setting_top_menu)
+# 하위 호환용 S
+app.route('/skin_set')(user_setting_skin_set)
+# 하위 호환용 E
+app.route('/change/skin_set/main', methods = ['POST', 'GET'])(user_setting_skin_set_main)
 
 
 app.route('/user')(user_info)
 app.route('/user')(user_info)
 app.route('/user/<name>')(user_info)
 app.route('/user/<name>')(user_info)
@@ -438,21 +521,16 @@ app.route('/watch_list/<everything:name>', defaults = { 'tool' : 'watch_list' })
 app.route('/star_doc', defaults = { 'tool' : 'star_doc' })(user_watch_list)
 app.route('/star_doc', defaults = { 'tool' : 'star_doc' })(user_watch_list)
 app.route('/star_doc/<everything:name>', defaults = { 'tool' : 'star_doc' })(user_watch_list_name)
 app.route('/star_doc/<everything:name>', defaults = { 'tool' : 'star_doc' })(user_watch_list_name)
 
 
-# 하위 호환용 S
-# /change/skin_set
-app.route('/skin_set')(user_setting_skin_set)
-# 하위 호환용 E
-
 # 개편 보류중 S
 # 개편 보류중 S
 @app.route('/change/email', methods = ['POST', 'GET'])
 @app.route('/change/email', methods = ['POST', 'GET'])
 def user_setting_email():
 def user_setting_email():
-    return user_setting_email_2(load_db.db_get())
+    return user_setting_email_2()
 
 
 app.route('/change/email/delete')(user_setting_email_delete)
 app.route('/change/email/delete')(user_setting_email_delete)
 
 
 @app.route('/change/email/check', methods = ['POST', 'GET'])
 @app.route('/change/email/check', methods = ['POST', 'GET'])
 def user_setting_email_check():
 def user_setting_email_check():
-    return user_setting_email_check_2(load_db.db_get())
+    return user_setting_email_check_2()
 # 개편 보류중 E
 # 개편 보류중 E
 
 
 # Func-login
 # Func-login
@@ -464,27 +542,27 @@ def user_setting_email_check():
 
 
 @app.route('/login', methods = ['POST', 'GET'])
 @app.route('/login', methods = ['POST', 'GET'])
 def login_login():
 def login_login():
-    return login_login_2(load_db.db_get())
+    return login_login_2()
 
 
 @app.route('/login/2fa', methods = ['POST', 'GET'])
 @app.route('/login/2fa', methods = ['POST', 'GET'])
 def login_login_2fa():
 def login_login_2fa():
-    return login_login_2fa_2(load_db.db_get())
+    return login_login_2fa_2()
 
 
 @app.route('/register', methods = ['POST', 'GET'])
 @app.route('/register', methods = ['POST', 'GET'])
 def login_register():
 def login_register():
-    return login_register_2(load_db.db_get())
+    return login_register_2()
 
 
 @app.route('/register/email', methods = ['POST', 'GET'])
 @app.route('/register/email', methods = ['POST', 'GET'])
 def login_register_email():
 def login_register_email():
-    return login_register_email_2(load_db.db_get())
+    return login_register_email_2()
 
 
 @app.route('/register/email/check', methods = ['POST', 'GET'])
 @app.route('/register/email/check', methods = ['POST', 'GET'])
 def login_register_email_check():
 def login_register_email_check():
-    return login_register_email_check_2(load_db.db_get())
+    return login_register_email_check_2()
 
 
 @app.route('/register/submit', methods = ['POST', 'GET'])
 @app.route('/register/submit', methods = ['POST', 'GET'])
 def login_register_submit():
 def login_register_submit():
-    return login_register_submit_2(load_db.db_get())
+    return login_register_submit_2()
 
 
 app.route('/login/find')(login_find)
 app.route('/login/find')(login_find)
 app.route('/login/find/key', methods = ['POST', 'GET'])(login_find_key)
 app.route('/login/find/key', methods = ['POST', 'GET'])(login_find_key)
@@ -503,6 +581,16 @@ app.route('/vote/list/close', defaults = { 'list_type' : 'close' })(vote_list)
 app.route('/vote/list/close/<int:num>', defaults = { 'list_type' : 'close' })(vote_list)
 app.route('/vote/list/close/<int:num>', defaults = { 'list_type' : 'close' })(vote_list)
 app.route('/vote/add', methods = ['POST', 'GET'])(vote_add)
 app.route('/vote/add', methods = ['POST', 'GET'])(vote_add)
 
 
+# Func-bbs
+# app.route('/bbs/main')
+# app.route('/bbs/main/set')
+# app.route('/bbs/make')
+# app.route('/bbs/w/<int:bbs_num>')
+# app.route('/bbs/set/<int:bbs_num>')
+# app.route('/bbs/edit/<int:bbs_num>')
+# app.route('/bbs/w/<int:bbs_num>/<int:post_num>')
+# app.route('/bbs/edit/<int:bbs_num>/<int:post_num>')
+
 # Func-api
 # Func-api
 app.route('/api/w/<everything:name>/doc_tool/<tool>/doc_rev/<int(signed = True):rev>')(api_w)
 app.route('/api/w/<everything:name>/doc_tool/<tool>/doc_rev/<int(signed = True):rev>')(api_w)
 app.route('/api/w/<everything:name>/doc_tool/<tool>', methods = ['POST', 'GET'])(api_w)
 app.route('/api/w/<everything:name>/doc_tool/<tool>', methods = ['POST', 'GET'])(api_w)
@@ -512,13 +600,12 @@ app.route('/api/raw/<everything:name>')(api_raw)
 app.route('/api/version', defaults = { 'version_list' : version_list })(api_version)
 app.route('/api/version', defaults = { 'version_list' : version_list })(api_version)
 app.route('/api/skin_info')(api_skin_info)
 app.route('/api/skin_info')(api_skin_info)
 app.route('/api/skin_info/<name>')(api_skin_info)
 app.route('/api/skin_info/<name>')(api_skin_info)
-app.route('/api/markup')(api_markup)
 app.route('/api/user_info/<name>', methods = ['POST', 'GET'])(api_user_info)
 app.route('/api/user_info/<name>', methods = ['POST', 'GET'])(api_user_info)
 app.route('/api/setting/<name>')(api_setting)
 app.route('/api/setting/<name>')(api_setting)
 
 
-app.route('/api/thread/<int:topic_num>/<tool>/<int:num>')(api_topic_sub)
-app.route('/api/thread/<int:topic_num>/<tool>')(api_topic_sub)
-app.route('/api/thread/<int:topic_num>')(api_topic_sub)
+app.route('/api/thread/<int:topic_num>/<tool>/<int:num>')(api_topic)
+app.route('/api/thread/<int:topic_num>/<tool>')(api_topic)
+app.route('/api/thread/<int:topic_num>')(api_topic)
 
 
 app.route('/api/search/<everything:name>/doc_num/<int:num>/<int:page>')(api_search)
 app.route('/api/search/<everything:name>/doc_num/<int:num>/<int:page>')(api_search)
 app.route('/api/search/<everything:name>')(api_search)
 app.route('/api/search/<everything:name>')(api_search)
@@ -532,37 +619,45 @@ app.route('/api/recent_discuss/<get_type>/<int:num>')(api_recent_discuss)
 app.route('/api/recent_discuss/<int:num>')(api_recent_discuss)
 app.route('/api/recent_discuss/<int:num>')(api_recent_discuss)
 app.route('/api/recent_discuss')(api_recent_discuss)
 app.route('/api/recent_discuss')(api_recent_discuss)
 
 
-app.route('/api/sha224/<everything:data>', methods = ['POST', 'GET'])(api_sha224)
+app.route('/api/lang/<data>', methods = ['POST', 'GET'])(api_func_lang)
+app.route('/api/sha224/<everything:data>', methods = ['POST', 'GET'])(api_func_sha224)
+
 app.route('/api/title_index')(api_title_index)
 app.route('/api/title_index')(api_title_index)
 app.route('/api/image/<everything:name>', methods = ['POST', 'GET'])(api_image_view)
 app.route('/api/image/<everything:name>', methods = ['POST', 'GET'])(api_image_view)
-# 이건 API 영역이 아닌 것 같아서 고심 중
-app.route('/api/sitemap.xml')(api_sitemap)
 
 
 # Func-main
 # Func-main
 # 여기도 전반적인 조정 시행 예정
 # 여기도 전반적인 조정 시행 예정
 app.route('/other')(main_tool_other)
 app.route('/other')(main_tool_other)
 app.route('/manager', methods = ['POST', 'GET'])(main_tool_admin)
 app.route('/manager', methods = ['POST', 'GET'])(main_tool_admin)
-app.route('/manager/<int:num>', methods = ['POST', 'GET'])(main_tool_admin)
-app.route('/manager/<int:num>/<add_2>', methods = ['POST', 'GET'])(main_tool_admin)
+app.route('/manager/<int:num>', methods = ['POST', 'GET'])(main_tool_redirect)
+app.route('/manager/<int:num>/<add_2>', methods = ['POST', 'GET'])(main_tool_redirect)
+# app.route('/guide/<doc_name>')(main_tool_guide)
 
 
 app.route('/search', methods=['POST'])(main_search)
 app.route('/search', methods=['POST'])(main_search)
 app.route('/search/<everything:name>')(main_search_deep)
 app.route('/search/<everything:name>')(main_search_deep)
+app.route('/search/<int:num>/<everything:name>')(main_search_deep)
+app.route('/search_data/<everything:name>', defaults = { 'search_type' : 'data' })(main_search_deep)
+app.route('/search_data/<int:num>/<everything:name>', defaults = { 'search_type' : 'data' })(main_search_deep)
 app.route('/goto', methods=['POST'])(main_search_goto)
 app.route('/goto', methods=['POST'])(main_search_goto)
 app.route('/goto/<everything:name>', methods=['POST'])(main_search_goto)
 app.route('/goto/<everything:name>', methods=['POST'])(main_search_goto)
 
 
 app.route('/setting')(main_func_setting)
 app.route('/setting')(main_func_setting)
 app.route('/setting/main', defaults = { 'db_set' : data_db_set['type'] }, methods = ['POST', 'GET'])(main_func_setting_main)
 app.route('/setting/main', defaults = { 'db_set' : data_db_set['type'] }, methods = ['POST', 'GET'])(main_func_setting_main)
 app.route('/setting/main/logo', methods = ['POST', 'GET'])(main_func_setting_main_logo)
 app.route('/setting/main/logo', methods = ['POST', 'GET'])(main_func_setting_main_logo)
+app.route('/setting/top_menu', methods = ['POST', 'GET'])(main_func_setting_top_menu)
 app.route('/setting/phrase', methods = ['POST', 'GET'])(main_func_setting_phrase)
 app.route('/setting/phrase', methods = ['POST', 'GET'])(main_func_setting_phrase)
 app.route('/setting/head', defaults = { 'num' : 3 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/head', defaults = { 'num' : 3 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/head/<skin_name>', defaults = { 'num' : 3 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/head/<skin_name>', defaults = { 'num' : 3 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/body/top', defaults = { 'num' : 4 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/body/top', defaults = { 'num' : 4 }, methods = ['POST', 'GET'])(main_func_setting_head)
-app.route('/setting/body/top/<skin_name>', defaults = { 'num' : 4 }, methods = ['POST', 'GET'])(main_func_setting_head)
+app.route('/setting_preview/body/top', defaults = { 'num' : 4, 'set_preview' : 1 }, methods = ['POST'])(main_func_setting_head)
 app.route('/setting/body/bottom', defaults = { 'num' : 7 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/body/bottom', defaults = { 'num' : 7 }, methods = ['POST', 'GET'])(main_func_setting_head)
-app.route('/setting/body/bottom/<skin_name>', defaults = { 'num' : 7 }, methods = ['POST', 'GET'])(main_func_setting_head)
+app.route('/setting_preview/body/bottom', defaults = { 'num' : 7, 'set_preview' : 1 }, methods = ['POST'])(main_func_setting_head)
 app.route('/setting/robot', methods = ['POST', 'GET'])(main_func_setting_robot)
 app.route('/setting/robot', methods = ['POST', 'GET'])(main_func_setting_robot)
 app.route('/setting/external', methods = ['POST', 'GET'])(main_func_setting_external)
 app.route('/setting/external', methods = ['POST', 'GET'])(main_func_setting_external)
 app.route('/setting/acl', methods = ['POST', 'GET'])(main_func_setting_acl)
 app.route('/setting/acl', methods = ['POST', 'GET'])(main_func_setting_acl)
+app.route('/setting/sitemap', methods = ['POST', 'GET'])(main_func_setting_sitemap)
+
+app.route('/easter_egg')(main_func_easter_egg)
 
 
 # views -> view
 # views -> view
 app.route('/view/<everything:name>')(main_view)
 app.route('/view/<everything:name>')(main_view)

+ 5 - 0
docker_build.bat

@@ -0,0 +1,5 @@
+docker build . -t opennamu/opennamu:dev
+docker build -t opennamu/opennamu:dev-ko -f Dockerfile.ko .
+docker login
+docker push opennamu/opennamu:dev
+docker push opennamu/opennamu:dev-ko

+ 59 - 11
emergency_tool.py

@@ -1,9 +1,15 @@
 # Load
 # Load
 import time
 import time
+import os
+import platform
+import urllib
+import zipfile
+
 from route.tool.func import *
 from route.tool.func import *
 
 
 while True:
 while True:
     data_db_load = input('Load DB (Y) [Y, N] : ')
     data_db_load = input('Load DB (Y) [Y, N] : ')
+    data_db_load = data_db_load.upper()
     if data_db_load in ('Y', 'N'):
     if data_db_load in ('Y', 'N'):
         break
         break
 
 
@@ -12,9 +18,10 @@ if data_db_load == 'Y':
 
 
     db_data_get(data_db_set['type'])
     db_data_get(data_db_set['type'])
     do_db_set(data_db_set)
     do_db_set(data_db_set)
-    load_db = get_db_connect_old(data_db_set)
 
 
-    conn = load_db.db_load()
+    load_db = get_db_connect()
+
+    conn = load_db.__enter__()
     curs = conn.cursor()
     curs = conn.cursor()
 else:
 else:
     print('----')
     print('----')
@@ -38,6 +45,10 @@ print('14. Delete Main <HEAD>')
 print('15. Give owner')
 print('15. Give owner')
 print('16. Delete 2FA password')
 print('16. Delete 2FA password')
 print('17. Change markup')
 print('17. Change markup')
+print('18. Change wiki access password')
+print('19. Forced update')
+print('20. Change domain')
+print('21. Change TLS')
 
 
 print('----')
 print('----')
 what_i_do = input('Select : ')
 what_i_do = input('Select : ')
@@ -88,8 +99,7 @@ if what_i_do == '1':
         curs.execute(db_change("select data from data where title = ?"), [name[0]])
         curs.execute(db_change("select data from data where title = ?"), [name[0]])
         data = curs.fetchall()
         data = curs.fetchall()
 
 
-        get_class_render = class_do_render(conn)
-        get_class_render.do_render(name[0], data[0][0], 'backlink', '')
+        class_do_render(conn).do_render(name[0], data[0][0], 'backlink', '')
 elif what_i_do == '2':
 elif what_i_do == '2':
     curs.execute(db_change("delete from other where name = 'recaptcha'"))
     curs.execute(db_change("delete from other where name = 'recaptcha'"))
     curs.execute(db_change("delete from other where name = 'sec_re'"))
     curs.execute(db_change("delete from other where name = 'sec_re'"))
@@ -190,12 +200,7 @@ elif what_i_do == '12':
         count_data = 0
         count_data = 0
 
 
     curs.execute(db_change('delete from other where name = "count_all_title"'))
     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, coverage) values ("count_all_title", ?, "")'), [str(count_data)])
 elif what_i_do == '14':
 elif what_i_do == '14':
     curs.execute(db_change('delete from other where name = "head"'))
     curs.execute(db_change('delete from other where name = "head"'))
 elif what_i_do == '15':
 elif what_i_do == '15':
@@ -215,6 +220,49 @@ elif what_i_do == '17':
     markup = input('Markup name : ')
     markup = input('Markup name : ')
 
 
     curs.execute(db_change("update other set data = ? where name = 'markup'"), [markup])
     curs.execute(db_change("update other set data = ? where name = 'markup'"), [markup])
+elif what_i_do == '18':
+    print('----')
+    wiki_access_password = input('Password : ')
+
+    curs.execute(db_change("update other set data = ? where name = 'wiki_access_password'"), [wiki_access_password])
+elif what_i_do == '19':
+    print('----')
+    up_data = input('Insert branch (beta) [stable, beta, dev] : ')
+
+    if not up_data in ['stable', 'beta', 'dev']:
+        up_data = 'beta'
+
+    if platform.system() == 'Linux':
+        ok = []
+
+        ok += [os.system('git remote rm origin')]
+        ok += [os.system('git remote add origin https://github.com/opennamu/opennamu.git')]
+        ok += [os.system('git fetch origin ' + up_data)]
+        ok += [os.system('git reset --hard origin/' + up_data)]
+        if (ok[0] and ok[1] and ok[2] and ok[3]) != 0:
+            print('Error : update failed')
+    elif platform.system() == 'Windows':
+        os.system('rd /s /q route')
+        urllib.request.urlretrieve('https://github.com/opennamu/opennamu/archive/' + up_data + '.zip', 'update.zip')
+        zipfile.ZipFile('update.zip').extractall('')
+        ok = os.system('xcopy /y /s /r opennamu-' + up_data + ' .')
+        if ok == 0:
+            os.system('rd /s /q opennamu-' + up_data)
+            os.system('del update.zip')
+        else:
+            print('Error : update failed')
+elif what_i_do == '20':
+    print('----')
+    domain = input('Domain (EX : 2du.pythonanywhere.com) : ')
+
+    curs.execute(db_change("update other set data = ? where name = 'domain'"), [domain])
+elif what_i_do == '21':
+    print('----')
+    tls_v = input('TLS (http) [http, https] : ')
+    if not tls_v in ['http', 'https']:
+        tls_v = 'http'
+
+    curs.execute(db_change("update other set data = ? where name = 'http_select'"), [tls_v])
 else:
 else:
     raise ValueError(what_i_do)
     raise ValueError(what_i_do)
 
 
@@ -222,4 +270,4 @@ if data_db_load == 'Y':
     conn.commit()
     conn.commit()
 
 
 print('----')
 print('----')
-print('OK')
+print('OK')

+ 103 - 17
lang/en-US.json

@@ -54,7 +54,6 @@
         "open" : "Open",
         "open" : "Open",
         "agreement" : "Agreement",
         "agreement" : "Agreement",
         "template" : "Template",
         "template" : "Template",
-        "category" : "Category",
         "file" : "File",
         "file" : "File",
         "writer" : "Writer",
         "writer" : "Writer",
         "editor" : "Editor",
         "editor" : "Editor",
@@ -109,6 +108,9 @@
         "alpha" : "Alpha",
         "alpha" : "Alpha",
         "beta" : "Beta",
         "beta" : "Beta",
         "example" : "Example",
         "example" : "Example",
+        "reset" : "Reset",
+        "top" : "Top",
+        "use" : "Use",
         "_comment_1.1_" : "Time",
         "_comment_1.1_" : "Time",
             "second" : "Second(s)",
             "second" : "Second(s)",
             "hour" : "Hour(s)",
             "hour" : "Hour(s)",
@@ -137,7 +139,6 @@
         "recent_change" : "Recently edit(s)",
         "recent_change" : "Recently edit(s)",
         "edit_filter" : "Contents filter",
         "edit_filter" : "Contents filter",
         "recent_ban" : "Block(s) record",
         "recent_ban" : "Block(s) record",
-        "load" : "Load another document",
         "edit_filter_rule" : "Contents filter rule",
         "edit_filter_rule" : "Contents filter rule",
         "move_history" : "History of moveing",
         "move_history" : "History of moveing",
         "other_tool" : "Other tools",
         "other_tool" : "Other tools",
@@ -175,7 +176,8 @@
         "edit_button_paragraph" : "Paragraph",
         "edit_button_paragraph" : "Paragraph",
         "password_change" : "Change password",
         "password_change" : "Change password",
         "email_change" : "Change email",
         "email_change" : "Change email",
-        "acl_change" : "Change documents ACL",
+        "acl_change" : "Change document ACL",
+        "acl_thread_change" : "Change thread ACL",
         "user_tool" : "Users tools",
         "user_tool" : "Users tools",
         "skin_info" : "Skin information",
         "skin_info" : "Skin information",
         "closed_discussion" : "Closed discussions",
         "closed_discussion" : "Closed discussions",
@@ -194,7 +196,7 @@
         "accept_edit_request" : "Accept edit request",
         "accept_edit_request" : "Accept edit request",
         "history_add" : "Add history",
         "history_add" : "Add history",
         "all_register_num" : "The number of application forms",
         "all_register_num" : "The number of application forms",
-        "replace_move" : "Swaping documents",
+        "replace_move" : "Interchange",
         "merge_move" : "Merging documents",
         "merge_move" : "Merging documents",
         "add_admin_group" : "Add administrator groups",
         "add_admin_group" : "Add administrator groups",
         "add_watchlist" : "Add watchlist",
         "add_watchlist" : "Add watchlist",
@@ -210,7 +212,6 @@
         "link_in_this" : "Links in this document",
         "link_in_this" : "Links in this document",
         "star_doc" : "Document(s) of interest",
         "star_doc" : "Document(s) of interest",
         "add_star_doc" : "Add document(s) of interest",
         "add_star_doc" : "Add document(s) of interest",
-        "get_sitemap" : "Create or renewal sitemap.xml",
         "simple_check" : "Simple check",
         "simple_check" : "Simple check",
         "add_user" : "Add user",
         "add_user" : "Add user",
         "2fa" : "2FA",
         "2fa" : "2FA",
@@ -226,6 +227,45 @@
         "email_delete" : "Delete email",
         "email_delete" : "Delete email",
         "challenge" : "Challenge",
         "challenge" : "Challenge",
         "user_title" : "User title",
         "user_title" : "User title",
+        "multiple_ban" : "Multiple ban",
+        "dont_move" : "Don't move",
+        "file_delete" : "File delete",
+        "added_menu" : "Added menu",
+        "document_set" : "Document settings",
+        "move_redirect_make" : "Redirect document generation (Only if possible)",
+        "_comment_" : "Edit",
+            "load" : "Load another document",
+            "turn_off_monaco" : "Turn off monaco editor",
+        "_comment_" : "Render",
+            "toc" : "TOC",
+            "category" : "Category",
+        "_comment_" : "Search",
+            "search_document_name" : "Search document name",
+            "search_document_data" : "Search document data",
+        "_comment_" : "Main skin set",
+            "_comment_" : "Part",
+                "render" : "Render",
+                "strike" : "Strike",
+                "bold" : "Bold",
+                "footnote" : "Footnote",
+                "include_link" : "Include link",
+                "image" : "Image",
+                "exter_link" : "Exter link",
+                "link_delimiter" : "Link delimiter",
+                "force_darkmode" : "Force darkmode",
+                "font_size" : "Font size",
+                "image_paste" : "Paste Image by Ctrl + C and V",
+                "monaco_editor" : "Monaco editor",
+            "_comment_" : "Option",
+                "change_to_normal" : "Change to plain text.",
+                "change_to_link" : "Change to Link.",
+                "click_load" : "Load by click.",
+                "all_off" : "Turn off all",
+                "in_content" : "Turn off automatic TOC",
+                "self_tab" : "Open a link in this tab",
+            "_comment_" : "Footnote",
+                "only_korean" : "Only Korean is available",
+                "unavailable_in_monaco" : "Not available in Monaco editor.",
         "_comment_2.1_" : "Filter",
         "_comment_2.1_" : "Filter",
             "_comment_2.1.1_" : "List",
             "_comment_2.1.1_" : "List",
                 "interwiki_list" : "Interwiki(s) list",
                 "interwiki_list" : "Interwiki(s) list",
@@ -254,6 +294,8 @@
             "adsense_enable" : "Adsense enable",
             "adsense_enable" : "Adsense enable",
             "skin_setting" : "Skin settings",
             "skin_setting" : "Skin settings",
             "main_acl_setting" : "Default ACL settings",
             "main_acl_setting" : "Default ACL settings",
+            "top_menu_setting" : "Added menu setting",
+            "enter_top_menu_setting" : "Enter name in the upper line and URL in the lower line.",
             "_comment_2.2.1_" : "List",
             "_comment_2.2.1_" : "List",
                 "main_setting" : "Main settings",
                 "main_setting" : "Main settings",
                 "text_setting" : "Text settings",
                 "text_setting" : "Text settings",
@@ -269,6 +311,7 @@
                 "edit_set" : "Edit-related settings",
                 "edit_set" : "Edit-related settings",
                 "communication_set" : "Communication-related settings",
                 "communication_set" : "Communication-related settings",
     
     
+                "namumark_fully_compatible_mode" : "namumark design compatible mode",
                 "wiki_name" : "Wikis name",
                 "wiki_name" : "Wikis name",
                 "wiki_logo" : "Wikis logo",
                 "wiki_logo" : "Wikis logo",
                 "main_page" : "Main page",
                 "main_page" : "Main page",
@@ -295,6 +338,10 @@
                 "tls_method" : "TLS method",
                 "tls_method" : "TLS method",
                 "title_max_length" : "Documents title maximum length",
                 "title_max_length" : "Documents title maximum length",
                 "title_topic_max_length" : "Discussions topic maximum length",
                 "title_topic_max_length" : "Discussions topic maximum length",
+                "password_min_length" : "Password minimum length",
+                "set_wiki_access_password_need" : "Password required for wiki access",
+                "set_wiki_access_password" : "Wiki access password",
+                "set_history_recording_off" : "Stop recording history",
             "_comment_2.2.3_" : "Text",
             "_comment_2.2.3_" : "Text",
                 "register_text" : "Terms of sign-up",
                 "register_text" : "Terms of sign-up",
                 "non_login_alert" : "Non-login alert",
                 "non_login_alert" : "Non-login alert",
@@ -312,6 +359,9 @@
                 "upload_help" : "File upload phrase",
                 "upload_help" : "File upload phrase",
                 "upload_default" : "File upload other Default",
                 "upload_default" : "File upload other Default",
                 "topic_text" : "Discussion textarea phrase",
                 "topic_text" : "Discussion textarea phrase",
+                "phrase_user_page_admin" : "Administrator user page phrase",
+                "phrase_user_page_owner" : "Onwer user page phrase",
+                "phrase_old_page_warring" : "Warning on previous revision document visit",
             "_comment_2.2.4_" : "Ext_API",
             "_comment_2.2.4_" : "Ext_API",
                 "recaptcha" : "reCAPTCHA",
                 "recaptcha" : "reCAPTCHA",
                 "hcaptcha" : "hCAPTCHA",
                 "hcaptcha" : "hCAPTCHA",
@@ -329,6 +379,12 @@
                 "oauth" : "OAuth",
                 "oauth" : "OAuth",
                 "_comment_2.2.4.2_" : "OAuth",
                 "_comment_2.2.4.2_" : "OAuth",
                     "oauth_client_id" : "OAuth client ID",
                     "oauth_client_id" : "OAuth client ID",
+            "_comment_" : "Sitemap",
+                "sitemap_management" : "sitemap.xml management",
+                "stiemap_exclude_domain" : "Exclude domain",
+                "stiemap_exclude_user_page" : "Exclude user page(s)",
+                "stiemap_exclude_file_page" : "Exclude file page(s)",
+                "stiemap_exclude_category_page" : "Exclude category page(s)",
         "_comment_2.3_" : "List",
         "_comment_2.3_" : "List",
             "open_discussion_list" : "Open discussion(s) list",
             "open_discussion_list" : "Open discussion(s) list",
             "discussion_list" : "Discussion(s) list",
             "discussion_list" : "Discussion(s) list",
@@ -360,6 +416,23 @@
             "topic_tool" : "Discussion management tools",
             "topic_tool" : "Discussion management tools",
             "topic_state" : "Discussion status",
             "topic_state" : "Discussion status",
             "topic_delete" : "Delete this thread",
             "topic_delete" : "Delete this thread",
+            "topic_view_acl" : "Discussion View ACL",
+            "topic_normal" : "Normal",
+            "topic_stop" : "Stop",
+            "topic_close" : "Close",
+            "topic_agree" : "Discussion Agreed",
+            "_comment_" : "Topic set",
+                "topic_change_agree" : "Transition to a consensus discussion",
+                "topic_progress" : "Discussion progress",
+                "topic_associate" : "Associate discussion with other features",
+                "topic_link_vote" : "Link votes to discussion",
+                "topic_insert_vote_number" : "Number of the vote",
+                "_comment_" : "Topic state",
+                    "topic_state_change_normal" : "The admin normalized the discussion.",
+                    "topic_state_change_stop" : "The admin has stopped the discussion.",
+                    "topic_state_change_close" : "The admin has closed the discussion.",
+                    "topic_state_change_agree" : "The admin has approved the discussion agreement.",
+                    "topic_state_change_disagree" : "The admin has broken the agreement of the discussion.",
         "_comment_2.5_" : "Period",
         "_comment_2.5_" : "Period",
             "1_day" : "1 day",
             "1_day" : "1 day",
             "5_day" : "5 days",
             "5_day" : "5 days",
@@ -367,19 +440,25 @@
             "180_day" : "180 days",
             "180_day" : "180 days",
             "360_day" : "360 days",
             "360_day" : "360 days",
         "_comment_2.6_" : "ACL",
         "_comment_2.6_" : "ACL",
-            "admin_acl" : "Administrators only",
-            "member_acl" : "Members only",
-            "50_edit_acl" : "Only members with 50 or more document edits",
-            "all_acl" : "All users",
-            "email_acl" : "Only users with email",
-            "owner_acl" : "Owner only",
-            "before_acl" : "Only those who have edited this document before",
-            "ban_acl" : "Include blocked users",
-            "ban_admin_acl" : "Blocked users and administrators",
-            "30_day_acl" : "Only members 30 days after sign up",
-            "_comment_2.6_1_" : "Set",
+            "_comment_" : "Set data",
+                "admin_acl" : "Administrators, owners",
+                "member_acl" : "Members",
+                "50_edit_acl" : "Members with 50 or more document edits, administrators, owners",
+                "all_acl" : "All users exclude blocked users",
+                "email_acl" : "Members with email, administrators, owners",
+                "owner_acl" : "Owners",
+                "before_acl" : "Those who have edited this document before, administrators, owners",
+                "ban_acl" : "All users include blocked users",
+                "ban_admin_acl" : "Blocked users, administrators, owners",
+                "30_day_acl" : "Members 30 days after sign up, administrators, owners",
+                "not_all_acl" : "All prohibited",
+            "_comment_" : "Set name",
                 "document_acl" : "Document ACL",
                 "document_acl" : "Document ACL",
+                "document_edit_acl" : "Document edit ACL",
+                "document_move_acl" : "Document move ACL",
+                "document_delete_acl" : "Document delete ACL",
                 "discussion_acl" : "Discussion(s) ACL",
                 "discussion_acl" : "Discussion(s) ACL",
+                "thread_acl" : "Thread ACL",
                 "view_acl" : "Reading ACL",
                 "view_acl" : "Reading ACL",
                 "user_document_acl" : "User document ACL",
                 "user_document_acl" : "User document ACL",
                 "upload_acl" : "Upload ACL",
                 "upload_acl" : "Upload ACL",
@@ -392,6 +471,7 @@
             "answer": "Answer",
             "answer": "Answer",
             "approve": "Approve",
             "approve": "Approve",
             "decline": "Decline",
             "decline": "Decline",
+            "new_application" : "A new register application exists.",
             "approve_or_decline": "Approve or reject",
             "approve_or_decline": "Approve or reject",
             "no_applications_now" : "There are no applications.",
             "no_applications_now" : "There are no applications.",
             "approval_requirement_disabled": "Approval requirement is disabled now. You can enable this feature on settings",
             "approval_requirement_disabled": "Approval requirement is disabled now. You can enable this feature on settings",
@@ -415,6 +495,7 @@
         "default_edit_help" : "Describe it here",
         "default_edit_help" : "Describe it here",
         "markup_enabled" : "Markup enabled",
         "markup_enabled" : "Markup enabled",
         "many_delete_help" : "Please write down the documents name one by one on the line.",
         "many_delete_help" : "Please write down the documents name one by one on the line.",
+        "name_or_ip_or_regex_multiple" : "Please write down the username or IP or Regex one by one on the line.",
         "sqlite_only" : "SQLite only",
         "sqlite_only" : "SQLite only",
         "approval_question_visible_only_when_approval_on" : "Approval questions are visible only when approval requirement is on",
         "approval_question_visible_only_when_approval_on" : "Approval questions are visible only when approval requirement is on",
         "msg_whatchlist_lmt": "You can add as many as",
         "msg_whatchlist_lmt": "You can add as many as",
@@ -441,7 +522,7 @@
             "edit_record_error" : "Edit reason can not be more than 500 characters.",
             "edit_record_error" : "Edit reason can not be more than 500 characters.",
             "same_file_error" : "A file with the same name exists.",
             "same_file_error" : "A file with the same name exists.",
             "file_capacity_error" : "Maximum file capacity (MB): ",
             "file_capacity_error" : "Maximum file capacity (MB): ",
-            "decument_exist_error" : "The document with that title already exists.",
+            "move_error" : "An error occurred while moving. All or part of it has not been moved.",
             "password_diffrent_error" : "Reconfirm password and input password are different.",
             "password_diffrent_error" : "Reconfirm password and input password are different.",
             "edit_filter_error" : "Censored by edit filter.",
             "edit_filter_error" : "Censored by edit filter.",
             "file_name_error" : "Only English alphabets, Korean alphabets, spaces, underscore, and hyphens are allowed for the file name.",
             "file_name_error" : "Only English alphabets, Korean alphabets, spaces, underscore, and hyphens are allowed for the file name.",
@@ -461,12 +542,17 @@
             "input_email_error" : "There is a problem with the input value.",
             "input_email_error" : "There is a problem with the input value.",
             "error_edit_send_request" : "Entering a reason is required.",
             "error_edit_send_request" : "Entering a reason is required.",
             "error_title_length_too_long" : "Documents title or Discussion topic length is too long. Maximum number of characters : ",
             "error_title_length_too_long" : "Documents title or Discussion topic length is too long. Maximum number of characters : ",
+            "error_password_length_too_short" : "Password length is too short. Minimum number of characters : ",
+            "error_password_require_for_wiki_access" : "A password is required to access the wiki.",
         "_comment_3.2_" : "Warning",
         "_comment_3.2_" : "Warning",
             "http_warning" : "Warning: If you are not on HTTPS connection, your information can be leaked. The users themselves have responsibility to any problems that happen because of this.",
             "http_warning" : "Warning: If you are not on HTTPS connection, your information can be leaked. The users themselves have responsibility to any problems that happen because of this.",
             "user_head_warning" : "User data will be deleted if you close the browser or when you sign in.",
             "user_head_warning" : "User data will be deleted if you close the browser or when you sign in.",
             "no_login_warning" : "You are not logged in. Your current IP address will be logged within editing or discussing until you log in.",
             "no_login_warning" : "You are not logged in. Your current IP address will be logged within editing or discussing until you log in.",
             "update_warning" : "Manual updates are recommended if your version is 0.2 or lower than the latest version. For Windows, the contents of the route folder will be deleted.",
             "update_warning" : "Manual updates are recommended if your version is 0.2 or lower than the latest version. For Windows, the contents of the route folder will be deleted.",
             "history_delete_warning" : "If you erase history, it's hard to restore it, so please be careful.",
             "history_delete_warning" : "If you erase history, it's hard to restore it, so please be careful.",
+            "user_css_warning" : "If you have a problem using this, connect here.",
+            "main_css_warning" : "If you have a problem using this, use the emergency tool.",
+            "not_support_skin_warning" : "It does not work on skins that do not support this feature.",
         "_comment_" : "Challenge",
         "_comment_" : "Challenge",
             "challenge_title_register" : "Hello, World!",
             "challenge_title_register" : "Hello, World!",
             "challenge_info_register" : "Sign up",
             "challenge_info_register" : "Sign up",

+ 89 - 14
lang/ko-KR.json

@@ -46,7 +46,6 @@
     "state": "상태",
     "state": "상태",
     "authorize": "권한 부여",
     "authorize": "권한 부여",
     "check_user": "사용자 검사",
     "check_user": "사용자 검사",
-    "email_acl": "이메일 인증을 받은 사용자만",
     "email_error": "해당 이메일을 가진 사용자가 존재하지 않습니다.",
     "email_error": "해당 이메일을 가진 사용자가 존재하지 않습니다.",
     "version": "버전",
     "version": "버전",
     "open": "열기",
     "open": "열기",
@@ -64,7 +63,6 @@
     "no_login_error": "비로그인 상태입니다.",
     "no_login_error": "비로그인 상태입니다.",
     "upload": "파일 올리기",
     "upload": "파일 올리기",
     "user_name": "사용자 이름",
     "user_name": "사용자 이름",
-    "member_acl": "가입자만",
     "search": "검색",
     "search": "검색",
     "etc": "기타",
     "etc": "기타",
     "edit_filter": "편집 필터",
     "edit_filter": "편집 필터",
@@ -81,7 +79,6 @@
     "password_diffrent_error": "입력한 비밀번호와 비밀번호 확인이 서로 다릅니다.",
     "password_diffrent_error": "입력한 비밀번호와 비밀번호 확인이 서로 다릅니다.",
     "180_day": "180일",
     "180_day": "180일",
     "markup_enabled": "문법 사용 가능",
     "markup_enabled": "문법 사용 가능",
-    "all_acl": "모든 사용자",
     "send": "전송",
     "send": "전송",
     "not_sure": "확실하지 않음",
     "not_sure": "확실하지 않음",
     "file_name_error": "파일명에는 알파벳, 한글, 공백, 밑줄 및 빼기 기호만 사용할 수 있습니다.",
     "file_name_error": "파일명에는 알파벳, 한글, 공백, 밑줄 및 빼기 기호만 사용할 수 있습니다.",
@@ -145,7 +142,6 @@
     "host": "호스트",
     "host": "호스트",
     "email_text": "이메일 내용",
     "email_text": "이메일 내용",
     "recent": "최근",
     "recent": "최근",
-    "admin_acl": "관리자만",
     "wiki_host": "위키 호스트",
     "wiki_host": "위키 호스트",
     "error_404": "존재하지 않는 문서 문구",
     "error_404": "존재하지 않는 문서 문구",
     "member_list": "사용자 목록",
     "member_list": "사용자 목록",
@@ -171,7 +167,7 @@
     "copyright_checkbox_text": "저작권 동의 문구(체크박스 형태)",
     "copyright_checkbox_text": "저작권 동의 문구(체크박스 형태)",
     "authority": "권한",
     "authority": "권한",
     "document": "문서",
     "document": "문서",
-    "decument_exist_error": "이동하려는 문서에 이미 문서가 존재합니다.",
+    "move_error": "이동하는 과정 중 오류가 발생하였습니다. 전부 또는 일부가 이동되지 않았습니다.",
     "skin_setting": "스킨 설정",
     "skin_setting": "스킨 설정",
     "discussion_list": "토론 목록",
     "discussion_list": "토론 목록",
     "restart_required": "재시작 필요",
     "restart_required": "재시작 필요",
@@ -274,7 +270,6 @@
     "hide_release": "숨김 해제",
     "hide_release": "숨김 해제",
     "360_day": "360일",
     "360_day": "360일",
     "inter_error": "내부 오류.",
     "inter_error": "내부 오류.",
-    "50_edit_acl": "기여 횟수가 50회 이상인 가입자만",
     "tool": "도구",
     "tool": "도구",
     "adsense_enable": "애드센스 사용",
     "adsense_enable": "애드센스 사용",
     "list": "목록",
     "list": "목록",
@@ -291,7 +286,6 @@
     "acl_record": "ACL 기록",
     "acl_record": "ACL 기록",
     "main_bottom_body": "본문 하단",
     "main_bottom_body": "본문 하단",
     "reference": "참고",
     "reference": "참고",
-    "owner_acl": "소유자만",
     "last_edit_time": "최근 수정 시각",
     "last_edit_time": "최근 수정 시각",
     "link": "링크",
     "link": "링크",
     "icon": "아이콘",
     "icon": "아이콘",
@@ -329,7 +323,7 @@
     "application_not_found": "존재하지 않는 회원가입 신청입니다.",
     "application_not_found": "존재하지 않는 회원가입 신청입니다.",
     "approval_requirement_disabled": "현재 가입시 승인필요 설정이 비활성화되어있습니다. 필요시 설정에서 활성화할 수 있습니다.",
     "approval_requirement_disabled": "현재 가입시 승인필요 설정이 비활성화되어있습니다. 필요시 설정에서 활성화할 수 있습니다.",
     "all_register_num": "모든 가입 신청자의 수",
     "all_register_num": "모든 가입 신청자의 수",
-    "replace_move": "서 바꾸기",
+    "replace_move": "서 바꾸기",
     "merge_move": "문서 병합",
     "merge_move": "문서 병합",
     "add_admin_group": "관리자 그룹 추가",
     "add_admin_group": "관리자 그룹 추가",
     "add_watchlist": "주시 문서 추가",
     "add_watchlist": "주시 문서 추가",
@@ -345,8 +339,6 @@
     "extension_filter_list": "확장자 필터 목록",
     "extension_filter_list": "확장자 필터 목록",
     "extension_filter_add": "확장자 필터 추가",
     "extension_filter_add": "확장자 필터 추가",
     "extension": "확장자",
     "extension": "확장자",
-    "ban_acl": "차단된 사용자 포함",
-    "ban_admin_acl": "차단된 사용자 및 관리자",
     "topic_name_change": "토론 제목 변경",
     "topic_name_change": "토론 제목 변경",
     "topic_acl_setting": "토론 ACL 설정",
     "topic_acl_setting": "토론 ACL 설정",
     "topic_acl": "토론 ACL",
     "topic_acl": "토론 ACL",
@@ -362,12 +354,10 @@
     "backup_where": "백업 위치",
     "backup_where": "백업 위치",
     "empty": "빈칸",
     "empty": "빈칸",
     "email_send_error": "이메일 전송이 실패했습니다.",
     "email_send_error": "이메일 전송이 실패했습니다.",
-    "get_sitemap": "sitemap.xml 만들거나 갱신하기",
+    "sitemap_management": "sitemap.xml 관리",
     "same_ip_exist": "동일한 아이피가 존재합니다.",
     "same_ip_exist": "동일한 아이피가 존재합니다.",
     "restart_fail_error": "재시작이 실패했습니다. 수동 재시작을 이용해주세요.",
     "restart_fail_error": "재시작이 실패했습니다. 수동 재시작을 이용해주세요.",
     "domain": "도메인",
     "domain": "도메인",
-    "before_acl": "이 문서를 이전에 편집한 적 있는 사람만",
-    "30_day_acl": "가입 후 30일이 지난 가입자만",
     "simple_check": "간편 검사",
     "simple_check": "간편 검사",
     "add_user": "계정 추가",
     "add_user": "계정 추가",
     "result": "결과",
     "result": "결과",
@@ -443,5 +433,90 @@
     "tls_method": "TLS 방식",
     "tls_method": "TLS 방식",
     "title_max_length": "문서 제목 최대 길이",
     "title_max_length": "문서 제목 최대 길이",
     "title_topic_max_length": "토론 제목 최대 길이",
     "title_topic_max_length": "토론 제목 최대 길이",
-    "error_title_length_too_long": "문서 제목이나 토론 제목의 길이가 너무 깁니다. 최대 글자 수 : "
+    "error_title_length_too_long": "문서 제목이나 토론 제목의 길이가 너무 깁니다. 최대 글자 수 : ",
+    "thread_acl": "스레드 ACL",
+    "password_min_length": "비밀번호 최소 길이",
+    "error_password_length_too_short": "비밀번호 길이가 너무 짧습니다. 최소 글자 수 : ",
+    "phrase_user_page_admin": "관리자인 사용자 문서 문구",
+    "phrase_user_page_owner": "소유자인 사용자 문서 문구",
+    "error_password_require_for_wiki_access": "위키에 접속하려면 비밀번호가 필요합니다.",
+    "set_wiki_access_password_need": "위키 접속시 비밀번호 필요",
+    "set_wiki_access_password": "위키 접속 비밀번호",
+    "set_history_recording_off": "역사 기록 중지",
+    "multiple_ban": "다중 차단",
+    "name_or_ip_or_regex_multiple": "한 줄에 IP나 정규식을 한 개씩 적어주세요.",
+    "dont_move": "이동하지 않음",
+    "stiemap_exclude_domain": "도메인 제외",
+    "stiemap_exclude_user_page": "사용자 문서 제외",
+    "stiemap_exclude_file_page": "파일 문서 제외",
+    "stiemap_exclude_category_page": "분류 문서 제외",
+    "search_document_name": "문서명 검색",
+    "search_document_data": "문서 내용 검색",
+    "admin_acl": "관리자, 소유자",
+    "member_acl": "가입자",
+    "50_edit_acl": "기여 횟수가 50회 이상인 가입자, 관리자, 소유자",
+    "all_acl": "전체 사용자 (차단자 제외)",
+    "email_acl": "이메일을 등록한 가입자, 관리자, 소유자",
+    "owner_acl": "소유자",
+    "before_acl": "전에 이 문서를 편집한 적 있는 사람, 관리자, 가입자",
+    "ban_acl": "전체 사용자 (차단자 포함)",
+    "ban_admin_acl": "차단자, 관리자, 소유자",
+    "30_day_acl": "가입 후 30일이 지난 가입자, 관리자, 소유자",
+    "not_all_acl": "전부 금지",
+    "document_move_acl": "문서 이동 ACL",
+    "document_delete_acl": "문서 삭제 ACL",
+    "document_edit_acl": "문서 편집 ACL",
+    "phrase_old_page_warring": "이전 리비전 문서 방문시 경고문",
+    "toc": "목차",
+    "topic_view_acl": "토론 보기 ACL",
+    "file_delete": "파일 삭제",
+    "topic_change_agree": "합의가 완료된 토론으로 전환",
+    "topic_progress": "토론 진행",
+    "topic_associate": "다른 기능과 토론 연계",
+    "topic_link_vote": "토론과 투표 연계",
+    "topic_insert_vote_number": "투표의 번호",
+    "topic_state_change_normal": "관리자가 토론을 정상화 했습니다.",
+    "topic_state_change_stop": "관리자가 토론을 중지 했습니다.",
+    "topic_state_change_close": "관리자가 토론을 닫았습니다.",
+    "topic_state_change_agree": "관리자가 토론의 합의를 승인했습니다.",
+    "topic_state_change_disagree": "관리자가 토론의 합의를 파기했습니다.",
+    "topic_normal": "일반",
+    "topic_stop": "중지",
+    "topic_close": "닫힘",
+    "turn_off_monaco": "모나코 에디터 끄기",
+    "topic_agree": "토론 합의 완료",
+    "user_css_warning": "만약 사용하다가 문제가 생기면 여기로 접속하세요.",
+    "main_css_warning": "만약 사용하다가 문제가 생기면 이머전시 툴을 사용하세요.",
+    "reset": "초기화",
+    "namumark_fully_compatible_mode": "나무마크 디자인 호환 모드",
+    "added_menu": "추가 메뉴",
+    "top_menu_setting": "추가 메뉴 설정",
+    "enter_top_menu_setting": "윗 줄에는 이름을 쓰고 아랫 줄에는 URL을 입력하세요.",
+    "not_support_skin_warning": "이 기능을 미지원하는 스킨에서는 작동하지 않습니다.",
+    "acl_thread_change": "스레드 ACL 변경",
+    "new_application": "새로운 가입 신청이 있습니다.",
+    "top": "상단",
+    "use": "사용",
+    "change_to_normal": "일반 글자로 변경",
+    "change_to_link": "링크로 변경",
+    "click_load": "클릭시 로드",
+    "all_off": "전부 끄기",
+    "in_content": "자동 목차 끄기",
+    "self_tab": "현재 탭에서 링크 열기",
+    "only_korean": "한국어만 사용 가능",
+    "unavailable_in_monaco": "모나코 에디터 상에서 사용 불가",
+    "render": "렌더링",
+    "strike": "취소선",
+    "bold": "굵게",
+    "footnote": "각주",
+    "include_link": "틀 링크",
+    "image": "이미지",
+    "exter_link": "외부 링크",
+    "link_delimiter": "링크 구분자",
+    "force_darkmode": "강제 다크모드",
+    "font_size": "글자 크기",
+    "image_paste": "이미지 붙여넣기 (컨트롤 C + V로)",
+    "monaco_editor": "모나코 에디터",
+    "document_set" : "문서 설정",
+    "move_redirect_make" : "리다이렉트 문서 생성 (가능한 경우에만)"
 }
 }

+ 1 - 1
readme.md

@@ -26,7 +26,7 @@
 오픈나무는 오픈소스 프로젝트입니다. 원한다면 직접 코드를 수정하고 [Pull Request](https://github.com/openNAMU/openNAMU/compare)를 보낼 수 있습니다.
 오픈나무는 오픈소스 프로젝트입니다. 원한다면 직접 코드를 수정하고 [Pull Request](https://github.com/openNAMU/openNAMU/compare)를 보낼 수 있습니다.
 
 
 ## 라이선스
 ## 라이선스
-오픈나무 프로젝트는 [BSD 3-Clause License](./LICENSE)의 보호를 받고 있으며, 오픈나무 프로젝트를 사용하고자 한다면 라이선스를 준수해야 합니다. 본 라이선스를 위반할 경우 법적인 조치가 취해질 수 있습니다. 자세한 내용은 문서를 참고하세요.
+오픈나무 프로젝트는 [BSD 3-Clause License](./LICENSE) [(ko-KR)](https://www.olis.or.kr/license/Detailselect.do?lId=1092)이며, 오픈나무 프로젝트를 사용하고자 한다면 라이선스를 준수해야 합니다. 자세한 내용은 문서를 참고하세요.
 
 
 ### 포함된 외부 프로젝트
 ### 포함된 외부 프로젝트
  * Quotes icon - [Dave Gandy](http://www.flaticon.com/free-icon/quote-left_25672)
  * Quotes icon - [Dave Gandy](http://www.flaticon.com/free-icon/quote-left_25672)

+ 0 - 1
requirements.txt

@@ -1,7 +1,6 @@
 flask
 flask
 
 
 waitress
 waitress
-netius
 
 
 requests
 requests
 
 

+ 18 - 0
route/api_func_lang.py

@@ -0,0 +1,18 @@
+from .tool.func import *
+
+def api_func_lang(data = 'Test'):
+    with get_db_connect() as conn:
+        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] = load_lang(i)
+
+            return flask.jsonify(data_list)
+        else:
+            return flask.jsonify({ "data" : load_lang(data) })

+ 18 - 0
route/api_func_sha224.py

@@ -0,0 +1,18 @@
+from .tool.func import *
+
+def api_func_sha224(data = 'Test'):
+    with get_db_connect() as conn:
+        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) })

+ 18 - 17
route/api_image_view.py

@@ -1,21 +1,22 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def api_image_view(name = 'Test'):
 def api_image_view(name = 'Test'):
-    if flask.request.method == 'POST':
-        try:
-            title_list = json.loads(flask.request.form.get('title_list', ''))
-            title_list = list(set(title_list))
-        except:
-            title_list = []
-        
-        data_list = {}
-        for i in title_list:
-            if os.path.exists(os.path.join(load_image_url(), i)):
-                data_list[i] = '1'
-        
-        return flask.jsonify(data_list)
-    else:
-        if os.path.exists(os.path.join(load_image_url(), name)):
-            return flask.jsonify({ "exist" : "1" })
+    with get_db_connect() as conn:
+        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:
         else:
-            return flask.jsonify({})
+            if os.path.exists(os.path.join(load_image_url(), name)):
+                return flask.jsonify({ "exist" : "1" })
+            else:
+                return flask.jsonify({})

+ 0 - 12
route/api_markup.py

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

+ 0 - 17
route/api_sha224.py

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

+ 0 - 56
route/api_sitemap.py

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

+ 76 - 0
route/api_topic.py

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

+ 0 - 65
route/api_topic_sub.py

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

+ 54 - 76
route/api_user_info.py

@@ -7,7 +7,7 @@ def api_user_info(name = ''):
         if flask.request.method == 'POST':
         if flask.request.method == 'POST':
             try:
             try:
                 data_list = json.loads(flask.request.form.get('title_list', ''))
                 data_list = json.loads(flask.request.form.get('title_list', ''))
-                data_list = list(set(title_list))
+                data_list = list(set(data_list))
             except:
             except:
                 data_list = [name]
                 data_list = [name]
 
 
@@ -15,6 +15,9 @@ def api_user_info(name = ''):
             for user_name in data_list:
             for user_name in data_list:
                 data_result[user_name] = {}
                 data_result[user_name] = {}
                 
                 
+                # name part
+                data_result[user_name]['render'] = ip_pas(user_name)
+                
                 # auth part
                 # auth part
                 curs.execute(db_change("select data from user_set where id = ? and name = 'acl'"), [user_name])
                 curs.execute(db_change("select data from user_set where id = ? and name = 'acl'"), [user_name])
                 db_data = curs.fetchall()
                 db_data = curs.fetchall()
@@ -24,18 +27,62 @@ def api_user_info(name = ''):
                         if curs.fetchall():
                         if curs.fetchall():
                             data_result[user_name]['auth'] = db_data[0][0]
                             data_result[user_name]['auth'] = db_data[0][0]
                         else:
                         else:
-                            data_result[user_name]['auth'] = 1
+                            data_result[user_name]['auth'] = '1'
                     else:
                     else:
-                        data_result[user_name]['auth'] = 1
+                        data_result[user_name]['auth'] = '1'
+                else:
+                    data_result[user_name]['auth'] = '0'
+                    
+                # ban part
+                if ban_check(name) == 0:
+                    data_result[user_name]['ban'] = '0'
                 else:
                 else:
-                    data_result[user_name]['auth'] = 0
+                    data_result[user_name]['ban'] = {}
+                    regex_ban = 0
+                    
+                    curs.execute(db_change("select login, block, end, why from rb where band = 'regex' and ongoing = '1'"))
+                    for db_data in curs.fetchall():
+                        if re.compile(db_data[1]).search(user_name):
+                            regex_ban = 1
+                            
+                            data_result[user_name]['ban']['type'] = 'regex'
+                            if db_data[0] == 'O':
+                                data_result[user_name]['ban']['login_able'] = '1'
+                            else:
+                                data_result[user_name]['ban']['login_able'] = '0'
+                                
+                            if db_data[2] == '':
+                                data_result[user_name]['ban']['period'] = '0'
+                            else:
+                                data_result[user_name]['ban']['period'] = db_data[2]
+                                
+                            data_result[user_name]['ban']['reason'] = db_data[3]
+                            
+                            break
+                            
+                    if regex_ban == 0:
+                        curs.execute(db_change("select login, block, end, why from rb where block = ? and ongoing = '1'"), [user_name])
+                        db_data = curs.fetchall()
+                        if db_data:
+                            data_result[user_name]['ban']['type'] = 'normal'
+                            if db_data[0][0] == 'O':
+                                data_result[user_name]['ban']['login_able'] = '1'
+                            else:
+                                data_result[user_name]['ban']['login_able'] = '0'
+                                
+                            if db_data[0][2] == '':
+                                data_result[user_name]['ban']['period'] = '0'
+                            else:
+                                data_result[user_name]['ban']['period'] = db_data[0][2]
+                                
+                            data_result[user_name]['ban']['reason'] = db_data[0][3]
                 
                 
                 # user document part
                 # user document part
                 curs.execute(db_change("select title from data where title = ?"), ['user:' + user_name])
                 curs.execute(db_change("select title from data where title = ?"), ['user:' + user_name])
                 if curs.fetchall():
                 if curs.fetchall():
-                    data_result[user_name]['document'] = 1
+                    data_result[user_name]['document'] = '1'
                 else:
                 else:
-                    data_result[user_name]['document'] = 0
+                    data_result[user_name]['document'] = '0'
 
 
                 # user title part
                 # user title part
                 curs.execute(db_change('select data from user_set where name = "user_title" and id = ?'), [user_name])
                 curs.execute(db_change('select data from user_set where name = "user_title" and id = ?'), [user_name])
@@ -47,73 +94,4 @@ def api_user_info(name = ''):
                     
                     
             return flask.jsonify(data_result)
             return flask.jsonify(data_result)
         else:
         else:
-            if flask.request.args.get('render', None):
-                plus_d = ''
-                plus_t = []
-
-                curs.execute(db_change("update rb set ongoing = '' where end < ? and end != '' and ongoing = '1'"), [get_time()])
-                conn.commit()
-
-                plus_d = '''
-                    <table class="user_info_table">
-                        <tbody>
-                            <tr>
-                                <td>''' + load_lang('user_name') + '''</td>
-                                <td>{}</td>
-                            </tr>
-                            <tr>
-                                <td>''' + load_lang('authority') + '''</td>
-                                <td>{}</td>
-                            </tr>
-                            <tr>
-                                <td>''' + load_lang('state') + '''</td>
-                                <td>{}</td>
-                            </tr>
-                        </tbody>
-                    </table>
-                '''
-
-                curs.execute(db_change("select data from user_set where id = ? and name = 'acl'"), [name])
-                data = curs.fetchall()
-                if data:
-                    if data[0][0] != 'user':
-                        curs.execute(db_change("select name from alist where name = ?"), [data[0][0]])
-                        if curs.fetchall():
-                            plus_t += [data[0][0]]
-                        else:
-                            plus_t += [load_lang('member')]
-                    else:
-                        plus_t += [load_lang('member')]
-                else:
-                    plus_t += [load_lang('normal')]
-
-                if ban_check(name) == 0:
-                    plus_t += [load_lang('normal')]
-                else:
-                    plus_t += [load_lang('blocked') + '<br>']
-                    regex_ban = 0
-
-                    curs.execute(db_change("select login, block, end, why from rb where band = 'regex' and ongoing = '1'"))
-                    for test_r in curs.fetchall():
-                        if re.compile(test_r[1]).search(name):
-                            plus_t[1] += load_lang('type') + ' : ' + load_lang('regex')
-                            plus_t[1] += '<br>' + load_lang('period') + ' : ' + (test_r[2] if test_r[2] != '' else load_lang('limitless'))
-                            plus_t[1] += ('<br>' + load_lang('login_able') if test_r[0] == 'O' else '')
-                            plus_t[1] += ('<br>' + load_lang('why') + ' : ' + test_r[3] if test_r[3] != '' else '')
-                            regex_ban = 1
-
-                    if regex_ban == 0:
-                        curs.execute(db_change("select end, login, band, why from rb where block = ? and ongoing = '1'"), [name])
-                        block_data = curs.fetchall()
-                        if block_data:
-                            plus_t[1] += load_lang('type') + ' : ' + (load_lang('band_blocked') if block_data[0][2] == 'O' else load_lang('normal'))
-                            plus_t[1] += (' (' + load_lang('login_able') + ')' if block_data[0][1] != '' else '')
-                            plus_t[1] += '<br>' + load_lang('period') + ' : ' + (block_data[0][0] if block_data[0][0] != '' else load_lang('limitless'))
-                            plus_t[1] += ('<br>' + load_lang('band_blocked') if block_data[0][2] == 'O' else '')
-                            plus_t[1] += ('<br>' + load_lang('why') + ' : ' + block_data[0][3] if block_data[0][3] != '' else '')
-
-                plus_d = plus_d.format(ip_pas(name), plus_t[0], plus_t[1])
-
-                return flask.jsonify({ "data" : plus_d })
-            else:
-                return flask.jsonify({})
+            return flask.jsonify({})

+ 211 - 89
route/edit.py

@@ -1,11 +1,11 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def edit(name = 'Test', name_load = 0, section = 0):
+def edit(name = 'Test', section = 0, do_type = ''):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
     
     
         ip = ip_check()
         ip = ip_check()
-        if acl_check(name) == 1:
+        if acl_check(name, 'document_edit') == 1:
             return redirect('/raw_acl/' + url_pas(name))
             return redirect('/raw_acl/' + url_pas(name))
         
         
         if do_title_length_check(name) == 1:
         if do_title_length_check(name) == 1:
@@ -19,6 +19,7 @@ def edit(name = 'Test', name_load = 0, section = 0):
         post_ver = flask.request.form.get('ver', '')
         post_ver = flask.request.form.get('ver', '')
         if flask.request.method == 'POST':
         if flask.request.method == 'POST':
             edit_repeat = 'error' if post_ver != doc_ver else 'post'
             edit_repeat = 'error' if post_ver != doc_ver else 'post'
+            edit_repeat = 'error' if do_type == 'preview' else 'post'
         else:
         else:
             edit_repeat = 'get'
             edit_repeat = 'get'
         
         
@@ -32,7 +33,7 @@ def edit(name = 'Test', name_load = 0, section = 0):
                 return re_error('/error/24')
                 return re_error('/error/24')
     
     
             today = get_time()
             today = get_time()
-            content = flask.request.form.get('content', '').replace('\r\n', '\n')
+            content = flask.request.form.get('content', '').replace('\r', '')
             send = flask.request.form.get('send', '')
             send = flask.request.form.get('send', '')
             agree = flask.request.form.get('copyright_agreement', '')
             agree = flask.request.form.get('copyright_agreement', '')
             
             
@@ -46,16 +47,42 @@ def edit(name = 'Test', name_load = 0, section = 0):
                 return re_error('/error/29')
                 return re_error('/error/29')
             
             
             curs.execute(db_change("select data from data where title = ?"), [name])
             curs.execute(db_change("select data from data where title = ?"), [name])
-            old = curs.fetchall()
-            if old:  
-                o_data = old[0][0].replace('\r\n', '\n')
+            db_data = curs.fetchall()
+            if db_data:
+                o_data = db_data[0][0].replace('\r', '')
+
+                if section != '':
+                    if flask.request.form.get('doc_section_edit_apply', 'X') != 'X':
+                        if flask.request.form.get('doc_section_data_where', '') != '':
+                            data_match_where = flask.request.form.get('doc_section_data_where', '').split(',')
+                            if len(data_match_where) == 2:
+                                data_match_a = int(number_check(data_match_where[0]))
+                                if data_match_where[1] != 'inf':
+                                    data_match_b = int(number_check(data_match_where[1]))
+                                else:
+                                    data_match_b = 'inf'
+
+                                try:
+                                    if data_match_b != 'inf':
+                                        content = o_data[ : data_match_a] + content + o_data[data_match_b : ]
+                                    else:
+                                        content = o_data[ : data_match_a] + content
+                                except:
+                                    pass
     
     
                 leng = leng_check(len(o_data), len(content))
                 leng = leng_check(len(o_data), len(content))
-                
-                curs.execute(db_change("update data set data = ? where title = ?"), [content, name])
             else:
             else:
                 leng = '+' + str(len(content))
                 leng = '+' + str(len(content))
-    
+
+            render_set(
+                doc_name = name,
+                doc_data = content,
+                data_in = ''
+            )
+                
+            if db_data:
+                curs.execute(db_change("update data set data = ? where title = ?"), [content, name])
+            else:    
                 curs.execute(db_change("insert into data (title, data) values (?, ?)"), [name, content])
                 curs.execute(db_change("insert into data (title, data) values (?, ?)"), [name, content])
     
     
                 curs.execute(db_change('select data from other where name = "count_all_title"'))
                 curs.execute(db_change('select data from other where name = "count_all_title"'))
@@ -63,7 +90,7 @@ def edit(name = 'Test', name_load = 0, section = 0):
     
     
             curs.execute(db_change("select user from scan where title = ? and type = ''"), [name])
             curs.execute(db_change("select user from scan where title = ? and type = ''"), [name])
             for scan_user in curs.fetchall():
             for scan_user in curs.fetchall():
-                add_alarm(scan_user[0], ip + ' | <a href="/w/' + url_pas(name) + '">' + name + '</a> | Edit')
+                add_alarm(scan_user[0], ip + ' | <a href="/w/' + url_pas(name) + '">' + html.escape(name) + '</a> | Edit')
                     
                     
             history_plus(
             history_plus(
                 name,
                 name,
@@ -90,8 +117,21 @@ def edit(name = 'Test', name_load = 0, section = 0):
             return redirect('/w/' + url_pas(name) + section)
             return redirect('/w/' + url_pas(name) + section)
         else:
         else:
             editor_top_text = ''
             editor_top_text = ''
+
+            doc_section_edit_apply = 'X'
+            data_section = ''
+            data_section_where = ''
+            data_preview = ''
+
             if edit_repeat == 'get':
             if edit_repeat == 'get':
-                load_title = name_load
+                if do_type == 'load':
+                    if flask.session and 'edit_load_document' in flask.session:
+                        load_title = flask.session['edit_load_document']
+                    else:
+                        load_title = 0
+                else:
+                    load_title = 0
+                
                 if load_title == 0 and section == '':
                 if load_title == 0 and section == '':
                     load_title = name
                     load_title = name
                     editor_top_text += '<a href="/manager/15/' + url_pas(name) + '">(' + load_lang('load') + ')</a> '
                     editor_top_text += '<a href="/manager/15/' + url_pas(name) + '">(' + load_lang('load') + ')</a> '
@@ -99,47 +139,113 @@ def edit(name = 'Test', name_load = 0, section = 0):
                     load_title = name
                     load_title = name
                     
                     
                 curs.execute(db_change("select data from data where title = ?"), [load_title])
                 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')
+                db_data = curs.fetchall()
+                data = db_data[0][0] if db_data else ''
+                data = data.replace('\r', '')
+
+                if section != '':
+                    curs.execute(db_change('select data from other where name = "markup"'))
+                    db_data = curs.fetchall()
+                    db_data = db_data[0][0] if db_data else 'namumark'
+                    if db_data in ('namumark', 'namumark_beta'):
+                        count = 1
+                        data_section = '\n' + data + '\n'
+                        
+                        while 1:
+                            data_match_re = r'\n((={1,6})(#?) ?([^\n]+))\n'
+                            data_match = re.search(data_match_re, data_section)
+                            if not data_match:
+                                data_section = ''
+
+                                break
+                            elif count > section:
+                                data_section = ''
+
+                                break
+
+                            if section == count:
+                                data_section_sub = data_section
+                                data_section_sub = re.sub(data_match_re, ('.' * (len(data_match.group(0)) - 1)) + '\n', data_section_sub, 1)
+
+                                data_match_plus = re.search(data_match_re, data_section_sub)
+                                if data_match_plus:
+                                    data_section = data[data_match.span()[0] : data_match_plus.span()[0] - 1]
+                                    data_section_where = str(data_match.span()[0]) + ',' + str(data_match_plus.span()[0] - 1)
+                                else:
+                                    data_section = data[data_match.span()[0] : ]
+                                    data_section_where = str(data_match.span()[0]) + ',inf'
+
+                                doc_section_edit_apply = 'O'
+
+                                break
+                            else:
+                                data_section = re.sub(data_match_re, ('.' * (len(data_match.group(0)) - 1)) + '\n', data_section, 1)
+
+                            count += 1
             else:
             else:
                 data = flask.request.form.get('content', '')
                 data = flask.request.form.get('content', '')
-                warning_edit = load_lang('exp_edit_conflict') + ' '
-    
-                if flask.request.form.get('ver', '0') == '0':
-                    warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
+                data = data.replace('\r', '')
+                
+                data_section_where = flask.request.form.get('doc_section_data_where', '')
+                doc_section_edit_apply = flask.request.form.get('doc_section_edit_apply', '')
+
+                doc_ver = flask.request.form.get('ver', '')
+
+                if do_type != 'preview':
+                    warning_edit = load_lang('exp_edit_conflict') + ' '
+        
+                    if flask.request.form.get('ver', '0') == '0':
+                        warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
+                    else:
+                        warning_edit += '' + \
+                            '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
+                                '(r' + doc_ver + ')' + \
+                            '</a>' + \
+                        ''
+        
+                    warning_edit += '<hr class="main_hr">'
+                    editor_top_text = warning_edit + editor_top_text
                 else:
                 else:
-                    warning_edit += '' + \
-                        '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
-                            '(r' + doc_ver + ')' + \
-                        '</a>' + \
-                    ''
-    
-                warning_edit += '<hr class="main_hr">'
-                editor_top_text = warning_edit + editor_top_text
+                    data_preview = render_set(
+                        doc_name = name, 
+                        doc_data = data,
+                        data_in = 'from'
+                    )
+
+            if data_section == '':
+                data_section = data
+
+            if section == '':
+                form_action = 'formaction="/edit/' + url_pas(name) + '"'
+                form_action_preview = 'formaction="/edit_preview/' + url_pas(name) + '"'
+            else:
+                form_action = 'formaction="/edit_section/' + str(section) + '/' + url_pas(name) + '"'
+                form_action_preview = 'formaction="/edit_section_preview/' + str(section) + '/' + url_pas(name) + '"'
     
     
-            editor_top_text += '' + \
-                '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>' + \
-                '<hr class="main_hr">' + \
-            ''
+            editor_top_text += '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
     
     
             curs.execute(db_change('select data from other where name = "edit_help"'))
             curs.execute(db_change('select data from other where name = "edit_help"'))
             sql_d = curs.fetchall()
             sql_d = curs.fetchall()
             p_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('default_edit_help')
             p_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('default_edit_help')
-    
-            data = re.sub(r'\n+$', '', data)
             
             
-            # 이 파트 JS로 이동 예정
-            monaco_on = flask.request.cookies.get('main_css_monaco', '0')
-            if monaco_on == '1':
+            if ip_or_user(ip) == 0:
+                curs.execute(db_change('select data from user_set where name = "main_css_monaco" and id = ?'), [ip])
+                db_data = curs.fetchall()
+                monaco_on = db_data[0][0] if db_data else 'normal'
+            else:
+                monaco_on = flask.session['main_css_monaco'] if 'main_css_monaco' in flask.session else 'normal'
+            
+            if monaco_on == 'use':
                 editor_display = 'style="display: none;"'
                 editor_display = 'style="display: none;"'
                 monaco_display = ''
                 monaco_display = ''
                 add_get_file = '''
                 add_get_file = '''
                     <link   rel="stylesheet"
                     <link   rel="stylesheet"
                             data-name="vs/editor/editor.main" 
                             data-name="vs/editor/editor.main" 
-                            href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.min.css">
-                    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/loader.min.js"></script>
+                            href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs/editor/editor.main.min.css">
+                    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs/loader.min.js"></script>
                 '''
                 '''
+
+                editor_top_text += ' <a href="javascript:opennamu_edit_turn_off_monaco();">(' + load_lang('turn_off_monaco') + ')</a>'
                 
                 
                 if flask.request.cookies.get('main_css_darkmode', '0') == '1':
                 if flask.request.cookies.get('main_css_darkmode', '0') == '1':
                     monaco_thema = 'vs-dark'
                     monaco_thema = 'vs-dark'
@@ -147,14 +253,15 @@ def edit(name = 'Test', name_load = 0, section = 0):
                     monaco_thema = ''
                     monaco_thema = ''
                 
                 
                 add_script = '''
                 add_script = '''
-                    require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs' }});
+                    require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs' }});
+                    require.config({ 'vs/nls': { availableLanguages: { '*': 'ko' } }});
                     require(["vs/editor/editor.main"], function () {
                     require(["vs/editor/editor.main"], function () {
-                        window.editor = monaco.editor.create(document.getElementById('monaco_editor'), {
-                            value: document.getElementById('textarea_edit_view').value,
+                        window.editor = monaco.editor.create(document.getElementById('opennamu_monaco_editor'), {
+                            value: document.getElementById('opennamu_edit_textarea').value,
                             language: 'plaintext',
                             language: 'plaintext',
+                            automaticLayout: true,
                             wordWrap: true,
                             wordWrap: true,
-                            theme: \'''' + monaco_thema + '''\',
-                            minimap: { enabled: false }
+                            theme: \'''' + monaco_thema + '''\'
                         });
                         });
                     });
                     });
                 '''
                 '''
@@ -162,63 +269,78 @@ def edit(name = 'Test', name_load = 0, section = 0):
                 editor_display = ''
                 editor_display = ''
                 monaco_display = 'style="display: none;"'
                 monaco_display = 'style="display: none;"'
                 add_get_file = ''
                 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
-             }
+                add_script = 'opennamu_edit_turn_off_monaco();'
+
+            if editor_top_text != '':
+                editor_top_text += '<hr class="main_hr">'
+
+            sub_menu = ' (' + str(section) + ')' if section != '' else ''
     
     
             return easy_minify(flask.render_template(skin_check(), 
             return easy_minify(flask.render_template(skin_check(), 
-                imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('edit') + ')', 0])],
+                imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('edit') + ')' + sub_menu, 0])],
                 data =  editor_top_text + add_get_file + '''
                 data =  editor_top_text + add_get_file + '''
-                    <span   id="server_set"
-                            style="display: none;">''' + json.dumps(server_set) + '''</span>
+                    <script>
+                        function opennamu_edit_turn_off_monaco() {
+                            do_monaco_to_textarea();
+                            
+                            document.getElementById('opennamu_edit_textarea').style.display = 'block';
+                            document.getElementById('opennamu_monaco_editor').style.display = 'none';
+                            document.getElementById('opennamu_monaco_editor').remove();
+                        }
+
+                        function do_monaco_to_textarea() {
+                            if(document.getElementById('opennamu_monaco_editor')) {
+                                try {
+                                    document.getElementById('opennamu_edit_textarea').value = window.editor.getValue();
+                                } catch(e) {}
+                            }
+                        }
+                    </script>
                     <form method="post">
                     <form method="post">
-                        <div>''' + edit_button(monaco_on) + '''</div>
-                        <div    id="monaco_editor"
-                                class="content" 
-                                ''' + monaco_display + '''></div>
-                        <textarea   id="textarea_edit_view"
-                                    ''' + editor_display + '''
-                                    class="content"
-                                    placeholder="''' + p_text + '''">''' + html.escape(data) + '''</textarea>
+                        <textarea style="display: none;" id="opennamu_edit_origin" name="doc_data_org">''' + html.escape(data_section) + '''</textarea>
+                        <textarea style="display: none;" name="doc_section_data_where">''' + data_section_where + '''</textarea>
+                        <input style="display: none;" name="doc_section_edit_apply" value="''' + doc_section_edit_apply + '''">
+
+                        <input style="display: none;" name="ver" value="''' + doc_ver + '''">
+                        
+                        <div>''' + edit_button('opennamu_edit_textarea', 'opennamu_monaco_editor') + '''</div>
+                        
+                        <div id="opennamu_monaco_editor" class="opennamu_textarea_500" ''' + monaco_display + '''></div>
+                        <textarea id="opennamu_edit_textarea" ''' + editor_display + ''' class="opennamu_textarea_500" name="content" placeholder="''' + p_text + '''">''' + html.escape(data_section) + '''</textarea>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <input  placeholder="''' + load_lang('why') + '''" 
-                                name="send">
-                        <textarea   style="display: none;" 
-                                    id="origin">''' + html.escape(data) + '''</textarea>
-                        <textarea   style="display: none;"
-                                    name="content"
-                                    id="content"></textarea>
-                        <input  style="display: none;" 
-                                name="ver" 
-                                value="''' + doc_ver + '''">
+                        
+                        <input placeholder="''' + load_lang('why') + '''" name="send">
                         <hr class="main_hr">
                         <hr class="main_hr">
+                        
                         ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
                         ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
-                        <button id="save"
-                                type="submit" 
-                                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>
+                        
+                        <button id="opennamu_save_button" type="submit" ''' + form_action + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_preview_button" type="submit" ''' + form_action_preview + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
                     </form>
                     </form>
+                    
                     <hr class="main_hr">
                     <hr class="main_hr">
-                    <div id="see_preview"></div>
+                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
+                    
                     <script>
                     <script>
-                        section_edit_init();
-                        do_paste_image();
-                        do_not_out();
+                        function do_stop_exit() {
+                            window.onbeforeunload = function() {
+                                do_monaco_to_textarea();
+
+                                let data = document.getElementById('opennamu_edit_textarea').value;
+                                let origin = document.getElementById('opennamu_edit_origin').value;
+                                if(data !== origin) {
+                                    return '';
+                                }
+                            }
+                        }
+
+                        function do_stop_exit_release() {
+                            window.onbeforeunload = function () {}
+                        }
+
+                        do_stop_exit();
+                        do_paste_image('opennamu_edit_textarea', 'opennamu_monaco_editor');
+
                         ''' + add_script + '''
                         ''' + add_script + '''
                     </script>
                     </script>
                 ''',
                 ''',

+ 2 - 2
route/edit_delete.py

@@ -5,7 +5,7 @@ def edit_delete(name):
         curs = conn.cursor()
         curs = conn.cursor()
 
 
         ip = ip_check()
         ip = ip_check()
-        if acl_check(name) == 1:
+        if acl_check(name, 'document_delete') == 1:
             return re_error('/ban')
             return re_error('/ban')
 
 
         curs.execute(db_change("select title from data where title = ?"), [name])
         curs.execute(db_change("select title from data where title = ?"), [name])
@@ -64,7 +64,7 @@ def edit_delete(name):
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('delete') + ')', 0])],
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('delete') + ')', 0])],
                 data = '''
                 data = '''
                     <form method="post">
                     <form method="post">
-                        <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
+                        <input placeholder="''' + load_lang('why') + '''" name="send">
                         <hr class="main_hr">
                         <hr class="main_hr">
                         ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
                         ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
                         <button type="submit">''' + load_lang('delete') + '''</button>
                         <button type="submit">''' + load_lang('delete') + '''</button>

+ 4 - 4
route/edit_delete_mutiple.py → route/edit_delete_multiple.py

@@ -1,7 +1,7 @@
 from .tool.func import *
 from .tool.func import *
 from . import edit_delete
 from . import edit_delete
 
 
-def edit_delete_mutiple():
+def edit_delete_multiple():
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
 
 
@@ -19,17 +19,17 @@ def edit_delete_mutiple():
             if do_edit_text_bottom_check_box_check(agree) == 1:
             if do_edit_text_bottom_check_box_check(agree) == 1:
                 return re_error('/error/29')
                 return re_error('/error/29')
             
             
-            all_title = re.findall(r'([^\n]+)\n', flask.request.form.get('content', '').replace('\r\n', '\n') + '\n')
+            all_title = re.findall(r'([^\n]+)\n', flask.request.form.get('content', '').replace('\r', '') + '\n')
             for name in all_title:
             for name in all_title:
                 edit_delete.edit_delete(name)
                 edit_delete.edit_delete(name)
 
 
-            return redirect('/recent_changes')
+            return redirect('/recent_change')
         else:
         else:
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('many_delete'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = [load_lang('many_delete'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                 data = '''
                     <form method="post">
                     <form method="post">
-                        <textarea rows="25" placeholder="''' + load_lang('many_delete_help') + '''" name="content"></textarea>
+                        <textarea class="opennamu_textarea_500" placeholder="''' + load_lang('many_delete_help') + '''" name="content"></textarea>
                         <hr class="main_hr">
                         <hr class="main_hr">
                         <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
                         <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
                         <hr class="main_hr">
                         <hr class="main_hr">

+ 148 - 31
route/edit_move.py

@@ -4,7 +4,7 @@ def edit_move(name):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
 
 
-        if acl_check(name) == 1:
+        if acl_check(name, 'document_move') == 1:
             return re_error('/ban')
             return re_error('/ban')
         
         
         if do_title_length_check(name) == 1:
         if do_title_length_check(name) == 1:
@@ -25,18 +25,29 @@ def edit_move(name):
             
             
             send = flask.request.form.get('send', '')
             send = flask.request.form.get('send', '')
             agree = flask.request.form.get('copyright_agreement', '')
             agree = flask.request.form.get('copyright_agreement', '')
+
             time = get_time()
             time = get_time()
             ip = ip_check()
             ip = ip_check()
             
             
+            has_error = 0
+
+            move_option = flask.request.form.get('move_option', 'none')
+            move_option_topic = flask.request.form.get('move_topic_option', 'none')
+            document_set_option = flask.request.form.get('document_set_option', 'none')
+            
             if do_edit_send_check(send) == 1:
             if do_edit_send_check(send) == 1:
                 return re_error('/error/37')
                 return re_error('/error/37')
             
             
             if do_edit_text_bottom_check_box_check(agree) == 1:
             if do_edit_text_bottom_check_box_check(agree) == 1:
                 return re_error('/error/29')
                 return re_error('/error/29')
 
 
+            # 문서 이동 파트 S
             curs.execute(db_change("select title from history where title = ?"), [move_title])
             curs.execute(db_change("select title from history where title = ?"), [move_title])
             if curs.fetchall():
             if curs.fetchall():
-                if flask.request.form.get('move_option', 'normal') == 'merge' and admin_check(None, 'merge documents') == 1:
+                if (
+                    move_option == 'merge' and 
+                    admin_check(None, 'merge documents (' + name + ') (' + move_title + ')') == 1
+                ):
                     curs.execute(db_change("select data from data where title = ?"), [move_title])
                     curs.execute(db_change("select data from data where title = ?"), [move_title])
                     data = curs.fetchall()
                     data = curs.fetchall()
                     if data:
                     if data:
@@ -87,30 +98,26 @@ def edit_move(name):
                             name, 
                             name, 
                             move[0]
                             move[0]
                         ])
                         ])
-
-                    conn.commit()
-
-                    return redirect('/w/' + url_pas(move_title))
-                elif flask.request.form.get('move_option', 'normal') == 'reverse':
-                    var_name = ''
+                elif move_option == 'reverse':
                     i = 0
                     i = 0
-                    while 1:
+                    var_name = ''
+                    while var_name == '':
                         curs.execute(db_change("select title from history where title = ?"), ['test ' + str(i)])
                         curs.execute(db_change("select title from history where title = ?"), ['test ' + str(i)])
                         if not curs.fetchall():
                         if not curs.fetchall():
-                            curs.execute(db_change("select data from data where title = ?"), [name])
-                            data = curs.fetchall()
-                            if data:
-                                curs.execute(db_change("update data set title = ? where title = ?"), ['test ' + str(i), name])
-                                curs.execute(db_change("update back set link = ? where link = ?"), ['test ' + str(i), name])
-
-                            curs.execute(db_change("update history set title = ? where title = ?"), ['test ' + str(i), name])
-                            curs.execute(db_change("update rc set title = ? where title = ?"), ['test ' + str(i), name])
-
-                            break
+                            var_name = 'test ' + str(i)
                         else:
                         else:
                             i += 1
                             i += 1
 
 
-                    for title_name in [[move_title, name], ['test ' + str(i), move_title]]:
+                    curs.execute(db_change("select data from data where title = ?"), [name])
+                    data = curs.fetchall()
+                    if data:
+                        curs.execute(db_change("update data set title = ? where title = ?"), [var_name, name])
+                        curs.execute(db_change("update back set link = ? where link = ?"), [var_name, name])
+
+                    curs.execute(db_change("update history set title = ? where title = ?"), [var_name, name])
+                    curs.execute(db_change("update rc set title = ? where title = ?"), [var_name, name])
+
+                    for title_name in [[move_title, name], [var_name, move_title]]:
                         curs.execute(db_change("select data from data where title = ?"), [title_name[0]])
                         curs.execute(db_change("select data from data where title = ?"), [title_name[0]])
                         data = curs.fetchall()
                         data = curs.fetchall()
                         if data:
                         if data:
@@ -128,18 +135,15 @@ def edit_move(name):
                             ip,
                             ip,
                             send,
                             send,
                             '0',
                             '0',
-                            t_check = '<a>' + (title_name[0] if title_name[0] != 'test ' + str(i) else name) + '</a> - <a>' + title_name[1] + '</a> move',
+                            t_check = '<a>' + (title_name[0] if title_name[0] != var_name else name) + '</a> - <a>' + title_name[1] + '</a> move',
                             mode = 'move'
                             mode = 'move'
                         )
                         )
 
 
                         curs.execute(db_change("update history set title = ? where title = ?"), [title_name[1], title_name[0]])
                         curs.execute(db_change("update history set title = ? where title = ?"), [title_name[1], title_name[0]])
                         curs.execute(db_change("update rc set title = ? where title = ?"), [title_name[1], title_name[0]])
                         curs.execute(db_change("update rc set title = ? where title = ?"), [title_name[1], title_name[0]])
-                        conn.commit()
-
-                    return redirect('/w/' + url_pas(move_title))
-                else:
-                    return re_error('/error/19')
-            else:
+                elif move_option != 'none':
+                    has_error = 1
+            elif move_option != 'none':                
                 curs.execute(db_change("select data from data where title = ?"), [name])
                 curs.execute(db_change("select data from data where title = ?"), [name])
                 data = curs.fetchall()
                 data = curs.fetchall()
                 if data:
                 if data:
@@ -166,26 +170,139 @@ def edit_move(name):
 
 
                 curs.execute(db_change("update history set title = ? where title = ?"), [move_title, name])
                 curs.execute(db_change("update history set title = ? where title = ?"), [move_title, name])
                 curs.execute(db_change("update rc set title = ? where title = ?"), [move_title, name])
                 curs.execute(db_change("update rc set title = ? where title = ?"), [move_title, name])
-                conn.commit()
+                
+            # 문서 이동 파트 E
+            
+            # 토론 이동 파트 S
+            if (
+                move_option_topic == 'merge' and
+                admin_check(None, 'merge document\'s topics (' + name + ') (' + move_title + ')') == 1
+            ):
+                curs.execute(db_change("update rd set title = ? where title = ?"), [move_title, name])
+            elif move_option_topic == 'reverse':
+                i = 0
+                var_name = ''
+                while var_name == '':
+                    curs.execute(db_change("select title from rd where title = ?"), ['test ' + str(i)])
+                    if not curs.fetchall():
+                        var_name = 'test ' + str(i)
+                    else:
+                        i += 1
+                
+                curs.execute(db_change("update rd set title = ? where title = ?"), [var_name, move_title])
+                curs.execute(db_change("update rd set title = ? where title = ?"), [move_title, name])
+                curs.execute(db_change("update rd set title = ? where title = ?"), [name, var_name])
+            elif move_option_topic == 'normal':
+                curs.execute(db_change("select title from rd where title = ?"), [move_title])
+                if curs.fetchall():
+                    has_error = 1
+                else:
+                    curs.execute(db_change("update rd set title = ? where title = ?"), [move_title, name])
 
 
+            # 토론 이동 파트 E
+
+            # data_set 이동 파트 S
+            if document_set_option == 'reverse':
+                i = 0
+                var_name = ''
+                while var_name == '':
+                    curs.execute(db_change("select title from rd where title = ?"), ['test ' + str(i)])
+                    if not curs.fetchall():
+                        var_name = 'test ' + str(i)
+                    else:
+                        i += 1
+                
+                # create_data['data_set'] = ['doc_name', 'doc_rev', 'set_name', 'set_data']
+                # create_data['acl'] = ['title', 'data', 'type']
+                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [var_name, move_title])
+                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [move_title, name])
+                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [name, var_name])
+
+                curs.execute(db_change("update acl set title = ? where title = ?"), [var_name, move_title])
+                curs.execute(db_change("update acl set title = ? where title = ?"), [move_title, name])
+                curs.execute(db_change("update acl set title = ? where title = ?"), [name, var_name])
+            elif document_set_option == 'normal':
+                curs.execute(db_change("delete from data_set where doc_name = ?"), [move_title])
+                curs.execute(db_change("update data_set set doc_name = ? where doc_name = ?"), [move_title, name])
+
+                curs.execute(db_change("delete from acl where title = ?"), [move_title])
+                curs.execute(db_change("update acl set title = ? where title = ?"), [move_title, name])
+
+            if document_set_option != 'reverse':
+                curs.execute(db_change("select data from data where title = ?"), [name])
+                db_data = curs.fetchall()
+                if db_data:
+                    render_set(
+                        doc_name = name,
+                        doc_data = db_data[0][0],
+                        data_type = 'backlink'
+                    )
+
+                curs.execute(db_change("select data from data where title = ?"), [move_title])
+                db_data = curs.fetchall()
+                if db_data:
+                    render_set(
+                        doc_name = move_title,
+                        doc_data = db_data[0][0],
+                        data_type = 'backlink'
+                    )
+
+            # data_set 이동 파트 E
+                
+            conn.commit()
+
+            if has_error == 0:
                 return redirect('/w/' + url_pas(move_title))
                 return redirect('/w/' + url_pas(move_title))
+            else:
+                return re_error('/error/19')
         else:
         else:
+            owner_auth = admin_check()
+
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('move') + ')', 0])],
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('move') + ')', 0])],
                 data = '''
                 data = '''
                     <form method="post">
                     <form method="post">
-                        ''' + ip_warning() + '''
-                        <input placeholder="''' + load_lang('document_name') + '" value="' + name + '''" name="title" type="text">
+                        <span>''' + load_lang('document_name') + '''</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
+                        <input value="''' + name + '''" name="title" type="text">
+                        <hr class="main_hr">
+                        
                         <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
                         <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
                         <hr class="main_hr">
                         <hr class="main_hr">
+                        
+                        <h2>''' + load_lang('document') + '''</h2>
                         <select name="move_option">
                         <select name="move_option">
+                            <option value="none"> ''' + load_lang('dont_move') + '''</option>
+                            <option value="normal"> ''' + load_lang('normal') + '''</option>
+                            <option value="reverse"> ''' + load_lang('replace_move') + '''</option>
+                            ''' + ('<option value="merge"> ' + load_lang('merge_move') + '</option>' if owner_auth == 1 else '') + '''
+                        </select>
+                        <hr class="main_hr">
+                        <!-- <input type="checkbox" name="move_redirect_make"> ''' + load_lang('move_redirect_make') + '''
+                        <hr class="main_hr"> -->
+                        
+                        <h2>''' + load_lang('discussion') + '''</h2>
+                        <select name="move_topic_option">
+                            <option value="none"> ''' + load_lang('dont_move') + '''</option>
                             <option value="normal"> ''' + load_lang('normal') + '''</option>
                             <option value="normal"> ''' + load_lang('normal') + '''</option>
                             <option value="reverse"> ''' + load_lang('replace_move') + '''</option>
                             <option value="reverse"> ''' + load_lang('replace_move') + '''</option>
-                            ''' + ('<option value="merge"> ' + load_lang('merge_move') + '</option>' if admin_check() == 1 else '') + '''
+                            ''' + ('<option value="merge"> ' + load_lang('merge_move') + '</option>' if owner_auth == 1 else '') + '''
                         </select>
                         </select>
                         <hr class="main_hr">
                         <hr class="main_hr">
+
+                        ''' + ((
+                            '''<h2>''' + load_lang('document_set') + '''</h2>
+                            <select name="document_set_option">
+                                <option value="none"> ''' + load_lang('dont_move') + '''</option>
+                                <option value="normal"> ''' + load_lang('normal') + '''</option>
+                                <option value="reverse"> ''' + load_lang('replace_move') + '''</option>
+                            </select>
+                            <hr class="main_hr">
+                            '''
+                        ) if owner_auth == 1 else '') + '''
+
                         ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
                         ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
+                        
                         <button type="submit">''' + load_lang('move') + '''</button>
                         <button type="submit">''' + load_lang('move') + '''</button>
                     </form>
                     </form>
                 ''',
                 ''',

+ 2 - 2
route/edit_revert.py

@@ -8,7 +8,7 @@ def edit_revert(name, num):
         if curs.fetchall() and admin_check(6) != 1:
         if curs.fetchall() and admin_check(6) != 1:
             return re_error('/error/3')
             return re_error('/error/3')
 
 
-        if acl_check(name) == 1:
+        if acl_check(name, 'document_edit') == 1:
             return re_error('/ban')
             return re_error('/ban')
         
         
         curs.execute(db_change("select data from history where title = ? and id = ?"), [name, str(num)])
         curs.execute(db_change("select data from history where title = ? and id = ?"), [name, str(num)])
@@ -71,7 +71,7 @@ def edit_revert(name, num):
             return redirect('/w/' + url_pas(name))
             return redirect('/w/' + url_pas(name))
         else:
         else:
             if data:
             if data:
-                preview = '<pre>' + data[0][0] + '</pre>'
+                preview = '<pre>' + html.escape(data[0][0]) + '</pre>'
             else:
             else:
                 preview = ''
                 preview = ''
             
             

+ 18 - 11
route/main_func_upload.py → route/edit_upload.py

@@ -1,11 +1,16 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def main_func_upload():
+def edit_upload():
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
 
 
         if acl_check(None, 'upload') == 1:
         if acl_check(None, 'upload') == 1:
             return re_error('/ban')
             return re_error('/ban')
+        
+        curs.execute(db_change('select data from other where name = "upload"'))
+        db_data = curs.fetchall()
+        file_max = number_check(db_data[0][0]) if db_data and db_data[0][0] != '' else '2'
+        file_max = int(file_max)
 
 
         if flask.request.method == 'POST':
         if flask.request.method == 'POST':
             if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
             if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
@@ -14,12 +19,9 @@ def main_func_upload():
                 captcha_post('', 0)
                 captcha_post('', 0)
 
 
             file_data = flask.request.files.getlist("f_data[]", None)
             file_data = flask.request.files.getlist("f_data[]", None)
-            if not file_data:
-                return re_error('/error/9')
-
             file_len = len(file_data)
             file_len = len(file_data)
 
 
-            if (int(wiki_set(3)) * 1000 * 1000 * file_len) < flask.request.content_length:
+            if (file_max * 1000 * 1000 * file_len) < flask.request.content_length:
                 return re_error('/error/17')
                 return re_error('/error/17')
 
 
             if file_len == 1:    
             if file_len == 1:    
@@ -31,6 +33,9 @@ def main_func_upload():
                 file_num = 1
                 file_num = 1
 
 
             for data in file_data:
             for data in file_data:
+                if data.filename == '':
+                    return re_error('/error/9')
+                
                 value = os.path.splitext(data.filename)[1]
                 value = os.path.splitext(data.filename)[1]
 
 
                 curs.execute(db_change("select html from html_filter where kind = 'extension'"))
                 curs.execute(db_change("select html from html_filter where kind = 'extension'"))
@@ -86,7 +91,9 @@ def main_func_upload():
                     ''
                     ''
 
 
                 curs.execute(db_change("insert into data (title, data) values (?, ?)"), ['file:' + name, file_d])
                 curs.execute(db_change("insert into data (title, data) values (?, ?)"), ['file:' + name, file_d])
-                curs.execute(db_change("insert into acl (title, data, type) values (?, 'admin', 'decu')"), ['file:' + name])
+
+                curs.execute(db_change('select data from other where name = "count_all_title"'))
+                curs.execute(db_change("update other set data = ? where name = 'count_all_title'"), [str(int(curs.fetchall()[0][0]) + 1)])
 
 
                 render_set(
                 render_set(
                     doc_name = 'file:' + name,
                     doc_name = 'file:' + name,
@@ -108,7 +115,7 @@ def main_func_upload():
                 if file_num:
                 if file_num:
                     file_num += 1
                     file_num += 1
 
 
-            conn.commit()
+                conn.commit()
 
 
             return redirect('/w/file:' + name)
             return redirect('/w/file:' + name)
         else:
         else:
@@ -126,14 +133,14 @@ def main_func_upload():
             curs.execute(db_change("select data from other where name = 'upload_default'"))
             curs.execute(db_change("select data from other where name = 'upload_default'"))
             db_data = curs.fetchall()
             db_data = curs.fetchall()
             upload_default = html.escape(db_data[0][0]) if db_data and db_data[0][0] != '' else ''
             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(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('upload'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = [load_lang('upload'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                 data = '''
                     <a href="/file_filter">(''' + load_lang('file_filter_list') + ''')</a> <a href="/extension_filter">(''' + load_lang('extension_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 + '''
                     ''' + upload_help + '''
                     <hr class="main_hr">
                     <hr class="main_hr">
-                    ''' + load_lang('max_file_size') + ''' : ''' + wiki_set(3) + '''MB
+                    ''' + load_lang('max_file_size') + ''' : ''' + str(file_max) + '''MB
                     <hr class="main_hr">
                     <hr class="main_hr">
                     <form method="post" enctype="multipart/form-data" accept-charset="utf8">
                     <form method="post" enctype="multipart/form-data" accept-charset="utf8">
                         <input multiple="multiple" type="file" name="f_data[]">
                         <input multiple="multiple" type="file" name="f_data[]">
@@ -144,10 +151,10 @@ def main_func_upload():
                             ''' + license_list + '''
                             ''' + license_list + '''
                         </select>
                         </select>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <textarea rows="10" placeholder="''' + load_lang('other') + '''" name="f_lice">''' + upload_default + '''</textarea>
+                        <textarea class="opennamu_textarea_200" placeholder="''' + load_lang('other') + '''" name="f_lice">''' + upload_default + '''</textarea>
                         <hr class="main_hr">
                         <hr class="main_hr">
                         ''' + captcha_get() + '''
                         ''' + captcha_get() + '''
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     </form>
                 ''',
                 ''',
                 menu = [['other', load_lang('return')]]
                 menu = [['other', load_lang('return')]]

+ 1 - 1
route/filter_inter_wiki.py

@@ -63,7 +63,7 @@ def filter_inter_wiki(tool):
             div += '</td>'
             div += '</td>'
 
 
             if tool == 'inter_wiki':
             if tool == 'inter_wiki':
-                div += '<td><a class="opennamuLinkOut" href="' + html.escape(data[1]) + '">' + html.escape(data[1]) + '</a></td>'
+                div += '<td><a class="opennamu_link_out" href="' + html.escape(data[1]) + '">' + html.escape(data[1]) + '</a></td>'
             else:
             else:
                 div += '<td>' + html.escape(data[1]) + '</td>'
                 div += '<td>' + html.escape(data[1]) + '</td>'
 
 

+ 2 - 2
route/filter_inter_wiki_add.py

@@ -150,10 +150,10 @@ def filter_inter_wiki_add(tool, name = None):
                 if stat == '':
                 if stat == '':
                     t_data = [
                     t_data = [
                         ['86400', load_lang('1_day')],
                         ['86400', load_lang('1_day')],
-                        ['432000', load_lang('5_day')],
+                        ['432000', load_lang('5_day')],
                         ['2592000', load_lang('30_day')],
                         ['2592000', load_lang('30_day')],
                         ['15552000', load_lang('180_day')],
                         ['15552000', load_lang('180_day')],
-                        ['31104000', load_lang('360_day')],
+                        ['31104000', load_lang('360_day')],
                         ['0', load_lang('limitless')]
                         ['0', load_lang('limitless')]
                     ]
                     ]
                     for i in t_data:
                     for i in t_data:

+ 171 - 113
route/give_acl.py

@@ -1,132 +1,190 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def give_acl_2(conn, name):
-    curs = conn.cursor()
+def give_acl_2(name):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    check_ok = ''
-    ip = ip_check()
+        check_ok = ''
+        user_page = 0
+        ip = ip_check()
 
 
-    if flask.request.method == 'POST':
-        check_data = 'acl (' + name + ')'
-    else:
-        check_data = None
+        if flask.request.method == 'POST':
+            check_data = 'document_set (' + name + ')'
+        else:
+            check_data = None
 
 
-    user_data = re.search(r'^user:(.+)$', name)
-    if user_data:
-        if check_data and ip_or_user(ip) != 0:
-            return redirect('/login')
+        user_data = re.search(r'^user:(.+)$', name)
+        if user_data:
+            if check_data and ip_or_user(ip) != 0:
+                return redirect('/login')
 
 
-        if user_data.group(1) != ip_check():
+            if user_data.group(1) != ip:
+                if admin_check(5) != 1:
+                    if check_data:
+                        return re_error('/error/3')
+                    else:
+                        check_ok = 'disabled'
+            else:
+                user_page = 1
+        else:
             if admin_check(5) != 1:
             if admin_check(5) != 1:
                 if check_data:
                 if check_data:
                     return re_error('/error/3')
                     return re_error('/error/3')
                 else:
                 else:
                     check_ok = 'disabled'
                     check_ok = 'disabled'
-    else:
-        if admin_check(5) != 1:
-            if check_data:
-                return re_error('/error/3')
-            else:
-                check_ok = 'disabled'
-
-    if flask.request.method == 'POST':
-        acl_data = [['decu', flask.request.form.get('decu', '')]]
-        acl_data += [['dis', flask.request.form.get('dis', '')]]
-        acl_data += [['view', flask.request.form.get('view', '')]]
-        acl_data += [['why', flask.request.form.get('why', '')]]
-        
-        curs.execute(db_change("select title from acl where title = ?"), [name])
-        if curs.fetchall():
-            for i in acl_data:
-                curs.execute(db_change("update acl set data = ? where title = ? and type = ?"), [i[1], name, i[0]])
-        else:
+
+        if flask.request.method == 'POST':
+            acl_data = [['decu', flask.request.form.get('decu', '')]]
+            acl_data += [['document_edit_acl', flask.request.form.get('document_edit_acl', '')]]
+            acl_data += [['document_move_acl', flask.request.form.get('document_move_acl', '')]]
+            acl_data += [['document_delete_acl', flask.request.form.get('document_delete_acl', '')]]
+            acl_data += [['dis', flask.request.form.get('dis', '')]]
+            acl_data += [['view', flask.request.form.get('view', '')]]
+            acl_data += [['why', flask.request.form.get('why', '')]]
+
             for i in acl_data:
             for i in acl_data:
-                curs.execute(db_change("insert into acl (title, data, type) values (?, ?, ?)"), [name, i[1], i[0]])
-
-        all_d = ''
-        for i in ['decu', 'dis', 'view']:
-            if flask.request.form.get(i, '') == '':
-                all_d += 'normal'
-                if i != 'view':
-                    all_d += ' | '
+                curs.execute(db_change("select title from acl where title = ? and type = ?"), [name, i[0]])
+                if curs.fetchall():
+                    curs.execute(db_change("update acl set data = ? where title = ? and type = ?"), [i[1], name, i[0]])
+                else:
+                    curs.execute(db_change("insert into acl (title, data, type) values (?, ?, ?)"), [name, i[1], i[0]])
+
+            all_d = ''
+            for i in ['decu', 'document_edit_acl', 'document_move_acl', 'document_delete_acl', 'dis', 'view']:
+                if flask.request.form.get(i, '') == '':
+                    all_d += 'normal'
+                    if i != 'view':
+                        all_d += ' | '
+                else:
+                    all_d += flask.request.form.get(i, '')
+                    if i != 'view':
+                        all_d += ' | '
+
+            markup_data = flask.request.form.get('document_markup', '')
+
+            curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'document_markup'"), [name])
+            db_data = curs.fetchall()
+            if db_data:
+                curs.execute(db_change("update data_set set set_data = ? where doc_name = ? and set_name = 'document_markup'"), [
+                    markup_data, name
+                ])
             else:
             else:
-                all_d += flask.request.form.get(i, '')
-                if i != 'view':
-                    all_d += ' | '
-
-        admin_check(5, check_data + ' (' + all_d + ')')
-
-        conn.commit()
-
-        return redirect('/acl/' + url_pas(name))
-    else:
-        data = ''
-        acl_list = get_acl_list('user') if re.search(r'^user:', name) else get_acl_list()
-        if not re.search(r'^user:', name):
-            acl_get_list = [
-                [load_lang('document_acl'), 'decu'], 
-                [load_lang('discussion_acl'), 'dis'], 
-                [load_lang('view_acl'), 'view']
-            ]
+                curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, '', 'document_markup', ?)"), [
+                    name, markup_data
+                ])
+
+            if not db_data or db_data[0][0] != markup_data:
+                curs.execute(db_change("select data from data where title = ?"), [name])
+                db_data_2 = curs.fetchall()
+                if db_data_2:
+                    render_set(
+                        doc_name = name,
+                        doc_data = db_data_2[0][0],
+                        data_type = 'backlink'
+                    )
+
+            markup_data = markup_data if markup_data != '' else 'default'
+
+            if user_page == 1:
+                admin_check(5, check_data + ' (' + all_d + ')' + ' (' + markup_data + ')')
+
+            conn.commit()
+
+            return redirect('/acl/' + url_pas(name))
         else:
         else:
-            acl_get_list = [
-                [load_lang('document_acl'), 'decu']
-            ]
-            
-        for i in acl_get_list:
+            data = '<h2>' + load_lang('acl') + '</h2>'
+            acl_list = get_acl_list('user') if re.search(r'^user:', name) else get_acl_list()
+            if not re.search(r'^user:', name):
+                acl_get_list = [
+                    [load_lang('view_acl'), 'view', '3'],
+                    [load_lang('document_acl'), 'decu', '4'],
+                    [load_lang('document_edit_acl'), 'document_edit_acl', '5'],
+                    [load_lang('document_move_acl'), 'document_move_acl', '5'],
+                    [load_lang('document_delete_acl'), 'document_delete_acl', '5'],
+                    [load_lang('discussion_acl'), 'dis', '3'],
+                ]
+            else:
+                acl_get_list = [
+                    [load_lang('document_acl'), 'decu', '2']
+                ]
+
+            for i in acl_get_list:
+                data += '' + \
+                    '<h' + i[2] + '>' + i[0] + (' (' + load_lang('beta') + ')' if i[2] == '4' else '') + '</h' + i[2] + '>' + \
+                    '<hr class="main_hr">' + \
+                    '<select name="' + i[1] + '" ' + check_ok + '>' + \
+                ''
+
+                curs.execute(db_change("select data from acl where title = ? and type = ?"), [name, i[1]])
+                acl_data = curs.fetchall()
+                for data_list in acl_list:
+                    check = 'selected="selected"' if acl_data and acl_data[0][0] == data_list else ''
+                    data += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
+
+                data += '</select>'
+                data += '<hr class="main_hr">'
+
+            curs.execute(db_change("select data from acl where title = ? and type = ?"), [name, 'why'])
+            acl_data = curs.fetchall()
+            acl_why = html.escape(acl_data[0][0]) if acl_data else ''
             data += '' + \
             data += '' + \
-                '<h2>' + i[0] + '</h2>' + \
+                '<h3>' + load_lang('why') + '</h3>' + \
+                '<input value="' + acl_why + '" placeholder="' + load_lang('why') + '" name="why" ' + check_ok + '>' + \
                 '<hr class="main_hr">' + \
                 '<hr class="main_hr">' + \
-                '<select name="' + i[1] + '" ' + check_ok + '>' + \
             ''
             ''
-    
-            curs.execute(db_change("select data from acl where title = ? and type = ?"), [name, i[1]])
-            acl_data = curs.fetchall()
-            for data_list in acl_list:
-                check = 'selected="selected"' if acl_data and acl_data[0][0] == data_list else ''
-                data += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
-    
-            data += '</select>'
+
+            data += '''
+                <h3>''' + load_lang('explanation') + '''</h3>
+                <span id="exp"></span>
+                <ul class="opennamu_ul">
+                    <li>normal : ''' + load_lang('unset') + '''</li>
+                    <li>admin : ''' + load_lang('admin_acl') + '''</li>
+                    <li>user : ''' + load_lang('member_acl') + '''</li>
+                    <li>50_edit : ''' + load_lang('50_edit_acl') + '''</li>
+                    <li>all : ''' + load_lang('all_acl') + '''</li>
+                    <li>email : ''' + load_lang('email_acl') + '''</li>
+                    <li>owner : ''' + load_lang('owner_acl') + '''</li>
+                    <li>ban : ''' + load_lang('ban_acl') + '''</li>
+                    <li>before : ''' + load_lang('before_acl') + '''</li>
+                    <li>30_day : ''' + load_lang('30_day_acl') + '''</li>
+                    <li>ban_admin : ''' + load_lang('ban_admin_acl') + '''</li>
+                    <li>not_all : ''' + load_lang('not_all_acl') + '''</li>
+                </ul>
+                <hr class="main_hr">
+                <h2>''' + load_lang('markup') + '''</h2>
+            '''
+
+
+            curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'document_markup'"), [name])
+            db_data = curs.fetchall()
+            markup_load = db_data[0][0] if db_data and db_data[0][0] != '' else ''
+
+            markup_list = ['default'] + get_init_set_list('markup')['list']
+            markup_html = ''
+            for for_a in markup_list:
+                if markup_load == for_a:
+                    markup_html = '<option value="' + (for_a if for_a != 'default' else '') + '">' + for_a + '</option>' + markup_html
+                else:
+                    markup_html += '<option value="' + (for_a if for_a != 'default' else '') + '">' + for_a + '</option>'
+            
+            markup_html = '<select name="document_markup" ' + check_ok + '>' + markup_html + '</select>'
+
+            data += markup_html
             data += '<hr class="main_hr">'
             data += '<hr class="main_hr">'
 
 
-        curs.execute(db_change("select data from acl where title = ? and type = ?"), [name, 'why'])
-        acl_data = curs.fetchall()
-        acl_why = html.escape(acl_data[0][0]) if acl_data else ''
-        data += '' + \
-            '<hr class="main_hr">' + \
-            '<input value="' + acl_why + '" placeholder="' + load_lang('why') + '" name="why" type="text" ' + check_ok + '>' + \
-        ''
-
-        data += '''
-            <h2 id="exp">''' + load_lang('explanation') + '''</h2>
-            <ul class="inside_ul">
-                <li>normal : ''' + load_lang('unset') + '''</li>
-                <li>admin : ''' + load_lang('admin_acl') + '''</li>
-                <li>user : ''' + load_lang('member_acl') + '''</li>
-                <li>50_edit : ''' + load_lang('50_edit_acl') + '''</li>
-                <li>all : ''' + load_lang('all_acl') + '''</li>
-                <li>email : ''' + load_lang('email_acl') + '''</li>
-                <li>owner : ''' + load_lang('owner_acl') + '''</li>
-                <li>ban : ''' + load_lang('ban_acl') + '''</li>
-                <li>before : ''' + load_lang('before_acl') + '''</li>
-                <li>30_day : ''' + load_lang('30_day_acl') + '''</li>
-                <li>ban_admin : ''' + load_lang('ban_admin_acl') + '''</li>
-                <li>not_all : ''' + load_lang('not_all_acl') + '''</li>
-            </ul>
-        '''
-
-        return easy_minify(flask.render_template(skin_check(),
-            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>
-                    ''' + data + '''
-                    <button type="submit" ''' + check_ok + '''>''' + load_lang('save') + '''</button>
-                </form>
-            ''',
-            menu = [
-                ['w/' + url_pas(name), load_lang('document')], 
-                ['manager', load_lang('admin')], 
-                ['admin_log?search=' + url_pas('acl (' + name + ')'), load_lang('acl_record')]
-            ]
-        ))
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('acl') + ')', 0])],
+                data = '''
+                    <form method="post">
+                        <a href="/setting/acl">(''' + load_lang('main_acl_setting') + ''')</a>
+                        <hr class="main_hr">
+                        ''' + render_simple_set(data) + '''
+                        <button type="submit" ''' + check_ok + '''>''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
+                menu = [
+                    ['w/' + url_pas(name), load_lang('document')], 
+                    ['manager', load_lang('admin')], 
+                    ['admin_log?search=' + url_pas('acl (' + name + ')'), load_lang('acl_record')]
+                ]
+            ))

+ 56 - 55
route/give_admin.py

@@ -1,67 +1,68 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def give_admin_2(conn, name):
-    curs = conn.cursor()
+def give_admin_2(name):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    owner = admin_check()
+        owner = admin_check()
 
 
-    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:
-        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')
+        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:
+            user_acl = user_acl[0][0]
 
 
-        if ip_check() == name:
-            return re_error('/error/3')
+        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 flask.request.method == 'POST':
-        if admin_check(7, 'admin (' + name + ')') != 1:
-            return re_error('/error/3')
+            if ip_check() == name:
+                return re_error('/error/3')
 
 
-        if flask.request.form.get('select', 'X') == 'X':
-            select_data = 'user'
-        else:
-            select_data = flask.request.form.get('select', 'X')
-        
-        curs.execute(db_change('select name from alist where name = ? and acl = "owner"'), [select_data])
-        if owner != 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
-        ])
+        if flask.request.method == 'POST':
+            if admin_check(7, 'admin (' + name + ')') != 1:
+                return re_error('/error/3')
 
 
-        conn.commit()
+            if flask.request.form.get('select', 'X') == 'X':
+                select_data = 'user'
+            else:
+                select_data = flask.request.form.get('select', 'X')
 
 
-        return redirect('/admin/' + url_pas(name))
-    else:
-        if admin_check(7) != 1:
-            return re_error('/error/3')
+            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')
 
 
-        div = '<option value="X">X</option>'
+            curs.execute(db_change("update user_set set data = ? where id = ? and name = 'acl'"), [
+                select_data, 
+                name
+            ])
 
 
-        curs.execute(db_change('select distinct name from alist order by name asc'))
-        for data in curs.fetchall():
-            if user_acl == data[0]:
-                div = '<option value="' + data[0] + '">' + data[0] + '</option>' + div
-            else:
-                div += '<option value="' + data[0] + '">' + data[0] + '</option>'
+            conn.commit()
+
+            return redirect('/admin/' + url_pas(name))
+        else:
+            if admin_check(7) != 1:
+                return re_error('/error/3')
+
+            div = '<option value="X">X</option>'
+
+            curs.execute(db_change('select distinct name from alist order by name asc'))
+            for data in curs.fetchall():
+                if user_acl == data[0]:
+                    div = '<option value="' + data[0] + '">' + data[0] + '</option>' + div
+                else:
+                    div += '<option value="' + data[0] + '">' + data[0] + '</option>'
 
 
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('authorize') + ')', 0])],
-            data =  '''
-                    <form method="post">
-                        <select name="select">''' + div + '''</select>
-                        <hr class="main_hr">
-                        <button type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                    ''',
-            menu = [['manager', load_lang('return')]]
-        ))
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('authorize') + ')', 0])],
+                data =  '''
+                        <form method="post">
+                            <select name="select">''' + div + '''</select>
+                            <hr class="main_hr">
+                            <button type="submit">''' + load_lang('save') + '''</button>
+                        </form>
+                        ''',
+                menu = [['manager', load_lang('return')]]
+            ))

+ 57 - 57
route/give_admin_groups.py

@@ -1,67 +1,67 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def give_admin_groups_2(conn, name):
-    curs = conn.cursor()
+def give_admin_groups_2(name):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    acl_name_list = ['ban', 'nothing', 'toron', 'check', 'acl', 'hidel', 'give', 'owner']
-    
-    if flask.request.method == 'POST':
-        if admin_check(None, 'admin_plus (' + name + ')') != 1:
-            return re_error('/error/3')
-        else:
-            if name in ['owner', 'ban']:
+        acl_name_list = ['ban', 'nothing', 'toron', 'check', 'acl', 'hidel', 'give', 'owner']
+
+        if flask.request.method == 'POST':
+            if admin_check(None, 'admin_plus (' + name + ')') != 1:
+                return re_error('/error/3')
+            elif name in get_default_admin_group():
                 return re_error('/error/3')
                 return re_error('/error/3')
 
 
-        curs.execute(db_change("delete from alist where name = ?"), [name])
-        for i in acl_name_list:
-            if flask.request.form.get(i, 0) != 0:
-                curs.execute(db_change("insert into alist (name, acl) values (?, ?)"), [name, i])
+            curs.execute(db_change("delete from alist where name = ?"), [name])
+            for i in acl_name_list:
+                if flask.request.form.get(i, 0) != 0:
+                    curs.execute(db_change("insert into alist (name, acl) values (?, ?)"), [name, i])
 
 
-        conn.commit()
+            conn.commit()
+
+            return redirect('/admin_plus/' + url_pas(name))
+        else:
+            data = ''
+            exist_list = ['', '', '', '', '', '', '', '']
+            state = 'disabled' if admin_check() != 1 else ''
+            state = 'disabled' if name in get_default_admin_group() else ''
 
 
-        return redirect('/admin_plus/' + url_pas(name))
-    else:
-        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()
+            for go in acl_list:
+                exist_list[acl_name_list.index(go[0])] = 'checked="checked"'
 
 
-        curs.execute(db_change('select acl from alist where name = ?'), [name])
-        acl_list = curs.fetchall()
-        for go in acl_list:
-            exist_list[acl_name_list.index(go[0])] = 'checked="checked"'
-            
-        for i in range(0, 8):
-            if i != 1:
-                data += '' + \
-                    '<input type="checkbox" ' + \
-                            state + ' ' + \
-                            'name="' + acl_name_list[i] + '" ' + \
-                            exist_list[i] + '> ' + acl_name_list[i] + \
-                    '<hr class="main_hr">' + \
-                ''
+            for i in range(0, 8):
+                if i != 1:
+                    data += '' + \
+                        '<input type="checkbox" ' + \
+                                state + ' ' + \
+                                'name="' + acl_name_list[i] + '" ' + \
+                                exist_list[i] + '> ' + acl_name_list[i] + \
+                        '<hr class="main_hr">' + \
+                    ''
 
 
-        data += ''
+            data += ''
 
 
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('admin_group') + ')', 0])],
-            data = '''
-                <form method="post">
-                    ''' + data + '''
-                    <hr class="main_hr">
-                    <h2>''' + load_lang('explanation') + '''</h2>
-                    <ul class="inside_ul">
-                        <li>ban : ''' + load_lang('ban_authority') + '''</li>
-                        <li>toron : ''' + load_lang('discussion_authority') + '''</li>
-                        <li>check : ''' + load_lang('user_check_authority') + '''</li>
-                        <li>acl : ''' + load_lang('document_acl_authority') + '''</li>
-                        <li>hidel : ''' + load_lang('history_hide_authority') + '''</li>
-                        <li>give : ''' + load_lang('authorization_authority') + '''</li>
-                        <li>owner : ''' + load_lang('owner_authority') + '''</li>
-                    </ul>
-                    <hr class="main_hr">
-                    <button ''' + state +  ''' type="submit">''' + load_lang('save') + '''</button>
-                </form>
-            ''',
-            menu = [['admin_group', load_lang('return')]]
-        ))
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('admin_group') + ')', 0])],
+                data = '''
+                    <form method="post">
+                        ''' + data + '''
+                        <hr class="main_hr">
+                        <h2>''' + load_lang('explanation') + '''</h2>
+                        <ul class="opennamu_ul">
+                            <li style="margin-left: 20px;">owner : ''' + load_lang('owner_authority') + '''</li>
+                            <li style="margin-left: 40px; list-style: circle;">ban : ''' + load_lang('ban_authority') + '''</li>
+                            <li style="margin-left: 40px; list-style: circle;">toron : ''' + load_lang('discussion_authority') + '''</li>
+                            <li style="margin-left: 40px; list-style: circle;">check : ''' + load_lang('user_check_authority') + '''</li>
+                            <li style="margin-left: 40px; list-style: circle;">acl : ''' + load_lang('document_acl_authority') + '''</li>
+                            <li style="margin-left: 40px; list-style: circle;">hidel : ''' + load_lang('history_hide_authority') + '''</li>
+                            <li style="margin-left: 40px; list-style: circle;">give : ''' + load_lang('authorization_authority') + '''</li>
+                        </ul>
+                        <hr class="main_hr">
+                        <button ''' + state +  ''' type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
+                menu = [['admin_group', load_lang('return')]]
+            ))

+ 22 - 21
route/give_delete_admin_group.py

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

+ 124 - 101
route/give_user_ban.py

@@ -1,116 +1,139 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def give_user_ban_2(conn, name):
-    curs = conn.cursor()
+def give_user_ban(name = None, ban_type = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    band = flask.request.args.get('type', '')
-    ip = ip_check()
-    if ban_check(ip = ip, tool = 'login') == 1:
-    	if ip_or_user(ip) == 1 or admin_check('all', None, ip) == 0:
-            return re_error('/ban')
-    else:
-    	if admin_check(1, None, ip) !=1:
-    	    return re_error('/error/3')
+        ip = ip_check()
+        
+        if ban_check(ip = ip, tool = 'login') == 1:
+            if ip_or_user(ip) == 1 or admin_check('all', None, ip) == 0:
+                return re_error('/ban')
+        else:
+            if admin_check(1, None, ip) != 1:
+                return re_error('/error/3')
 
 
-    if flask.request.method == 'POST':
-        end = flask.request.form.get('second', '0')
-        end = end if end else '0'
-        name = name if name else flask.request.form.get('name', 'test')
-        regex_get = flask.request.form.get('regex', None)
-        login = flask.request.form.get('login', '')
-        why = flask.request.form.get('why', '')
+        if flask.request.method == 'POST':
+            end = flask.request.form.get('second', '0')
+            end = end if end else '0'
+            
+            regex_get = flask.request.form.get('regex', None)
+            login = flask.request.form.get('login', '')
+            why = flask.request.form.get('why', '')
 
 
-        if regex_get or band != '':
-            type_d = 'regex' if regex_get else band
+            if ban_type == 'multiple':
+                all_user = re.findall(r'([^\n]+)\n', flask.request.form.get('name', 'test').replace('\r', '') + '\n')
+            else:
+                if name:
+                    all_user = [name]
+                else:
+                    all_user = [flask.request.form.get('name', 'test')]
 
 
-            try:
-                re.compile(name)
-            except:
-                return re_error('/error/23')
-        else:
-            type_d = None
+            for name in all_user:
+                if regex_get or ban_type == 'regex':
+                    type_d = 'regex' if regex_get else ban_type
 
 
-        if type_d:
-            if admin_check(None, 'ban' + (' ' + type_d if type_d else '') + ' (' + name + ')') != 1:
-                return re_error('/error/3')
-        else:
-            if name == ip:
-                if admin_check('all', 'ban (' + name + ')') != 1:
-                    return re_error('/error/3')
-            else:
-            	if admin_check(1, 'ban (' + name + ')') != 1:
-                    return re_error('/error/3')
+                    try:
+                        re.compile(name)
+                    except:
+                        return re_error('/error/23')
+                else:
+                    type_d = None
 
 
-        ban_insert(
-            name,
-            end,
-            why,
-            login,
-            ip_check(),
-            type_d
-        )
+                if type_d:
+                    if admin_check(None, 'ban' + (' ' + type_d if type_d else '') + ' (' + name + ')') != 1:
+                        return re_error('/error/3')
+                else:
+                    if name == ip:
+                        if admin_check('all', 'ban (' + name + ')') != 1:
+                            return re_error('/error/3')
+                    else:
+                        if admin_check(1, 'ban (' + name + ')') != 1:
+                            return re_error('/error/3')
 
 
-        return redirect('/block_log')
-    else:
-        curs.execute(db_change("select end, why from rb where block = ? and ongoing = '1' and band = ?"), [name, band])
-        end = curs.fetchall()
-        if end:
-            main_name = name
-            b_now = load_lang('release')
-            now = '(' + b_now + ')'
-            action = 'action="/ban/' + url_pas(name) + ('?type=' + band if band != '' else '') + '"'
+                ban_insert(
+                    name,
+                    end,
+                    why,
+                    login,
+                    ip_check(),
+                    type_d
+                )
 
 
-            if end[0][0] == '':
-                data = '<ul class="inside_ul"><li>' + load_lang('limitless') + '</li>'
-            else:
-                data = '<ul class="inside_ul"><li>' + load_lang('period') + ' : ' + end[0][0] + '</li>'
+            return redirect('/block_log')
+        else:
+            curs.execute(db_change("select end, why from rb where block = ? and ongoing = '1' and band = ?"), [name, ban_type])
+            end = curs.fetchall()
+            if end:
+                main_name = name
+                b_now = load_lang('release')
+                now = '(' + b_now + ')'
+                
+                if ban_type == 'regex':
+                    action = 'action="/auth/give/ban_regex/' + url_pas(name) + '"'
+                else:
+                    action = 'action="/auth/give/ban/' + url_pas(name) + '"'
+
+                if end[0][0] == '':
+                    data = '<ul class="opennamu_ul"><li>' + load_lang('limitless') + '</li>'
+                else:
+                    data = '<ul class="opennamu_ul"><li>' + load_lang('period') + ' : ' + end[0][0] + '</li>'
 
 
-            curs.execute(db_change("select block from rb where block = ? and login = 'O' and ongoing = '1'"), [name])
-            if curs.fetchall():
-                data += '<li>' + load_lang('login_able') + '</li>'
+                curs.execute(db_change("select block from rb where block = ? and login = 'O' and ongoing = '1'"), [name])
+                if curs.fetchall():
+                    data += '<li>' + load_lang('login_able') + '</li>'
 
 
-            if end[0][1] != '':
-                data += '<li>' + load_lang('why') + ' : ' + end[0][1] + '</li></ul><hr class="main_hr">'
+                if end[0][1] != '':
+                    data += '<li>' + load_lang('why') + ' : ' + end[0][1] + '</li></ul><hr class="main_hr">'
+                else:
+                    data += '</ul><hr class="main_hr">'
             else:
             else:
-                data += '</ul><hr class="main_hr">'
-        else:
-            main_name = load_lang('ban')
-            n_name = '<input placeholder="' + load_lang('name_or_ip_or_regex') + '" value="' + (name if name else '') + '" name="name" type="text"><hr class="main_hr">'
-            regex = '<input type="checkbox" name="regex" ' + ('checked' if band == 'regex' else '') + '> ' + load_lang('regex') + '<hr class="main_hr">'
-            plus = '<input type="checkbox" name="login"> ' + load_lang('login_able') + '<hr class="main_hr">'
-            now = 0
-            b_now = load_lang('ban')
-            action = 'action="/ban"'
-            
-            time_data = [
-                ['86400', load_lang('1_day')],
-                ['432000', load_lang('5_day')],
-                ['2592000', load_lang('30_day')],
-                ['15552000', load_lang('180_day')],
-                ['31104000', load_lang('360_day')],
-                ['0', load_lang('limitless')]
-            ]
-            insert_data = ''
-            for i in time_data:
-                insert_data += '<a href="javascript:insert_v(\'second\', \'' + i[0] + '\')">(' + i[1] + ')</a> '
+                if ban_type == 'multiple':
+                    main_name = load_lang('multiple_ban')
+                    n_name = '<textarea class="opennamu_textarea_500" placeholder="' + load_lang('name_or_ip_or_regex_multiple') + '" name="name"></textarea><hr class="main_hr">'
+                else:
+                    main_name = load_lang('ban')
+                    n_name = '<input placeholder="' + load_lang('name_or_ip_or_regex') + '" value="' + (name if name else '') + '" name="name"><hr class="main_hr">'
+                
+                regex = '<input type="checkbox" name="regex" ' + ('checked' if ban_type == 'regex' else '') + '> ' + load_lang('regex') + '<hr class="main_hr">'
+                plus = '<input type="checkbox" name="login"> ' + load_lang('login_able') + '<hr class="main_hr">'
+                now = 0
+                b_now = load_lang('ban')
+                
+                if ban_type == 'multiple':
+                    action = 'action="/auth/give/ban_multiple"'
+                else:
+                    action = 'action="/auth/give/ban"'
+
+                time_data = [
+                    ['86400', load_lang('1_day')],
+                    ['432000', load_lang('5_day')],
+                    ['2592000', load_lang('30_day')],
+                    ['15552000', load_lang('180_day')],
+                    ['31104000', load_lang('360_day')],
+                    ['0', load_lang('limitless')]
+                ]
+                insert_data = ''
+                for i in time_data:
+                    insert_data += '<a href="javascript:insert_v(\'second\', \'' + i[0] + '\')">(' + i[1] + ')</a> '
 
 
-            data = n_name + '''
-                ''' + regex + '''
-                <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''
-                <hr class="main_hr">
-                <input placeholder="''' + load_lang('ban_period') + ''' (''' + load_lang('second') + ''')" name="second" id="second" type="text">
-                <hr class="main_hr">
-                <input placeholder="''' + load_lang('why') + '''" name="why" type="text">
-                <hr class="main_hr">
-            ''' + plus
+                data = n_name + '''
+                    ''' + regex + '''
+                    <script>function insert_v(name, data) { document.getElementById(name).value = data; }</script>''' + insert_data + '''
+                    <hr class="main_hr">
+                    <input placeholder="''' + load_lang('ban_period') + ''' (''' + load_lang('second') + ''')" name="second" id="second" type="text">
+                    <hr class="main_hr">
+                    <input placeholder="''' + load_lang('why') + '''" name="why" type="text">
+                    <hr class="main_hr">
+                ''' + plus
 
 
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [main_name, wiki_set(), wiki_custom(), wiki_css([now, 0])],
-            data = '''
-                <form method="post" ''' + action + '''>
-                    ''' + data + '''
-                    <button type="submit">''' + b_now + '''</button>
-                </form>
-            ''',
-            menu = [['manager', load_lang('return')]]
-        ))   
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [main_name, wiki_set(), wiki_custom(), wiki_css([now, 0])],
+                data = '''
+                    <form method="post" ''' + action + '''>
+                        ''' + data + '''
+                        <button type="submit">''' + b_now + '''</button>
+                    </form>
+                ''',
+                menu = [['manager', load_lang('return')]]
+            ))   

+ 163 - 162
route/give_user_check.py

@@ -1,178 +1,179 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def give_user_check_2(conn, name):
-    curs = conn.cursor()
-
-    plus_id = flask.request.args.get('plus', None)
-
-    if admin_check('all', None, name) == 1 or (plus_id and admin_check('all', None, plus_id) == 1):
-        if admin_check() != 1:
-            return re_error('/error/4')
-
-    num = int(number_check(flask.request.args.get('num', '1')))
-    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
-    
-    div = ''
-    check_type = flask.request.args.get('type', '')
-
-    if admin_check(4, (check_type + ' ' if check_type != '' else '') + 'check (' + name + ')') != 1:
-        return re_error('/error/3')
-
-    if check_type == '':
-        if ip_or_user(name) == 0:
-            curs.execute(db_change("select data from user_set where name = \"approval_question\" and id = ?"), [name])
-            approval_question = curs.fetchall()
-            if approval_question and approval_question[0][0]:
-                curs.execute(db_change("select data from user_set where name = \"approval_question_answer\" and id = ?"), [name])
-                approval_question_answer = curs.fetchall()
-                if approval_question_answer and approval_question_answer[0]:
-                    div += '''
-                        <table id="main_table_set">
-                            <tbody>
-                                <tr id="main_table_top_tr">
-                                    <td>Q</td>
-                                    <td>''' + approval_question[0][0] + '''</td>
-                                    <td>A</td>
-                                    <td>''' + approval_question_answer[0][0] + '''</td>
-                                </tr>
-                            </tbody>
-                        </table>
-                        <hr class="main_hr">
-                    '''
+def give_user_check_2(name):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-        if plus_id:
-            plus = "or " + ('ip' if ip_or_user(plus_id) == 1 else 'name') + " = ? "
-            set_list = [name, plus_id, sql_num]
-            
-            if num == 1:
-                curs.execute(db_change("" + \
-                    "select distinct ip from ua_d " + \
-                    "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ? or " + ('ip' if ip_or_user(plus_id) == 1 else 'name') + " = ? "
-                ""), [name, plus_id])
-                all_ip_count = len(curs.fetchall())
-                
-                curs.execute(db_change("" + \
-                    "select distinct ip from ua_d " + \
-                    "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ?" + \
-                ""), [name])
-                a_ip_count = len(curs.fetchall())
-                
-                curs.execute(db_change("" + \
-                    "select distinct ip from ua_d " + \
-                    "where " + ('ip' if ip_or_user(plus_id) == 1 else 'name') + " = ? "
-                ""), [plus_id])
-                b_ip_count = len(curs.fetchall())
-                
-                if a_ip_count + b_ip_count != all_ip_count:
-                    div += load_lang('same_ip_exist') + '<hr class="main_hr">'    
-        else:
-            plus = ''
-            set_list = [name, sql_num]
-
-        curs.execute(db_change("" + \
-            "select name, ip, ua, today from ua_d " + \
-            "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ? " + \
-            plus + \
-            "order by today desc limit ?, 50" + \
-        ""), set_list)
-
-        record = curs.fetchall()
-        if record:
-            if not plus_id:
-                div = '' + \
-                    '<a href="/manager/14?plus=' + url_pas(name) + '">(' + load_lang('compare') + ')</a> ' + \
-                    '<a href="/check/' + url_pas(name) + '?type=simple">(' + load_lang('simple_check') + ')</a>' + \
-                    '<hr class="main_hr">' + \
-                '' + div
+        plus_id = flask.request.args.get('plus', None)
+
+        if admin_check('all', None, name) == 1 or (plus_id and admin_check('all', None, plus_id) == 1):
+            if admin_check() != 1:
+                return re_error('/error/4')
+
+        num = int(number_check(flask.request.args.get('num', '1')))
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
+
+        div = ''
+        check_type = flask.request.args.get('type', '')
+
+        if admin_check(4, (check_type + ' ' if check_type != '' else '') + 'check (' + name + ')') != 1:
+            return re_error('/error/3')
+
+        if check_type == '':
+            if ip_or_user(name) == 0:
+                curs.execute(db_change("select data from user_set where name = \"approval_question\" and id = ?"), [name])
+                approval_question = curs.fetchall()
+                if approval_question and approval_question[0][0]:
+                    curs.execute(db_change("select data from user_set where name = \"approval_question_answer\" and id = ?"), [name])
+                    approval_question_answer = curs.fetchall()
+                    if approval_question_answer and approval_question_answer[0]:
+                        div += '''
+                            <table id="main_table_set">
+                                <tbody>
+                                    <tr id="main_table_top_tr">
+                                        <td>Q</td>
+                                        <td>''' + approval_question[0][0] + '''</td>
+                                        <td>A</td>
+                                        <td>''' + approval_question_answer[0][0] + '''</td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                            <hr class="main_hr">
+                        '''
+
+            if plus_id:
+                plus = "or " + ('ip' if ip_or_user(plus_id) == 1 else 'name') + " = ? "
+                set_list = [name, plus_id, sql_num]
+
+                if num == 1:
+                    curs.execute(db_change("" + \
+                        "select distinct ip from ua_d " + \
+                        "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ? or " + ('ip' if ip_or_user(plus_id) == 1 else 'name') + " = ?"
+                    ""), [name, plus_id])
+                    all_ip_count = len(curs.fetchall())
+
+                    curs.execute(db_change("" + \
+                        "select distinct ip from ua_d " + \
+                        "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ?" + \
+                    ""), [name])
+                    a_ip_count = len(curs.fetchall())
+
+                    curs.execute(db_change("" + \
+                        "select distinct ip from ua_d " + \
+                        "where " + ('ip' if ip_or_user(plus_id) == 1 else 'name') + " = ?"
+                    ""), [plus_id])
+                    b_ip_count = len(curs.fetchall())
+
+                    if a_ip_count + b_ip_count != all_ip_count:
+                        div += load_lang('same_ip_exist') + '<hr class="main_hr">'    
             else:
             else:
-                div = '' + \
-                    '<a href="/check/' + url_pas(name) + '">(' + name + ')</a> ' + \
-                    '<a href="/check/' + url_pas(plus_id) + '">(' + plus_id + ')</a>' + \
-                    '<hr class="main_hr">' + \
-                '' + div
-
-            div += '''
-                <table id="main_table_set">
-                    <tbody>
-                        <tr id="main_table_top_tr">
-                            <td id="main_table_width">''' + load_lang('name') + '''</td>
-                            <td id="main_table_width">''' + load_lang('ip') + '''</td>
-                            <td id="main_table_width">''' + load_lang('time') + '''</td>
-                        </tr>
-            '''
-
-            set_n = 0
-            for data in record:
-                if data[2]:
-                    if len(data[2]) > 300:
-                        ua = '' + \
-                            '<a href="javascript:void();" onclick="document.getElementById(\'check_' + str(set_n) + '\').style.display=\'block\';">(300+)</a>' + \
-                            '<div id="check_' + str(set_n) + '" style="display:none;">' + html.escape(data[2]) + '</div>' + \
-                        ''
-                        set_n += 1
-                    else:
-                        ua = html.escape(data[2])
+                plus = ''
+                set_list = [name, sql_num]
+
+            curs.execute(db_change("" + \
+                "select name, ip, ua, today from ua_d " + \
+                "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ? " + \
+                plus + \
+                "order by today desc limit ?, 50" + \
+            ""), set_list)
+
+            record = curs.fetchall()
+            if record:
+                if not plus_id:
+                    div = '' + \
+                        '<a href="/manager/14?plus=' + url_pas(name) + '">(' + load_lang('compare') + ')</a> ' + \
+                        '<a href="/check/' + url_pas(name) + '?type=simple">(' + load_lang('simple_check') + ')</a>' + \
+                        '<hr class="main_hr">' + \
+                    '' + div
                 else:
                 else:
-                    ua = '<br>'
+                    div = '' + \
+                        '<a href="/check/' + url_pas(name) + '">(' + name + ')</a> ' + \
+                        '<a href="/check/' + url_pas(plus_id) + '">(' + plus_id + ')</a>' + \
+                        '<hr class="main_hr">' + \
+                    '' + div
 
 
                 div += '''
                 div += '''
-                    <tr>
-                        <td>
-                            <a href="/check/''' + url_pas(data[0]) + '''">''' + data[0] + '''</a>
-                            <a  href="/check_delete''' + \
-                                '''?name=''' + url_pas(data[0]) + \
-                                '''&ip=''' + url_pas(data[1]) + \
-                                '''&time=''' + url_pas(data[3].replace(' ', '').replace(':', '').replace('-', '')) + \
-                                '''&return_type=''' + ('0' if ip_or_user(name) == 0 else '1') + '''">
-                                (''' + load_lang('delete') + ''')
-                            </a>
-                        </td>
-                        <td><a href="/check/''' + url_pas(data[1]) + '''">''' + data[1] + '''</a></td>
-                        <td>''' + data[3] + '''</td>
-                    </tr>
-                    <tr>
-                        <td colspan="3">''' + ua + '''</td>
-                    </tr>
+                    <table id="main_table_set">
+                        <tbody>
+                            <tr id="main_table_top_tr">
+                                <td id="main_table_width">''' + load_lang('name') + '''</td>
+                                <td id="main_table_width">''' + load_lang('ip') + '''</td>
+                                <td id="main_table_width">''' + load_lang('time') + '''</td>
+                            </tr>
                 '''
                 '''
 
 
-            div += '''
-                    </tbody>
-                </table>
-            '''
-            
-        div += next_fix(
-            '/check/' + url_pas(name) + ('?plus=' + plus_id + '&num=' if plus_id else '?num='), 
-            num, 
-            record
-        )
-
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [load_lang('check'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = div,
-            menu = [['manager', load_lang('return')]]
-        ))
-    else:
-        curs.execute(db_change("" + \
-            "select distinct " + ('name' if ip_or_user(name) == 1 else 'ip') + " from ua_d " + \
-            "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ? "
-            "order by today desc limit ?, 50" + \
-        ""), [name, sql_num])
-        record = curs.fetchall()
+                set_n = 0
+                for data in record:
+                    if data[2]:
+                        if len(data[2]) > 300:
+                            ua = '' + \
+                                '<a href="javascript:void();" onclick="document.getElementById(\'check_' + str(set_n) + '\').style.display=\'block\';">(300+)</a>' + \
+                                '<div id="check_' + str(set_n) + '" style="display:none;">' + html.escape(data[2]) + '</div>' + \
+                            ''
+                            set_n += 1
+                        else:
+                            ua = html.escape(data[2])
+                    else:
+                        ua = '<br>'
 
 
-        div = ''
-        for i in record:
-            div += '<li><a href="/check/' + url_pas(i[0]) + '?type=simple">' + i[0] + '</a></li>'
+                    div += '''
+                        <tr>
+                            <td>
+                                <a href="/check/''' + url_pas(data[0]) + '''">''' + data[0] + '''</a>
+                                <a  href="/check_delete''' + \
+                                    '''?name=''' + url_pas(data[0]) + \
+                                    '''&ip=''' + url_pas(data[1]) + \
+                                    '''&time=''' + url_pas(data[3].replace(' ', '').replace(':', '').replace('-', '')) + \
+                                    '''&return_type=''' + ('0' if ip_or_user(name) == 0 else '1') + '''">
+                                    (''' + load_lang('delete') + ''')
+                                </a>
+                            </td>
+                            <td><a href="/check/''' + url_pas(data[1]) + '''">''' + data[1] + '''</a></td>
+                            <td>''' + data[3] + '''</td>
+                        </tr>
+                        <tr>
+                            <td colspan="3">''' + ua + '''</td>
+                        </tr>
+                    '''
+
+                div += '''
+                        </tbody>
+                    </table>
+                '''
 
 
-        if div != '':
-            div = '<ul class="inside_ul">' + div + '</ul>'
             div += next_fix(
             div += next_fix(
-                '/check/' + url_pas(name) + '?type=' + check_type + '&num=', 
+                '/check/' + url_pas(name) + ('?plus=' + plus_id + '&num=' if plus_id else '?num='), 
                 num, 
                 num, 
                 record
                 record
             )
             )
 
 
-        return easy_minify(flask.render_template(skin_check(),
-            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('simple_check') + ')', 0])],
-            data = div,
-            menu = [['check/' + url_pas(name), load_lang('return')]]
-        ))
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('check'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                data = div,
+                menu = [['manager', load_lang('return')]]
+            ))
+        else:
+            curs.execute(db_change("" + \
+                "select distinct " + ('name' if ip_or_user(name) == 1 else 'ip') + ", today from ua_d " + \
+                "where " + ('ip' if ip_or_user(name) == 1 else 'name') + " = ? "
+                "order by today desc limit ?, 50" + \
+            ""), [name, sql_num])
+            record = curs.fetchall()
+
+            div = ''
+            for i in record:
+                div += '<li><a href="/check/' + url_pas(i[0]) + '?type=simple">' + i[0] + '</a></li>'
+
+            if div != '':
+                div = '<ul class="opennamu_ul">' + div + '</ul>'
+                div += next_fix(
+                    '/check/' + url_pas(name) + '?type=' + check_type + '&num=', 
+                    num, 
+                    record
+                )
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('simple_check') + ')', 0])],
+                data = div,
+                menu = [['check/' + url_pas(name), load_lang('return')]]
+            ))

+ 44 - 43
route/give_user_check_delete.py

@@ -1,46 +1,47 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def give_user_check_delete_2(conn):
-    curs = conn.cursor()
-    
-    if admin_check() != 1:
-        return re_error('/error/4')
-
-    user_id = flask.request.args.get('name', None)
-    user_ip = flask.request.args.get('ip', None)
-    
-    time = flask.request.args.get('time', None)
-    time_set = re.search(r'([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})', time)
-    if not time_set:
-        return redirect()
-    
-    time_set = time_set.groups()
-    time = time_set[0] + '-' + time_set[1] + '-' + time_set[2] + ' '
-    time += time_set[3] + ':' + time_set[4] + ':' + time_set[5]
-    
-    return_type = flask.request.args.get('return_type', '1')
-        
-    if user_id and user_ip and time:
-        if flask.request.method == 'POST':
-            curs.execute(db_change("delete from ua_d where name = ? and ip = ? and today = ?"), [user_id, user_ip, time])
-            conn.commit()
-            
-            return redirect('/check/' + url_pas(user_id if return_type == '0' else user_ip))
+def give_user_check_delete_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if admin_check() != 1:
+            return re_error('/error/4')
+
+        user_id = flask.request.args.get('name', None)
+        user_ip = flask.request.args.get('ip', None)
+
+        time = flask.request.args.get('time', None)
+        time_set = re.search(r'([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})', time)
+        if not time_set:
+            return redirect()
+
+        time_set = time_set.groups()
+        time = time_set[0] + '-' + time_set[1] + '-' + time_set[2] + ' '
+        time += time_set[3] + ':' + time_set[4] + ':' + time_set[5]
+
+        return_type = flask.request.args.get('return_type', '1')
+
+        if user_id and user_ip and time:
+            if flask.request.method == 'POST':
+                curs.execute(db_change("delete from ua_d where name = ? and ip = ? and today = ?"), [user_id, user_ip, time])
+                conn.commit()
+
+                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(), wiki_custom(), wiki_css(['(' + load_lang('delete') + ')', 0])],
+                    data = '''
+                        ''' + load_lang('name') + ''' : ''' + user_id + '''
+                        <hr class="main_hr">
+                        ''' + load_lang('ip') + ''' : ''' + user_ip + '''
+                        <hr class="main_hr">
+                        ''' + load_lang('time') + ''' : ''' + time + '''
+                        <hr class="main_hr">
+                        <form method="post">
+                            <button type="submit">''' + load_lang('delete') + '''</button>
+                        </form>
+                    ''',
+                    menu = [['check/' + url_pas(user_id if return_type == '0' else user_ip), load_lang('return')]]
+                ))
         else:
         else:
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('check'), wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('delete') + ')', 0])],
-                data = '''
-                    ''' + load_lang('name') + ''' : ''' + user_id + '''
-                    <hr class="main_hr">
-                    ''' + load_lang('ip') + ''' : ''' + user_ip + '''
-                    <hr class="main_hr">
-                    ''' + load_lang('time') + ''' : ''' + time + '''
-                    <hr class="main_hr">
-                    <form method="post">
-                        <button type="submit">''' + load_lang('delete') + '''</button>
-                    </form>
-                ''',
-                menu = [['check/' + url_pas(user_id if return_type == '0' else user_ip), load_lang('return')]]
-            ))
-    else:
-        return redirect()
+            return redirect()

+ 31 - 30
route/list_acl.py

@@ -1,38 +1,39 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_acl_2(conn):
-    curs = conn.cursor()
+def list_acl_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    num = int(number_check(flask.request.args.get('num', '1')))
-    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
-    div = '<ul class="inside_ul">'
+        num = int(number_check(flask.request.args.get('num', '1')))
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
+        div = '<ul class="opennamu_ul">'
 
 
-    curs.execute(db_change(
-        "select distinct title, data, type from acl where data != '' and not title like 'user:%' order by title desc limit ?, 50"
-    ), [sql_num])
-    list_data = curs.fetchall()
-    for data in list_data:
-        curs.execute(db_change("select time from re_admin where what like ? order by time desc limit 1"), ['acl (' + data[0] + ')%'])
-        time_data = curs.fetchall()
-        time_data = (time_data[0][0] + ' | ') if time_data else ''
+        curs.execute(db_change(
+            "select distinct title, data, type from acl where data != '' and not title like 'user:%' order by title desc limit ?, 50"
+        ), [sql_num])
+        list_data = curs.fetchall()
+        for data in list_data:
+            curs.execute(db_change("select time from re_admin where what like ? order by time desc limit 1"), ['acl (' + data[0] + ')%'])
+            time_data = curs.fetchall()
+            time_data = (time_data[0][0] + ' | ') if time_data else ''
 
 
-        curs.execute(db_change("select data from acl where title = ? and type = 'why'"), [data[0]])
-        why_data = curs.fetchall()
-        why_data = (' | ' + why_data[0][0]) if why_data and why_data[0][0] != '' else ''
+            curs.execute(db_change("select data from acl where title = ? and type = 'why'"), [data[0]])
+            why_data = curs.fetchall()
+            why_data = (' | ' + why_data[0][0]) if why_data and why_data[0][0] != '' else ''
 
 
-        div += '' + \
-            '<li>' + \
-                time_data + \
-                '<a href="/acl/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a>' + \
-                why_data + \
-            '</li>' + \
-        ''
+            div += '' + \
+                '<li>' + \
+                    time_data + \
+                    '<a href="/acl/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a>' + \
+                    why_data + \
+                '</li>' + \
+            ''
 
 
-    div += '</ul>'
-    div += next_fix('/acl_list?num=', num, list_data)
+        div += '</ul>'
+        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(), wiki_custom(), wiki_css([0, 0])],
-        data = div,
-        menu = [['other', load_lang('return')]]
-    ))
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('acl_document_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = div,
+            menu = [['other', load_lang('return')]]
+        ))

+ 19 - 18
route/list_admin.py

@@ -1,25 +1,26 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_admin_2(conn):
-    curs = conn.cursor()
+def list_admin_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    div = '<ul class="inside_ul">'
+        div = '<ul class="opennamu_ul">'
 
 
-    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>' + \
-        ''
+        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>' + \
+            ''
 
 
-        div += '<li>' + name + '</li>'
+            div += '<li>' + name + '</li>'
 
 
-    div += '</ul>'
+        div += '</ul>'
 
 
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('admin_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-        data = div,
-        menu = [['other', load_lang('return')]]
-    ))
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('admin_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = div,
+            menu = [['other', load_lang('return')]]
+        ))

+ 27 - 26
route/list_admin_group.py

@@ -1,34 +1,35 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_admin_group_2(conn):
-    curs = conn.cursor()
+def list_admin_group_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    list_data = '<ul class="inside_ul">'
-    org_acl_list = get_default_admin_group()
+        list_data = '<ul class="opennamu_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 = ''
+        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]) + '">' + html.escape(data[0]) + '</a>' + \
+                    delete_admin_group + \
+                '</li>' + \
+            ''
 
 
         list_data += '' + \
         list_data += '' + \
-            '<li>' + \
-                '<a href="/admin_plus/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a>' + \
-                delete_admin_group + \
-            '</li>' + \
+            '</ul>' + \
+            '<hr class="main_hr">' + \
+            '<a href="/manager/8">(' + load_lang('add') + ')</a>' + \
         ''
         ''
 
 
-    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')]]
-    ))    
+        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')]]
+        ))

+ 44 - 33
route/list_admin_use.py

@@ -1,38 +1,49 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_admin_use_2(conn):
-    curs = conn.cursor()
+def list_admin_use(arg_num = 1, arg_search = 'normal'):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    num = int(number_check(flask.request.args.get('num', '1')))
-    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
+        sql_num = (arg_num * 50 - 50) if arg_num * 50 > 0 else 0
 
 
-    if flask.request.method == 'POST':
-        return redirect('/admin_log?search=' + flask.request.form.get('search', 'normal'))
-    else:
-        list_data = '<ul class="inside_ul">'
-
-        if flask.request.args.get('search', 'normal') == 'normal':
-            curs.execute(db_change("select who, what, time from re_admin order by time desc limit ?, 50"), [sql_num])
+        if flask.request.method == 'POST':
+            return redirect('/list/admin/auth_use/' + url_pas(flask.request.form.get('search', 'normal')) + '/1')
         else:
         else:
-            curs.execute(db_change("select who, what, time from re_admin where what like ? order by time desc limit ?, 50"), [
-                flask.request.args.get('search', 'normal') + "%",
-                sql_num
-            ])
-
-        get_list = curs.fetchall()
-        for data in get_list:
-            list_data += '<li>' + ip_pas(data[0]) + ' / ' + html.escape(data[1]) + ' / ' + data[2] + '</li>'
-
-        list_data += '</ul>'
-        list_data += next_fix('/admin_log?num=', num, get_list)
-
-        return easy_minify(flask.render_template(skin_check(),
-            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>
-                </form>
-                <hr class=\"main_hr\">
-            ''' + list_data,
-            menu = [['other', load_lang('return')]]
-        ))
+            if arg_search == 'normal':
+                curs.execute(db_change("select who, what, time from re_admin order by time desc limit ?, 50"), [sql_num])
+            else:
+                curs.execute(
+                    db_change("select who, what, time from re_admin where what like ? order by time desc limit ?, 50"),
+                    [arg_search + "%", sql_num]
+                )
+
+            list_data = '<ul class="opennamu_ul">'
+
+            get_list = curs.fetchall()
+            for data in get_list:
+                do_data = data[1]
+
+                if ip_pas('127.0.0.1', 1) != '127.0.0.1': 
+                    do_data = do_data.split(' ')
+                    if do_data[0] in ('ban'):
+                        do_data = do_data[0]
+                    else:
+                        do_data = data[1]
+
+                list_data += '<li>' + ip_pas(data[0]) + ' | ' + html.escape(do_data) + ' | ' + data[2] + '</li>'
+
+            list_data += '</ul>'
+            list_data += next_fix('/list/admin/auth_use/' + url_pas(arg_search) + '/', arg_num, get_list)
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('authority_use_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                data = '''
+                    <form method="post">
+                        <input name="search">
+                        <hr class="main_hr">
+                        <button type="submit">''' + load_lang('search') + '''</button>
+                    </form>
+                    <hr class="main_hr">
+                ''' + list_data,
+                menu = [['other', load_lang('return')]]
+            ))

+ 17 - 19
route/list_image_file.py

@@ -1,26 +1,24 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_image_file_2(conn):
-    curs = conn.cursor()
+def list_image_file_2():
+    with get_db_connect() as 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
+        num = int(number_check(flask.request.args.get('num', '1')))
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
 
-    list_data = '<ul class="inside_ul">'
-    back = ''
+        list_data = '<ul class="opennamu_ul">'
+        back = ''
 
 
-    curs.execute(db_change("select title from data where title like 'file:%' limit ?, 50"), [sql_num])
-    data_list = curs.fetchall()
-    for data in data_list:
-        list_data += '<li><a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
+        curs.execute(db_change("select title from data where title like 'file:%' limit ?, 50"), [sql_num])
+        data_list = curs.fetchall()
+        for data in data_list:
+            list_data += '<li><a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
 
 
-    list_data += next_fix('/image_file_list?num=', num, data_list)
+        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(), wiki_custom(), wiki_css([0, 0])],
-        data = list_data,
-        menu = [['other', load_lang('return')]]
-    ))    
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('image_file_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = list_data,
+            menu = [['other', load_lang('return')]]
+        ))

+ 18 - 17
route/list_long_page.py

@@ -1,24 +1,25 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_long_page_2(conn, tool):
-    curs = conn.cursor()
+def list_long_page_2(tool):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    curs.execute(db_change('select data from other where name = "count_all_title"'))
-    if int(curs.fetchall()[0][0]) > 30000:
-        return re_error('/error/25')
+        curs.execute(db_change('select data from other where name = "count_all_title"'))
+        if int(curs.fetchall()[0][0]) > 30000:
+            return re_error('/error/25')
 
 
-    div = '<ul class="inside_ul">'
-    select_data = 'desc' if tool == 'long_page' else 'asc'
-    title = 'long_page' if tool == 'long_page' else 'short_page'
+        div = '<ul class="opennamu_ul">'
+        select_data = 'desc' if tool == 'long_page' else 'asc'
+        title = 'long_page' if tool == 'long_page' else 'short_page'
 
 
-    curs.execute(db_change("select title, length(data) from data order by length(data) " + select_data + " limit 50"))
-    for data in curs.fetchall():
-        div += '<li>' + str(data[1]) + ' : <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
+        curs.execute(db_change("select title, length(data) from data order by length(data) " + select_data + " limit 50"))
+        for data in curs.fetchall():
+            div += '<li>' + str(data[1]) + ' : <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
 
 
-    div += '</ul>'
+        div += '</ul>'
 
 
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang(title), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-        data = div,
-        menu = [['other', load_lang('return')]]
-    ))
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang(title), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = div,
+            menu = [['other', load_lang('return')]]
+        ))

+ 4 - 8
route/list_old_page.py

@@ -1,27 +1,23 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_old_page():
+def list_old_page(num = 1):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
         
         
-        num = flask.request.args.get('num', '1')
-        num = int(number_check(num))
         sql_num = (num * 50 - 50) if num * 50 > 0 else 0
         sql_num = (num * 50 - 50) if num * 50 > 0 else 0
         
         
         curs.execute(db_change('select data from other where name = "count_all_title"'))
         curs.execute(db_change('select data from other where name = "count_all_title"'))
         if int(curs.fetchall()[0][0]) > 30000:
         if int(curs.fetchall()[0][0]) > 30000:
             return re_error('/error/25')
             return re_error('/error/25')
         
         
-        div = '<ul class="inside_ul">'
+        div = '<ul class="opennamu_ul">'
         
         
-        curs.execute(db_change('' + \
-            'select h.title, max(h.date) from history as h where not (title like "user:%" or title like "category:%" or title like "file:%") and exists (select title from data where title = h.title) and not exists (select title from back where link = h.title and type = "redirect") group by h.title order by h.date asc limit ?, 50' + \
-        ''), [sql_num])
+        curs.execute(db_change("select doc_name, set_data from data_set where set_name = 'last_edit' and doc_rev = '' order by set_data asc limit ?, 50"), [sql_num])
         n_list = curs.fetchall()
         n_list = curs.fetchall()
         for data in n_list:
         for data in n_list:
             div += '<li>' + data[1] + ' | <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
             div += '<li>' + data[1] + ' | <a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a></li>'
         
         
-        div += '</ul>' + next_fix('/old_page?num=', num, n_list)
+        div += '</ul>' + next_fix('/list/document/old/', num, n_list)
         
         
         return easy_minify(flask.render_template(skin_check(),
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('old_page'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             imp = [load_lang('old_page'), wiki_set(), wiki_custom(), wiki_css([0, 0])],

+ 24 - 23
route/list_please.py

@@ -1,31 +1,32 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_please_2(conn):
-    curs = conn.cursor()
+def list_please_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    num = int(number_check(flask.request.args.get('num', '1')))
-    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
+        num = int(number_check(flask.request.args.get('num', '1')))
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
 
-    curs.execute(db_change('select data from other where name = "count_all_title"'))
-    if int(curs.fetchall()[0][0]) > 30000:
-        return re_error('/error/25')
+        curs.execute(db_change('select data from other where name = "count_all_title"'))
+        if int(curs.fetchall()[0][0]) > 30000:
+            return re_error('/error/25')
 
 
-    div = '<ul class="inside_ul">'
+        div = '<ul class="opennamu_ul">'
 
 
-    curs.execute(db_change("select distinct title, link from back where type = 'no' order by title asc limit ?, 50"), [sql_num])
-    data_list = curs.fetchall()
-    for data in data_list:
-        div += '' + \
-            '<li>' + \
-                '<a id="not_thing" href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a> ' + \
-                '<a href="/w/' + url_pas(data[1]) + '">(' + html.escape(data[1]) + ')</a>' + \
-            '</li>' + \
-        ''
+        curs.execute(db_change("select distinct title, link from back where type = 'no' order by title asc limit ?, 50"), [sql_num])
+        data_list = curs.fetchall()
+        for data in data_list:
+            div += '' + \
+                '<li>' + \
+                    '<a class="opennamu_not_exist_link" href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a> ' + \
+                    '<a href="/w/' + url_pas(data[1]) + '">(' + html.escape(data[1]) + ')</a>' + \
+                '</li>' + \
+            ''
 
 
-    div += '</ul>' + next_fix('/please?num=', num, data_list)
+        div += '</ul>' + next_fix('/please?num=', num, data_list)
 
 
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('need_document'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-        data = div,
-        menu = [['other', load_lang('return')]]
-    ))
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('need_document'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = div,
+            menu = [['other', load_lang('return')]]
+        ))

+ 52 - 65
route/list_title_index.py

@@ -1,78 +1,65 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_title_index_2(conn):
-    curs = conn.cursor()
+def list_title_index(num = 1):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    page = int(number_check(flask.request.args.get('page', '1')))
-    num = int(number_check(flask.request.args.get('num', '100')))
-    sql_num = (page * num - num) if page * num > 0 else 0
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
 
-    all_list = sql_num + 1
+        all_list = sql_num + 1
+        data = ''
 
 
-    if num > 1000:
-        return re_error('/error/3')
+        curs.execute(db_change("select title from data asc limit ?, 50"), [sql_num])
+        title_list = curs.fetchall()
+        if title_list:
+            data += '<hr class="main_hr"><ul class="opennamu_ul">'
 
 
-    data = '<a href="/title_index?num=250">(250)</a> <a href="/title_index?num=500">(500)</a> <a href="/title_index?num=1000">(1000)</a>'
+        for list_data in title_list:
+            data += '<li>' + str(all_list) + '. <a href="/w/' + url_pas(list_data[0]) + '">' + html.escape(list_data[0]) + '</a></li>'
+            all_list += 1
 
 
-    curs.execute(db_change("select title from data order by title asc limit ?, ?"), [sql_num, num])
-    title_list = curs.fetchall()
-    if title_list:
-        data += '<hr class="main_hr"><ul class="inside_ul">'
+        if num == 1:
+            count_end = []
 
 
-    for list_data in title_list:
-        data += '<li>' + str(all_list) + '. <a href="/w/' + url_pas(list_data[0]) + '">' + html.escape(list_data[0]) + '</a></li>'
-        all_list += 1
+            curs.execute(db_change('select data from other where name = "count_all_title"'))
+            all_title = curs.fetchall()
+            if int(all_title[0][0]) < 30000:
+                count_end += [int(all_title[0][0])]
 
 
-    if page == 1:
-        count_end = []
+                sql_list = ['category:', 'user:', 'file:']
+                for sql in sql_list:
+                    curs.execute(db_change("select count(*) from data where title like ?"), [sql + '%'])
+                    count = curs.fetchall()
+                    if count:
+                        count_end += [int(count[0][0])]
+                    else:
+                        count_end += [0]
 
 
-        curs.execute(db_change('select data from other where name = "count_all_title"'))
-        all_title = curs.fetchall()
-        if int(all_title[0][0]) < 30000:
-            curs.execute(db_change("select count(*) from data"))
-            count = curs.fetchall()
-            if count:
-                count_end += [count[0][0]]
-            else:
-                count_end += [0]
-
-            sql_list = ['category:', 'user:', 'file:']
-            for sql in sql_list:
-                curs.execute(db_change("select count(*) from data where title like ?"), [sql + '%'])
-                count = curs.fetchall()
-                if count:
-                    count_end += [count[0][0]]
-                else:
-                    count_end += [0]
+                count_end += [count_end[0] - count_end[1]  - count_end[2]  - count_end[3]]
 
 
-            count_end += [count_end[0] - count_end[1]  - count_end[2]  - count_end[3]]
-
-            data += '''
-                </ul>
-                <hr class="main_hr">
-                <ul class="inside_ul">
-                    <li>''' + load_lang('all') + ' : ' + str(count_end[0]) + '''</li>
-                </ul>
-                <hr class="main_hr">
-                <ul class="inside_ul">
-                    <li>''' + load_lang('category') + ' : ' + str(count_end[1]) + '''</li>
-                    <li>''' + load_lang('user_document') + ' : ' + str(count_end[2]) + '''</li>
-                    <li>''' + load_lang('file') + ' : ' + str(count_end[3]) + '''</li>
-                    <li>''' + load_lang('other') + ' : ' + str(count_end[4]) + '''</li>
-            '''
-        else:
-            data += '''
-                </ul>
-                <hr class="main_hr">
-                <ul class="inside_ul">
-                    <li>''' + load_lang('all') + ' : ' + all_title[0][0] + '''</li>
-            '''
+                data += '''
+                    </ul>
+                    <ul class="opennamu_ul">
+                        <li>''' + load_lang('all') + ' : ' + str(count_end[0]) + '''</li>
+                    </ul>
+                    <ul class="opennamu_ul">
+                        <li>''' + load_lang('category') + ' : ' + str(count_end[1]) + '''</li>
+                        <li>''' + load_lang('user_document') + ' : ' + str(count_end[2]) + '''</li>
+                        <li>''' + load_lang('file') + ' : ' + str(count_end[3]) + '''</li>
+                        <li>''' + load_lang('other') + ' : ' + str(count_end[4]) + '''</li>
+                '''
+            else:
+                data += '''
+                    </ul>
+                    <ul class="opennamu_ul">
+                        <li>''' + load_lang('all') + ' : ' + all_title[0][0] + '''</li>
+                '''
 
 
-    data += '</ul>' + next_fix('/title_index?num=' + str(num) + '&page=', page, title_list, num)
-    sub = ' (' + str(num) + ')'
+        data += '</ul>' + next_fix('/list/document/all/', num, title_list, num)
+        sub = ' (' + str(num) + ')'
 
 
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('all_document_list'), wiki_set(), wiki_custom(), wiki_css([sub, 0])],
-        data = data,
-        menu = [['other', load_lang('return')]]
-    ))
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('all_document_list'), wiki_set(), wiki_custom(), wiki_css([sub, 0])],
+            data = data,
+            menu = [['other', load_lang('return')]]
+        ))

+ 20 - 19
route/list_user.py

@@ -1,26 +1,27 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def list_user_2(conn):
-    curs = conn.cursor()
+def list_user_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    num = int(number_check(flask.request.args.get('num', '1')))
-    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
+        num = int(number_check(flask.request.args.get('num', '1')))
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
 
-    list_data = '<ul class="inside_ul">'
+        list_data = '<ul class="opennamu_ul">'
 
 
-    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>' + \
-        ''
+        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 += '</ul>' + next_fix('/user_log?num=', num, user_list)
+        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(), wiki_custom(), wiki_css([0, 0])],
-        data = list_data,
-        menu = [['other', load_lang('return')]]
-    ))
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('member_list'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = list_data,
+            menu = [['other', load_lang('return')]]
+        ))

+ 11 - 10
route/login_find.py

@@ -1,13 +1,14 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def login_find():
 def login_find():
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('password_search'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-        data = '''
-            <ul class="inside_ul">
-                <li><a href="/login/find/email">''' + load_lang('email') + '''</a></li>
-                <li><a href="/login/find/key">''' + load_lang('key') + '''</a></li>
-            </ul>
-        ''',
-        menu = [['user', load_lang('return')]]
-    ))
+    with get_db_connect() as conn:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('password_search'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = '''
+                <ul class="opennamu_ul">
+                    <li><a href="/login/find/email">''' + load_lang('email') + '''</a></li>
+                    <li><a href="/login/find/key">''' + load_lang('key') + '''</a></li>
+                </ul>
+            ''',
+            menu = [['user', load_lang('return')]]
+        ))

+ 62 - 59
route/login_login.py

@@ -1,72 +1,75 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def login_login_2(conn):
-    curs = conn.cursor()
+def login_login_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    ip = ip_check()
-    if ip_or_user(ip) == 0:
-        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 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)
+        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.request.form.get('id', '')
-        user_data = {}
+            user_agent = flask.request.headers.get('User-Agent', '')
+            user_id = flask.request.form.get('id', '')
+            user_data = {}
 
 
-        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')
+            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')
 
 
-        for i in sql_data:
-            user_data[i[0]] = i[1]
-                
-        if len(user_data) < 2:
-            return re_error('/error/2')
+            for i in sql_data:
+                user_data[i[0]] = i[1]
 
 
-        if pw_check(
-            flask.request.form.get('pw', ''),
-            user_data['pw'],
-            user_data['encode'],
-            user_id
-        ) != 1:
-            return re_error('/error/10')
+            if len(user_data) < 2:
+                return re_error('/error/2')
 
 
-        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['login_id'] = user_id
+            if pw_check(
+                flask.request.form.get('pw', ''),
+                user_data['pw'],
+                user_data['encode'],
+                user_id
+            ) != 1:
+                return re_error('/error/10')
 
 
-            return redirect('/login/2fa')
-        else:
-            flask.session['id'] = user_id
+            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['login_id'] = user_id
 
 
-            ua_plus(user_id, ip, user_agent, get_time())
-            conn.commit()
+                return redirect('/login/2fa')
+            else:
+                flask.session['id'] = user_id
 
 
-            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('id') + '''" name="id" type="text">
-                        <hr class="main_hr">
-                        <input placeholder="''' + load_lang('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')]]
-        ))
+                ua_plus(user_id, ip, user_agent, get_time())
+                conn.commit()
+
+                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('id') + '''" name="id" type="text">
+                            <hr class="main_hr">
+                            <input placeholder="''' + load_lang('password') + '''" name="pw" type="password">
+                            <hr class="main_hr">
+                            <!-- <input type="checkbox" name="auto_login"> ''' + load_lang('auto_login') + ''' (''' + load_lang('not_working') + ''') -->
+                            <hr class="main_hr">
+                            ''' + captcha_get() + '''
+                            <button type="submit">''' + load_lang('login') + '''</button>
+                            ''' + http_warning() + '''
+                        </form>
+                        ''',
+                menu = [['user', load_lang('return')]]
+            ))

+ 58 - 57
route/login_login_2fa.py

@@ -1,70 +1,71 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def login_login_2fa_2(conn):
-    curs = conn.cursor()
+def login_login_2fa_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    # email 2fa
-    # pw 2fa
-    # q_a 2fa
-    if not (flask.session and 'login_id' in flask.session):
-        return redirect('/user')
+        # 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')
+        ip = ip_check()
+        if ip_or_user(ip) == 0:
+            return redirect('/user')
 
 
-    if ban_check(None, 'login') == 1:
-        return re_error('/ban')
+        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)
+        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']
+            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]
+            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')
+                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
+            flask.session['id'] = user_id
 
 
-        ua_plus(
-            user_id, 
-            ip, 
-            user_agent, 
-            get_time()
-        )
-        conn.commit()
+            ua_plus(
+                user_id, 
+                ip, 
+                user_agent, 
+                get_time()
+            )
+            conn.commit()
 
 
-        flask.session.pop('b_id', None)
+            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')]]
-        ))
+            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')]]
+            ))

+ 53 - 52
route/login_login_2fa_email.py

@@ -1,65 +1,66 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def login_login_2fa_email_2(conn):
-    curs = conn.cursor()
+def login_login_2fa_email_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    # email 2fa
-    # pw 2fa
-    # q_a 2fa
-    if not (flask.session and 'login_id' in flask.session):
-        return redirect('/user')
+        # 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')
+        ip = ip_check()
+        if ip_or_user(ip) == 0:
+            return redirect('/user')
 
 
-    if ban_check(None, 'login') == 1:
-        return re_error('/ban')
+        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)
+        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['b_id']
+            user_agent = flask.request.headers.get('User-Agent', '')
+            user_id = flask.session['b_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]
+            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')
+                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
+            flask.session['id'] = user_id
 
 
-        ua_plus(user_id, ip, user_agent, get_time())
-        conn.commit()
+            ua_plus(user_id, ip, user_agent, get_time())
+            conn.commit()
 
 
-        flask.session.pop('b_id', None)
+            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')]]
-        ))
+            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')]]
+            ))

+ 4 - 3
route/login_logout.py

@@ -1,7 +1,8 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def login_logout():
 def login_logout():
-    flask.session.pop('state', None)
-    flask.session.pop('id', None)
+    with get_db_connect() as conn:
+        flask.session.pop('state', None)
+        flask.session.pop('id', None)
 
 
-    return redirect('/user')
+        return redirect('/user')

+ 120 - 113
route/login_register.py

@@ -1,122 +1,129 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def login_register_2(conn):
-    curs = conn.cursor()
+def login_register_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-    if ban_check(None, 'login') == 1:
-        return re_error('/ban')
+        if ban_check(None, 'login') == 1:
+            return re_error('/ban')
 
 
-    ip = ip_check()
-    admin = admin_check()
-    if admin != 1 and ip_or_user(ip) == 0:
-        return redirect('/user')
+        ip = ip_check()
+        admin = admin_check()
+        if admin != 1 and ip_or_user(ip) == 0:
+            return redirect('/user')
 
 
-    if admin != 1:
-        curs.execute(db_change('select data from other where name = "reg"'))
-        set_d = curs.fetchall()
-        if set_d and set_d[0][0] == 'on':
-            return re_error('/ban')
+        if admin != 1:
+            curs.execute(db_change('select data from other where name = "reg"'))
+            set_d = curs.fetchall()
+            if set_d and set_d[0][0] == 'on':
+                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', '')
-        if user_id == '' or user_pw == '':
-            return re_error('/error/27')
-
-        if user_pw != user_repeat:
-            return re_error('/error/20')
-
-        if re.search(r'(?:[^A-Za-zㄱ-힣0-9])', user_id):
-            return re_error('/error/8')
-
-        curs.execute(db_change('select html from html_filter where kind = "name"'))
-        set_d = curs.fetchall()
-        for i in set_d:
-            check_r = re.compile(i[0], re.I)
-            if check_r.search(user_id):
+        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', '')
+
+            # PW 검증
+            if user_id == '' or user_pw == '':
+                return re_error('/error/27')
+
+            if user_pw != user_repeat:
+                return re_error('/error/20')
+
+            # PW 길이 제한
+            curs.execute(db_change("select data from other where name = 'password_min_length'"))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                password_min_length = int(number_check(db_data[0][0]))
+                if password_min_length > len(user_pw):
+                    return re_error('/error/40')
+
+            # ID 글자 확인
+            if re.search(r'(?:[^A-Za-zㄱ-힣0-9])', user_id):
                 return re_error('/error/8')
                 return re_error('/error/8')
 
 
-        if len(user_id) > 32:
-            return re_error('/error/7')
+            # ID 필터
+            curs.execute(db_change('select html from html_filter where kind = "name"'))
+            set_d = curs.fetchall()
+            for i in set_d:
+                check_r = re.compile(i[0], re.I)
+                if check_r.search(user_id):
+                    return re_error('/error/8')
 
 
-        curs.execute(db_change("select id from user_set where id = ?"), [user_id])
-        if curs.fetchall():
-            return re_error('/error/6')
-        
-        if admin != 1:
-            # 이메일 필요시 /register/email로 발송
-            curs.execute(db_change('select data from other where name = "email_have"'))
-            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 ''
-                
-        return easy_minify(flask.render_template(skin_check(),
-            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">
-                    
-                    ''' + captcha_get() + '''
-                    
-                    <!--
-                    <a href="" id="oauth_google">(Google)</a>     
-                    <hr class="main_hr">
-                    -->
-                    
-                    <button type="submit">''' + load_lang('save') + '''</button>
-                    
-                    ''' + 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')]]
-        ))
+            # ID 길이 제한 (32글자)
+            if len(user_id) > 32:
+                return re_error('/error/7')
+
+            # 중복 확인
+            curs.execute(db_change("select id from user_set where id = ?"), [user_id])
+            if curs.fetchall():
+                return re_error('/error/6')
+
+            if admin != 1:
+                # 이메일 필요시 /register/email로 발송
+                curs.execute(db_change('select data from other where name = "email_have"'))
+                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)
+
+            conn.commit()
+
+            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 ''
+
+            curs.execute(db_change("select data from other where name = 'password_min_length'"))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                password_min_length = ' (' + load_lang('password_min_length') + ' : ' + db_data[0][0] + ')'
+            else:
+                password_min_length = ''
+
+            return easy_minify(flask.render_template(skin_check(),
+                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') + password_min_length + '''" name="pw" type="password">
+                        <hr class="main_hr">
+
+                        <input placeholder="''' + load_lang('password_confirm') + '''" name="pw2" type="password">
+                        <hr class="main_hr">
+
+                        ''' + captcha_get() + '''
+
+                        <button type="submit">''' + load_lang('save') + '''</button>
+
+                        ''' + http_warning() + '''
+                    </form>
+                ''',
+                menu = [['user', load_lang('return')]]
+            ))

+ 56 - 55
route/login_register_email.py

@@ -1,66 +1,67 @@
 from .tool.func import *
 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)
+def login_register_email_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-        user_email = re.sub(r'\\', '', 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')
+        if not 'reg_id' in flask.session:
+            return redirect('/register')
 
 
-        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'
+        if flask.request.method == 'POST':
+            flask.session['reg_key'] = load_random_key(32)
 
 
-        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 : ' + str(flask.session.get('reg_key'))
-        else:
-            i_text = 'Key : ' + str(flask.session.get('reg_key'))
-        
+            user_email = re.sub(r'\\', '', 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 id from user_set where name = "email" and data = ?'), [user_email])
-        if curs.fetchall():
-            return re_error('/error/35')
+            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 : ' + str(flask.session.get('reg_key'))
+            else:
+                i_text = 'Key : ' + str(flask.session.get('reg_key'))
 
 
-        if send_email(user_email, t_text, i_text) == 0:
-            return re_error('/error/18')
 
 
-        flask.session['reg_email'] = user_email
+            curs.execute(db_change('select id from user_set where name = "email" and data = ?'), [user_email])
+            if curs.fetchall():
+                return re_error('/error/35')
 
 
-        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 ''
+            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">
+            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">
                     <hr class="main_hr">
-                    <button type="submit">''' + load_lang('save') + '''</button>
-                </form>
-            ''',
-            menu = [['user', load_lang('return')]]
-        ))
+                    ''' + 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')]]
+            ))

+ 43 - 42
route/login_register_email_check.py

@@ -1,47 +1,48 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def login_register_email_check_2(conn):
-    curs = conn.cursor()
+def login_register_email_check_2():
+    with get_db_connect() as 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:
+        if not 'reg_email' in flask.session:
             return redirect('/register')
             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')]]
-        ))
+        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')]]
+            ))

+ 59 - 57
route/login_register_submit.py

@@ -1,61 +1,63 @@
 from .tool.func import *
 from .tool.func import *
 
 
-from .tool.func import *
+def login_register_submit_2():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
 
 
-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'] = ''
+        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()
             
             
-        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('/')
-    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')]]
-        ))
+            for for_a in get_admin_list():
+                add_alarm(for_a, flask.session['submit_id'] + ' | <a href="/app_submit">' + load_lang('new_application') + '</a>')
+
+            return redirect('/')
+        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')]]
+            ))

+ 11 - 4
route/main_error_404.py

@@ -1,7 +1,14 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def main_error_404(e = ''):
 def main_error_404(e = ''):
-    if os.path.exists('404.html') and flask.request.path != '/':
-        return open('404.html', encoding = 'utf8').read(), 404
-    else:
-        return redirect('/w/' + wiki_set(2))
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+        
+        if os.path.exists('404.html') and flask.request.path != '/':
+            return open('404.html', encoding = 'utf8').read(), 404
+        else:
+            curs.execute(db_change('select data from other where name = "frontpage"'))
+            db_data = curs.fetchall()
+            db_data = db_data[0][0] if db_data and db_data[0][0] != '' else 'FrontPage'
+            
+            return redirect('/w/' + db_data)

+ 35 - 0
route/main_func_easter_egg.py

@@ -0,0 +1,35 @@
+from .tool.func import *
+
+def main_func_easter_egg():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+        
+        random_n = random.randrange(0, 8)
+        select_list = [
+            'PWD0ZbR7AOY', # TH06   - Shanghai Teahouse ~ Chinese Tea
+            'HoU29ljOmTE', # TH10.5 - Flawless Clothing of Celestials
+            'PR2vUm-Ald8', # TH06   - U.N. Owen Was Her
+            'opZoEmsu_Lo', # TH09   - Flowering Night
+            'txZFFTusSvw', # TH08   - Reach for the Moon ~ Immortal Smoke
+            'Ixq9xL2tvRU', # TH07   - Phantom Ensemble
+            '-3IAx_r4Au0', # TH17   - Entrusting This World to Idols ~ Idolatrize World
+            'wObZkycA6sc', # TH11   - Last Remote
+            'hZxYLa97gDg', # TH12   - Emotional Skyscraper ~ Cosmic Mind
+            'hwn2kw4eFJM', # TH07   - Border of Life
+            'wX2t_8HOtiY', # TH08   - Voyage 1969
+            'tLQjcf45fKE', # TH07   - Necrofantasia
+            # Remix by NyxTheShield
+        ]
+
+        ip = ip_check()
+        if ip_or_user(ip) == 0:
+            curs.execute(db_change('select name from user_set where id = ? and name = ?'), [ip, 'get_🥚'])
+            if not curs.fetchall():
+                curs.execute(db_change('insert into user_set (name, id, data) values ("get_🥚", ?, "Y")'), [ip])
+                conn.commit()
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = ['Easter Egg', wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = '<iframe width="640" height="360" src="https://www.youtube.com/embed/' + select_list[random_n] + '" frameborder="0" allowfullscreen></iframe>',
+            menu = [['manager', load_lang('return')]]
+        ))

+ 18 - 15
route/main_func_setting.py

@@ -1,20 +1,23 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def main_func_setting():
 def main_func_setting():
-    li_list = [
-        ['main', load_lang('main_setting')],
-        ['phrase', load_lang('text_setting')],
-        ['robot', 'robots.txt'],
-        ['external', load_lang('ext_api_req_set')],
-        ['head', load_lang('main_head')],
-        ['body/top', load_lang('main_body')],
-        ['body/bottom', load_lang('main_bottom_body')]
-    ]
+    with get_db_connect() as conn:
+        li_list = [
+            ['main', load_lang('main_setting')],
+            ['phrase', load_lang('text_setting')],
+            ['robot', 'robots.txt'],
+            ['external', load_lang('ext_api_req_set')],
+            ['head', load_lang('main_head')],
+            ['body/top', load_lang('main_body')],
+            ['body/bottom', load_lang('main_bottom_body')],
+            ['sitemap', load_lang('sitemap_management')],
+            ['top_menu', load_lang('top_menu_setting') + ' (' + load_lang('beta') + ')']
+        ]
 
 
-    li_data = ''.join(['<li><a href="/setting/' + str(li[0]) + '">' + li[1] + '</a></li>' for li in li_list])
+        li_data = ''.join(['<li><a href="/setting/' + str(li[0]) + '">' + li[1] + '</a></li>' for li in li_list])
 
 
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-        data = '<h2>' + load_lang('list') + '</h2><ul class="inside_ul">' + li_data + '</ul>',
-        menu = [['manager', load_lang('return')]]
-    ))
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = '<h2>' + load_lang('list') + '</h2><ul class="opennamu_ul">' + li_data + '</ul>',
+            menu = [['manager', load_lang('return')]]
+        ))

+ 32 - 16
route/main_func_setting_acl.py

@@ -10,7 +10,10 @@ def main_func_setting_acl():
             3 : 'upload_acl',
             3 : 'upload_acl',
             4 : 'all_view_acl',
             4 : 'all_view_acl',
             5 : 'many_upload_acl',
             5 : 'many_upload_acl',
-            6 : 'vote_acl'
+            6 : 'vote_acl',
+            7 : 'document_edit_acl',
+            8 : 'document_move_acl',
+            9 : 'document_delete_acl'
         }
         }
 
 
         if flask.request.method == 'POST':
         if flask.request.method == 'POST':
@@ -40,7 +43,7 @@ def main_func_setting_acl():
                 if sql_d:
                 if sql_d:
                     d_list[i] = sql_d[0][0]
                     d_list[i] = sql_d[0][0]
                 else:
                 else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i_list[i], 'normal'])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i_list[i], 'normal'])
 
 
                     d_list[i] = 'normal'
                     d_list[i] = 'normal'
 
 
@@ -62,36 +65,49 @@ def main_func_setting_acl():
 
 
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('main_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = [load_lang('main_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
+                data = render_simple_set('''
                     <form method="post">
                     <form method="post">
+                        <hr class="main_hr">
                         <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
                         <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
+                        
+                        <h2>''' + load_lang('document_acl') + '''</h2>
+                        <select ''' + disable + ''' name="edit">''' + acl_div[0] + '''</select>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <span>''' + load_lang('document_acl') + '''</span> 
+
+                        <h3>''' + load_lang('document_edit_acl') + '''</h3>
+                        <select ''' + disable + ''' name="document_edit_acl">''' + acl_div[6] + '''</select>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <select ''' + disable + ''' name="edit">''' + acl_div[0] + '''</select>
+
+                        <h3>''' + load_lang('document_move_acl') + '''</h3>
+                        <select ''' + disable + ''' name="document_move_acl">''' + acl_div[7] + '''</select>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <span>''' + load_lang('discussion_acl') + '''</span>
+
+                        <h3>''' + load_lang('document_delete_acl') + '''</h3>
+                        <select ''' + disable + ''' name="document_delete_acl">''' + acl_div[8] + '''</select>
                         <hr class="main_hr">
                         <hr class="main_hr">
+                        
+                        <h2>''' + load_lang('discussion_acl') + '''</h2>
                         <select ''' + disable + ''' name="discussion">''' + acl_div[1] + '''</select>
                         <select ''' + disable + ''' name="discussion">''' + acl_div[1] + '''</select>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <span>''' + load_lang('upload_acl') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>''' + load_lang('upload_acl') + '''</h2>
                         <select ''' + disable + ''' name="upload_acl">''' + acl_div[2] + '''</select>
                         <select ''' + disable + ''' name="upload_acl">''' + acl_div[2] + '''</select>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <span>''' + load_lang('view_acl') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>''' + load_lang('view_acl') + '''</h2>
                         <select ''' + disable + ''' name="all_view_acl">''' + acl_div[3] + '''</select>
                         <select ''' + disable + ''' name="all_view_acl">''' + acl_div[3] + '''</select>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <span>''' + load_lang('many_upload_acl') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>''' + load_lang('many_upload_acl') + '''</h2>
                         <select ''' + disable + ''' name="many_upload_acl">''' + acl_div[4] + '''</select>
                         <select ''' + disable + ''' name="many_upload_acl">''' + acl_div[4] + '''</select>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <span>''' + load_lang('vote_acl') + '''</span>
-                        <hr class="main_hr">
+                        
+                        <h2>''' + load_lang('vote_acl') + '''</h2>
                         <select ''' + disable + ''' name="vote_acl">''' + acl_div[5] + '''</select>
                         <select ''' + disable + ''' name="vote_acl">''' + acl_div[5] + '''</select>
+                        
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     </form>
-                ''',
+                '''),
                 menu = [['setting', load_lang('return')]]
                 menu = [['setting', load_lang('return')]]
             ))
             ))

+ 9 - 10
route/main_func_setting_external.py

@@ -42,7 +42,7 @@ def main_func_setting_external():
                 if sql_d:
                 if sql_d:
                     d_list += [sql_d[0][0]]
                     d_list += [sql_d[0][0]]
                 else:
                 else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i, ''])
 
 
                     d_list += ['']
                     d_list += ['']
 
 
@@ -71,9 +71,9 @@ def main_func_setting_external():
 
 
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('ext_api_req_set'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = [load_lang('ext_api_req_set'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post" id="main_set_data">
-                        <h2>1. ''' + load_lang('captcha') + '''</h2>
+                data = render_simple_set('''
+                    <form method="post">
+                        <h2>''' + load_lang('captcha') + '''</h2>
                         <a href="https://www.google.com/recaptcha/">(''' + load_lang('recaptcha') + ''')</a> <a href="https://www.hcaptcha.com/">(''' + load_lang('hcaptcha') + ''')</a>
                         <a href="https://www.google.com/recaptcha/">(''' + load_lang('recaptcha') + ''')</a> <a href="https://www.hcaptcha.com/">(''' + load_lang('hcaptcha') + ''')</a>
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
@@ -93,11 +93,11 @@ def main_func_setting_external():
                             ''' + re_ver + '''
                             ''' + re_ver + '''
                         </select>
                         </select>
 
 
-                        <h2>2. ''' + load_lang('email_setting') + '''</h1>
+                        <h2>''' + load_lang('email_setting') + '''</h1>
                         <input type="checkbox" name="email_have" ''' + ('checked' if d_list[9] != '' else '')  + '''> ''' + \
                         <input type="checkbox" name="email_have" ''' + ('checked' if d_list[9] != '' else '')  + '''> ''' + \
                              load_lang('email_required') + '''
                              load_lang('email_required') + '''
 
 
-                        <h2>2.1. ''' + load_lang('smtp_setting') + '''</h1>
+                        <h2>''' + load_lang('smtp_setting') + '''</h1>
                         <a href="https://support.google.com/mail/answer/7126229">(Google)</a>
                         <a href="https://support.google.com/mail/answer/7126229">(Google)</a>
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
@@ -127,7 +127,7 @@ def main_func_setting_external():
                         <hr class="main_hr">
                         <hr class="main_hr">
                         <input type="password" name="smtp_pass" value="''' + html.escape(d_list[6]) + '''">
                         <input type="password" name="smtp_pass" value="''' + html.escape(d_list[6]) + '''">
 
 
-                        <h2>3. ''' + load_lang('oauth') + ''' (''' + load_lang('not_working') + ''')</h2>
+                        <h2>''' + load_lang('oauth') + ''' (''' + load_lang('not_working') + ''')</h2>
                         <a href="https://developers.google.com/identity/protocols/oauth2">(Google)</a>
                         <a href="https://developers.google.com/identity/protocols/oauth2">(Google)</a>
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
@@ -137,9 +137,8 @@ def main_func_setting_external():
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     </form>
-                    <script>simple_render('main_set_data');</script>
-                ''',
+                '''),
                 menu = [['setting', load_lang('return')]]
                 menu = [['setting', load_lang('return')]]
             ))
             ))

+ 29 - 20
route/main_func_setting_head.py

@@ -1,13 +1,13 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def main_func_setting_head(num, skin_name = ''):
+def main_func_setting_head(num, skin_name = '', set_preview = 0):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
 
 
         if admin_check() != 1:
         if admin_check() != 1:
             return re_error('/ban')
             return re_error('/ban')
         
         
-        if flask.request.method == 'POST':
+        if flask.request.method == 'POST' and set_preview == 0:
             if num == 4:
             if num == 4:
                 info_d = 'body'
                 info_d = 'body'
                 end_r = 'body/top'
                 end_r = 'body/top'
@@ -26,11 +26,7 @@ def main_func_setting_head(num, skin_name = ''):
 
 
             curs.execute(db_change("select name from other where name = ? and coverage = ?"), [info_d, coverage])
             curs.execute(db_change("select name from other where name = ? and coverage = ?"), [info_d, coverage])
             if curs.fetchall():
             if curs.fetchall():
-                curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [
-                    flask.request.form.get('content', ''),
-                    info_d,
-                    coverage
-                ])
+                curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [flask.request.form.get('content', ''), info_d, coverage])
             else:
             else:
                 curs.execute(db_change("insert into other (name, data, coverage) values (?, ?, ?)"), [info_d, flask.request.form.get('content', ''), coverage])
                 curs.execute(db_change("insert into other (name, data, coverage) values (?, ?, ?)"), [info_d, flask.request.form.get('content', ''), coverage])
 
 
@@ -47,37 +43,49 @@ def main_func_setting_head(num, skin_name = ''):
                 curs.execute(db_change("select data from other where name = 'body'"))
                 curs.execute(db_change("select data from other where name = 'body'"))
                 title = '_body'
                 title = '_body'
                 start = ''
                 start = ''
+                form_action = 'formaction="/setting/body/top"'
+                data_preview = flask.request.form.get('content', '') if set_preview == 1 else ''
                 plus = '''
                 plus = '''
-                    <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
+                    <button id="opennamu_preview_button" type="submit" formaction="/setting_preview/body/top">''' + load_lang('preview') + '''</button>
                     <hr class="main_hr">
                     <hr class="main_hr">
-                    <div id="see_preview"></div>
+                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 '''
                 '''
             elif num == 7:
             elif num == 7:
                 curs.execute(db_change("select data from other where name = 'bottom_body'"))
                 curs.execute(db_change("select data from other where name = 'bottom_body'"))
                 title = '_bottom_body'
                 title = '_bottom_body'
                 start = ''
                 start = ''
+                data_preview = flask.request.form.get('content', '') if set_preview == 1 else ''
+                form_action = 'formaction="/setting/body/bottom"'
                 plus = '''
                 plus = '''
-                    <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
+                    <button id="opennamu_preview_button" type="submit" formaction="/setting_preview/body/bottom">''' + load_lang('preview') + '''</button>
                     <hr class="main_hr">
                     <hr class="main_hr">
-                    <div id="see_preview"></div>
+                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 '''
                 '''
             else:
             else:
                 curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [skin_name])
                 curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [skin_name])
                 title = '_head'
                 title = '_head'
                 start = '' + \
                 start = '' + \
-                    '<a href="?">(' + load_lang('all') + ')</a> ' + \
-                    ' '.join(['<a href="/setting/head/' + i + '">(' + i + ')</a>' for i in load_skin('', 1)]) + '''
+                    '<a href="/setting/head">(' + load_lang('all') + ')</a> ' + \
+                    ' '.join(['<a href="/setting/head/' + url_pas(i) + '">(' + html.escape(i) + ')</a>' for i in load_skin('', 1)]) + '''
                     <hr class="main_hr">
                     <hr class="main_hr">
-                    <span>&lt;style&gt;CSS&lt;/style&gt;<br>&lt;script&gt;JS&lt;/script&gt;</span>
+                    <span>
+                        &lt;style&gt;CSS&lt;/style&gt;
+                        <br>
+                        &lt;script&gt;JS&lt;/script&gt;
+                    </span>
                     <hr class="main_hr">
                     <hr class="main_hr">
                 '''
                 '''
+                form_action = ''
                 plus = ''
                 plus = ''
 
 
-            head = curs.fetchall()
-            if head:
-                data = head[0][0]
+            if set_preview == 1:
+                data = data_preview
             else:
             else:
-                data = ''
+                head = curs.fetchall()
+                if head:
+                    data = head[0][0]
+                else:
+                    data = ''
 
 
             if skin_name != '':
             if skin_name != '':
                 sub_plus = ' (' + skin_name + ')'
                 sub_plus = ' (' + skin_name + ')'
@@ -89,9 +97,10 @@ def main_func_setting_head(num, skin_name = ''):
                 data = '''
                 data = '''
                     <form method="post">
                     <form method="post">
                         ''' + start + '''
                         ''' + start + '''
-                        <textarea rows="25" placeholder="''' + load_lang('enter_html') + '''" name="content" id="content">''' + html.escape(data) + '''</textarea>
+                        <textarea class="opennamu_textarea_500" placeholder="''' + load_lang('enter_html') + '''" name="content" id="content">''' + html.escape(data) + '''</textarea>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        ''' + (load_lang('main_css_warning') + '<hr class="main_hr">' if title == '_head' else '') + '''
+                        <button id="opennamu_save_button" type="submit" ''' + form_action + '''>''' + load_lang('save') + '''</button>
                         ''' + plus + '''
                         ''' + plus + '''
                     </form>
                     </form>
                 ''',
                 ''',

+ 65 - 30
route/main_func_setting_main.py

@@ -14,13 +14,13 @@ def main_func_setting_main(db_set):
             5 : ['skin', ''],
             5 : ['skin', ''],
             7 : ['reg', ''],
             7 : ['reg', ''],
             8 : ['ip_view', ''],
             8 : ['ip_view', ''],
-            9 : ['back_up', '0'],
+            9 : ['back_up', ''],
             10 : ['port', '3000'],
             10 : ['port', '3000'],
             11 : ['key', load_random_key()],
             11 : ['key', load_random_key()],
             12 : ['update', 'stable'],
             12 : ['update', 'stable'],
             15 : ['encode', 'sha3'],
             15 : ['encode', 'sha3'],
             16 : ['host', '0.0.0.0'],
             16 : ['host', '0.0.0.0'],
-            19 : ['slow_edit', '0'],
+            19 : ['slow_edit', ''],
             20 : ['requires_approval', ''],
             20 : ['requires_approval', ''],
             21 : ['backup_where', ''],
             21 : ['backup_where', ''],
             22 : ['domain', flask.request.host],
             22 : ['domain', flask.request.host],
@@ -30,7 +30,12 @@ def main_func_setting_main(db_set):
             26 : ['edit_bottom_compulsion', ''],
             26 : ['edit_bottom_compulsion', ''],
             27 : ['http_select', 'http'],
             27 : ['http_select', 'http'],
             28 : ['title_max_length', ''],
             28 : ['title_max_length', ''],
-            29 : ['title_topic_max_length', '']
+            29 : ['title_topic_max_length', ''],
+            30 : ['password_min_length', ''],
+            31 : ['wiki_access_password_need', ''],
+            32 : ['wiki_access_password', ''],
+            33 : ['history_recording_off', ''],
+            34 : ['namumark_compatible', '']
         }
         }
 
 
         if flask.request.method == 'POST':
         if flask.request.method == 'POST':
@@ -51,14 +56,21 @@ def main_func_setting_main(db_set):
                 curs.execute(db_change('select data from other where name = ?'), [setting_list[i][0]])
                 curs.execute(db_change('select data from other where name = ?'), [setting_list[i][0]])
                 db_data = curs.fetchall()
                 db_data = curs.fetchall()
                 if not db_data:
                 if not db_data:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [setting_list[i][0], setting_list[i][1]])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [
+                        setting_list[i][0],
+                        setting_list[i][1]
+                    ])
 
 
                 d_list[i] = db_data[0][0] if db_data else setting_list[i][1]
                 d_list[i] = db_data[0][0] if db_data else setting_list[i][1]
             else:
             else:
                 conn.commit()
                 conn.commit()
 
 
+            init_set_list = get_init_set_list()
+                
+            # 언어도 변경 가능하도록 필요
+                
             encode_select = ''
             encode_select = ''
-            encode_select_data = ['sha256', 'sha3']
+            encode_select_data = init_set_list['encode']['list'] + ['sha256']
             for encode_select_one in encode_select_data:
             for encode_select_one in encode_select_data:
                 if encode_select_one == d_list[15]:
                 if encode_select_one == d_list[15]:
                     encode_select = '<option value="' + encode_select_one + '">' + encode_select_one + '</option>' + encode_select
                     encode_select = '<option value="' + encode_select_one + '">' + encode_select_one + '</option>' + encode_select
@@ -73,7 +85,7 @@ def main_func_setting_main(db_set):
                 else:
                 else:
                     tls_select += '<option value="' + tls_select_one + '">' + tls_select_one + '</option>'
                     tls_select += '<option value="' + tls_select_one + '">' + tls_select_one + '</option>'
 
 
-            check_box_div = ['', '', '', '', '', '', '', '']
+            check_box_div = ['', '', '', '', '', '', '', '', '', '', '']
             for i in range(0, len(check_box_div)):
             for i in range(0, len(check_box_div)):
                 if i == 0:
                 if i == 0:
                     acl_num = 7
                     acl_num = 7
@@ -89,6 +101,12 @@ def main_func_setting_main(db_set):
                     acl_num = 25
                     acl_num = 25
                 elif i == 7:
                 elif i == 7:
                     acl_num = 26
                     acl_num = 26
+                elif i == 8:
+                    acl_num = 31
+                elif i == 9:
+                    acl_num = 33
+                elif i == 10:
+                    acl_num = 34
 
 
                 if d_list[acl_num]:
                 if d_list[acl_num]:
                     check_box_div[i] = 'checked="checked"'
                     check_box_div[i] = 'checked="checked"'
@@ -105,9 +123,9 @@ def main_func_setting_main(db_set):
 
 
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('main_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = [load_lang('main_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post" id="main_set_data">
-                        <h2>1. ''' + load_lang('basic_set') + '''</h2>
+                data = render_simple_set('''
+                    <form method="post">
+                        <h2>''' + load_lang('basic_set') + '''</h2>
                         <span>''' + load_lang('wiki_name') + '''</span>
                         <span>''' + load_lang('wiki_name') + '''</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
                         <input name="name" value="''' + html.escape(d_list[0]) + '''">
                         <input name="name" value="''' + html.escape(d_list[0]) + '''">
@@ -149,20 +167,30 @@ def main_func_setting_main(db_set):
                         <span>''' + load_lang('encryption_method') + '''</span>
                         <span>''' + load_lang('encryption_method') + '''</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
                         <select name="encode">''' + encode_select + '''</select>
                         <select name="encode">''' + encode_select + '''</select>
+                        <hr class="main_hr">
+                        
+                        <input type="checkbox" name="wiki_access_password_need" ''' + check_box_div[8] + '''> ''' + load_lang('set_wiki_access_password_need') + ''' (''' + load_lang('restart_required') + ''') (''' + load_lang('beta') + ''')
+                        <hr class="main_hr">
+                        <span>''' + load_lang('set_wiki_access_password') + ''' (''' + load_lang('restart_required') + ''') (''' + load_lang('beta') + ''')</span>
+                        <hr class="main_hr">
+                        <input type="password" name="wiki_access_password" value="''' + html.escape(d_list[32]) + '''">
 
 
-                        <h3>1.1. ''' + load_lang('communication_set') + '''</h3>
+                        <h3>''' + load_lang('communication_set') + '''</h3>
                         <input type="checkbox" name="enable_comment" ''' + check_box_div[5] + '''> ''' + load_lang('enable_comment_function') + ''' (''' + load_lang('not_working') + ''')
                         <input type="checkbox" name="enable_comment" ''' + check_box_div[5] + '''> ''' + load_lang('enable_comment_function') + ''' (''' + load_lang('not_working') + ''')
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
                         <input type="checkbox" name="enable_challenge" ''' + check_box_div[6] + '''> ''' + load_lang('enable_challenge_function') + ''' (''' + load_lang('not_working') + ''')
                         <input type="checkbox" name="enable_challenge" ''' + check_box_div[6] + '''> ''' + load_lang('enable_challenge_function') + ''' (''' + load_lang('not_working') + ''')
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
-                        <h2>2. ''' + load_lang('design_set') + '''</h2>
+                        <h2>''' + load_lang('design_set') + '''</h2>
                         <span>''' + load_lang('wiki_skin') + '''</span>
                         <span>''' + load_lang('wiki_skin') + '''</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <select name="skin">''' + load_skin(d_list[5] if d_list[5] != '' else 'tenshi') + '''</select>
+                        <select name="skin">''' + load_skin(d_list[5] if d_list[5] != '' else 'ringo') + '''</select>
+
+                        <hr class="main_hr">
+                        <input type="checkbox" name="namumark_compatible" ''' + check_box_div[10] + '''> ''' + load_lang('namumark_fully_compatible_mode') + '''
 
 
-                        <h2>3. ''' + load_lang('login_set') + '''</h2>
+                        <h2>''' + load_lang('login_set') + '''</h2>
                         <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
                         <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
@@ -173,40 +201,41 @@ def main_func_setting_main(db_set):
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
                         <input type="checkbox" name="ua_get" ''' + check_box_div[4] + '''> ''' + load_lang('ua_get_off') + '''
                         <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">
                         <hr class="main_hr">
-                        <input name="upload" value="''' + html.escape(d_list[4]) + '''">
+                        
+                        <span>''' + load_lang('password_min_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
+                        <input name="password_min_length" value="''' + html.escape(d_list[30]) + '''">
+                        
+                        <h2>''' + load_lang('server_set') + '''</h2>
 
 
                         <span>''' + load_lang('update_branch') + '''</span>
                         <span>''' + load_lang('update_branch') + '''</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
                         <select name="update">''' + branch_div + '''</select>
                         <select name="update">''' + branch_div + '''</select>
 
 
                         <span ''' + sqlite_only + '''>
                         <span ''' + sqlite_only + '''>
-                            <h3>4.1. ''' + load_lang('sqlite_only') + '''</h3>
+                            <h3>''' + load_lang('sqlite_only') + '''</h3>
                             <span>
                             <span>
-                                ''' + load_lang('backup_interval') + ' (' + load_lang('hour') + ') (' + load_lang('off') + ' : 0) ' + \
-                                '(' + load_lang('restart_required') + ''')</span>
+                                ''' + load_lang('backup_interval') + ''' (''' + load_lang('hour') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''') ''' + \
+                                '''(''' + load_lang('restart_required') + ''')</span>
                             <hr class="main_hr">
                             <hr class="main_hr">
                             <input name="back_up" value="''' + html.escape(d_list[9]) + '''">
                             <input name="back_up" value="''' + html.escape(d_list[9]) + '''">
                             <hr class="main_hr">
                             <hr class="main_hr">
 
 
                             <span>
                             <span>
-                                ''' + load_lang('backup_where') + ' (' + load_lang('empty') + ' : ' + load_lang('default') + ') ' + \
-                                '(' + load_lang('restart_required') + ''') (''' + load_lang('example') + ''' : ./data/backup.db)
+                                ''' + load_lang('backup_where') + ''' (''' + load_lang('default') + ''' : ''' + load_lang('empty') + ''') ''' + \
+                                '''(''' + load_lang('restart_required') + ''') (''' + load_lang('example') + ''' : ./data/backup.db)
                             </span>
                             </span>
                             <hr class="main_hr">
                             <hr class="main_hr">
                             <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
                             <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
                             <hr class="main_hr">
                             <hr class="main_hr">
                         </span>
                         </span>
 
 
-                        <h2>5. ''' + load_lang('edit_set') + '''</h2>
+                        <h2>''' + load_lang('edit_set') + '''</h2>
                         <span><a href="/setting/acl">(''' + load_lang('main_acl_setting') + ''')</a></span>
                         <span><a href="/setting/acl">(''' + load_lang('main_acl_setting') + ''')</a></span>
                         <hr class="main_hr">
                         <hr class="main_hr">
 
 
-                        <span>''' + load_lang('slow_edit') + ' (' + load_lang('second') + ') (' + load_lang('off') + ''' : 0)</span>
+                        <span>''' + load_lang('slow_edit') + ''' (''' + load_lang('second') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
                         <input name="slow_edit" value="''' + html.escape(d_list[19]) + '''">
                         <input name="slow_edit" value="''' + html.escape(d_list[19]) + '''">
                         <hr class="main_hr">
                         <hr class="main_hr">
@@ -214,20 +243,26 @@ def main_func_setting_main(db_set):
                         <input type="checkbox" name="edit_bottom_compulsion" ''' + check_box_div[7] + '''> ''' + load_lang('edit_bottom_compulsion') + ''' (''' + load_lang('beta') + ''')
                         <input type="checkbox" name="edit_bottom_compulsion" ''' + check_box_div[7] + '''> ''' + load_lang('edit_bottom_compulsion') + ''' (''' + load_lang('beta') + ''')
                         <hr class="main_hr">
                         <hr class="main_hr">
                         
                         
-                        <span>''' + load_lang('title_max_length') + ''' (''' + load_lang('beta') + ''')</span>
+                        <span>''' + load_lang('title_max_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
                         <input name="title_max_length" value="''' + html.escape(d_list[28]) + '''">
                         <input name="title_max_length" value="''' + html.escape(d_list[28]) + '''">
                         <hr class="main_hr">
                         <hr class="main_hr">
                         
                         
-                        <span>''' + load_lang('title_topic_max_length') + ''' (''' + load_lang('not_working') + ''')</span>
+                        <span>''' + load_lang('title_topic_max_length') + ''' (''' + load_lang('beta') + ''') (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
                         <input name="title_topic_max_length" value="''' + html.escape(d_list[29]) + '''">
                         <input name="title_topic_max_length" value="''' + html.escape(d_list[29]) + '''">
                         <hr class="main_hr">
                         <hr class="main_hr">
-
+                        
+                        <span>''' + load_lang('max_file_size') + ''' (MB)</span>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        <input name="upload" value="''' + html.escape(d_list[4]) + '''">
+                        <hr class="main_hr">
+                        
+                        <input type="checkbox" name="history_recording_off" ''' + check_box_div[9] + '''> ''' + load_lang('set_history_recording_off') + ''' (''' + load_lang('beta') + ''')
+                        <hr class="main_hr">
+
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     </form>
-                    <script>simple_render('main_set_data');</script>
-                ''',
+                '''),
                 menu = [['setting', load_lang('return')]]
                 menu = [['setting', load_lang('return')]]
             ))
             ))

+ 1 - 1
route/main_func_setting_main_logo.py

@@ -53,7 +53,7 @@ def main_func_setting_main_logo():
                 data = '''
                 data = '''
                     <form method="post">
                     <form method="post">
                         ''' + end_data + '''
                         ''' + end_data + '''
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     </form>
                 ''',
                 ''',
                 menu = [['setting/main', load_lang('return')]]
                 menu = [['setting/main', load_lang('return')]]

+ 55 - 47
route/main_func_setting_phrase.py

@@ -25,7 +25,10 @@ def main_func_setting_phrase():
             'upload_help',
             'upload_help',
             'upload_default',
             'upload_default',
             'license',
             'license',
-            'topic_text'
+            'topic_text',
+            'phrase_user_page_admin',
+            'phrase_user_page_owner',
+            'phrase_old_page_warring'
         ]
         ]
         if flask.request.method == 'POST':
         if flask.request.method == 'POST':
             for i in i_list:
             for i in i_list:
@@ -48,7 +51,7 @@ def main_func_setting_phrase():
                 if sql_d:
                 if sql_d:
                     d_list += [sql_d[0][0]]
                     d_list += [sql_d[0][0]]
                 else:
                 else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i, ''])
 
 
                     d_list += ['']
                     d_list += ['']
 
 
@@ -56,71 +59,76 @@ def main_func_setting_phrase():
 
 
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('text_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = [load_lang('text_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post" id="main_set_data">
-                        <h2>1. ''' + load_lang('register_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[0] + '''">''' + html.escape(d_list[0]) + '''</textarea>
+                data = render_simple_set('''
+                    <form method="post">
+                        <h2>''' + load_lang('register_text') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[0] + '''">''' + html.escape(d_list[0]) + '''</textarea>
 
 
-                        <h2>2. ''' + load_lang('non_login_alert') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[1] + '''">''' + html.escape(d_list[1]) + '''</textarea>
+                        <h2>''' + load_lang('non_login_alert') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[1] + '''">''' + html.escape(d_list[1]) + '''</textarea>
 
 
-                        <h2>3. ''' + load_lang('edit_bottom_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[2] + '''">''' + html.escape(d_list[2]) + '''</textarea>
+                        <h2>''' + load_lang('edit_bottom_text') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[2] + '''">''' + html.escape(d_list[2]) + '''</textarea>
 
 
-                        <h2>4. ''' + load_lang('copyright_checkbox_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[3] + '''">''' + html.escape(d_list[3]) + '''</textarea>
+                        <h2>''' + load_lang('copyright_checkbox_text') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[3] + '''">''' + html.escape(d_list[3]) + '''</textarea>
 
 
-                        <h2>5. ''' + load_lang('check_key_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[4] + '''">''' + html.escape(d_list[4]) + '''</textarea>
+                        <h2>''' + load_lang('check_key_text') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[4] + '''">''' + html.escape(d_list[4]) + '''</textarea>
 
 
-                        <h2>6. ''' + load_lang('email_title') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[5] + '''">''' + html.escape(d_list[5]) + '''</textarea>
+                        <h2>''' + load_lang('email_title') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[5] + '''">''' + html.escape(d_list[5]) + '''</textarea>
 
 
-                        <h2>7. ''' + load_lang('email_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[6] + '''">''' + html.escape(d_list[6]) + '''</textarea>
+                        <h2>''' + load_lang('email_text') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[6] + '''">''' + html.escape(d_list[6]) + '''</textarea>
 
 
-                        <h2>8. ''' + load_lang('email_insert_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[7] + '''">''' + html.escape(d_list[7]) + '''</textarea>
+                        <h2>''' + load_lang('email_insert_text') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[7] + '''">''' + html.escape(d_list[7]) + '''</textarea>
 
 
-                        <h2>9. ''' + load_lang('password_search_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[8] + '''">''' + html.escape(d_list[8]) + '''</textarea>
+                        <h2>''' + load_lang('password_search_text') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[8] + '''">''' + html.escape(d_list[8]) + '''</textarea>
 
 
-                        <h2>10. ''' + load_lang('reset_user_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[9] + '''">''' + html.escape(d_list[9]) + '''</textarea>
+                        <h2>''' + load_lang('reset_user_text') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[9] + '''">''' + html.escape(d_list[9]) + '''</textarea>
 
 
-                        <h2>11. ''' + load_lang('error_401') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[10] + '''">''' + html.escape(d_list[10]) + '''</textarea>
+                        <h2>''' + load_lang('error_401') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[10] + '''">''' + html.escape(d_list[10]) + '''</textarea>
 
 
-                        <h2>12. ''' + load_lang('error_404') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[11] + '''">''' + html.escape(d_list[11]) + '''</textarea>
+                        <h2>''' + load_lang('error_404') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[11] + '''">''' + html.escape(d_list[11]) + '''</textarea>
 
 
-                        <h2>13. ''' + load_lang('approval_question') + '''</h2>
-                        <sup>(1)</sup>
+                        <h2>''' + load_lang('approval_question') + '''</h2>
+                        <sup><a href="/setting/main">''' + load_lang('approval_question_visible_only_when_approval_on') + '''</a></sup>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <textarea rows="3" name="''' + i_list[12] + '''">''' + html.escape(d_list[12]) + '''</textarea>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[12] + '''">''' + html.escape(d_list[12]) + '''</textarea>
 
 
-                        <h2>14. ''' + load_lang('edit_help') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[13] + '''">''' + html.escape(d_list[13]) + '''</textarea>
+                        <h2>''' + load_lang('edit_help') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[13] + '''">''' + html.escape(d_list[13]) + '''</textarea>
 
 
-                        <h2>15. ''' + load_lang('upload_help') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[14] + '''">''' + html.escape(d_list[14]) + '''</textarea>
+                        <h2>''' + load_lang('upload_help') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[14] + '''">''' + html.escape(d_list[14]) + '''</textarea>
 
 
-                        <h2>16. ''' + load_lang('upload_default') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[15] + '''">''' + html.escape(d_list[15]) + '''</textarea>
+                        <h2>''' + load_lang('upload_default') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[15] + '''">''' + html.escape(d_list[15]) + '''</textarea>
 
 
-                        <h2>17. ''' + load_lang('bottom_text') + ''' (HTML)</h2>
-                        <textarea rows="3" name="''' + i_list[16] + '''">''' + html.escape(d_list[16]) + '''</textarea>
+                        <h2>''' + load_lang('bottom_text') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[16] + '''">''' + html.escape(d_list[16]) + '''</textarea>
 
 
-                        <h2>18. ''' + load_lang('topic_text') + '''</h2>
-                        <textarea rows="3" name="''' + i_list[17] + '''">''' + html.escape(d_list[17]) + '''</textarea>
+                        <h2>''' + load_lang('topic_text') + '''</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[17] + '''">''' + html.escape(d_list[17]) + '''</textarea>
+                        
+                        <h2>''' + load_lang('phrase_user_page_admin') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[18] + '''">''' + html.escape(d_list[18]) + '''</textarea>
+                        
+                        <h2>''' + load_lang('phrase_user_page_owner') + ''' (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[19] + '''">''' + html.escape(d_list[19]) + '''</textarea>
+
+                        <h2>''' + load_lang('phrase_old_page_warring') + ''' (''' + load_lang('beta') + ''') (HTML)</h2>
+                        <textarea class="opennamu_textarea_200" name="''' + i_list[20] + '''">''' + html.escape(d_list[20]) + '''</textarea>
 
 
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     </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')]]
                 menu = [['setting', load_lang('return')]]
             ))
             ))

+ 25 - 37
route/main_func_setting_robot.py

@@ -6,61 +6,49 @@ def main_func_setting_robot():
 
 
         if admin_check() != 1:
         if admin_check() != 1:
             return re_error('/ban')
             return re_error('/ban')
+
+        curs.execute(db_change("select data from other where name = 'robot'"))
+        db_data = curs.fetchall()
+        if db_data:
+            data = db_data[0][0]
+        else:
+            data = ''
+
+        curs.execute(db_change("select data from other where name = 'robot_default'"))
+        db_data_2 = curs.fetchall()
+        if db_data_2 and db_data_2[0][0] != '':
+            default_data = 'checked'
+        else:
+            default_data = ''
         
         
         if flask.request.method == 'POST':
         if flask.request.method == 'POST':
-            curs.execute(db_change("select name from other where name = 'robot'"))
-            if curs.fetchall():
+            if db_data:
                 curs.execute(db_change("update other set data = ? where name = 'robot'"), [flask.request.form.get('content', '')])
                 curs.execute(db_change("update other set data = ? where name = 'robot'"), [flask.request.form.get('content', '')])
             else:
             else:
-                curs.execute(db_change("insert into other (name, data) values ('robot', ?)"), [flask.request.form.get('content', '')])
+                curs.execute(db_change("insert into other (name, data, coverage) values ('robot', ?, '')"), [flask.request.form.get('content', '')])
 
 
-            conn.commit()
+            if db_data_2:
+                curs.execute(db_change("update other set data = ? where name = 'robot_default'"), [flask.request.form.get('default', '')])
+            else:
+                curs.execute(db_change("insert into other (name, data, coverage) values ('robot_default', ?, '')"), [flask.request.form.get('default', '')])
 
 
-            fw = open('./robots.txt', 'w', encoding='utf8')
-            fw.write(re.sub('\r\n', '\n', flask.request.form.get('content', '')))
-            fw.close()
+            conn.commit()
 
 
             admin_check(None, 'edit_set (robot)')
             admin_check(None, 'edit_set (robot)')
 
 
             return redirect('/setting/robot')
             return redirect('/setting/robot')
         else:
         else:
-            if not os.path.exists('robots.txt'):
-                curs.execute(db_change('select data from other where name = "robot"'))
-                robot_test = curs.fetchall()
-                if robot_test:
-                    fw_test = open('./robots.txt', 'w', encoding='utf8')
-                    fw_test.write(re.sub('\r\n', '\n', robot_test[0][0]))
-                    fw_test.close()
-                else:
-                    fw_test = open('./robots.txt', 'w', encoding='utf8')
-                    fw_test.write('User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/')
-                    fw_test.close()
-
-                    curs.execute(db_change('insert into other (name, data) values ("robot", "User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/")'))
-
-            curs.execute(db_change("select data from other where name = 'robot'"))
-            robot = curs.fetchall()
-            if robot:
-                data = robot[0][0]
-            else:
-                data = ''
-
-            f = open('./robots.txt', encoding='utf8')
-            lines = f.readlines()
-            f.close()
-
-            if not data or data == '':
-                data = ''.join(lines)
-
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = ['robots.txt', wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = ['robots.txt', wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                 data = '''
                     <a href="/robots.txt">(''' + load_lang('view') + ''')</a>
                     <a href="/robots.txt">(''' + load_lang('view') + ''')</a>
                     <hr class="main_hr">
                     <hr class="main_hr">
                     <form method="post">
                     <form method="post">
-                        <textarea rows="25" name="content">''' + html.escape(data) + '''</textarea>
+                        <textarea class="opennamu_textarea_500" name="content">''' + html.escape(data) + '''</textarea>
+                        <hr class="main_hr">
+                        <input type="checkbox" name="default" ''' + default_data + '''> ''' + load_lang('default') + '''
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     </form>
                 ''',
                 ''',
                 menu = [['setting', load_lang('return')]]
                 menu = [['setting', load_lang('return')]]

+ 116 - 0
route/main_func_setting_sitemap.py

@@ -0,0 +1,116 @@
+from .tool.func import *
+
+def main_func_setting_sitemap():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if admin_check() != 1:
+            return re_error('/ban')
+        
+        if flask.request.method == 'POST':
+            admin_check(None, 'make sitemap')
+
+            data = '' + \
+                '<?xml version="1.0" encoding="UTF-8"?>\n' + \
+                '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + \
+            ''
+
+            if flask.request.form.get('exclude_domain', None):
+                domain = ''
+            else:
+                domain = load_domain('full')
+
+            sql_add = ''
+            if flask.request.form.get('exclude_user_page', None):
+                sql_add += ' title not like "user:%"'
+
+            if flask.request.form.get('exclude_file_page', None):
+                if sql_add != '':
+                    sql_add += ' and'
+
+                sql_add += ' title not like "file:%"'
+
+            if flask.request.form.get('exclude_category_page', None):
+                if sql_add != '':
+                    sql_add += ' and'
+
+                sql_add += ' title not like "category:%"'
+
+            if sql_add != '':
+                sql_add = ' where' + sql_add
+
+            print(sql_add)
+            curs.execute(db_change("select title from data" + sql_add))
+            all_data = curs.fetchall()
+
+            len_all_data = len(all_data)
+            count = int(len_all_data / 30000)
+            other_count = len_all_data % 30000
+
+            for i in range(count + 1):
+                data += '<sitemap><loc>' + domain + '/sitemap_' + str(i) + '.xml</loc></sitemap>\n'
+
+            data += '' + \
+                '</sitemapindex>' + \
+            ''
+
+            f = open("sitemap.xml", 'w')
+            f.write(data)
+            f.close()
+
+            for i in range(count + 1):
+                data = '' + \
+                    '<?xml version="1.0" encoding="UTF-8"?>\n' + \
+                    '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + \
+                ''
+
+                if count == i:
+                    for x in all_data[30000 * i:]:
+                        data += '<url><loc>' + domain + '/w/' + url_pas(x[0]) + '</loc></url>\n'
+                else:
+                    for x in all_data[30000 * i:30000 * (i + 1)]:
+                        data += '<url><loc>' + domain + '/w/' + url_pas(x[0]) + '</loc></url>\n'
+
+                data += '' + \
+                    '</urlset>' + \
+                ''
+
+                f = open("sitemap_" + str(i) + ".xml", 'w')
+                f.write(data)
+                f.close()
+
+            return redirect('/setting/sitemap')
+        else:
+            sitemap_list = ''
+            if os.path.exists('sitemap.xml'):
+                sitemap_list += '<a href="/sitemap.xml">(' + load_lang('view') + ')</a>'
+
+                for_a = 0
+                while os.path.exists('sitemap_' + str(for_a) + '.xml'):
+                    sitemap_list += ' <a href="/sitemap_' + str(for_a) + '.xml">(sitemap_' + str(for_a) + '.xml)</a>'
+
+                    for_a += 1
+
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('sitemap_management'), wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('beta') + ')', 0])],
+                data = '''
+                    ''' + sitemap_list + '''
+                    <hr class="main_hr">
+                    <form method="post">
+                        <input type="checkbox" name="exclude_domain"> ''' + load_lang('stiemap_exclude_domain') + '''
+                        <hr class="main_hr">
+
+                        <input type="checkbox" name="exclude_user_page"> ''' + load_lang('stiemap_exclude_user_page') + '''
+                        <hr class="main_hr">
+
+                        <input type="checkbox" name="exclude_file_page"> ''' + load_lang('stiemap_exclude_file_page') + '''
+                        <hr class="main_hr">
+
+                        <input type="checkbox" name="exclude_category_page"> ''' + load_lang('stiemap_exclude_category_page') + '''
+                        <hr class="main_hr">
+
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('create') + '''</button>
+                    </form>
+                ''',
+                menu = [['setting', load_lang('return')]]
+            ))

+ 51 - 0
route/main_func_setting_top_menu.py

@@ -0,0 +1,51 @@
+from .tool.func import *
+
+def main_func_setting_top_menu():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if admin_check() != 1:
+            return re_error('/ban')
+        
+        if flask.request.method == 'POST':
+            curs.execute(db_change("select name from other where name = 'top_menu'"))
+            if curs.fetchall():
+                curs.execute(db_change("update other set data = ? where name = 'top_menu'"), [flask.request.form.get('content', '')])
+            else:
+                curs.execute(db_change("insert into other (name, data, coverage) values ('top_menu', ?, '')"), [flask.request.form.get('content', '')])
+
+            conn.commit()
+
+            admin_check(None, 'edit_set (top_menu)')
+
+            return redirect('/setting/top_menu')
+        else:
+            curs.execute(db_change("select data from other where name = 'top_menu'"))
+            db_data = curs.fetchall()
+            db_data = db_data[0][0] if db_data else ''
+            
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('top_menu_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                data = '''
+                    <span>
+                        EX)
+                        <br>
+                        ONTS
+                        <br>
+                        https://2du.pythonanywhere.com/
+                        <br>
+                        FrontPage
+                        <br>
+                        /w/FrontPage
+                    </span>
+                    <hr class="main_hr">
+                    ''' + load_lang('not_support_skin_warning') + '''
+                    <hr class="main_hr">
+                    <form method="post">
+                        <textarea class="opennamu_textarea_500" placeholder="''' + load_lang('enter_top_menu_setting') + '''" name="content" id="content">''' + html.escape(db_data) + '''</textarea>
+                        <hr class="main_hr">
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
+                menu = [['setting', load_lang('return')]]
+            ))

+ 2 - 1
route/main_search.py

@@ -1,4 +1,5 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def main_search():
 def main_search():
-    return redirect('/search/' + url_pas(flask.request.form.get('search', 'test')))
+    with get_db_connect() as conn:
+        return redirect('/search/' + url_pas(flask.request.form.get('search', 'test')))

+ 34 - 34
route/main_search_deep.py

@@ -1,63 +1,63 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def main_search_deep(name = 'Test'):
+def main_search_deep(name = 'Test', search_type = 'title', num = 1):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
 
 
         if name == '':
         if name == '':
             return redirect()
             return redirect()
 
 
-        num = int(number_check(flask.request.args.get('num', '1')))
         sql_num = (num * 50 - 50) if num * 50 > 0 else 0
         sql_num = (num * 50 - 50) if num * 50 > 0 else 0
 
 
-        div = '<ul class="inside_ul">'
+        div = ''
+        if search_type == 'title':
+            div += '<a href="/search_data/1/' + url_pas(name) + '">(' + load_lang('search_document_data') + ')</a>'
+        else:
+            div += '<a href="/search/1/' + url_pas(name) + '">(' + load_lang('search_document_name') + ')</a>'
+
+        name_new = ''
+        if re.search(r'^분류:', name):
+            name_new = re.sub(r"^분류:", 'category:', name)
+        elif re.search(r"^사용자:", name):
+            name_new = re.sub(r"^사용자:", 'user:', name)
+        elif re.search(r"^파일:", name):
+            name_new = re.sub(r"^파일:", 'file:', name)
 
 
-        div_plus = ''
-        test = ''
+        if name_new != '':
+            div += ' <a href="/search/1/' + url_pas(name_new) + '">(' + name_new + ')</a>'
 
 
         curs.execute(db_change("select title from data where title = ?"), [name])
         curs.execute(db_change("select title from data where title = ?"), [name])
-        link_id = '' if curs.fetchall() else 'id="not_thing"'
+        link_id = '' if curs.fetchall() else 'class="opennamu_not_exist_link"'
 
 
-        div = '''
-            <ul class="inside_ul">
+        div += '''
+            <ul class="opennamu_ul">
                 <li>
                 <li>
                     <a ''' + link_id + ' href="/w/' + url_pas(name) + '">' + html.escape(name) + '''</a>
                     <a ''' + link_id + ' href="/w/' + url_pas(name) + '">' + html.escape(name) + '''</a>
                 </li>
                 </li>
             </ul>
             </ul>
             <hr class="main_hr">
             <hr class="main_hr">
-            <ul class="inside_ul">
+            <ul class="opennamu_ul">
         '''
         '''
 
 
-        curs.execute(db_change('select data from other where name = "count_all_title"'))
-        if int(curs.fetchall()[0][0]) < 30000:
-            curs.execute(db_change("" + \
-                "select distinct title, case " + \
-                "when title like ? then 'title' else 'data' end from data " + \
-                "where (title like ? or data like ?) order by case " + \
-                "when title like ? then 1 else 2 end limit ?, 50"),
-                ['%' + name + '%', '%' + name + '%', '%' + name + '%', '%' + name + '%', sql_num]
+        if search_type == 'title':
+            curs.execute(db_change("select title from data where title like ? order by title limit ?, 50"),
+                ['%' + name + '%', sql_num]
             )
             )
-            all_list = curs.fetchall()
-            if all_list:
-                test = all_list[0][1]
-
-                for data in all_list:
-                    if data[1] != test:
-                        div_plus += '</ul><hr class="main_hr"><ul class="inside_ul">'
-
-                        test = data[1]
-
-                    div_plus += '<li><a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a> (' + data[1] + ')</li>'
         else:
         else:
-            curs.execute(db_change("select title from data where title like ? order by title limit ?, 50"),
+            curs.execute(db_change("select title from data where data like ? order by title limit ?, 50"),
                 ['%' + name + '%', sql_num]
                 ['%' + name + '%', sql_num]
             )
             )
-            all_list = curs.fetchall()
-            for data in all_list:
-                div_plus += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a> (title)</li>'
 
 
-        div += div_plus + '</ul>'
-        div += next_fix('/search/' + url_pas(name) + '?num=', num, all_list)
+        all_list = curs.fetchall()
+        for data in all_list:
+            div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
+
+        div += '</ul>'
+        
+        if search_type == 'title':
+            div += get_next_page_bottom('/search/{}/' + url_pas(name), num, all_list)
+        else:
+            div += get_next_page_bottom('/search_data/{}/' + url_pas(name), num, all_list)
 
 
         return easy_minify(flask.render_template(skin_check(),
         return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('search') + ')', 0])],
             imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('search') + ')', 0])],

+ 26 - 25
route/main_sys_restart.py

@@ -1,31 +1,32 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def main_sys_restart():
 def main_sys_restart():
-    if admin_check() != 1:
-        return re_error('/error/3')
+    with get_db_connect() as conn:
+        if admin_check() != 1:
+            return re_error('/error/3')
 
 
-    if flask.request.method == 'POST':
-        admin_check(None, 'restart')
+        if flask.request.method == 'POST':
+            admin_check(None, 'restart')
 
 
-        print('----')
-        print('Restart')
+            print('----')
+            print('Restart')
 
 
-        try:
-            os.execl(sys.executable, sys.executable, *sys.argv)
-        except:
-            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(), wiki_custom(), wiki_css([0, 0])],
-            data = '''
-                <form method="post">
-                    <button type="submit">''' + load_lang('restart') + '''</button>
-                </form>
-            ''',
-            menu = [['manager', load_lang('return')]]
-        ))
+            try:
+                os.execl(sys.executable, sys.executable, *sys.argv)
+            except:
+                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(), wiki_custom(), wiki_css([0, 0])],
+                data = '''
+                    <form method="post">
+                        <button type="submit">''' + load_lang('restart') + '''</button>
+                    </form>
+                ''',
+                menu = [['manager', load_lang('return')]]
+            ))

+ 20 - 17
route/main_sys_shutdown.py

@@ -1,23 +1,26 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def main_sys_shutdown():
 def main_sys_shutdown():
-    if admin_check() != 1:
-        return re_error('/error/3')
+    with get_db_connect() as conn:
+        if admin_check() != 1:
+            return re_error('/error/3')
 
 
-    if flask.request.method == 'POST':
-        admin_check(None, 'shutdown')
+        if flask.request.method == 'POST':
+            admin_check(None, 'shutdown')
 
 
-        print('----')
-        print('shutdown')
+            conn.commit()
 
 
-        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')]]
-        ))
+            print('----')
+            print('Shutdown')
+
+            os._exit(0)
+        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')]]
+            ))

+ 6 - 6
route/main_sys_update.py

@@ -46,17 +46,17 @@ def main_sys_update():
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('update'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = [load_lang('update'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = load_lang('update_warning') + '''
                 data = load_lang('update_warning') + '''
-                    <hr class=\"main_hr\">
-                    <ul class="inside_ul">
-                        <li>''' + load_lang('version') + ''' : <span id="ver_send_2"></span></li>
-                        <li id="ver_send" style="display: none;">''' + load_lang('lastest') + ''' : </li>
+                    <hr class="main_hr">
+                    <ul class="opennamu_ul">
+                        <li id="ver_send_2">''' + load_lang('version') + ''' : </li>
+                        <li id="ver_send">''' + load_lang('lastest') + ''' : </li>
                     </ul>
                     </ul>
                     <a href="https://github.com/openNAMU/openNAMU">(Beta)</a> <a href="https://github.com/openNAMU/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\">
+                    <hr class="main_hr">
                     <form method="post">
                     <form method="post">
                         <button type="submit">''' + load_lang('update') + '''</button>
                         <button type="submit">''' + load_lang('update') + '''</button>
                     </form>
                     </form>
-                    <script>load_ver();</script>
+                    <!-- JS : opennamu_do_insert_version -->
                 ''',
                 ''',
                 menu = [['manager', load_lang('return')]]
                 menu = [['manager', load_lang('return')]]
             ))
             ))

+ 52 - 107
route/main_tool_admin.py

@@ -1,112 +1,57 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def main_tool_admin(num = 1, add_2 = ''):
-    title_list = {
-        0 : [load_lang('document_name'), 'acl', load_lang('acl')],
-        1 : [0, 'check', load_lang('check')],
-        2 : [load_lang('file_name'), 'file_filter/add', load_lang('file_filter_add')],
-        3 : [0, 'admin', load_lang('authorize')],
-        4 : [0, 'record', load_lang('edit_record')],
-        5 : [0, 'record/topic', load_lang('discussion_record')],
-        6 : [load_lang('name'), 'admin_plus', load_lang('add_admin_group')],
-        7 : [load_lang('name'), 'edit_filter/add', load_lang('edit_filter_add')],
-        8 : [load_lang('document_name'), 'search', load_lang('search')],
-        9 : [0, 'block_log/user', load_lang('blocked_user')],
-        10 : [0, 'block_log/admin', load_lang('blocked_admin')],
-        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')],
-        14 : [load_lang('document_name'), 'star_doc', load_lang('add_star_doc')],
-        15 : [load_lang('name_or_ip_or_regex'), 'ban', load_lang('release')]
-    }
-
-    if num == 1:
+def main_tool_admin():
+    with get_db_connect() as conn:
         return easy_minify(flask.render_template(skin_check(),
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('admin_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
             imp = [load_lang('admin_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = '''
-                <div id="other_simple_render">
-                    <h2>1. ''' + load_lang('admin') + '''</h2>
-                    <ul class="inside_ul">
-                        <li><a href="/manager/2">''' + load_lang('acl_change') + '''</a></li>
-                        <li><a href="/manager/3">''' + load_lang('check_user') + '''</a></li>
-                        <li><a href="/ban">''' + load_lang('ban') + '''</a></li>
-                        <li><a href="/manager/17">''' + load_lang('release') + '''</a></li>
-                        <li><a href="/manager/5">''' + load_lang('authorize') + '''</a></li>
-                    </ul>
-                    <h2>2. ''' + load_lang('owner') + '''</h2>
-                    <ul class="inside_ul">
-                        <li><a href="/admin_group">''' + load_lang('admin_group_list') + '''</a></li>
-                        <li><a href="/delete_mutiple">''' + load_lang('many_delete') + '''</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>
-                    </ul>
-                    <h3>2.1. ''' + load_lang('filter') + '''</h3>
-                    <ul class="inside_ul">
-                        <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
-                        <li><a href="/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
-                        <li><a href="/edit_top">''' + load_lang('edit_tool_list') + '''</a></li>
-                        <li><a href="/image_license">''' + load_lang('image_license_list') + '''</a></li>
-                        <li><a href="/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
-                        <li><a href="/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
-                        <li><a href="/file_filter">''' + load_lang('file_filter_list') + '''</a></li>
-                        <li><a href="/extension_filter">''' + load_lang('extension_filter_list') + '''</a></li>
-                        <li><a href="/filter/document/list">''' + load_lang('document_filter_list') + '''</a></li>
-                    </ul>
-                    <h3>2.2. ''' + 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>
-                    <h2>3. ''' + load_lang('version') + '''</h2>
-                    <ul class="inside_ul">
-                        <li>''' + load_lang('version') + ''' : <span id="ver_send_2"></span></li>
-                        <li id="ver_send" style="display: none;">''' + load_lang('lastest') + ''' : </li>
-                    </ul>
-                    <h3>3.1. ''' + load_lang('skin_info') + '''</h3>
-                    <ul class="inside_ul">
-                        <li><a href="/api/skin_info?all=true">''' + load_lang('skin_info') + '''</a></li>
-                        <div id="ver_send_3"></div>
-                    </ul>
-                </div>
-                <script>load_ver(); do_skin_ver_check(); simple_render('other_simple_render');</script>
-            ''',
+            data = render_simple_set('''
+                <h2>''' + load_lang('admin') + '''</h2>
+                <ul class="opennamu_ul">
+                    <li><a href="/manager/2">''' + load_lang('acl_change') + '''</a></li>
+                    <li><a href="/manager/3">''' + load_lang('check_user') + '''</a></li>
+                    <li><a href="/auth/give/ban">''' + load_lang('ban') + '''</a></li>
+                    <li><a href="/auth/give/ban_multiple">''' + load_lang('multiple_ban') + '''</a></li>
+                    <li><a href="/manager/17">''' + load_lang('release') + '''</a></li>
+                    <li><a href="/manager/5">''' + load_lang('authorize') + '''</a></li>
+                </ul>
+                <h2>''' + load_lang('owner') + '''</h2>
+                <ul class="opennamu_ul">
+                    <li><a href="/admin_group">''' + load_lang('admin_group_list') + '''</a></li>
+                    <li><a href="/delete_multiple">''' + load_lang('many_delete') + '''</a></li>
+                    <li><a href="/app_submit">''' + load_lang('application_list') + '''</a></li>
+                    <li><a href="/register">''' + load_lang('add_user') + '''</a></li>
+                    <li><a href="/setting">''' + load_lang('setting') + '''</a></li>
+                </ul>
+                <h3>''' + load_lang('filter') + '''</h3>
+                <ul class="opennamu_ul">
+                    <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
+                    <li><a href="/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
+                    <li><a href="/edit_top">''' + load_lang('edit_tool_list') + '''</a></li>
+                    <li><a href="/image_license">''' + load_lang('image_license_list') + '''</a></li>
+                    <li><a href="/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
+                    <li><a href="/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
+                    <li><a href="/file_filter">''' + load_lang('file_filter_list') + '''</a></li>
+                    <li><a href="/extension_filter">''' + load_lang('extension_filter_list') + '''</a></li>
+                    <li><a href="/filter/document/list">''' + load_lang('document_filter_list') + ''' (''' + load_lang('beta') + ''')</a></li>
+                </ul>
+                <h3>''' + load_lang('server') + '''</h2>
+                <ul class="opennamu_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>
+                <h2>''' + load_lang('version') + '''</h2>
+                <ul class="opennamu_ul">
+                    <li id="ver_send_2">''' + load_lang('version') + ''' : </li>
+                    <li id="ver_send">''' + load_lang('lastest') + ''' : </li>
+                </ul>
+                <h3>''' + load_lang('skin_info') + '''</h3>
+                <ul class="opennamu_ul">
+                    <li><a href="/api/skin_info?all=true">''' + load_lang('skin_info') + '''</a></li>
+                    <div id="ver_send_3"></div>
+                </ul>
+                <!-- JS : opennamu_do_insert_version -->
+                <!-- JS : opennamu_do_insert_version_skin -->
+            '''),
             menu = [['other', load_lang('return')]]
             menu = [['other', load_lang('return')]]
-        ))
-    elif not num - 1 > len(title_list):
-        num -= 2
-        
-        add_1 = flask.request.form.get('name', 'test')
-        if flask.request.method == 'POST':
-            if add_2 != '':
-                return redirect('/' + title_list[num][1] + '/' + url_pas(add_2) + '/doc_from/' + url_pas(add_1))
-            elif flask.request.form.get('regex', '') != '':
-                return redirect('/' + title_list[num][1] + '/' + url_pas(add_1) + '?type=regex')
-            else:
-                return redirect('/' + title_list[num][1] + '/' + url_pas(add_1))
-        else:
-            if title_list[num][0] == 0:
-                placeholder = load_lang('user_name')
-            else:
-                placeholder = title_list[num][0]
-
-            plus = ''
-            if num == 15:
-                plus = '<input type="checkbox" name="regex"> ' + load_lang('regex') + '<hr class="main_hr">'
-
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [title_list[num][2], wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
-                    <form method="post">
-                        <input placeholder="''' + placeholder + '''" name="name" type="text">
-                        <hr class="main_hr">
-                        ''' + plus + '''
-                        <button type="submit">''' + load_lang('go') + '''</button>
-                    </form>
-                ''',
-                menu = [['manager', load_lang('return')]]
-            ))
-    else:
-        return redirect()
+        ))

+ 0 - 0
route/tool/func_render_wiki.py → route/main_tool_guide.py


+ 28 - 30
route/main_tool_other.py

@@ -1,56 +1,54 @@
 from .tool.func import *
 from .tool.func import *
 
 
 def main_tool_other():
 def main_tool_other():
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('other_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-        data = '''
-            <div id="other_simple_render">
-                <h2>1. ''' + load_lang('record') + '''</h2>
-                <ul class="inside_ul">
+    with get_db_connect() as conn:
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('other_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = render_simple_set('''
+                <h2>''' + load_lang('record') + '''</h2>
+                <ul class="opennamu_ul">
                     <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
                     <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
                     <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
                     <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
                 </ul>
                 </ul>
-                <h2>2. ''' + load_lang('list') + '''</h2>
-                <h3>2.1. ''' + load_lang('admin') + '''</h3>
-                <ul class="inside_ul">               
+                <h2>''' + load_lang('list') + '''</h2>
+                <h3>''' + load_lang('admin') + '''</h3>
+                <ul class="opennamu_ul">               
                     <li><a href="/admin_list">''' + load_lang('admin_list') + '''</a></li>
                     <li><a href="/admin_list">''' + load_lang('admin_list') + '''</a></li>
-                    <li><a href="/admin_log">''' + load_lang('authority_use_list') + '''</a></li>
+                    <li><a href="/list/admin/auth_use">''' + load_lang('authority_use_list') + '''</a></li>
                 </ul>
                 </ul>
-                <h3>2.2. ''' + load_lang('discussion') + '''</h3>
-                <ul class="inside_ul">
+                <h3>''' + load_lang('discussion') + '''</h3>
+                <ul class="opennamu_ul">
                     <li><a href="/recent_discuss">''' + load_lang('recent_discussion') + '''</a></li>
                     <li><a href="/recent_discuss">''' + load_lang('recent_discussion') + '''</a></li>
                 </ul>
                 </ul>
-                <h3>2.3. ''' + load_lang('document') + '''</h3>
-                <ul class="inside_ul">
-                    <li><a href="/recent_changes">''' + load_lang('recent_change') + '''</a></li>
-                    <li><a href="/title_index">''' + load_lang('all_document_list') + '''</a></li>
+                <h3>''' + load_lang('document') + '''</h3>
+                <ul class="opennamu_ul">
+                    <li><a href="/recent_change">''' + load_lang('recent_change') + '''</a></li>
+                    <li><a href="/list/document/all">''' + load_lang('all_document_list') + '''</a></li>
                     <li><a href="/acl_list">''' + load_lang('acl_document_list') + '''</a></li>
                     <li><a href="/acl_list">''' + load_lang('acl_document_list') + '''</a></li>
                     <li><a href="/please">''' + load_lang('need_document') + '''</a></li>
                     <li><a href="/please">''' + load_lang('need_document') + '''</a></li>
                     <li><a href="/long_page">''' + load_lang('long_page') + '''</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>
-                    <li><a href="/old_page">''' + load_lang('old_page') + '''</a></li>
+                    <li><a href="/list/document/old">''' + load_lang('old_page') + '''</a></li>
                 </ul>
                 </ul>
-                <h3>2.4. ''' + load_lang('user') + '''</h3>
-                <ul class="inside_ul">
+                <h3>''' + load_lang('user') + '''</h3>
+                <ul class="opennamu_ul">
                     <li><a href="/block_log">''' + load_lang('recent_ban') + '''</a></li>
                     <li><a href="/block_log">''' + load_lang('recent_ban') + '''</a></li>
                     <li><a href="/user_log">''' + load_lang('member_list') + '''</a></li>
                     <li><a href="/user_log">''' + load_lang('member_list') + '''</a></li>
                 </ul>
                 </ul>
-                <h3>2.5. ''' + load_lang('other') + '''</h3>
-                <ul class="inside_ul">
+                <h3>''' + load_lang('other') + '''</h3>
+                <ul class="opennamu_ul">
                     <li><a href="/image_file_list">''' + load_lang('image_file_list') + '''</a></li>
                     <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="/vote">''' + load_lang('vote_list') + '''</a></li>
                 </ul>
                 </ul>
-                <h2>3. ''' + load_lang('other') + '''</h2>
-                <ul class="inside_ul">
+                <h2>''' + load_lang('other') + '''</h2>
+                <ul class="opennamu_ul">
                     <li><a href="/upload">''' + load_lang('upload') + '''</a></li>
                     <li><a href="/upload">''' + load_lang('upload') + '''</a></li>
                     <li><a href="/manager/10">''' + load_lang('search') + '''</a></li>
                     <li><a href="/manager/10">''' + load_lang('search') + '''</a></li>
                 </ul>
                 </ul>
-                <h2>4. ''' + load_lang('admin') + '''</h2>
-                <ul class="inside_ul">
+                <h2>''' + load_lang('admin') + '''</h2>
+                <ul class="opennamu_ul">
                     <li><a href="/manager/1">''' + load_lang('admin_tool') + '''</a></li>
                     <li><a href="/manager/1">''' + load_lang('admin_tool') + '''</a></li>
                 </ul>
                 </ul>
-            </div>
-            <script>simple_render('other_simple_render');</script>
-        ''',
-        menu = 0
-    ))
+            '''),
+            menu = 0
+        ))

+ 61 - 0
route/main_tool_redirect.py

@@ -0,0 +1,61 @@
+from .tool.func import *
+
+def main_tool_redirect(num = 1, add_2 = ''):
+    with get_db_connect() as conn:
+        title_list = {
+            0 : [load_lang('document_name'), 'acl', load_lang('acl')],
+            1 : [0, 'check', load_lang('check')],
+            2 : [load_lang('file_name'), 'file_filter/add', load_lang('file_filter_add')],
+            3 : [0, 'admin', load_lang('authorize')],
+            4 : [0, 'record', load_lang('edit_record')],
+            5 : [0, 'record/topic', load_lang('discussion_record')],
+            6 : [load_lang('name'), 'admin_plus', load_lang('add_admin_group')],
+            7 : [load_lang('name'), 'edit_filter/add', load_lang('edit_filter_add')],
+            8 : [load_lang('document_name'), 'search', load_lang('search')],
+            9 : [0, 'block_log/user', load_lang('blocked_user')],
+            10 : [0, 'block_log/admin', load_lang('blocked_admin')],
+            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')],
+            14 : [load_lang('document_name'), 'star_doc', load_lang('add_star_doc')],
+            15 : [load_lang('name_or_ip_or_regex'), 'auth/give/ban', load_lang('release')]
+        }
+        
+        if num == 1:
+            return redirect('/manager')
+        elif not num - 1 > len(title_list):
+            num -= 2
+
+            add_1 = flask.request.form.get('name', 'test')
+            if flask.request.method == 'POST':
+                if add_2 != '':
+                    flask.session['edit_load_document'] = add_1
+                    return redirect('/edit_from/' + url_pas(add_2))
+                elif flask.request.form.get('regex', '') != '':
+                    return redirect('/auth/give/ban_regex/' + url_pas(add_1))
+                else:
+                    return redirect('/' + title_list[num][1] + '/' + url_pas(add_1))
+            else:
+                if title_list[num][0] == 0:
+                    placeholder = load_lang('user_name')
+                else:
+                    placeholder = title_list[num][0]
+
+                plus = ''
+                if num == 15:
+                    plus = '<input type="checkbox" name="regex"> ' + load_lang('regex') + '<hr class="main_hr">'
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = [title_list[num][2], wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                    data = '''
+                        <form method="post">
+                            <input placeholder="''' + placeholder + '''" name="name" type="text">
+                            <hr class="main_hr">
+                            ''' + plus + '''
+                            <button type="submit">''' + load_lang('go') + '''</button>
+                        </form>
+                    ''',
+                    menu = [['manager', load_lang('return')]]
+                ))
+        else:
+            return redirect()

+ 27 - 23
route/main_view.py

@@ -2,29 +2,33 @@ from .tool.func import *
 from .main_error_404 import main_error_404
 from .main_error_404 import main_error_404
 
 
 def main_view(name = ''):
 def main_view(name = ''):
-    file_name = re.search(r'([^/]+)$', name)
-    if not file_name:
-        return main_error_404(conn)
-    else:
-        file_name = file_name.group(1)
-        dir_name = './views/' + re.sub(r'\.{2,}', '', re.sub(r'([^/]+)$', '', name))
-
-        mime_type = file_name.split('.')
-        if len(mime_type) < 2:
-            mime_type = 'text/plain'
+    with get_db_connect() as conn:
+        file_name = re.search(r'([^/]+)$', name)
+        if not file_name:
+            return main_error_404()
         else:
         else:
-            mime_type = mime_type[len(mime_type) - 1].lower()
-            image_type = ['jpeg', 'jpg', 'gif', 'png', 'webp']
-            if mime_type in image_type:
-                mime_type = 'image/' + mime_type
-            elif mime_type == 'js':
-                mime_type = 'text/javascript'
-            elif mime_type == 'txt':
+            file_name = file_name.group(1)
+            dir_name = './views/' + re.sub(r'\.{2,}', '', re.sub(r'([^/]+)$', '', name))
+
+            mime_type = file_name.split('.')
+            if len(mime_type) < 2:
                 mime_type = 'text/plain'
                 mime_type = 'text/plain'
             else:
             else:
-                mime_type = 'text/' + mime_type
-        
-        return flask.send_from_directory(
-            dir_name, file_name, 
-            mimetype = mime_type
-        )
+                mime_type = mime_type[len(mime_type) - 1].lower()
+                image_type = ['jpeg', 'jpg', 'gif', 'png', 'webp', 'ico', 'svg']
+                if mime_type in image_type:
+                    if not mime_type == 'svg':
+                        mime_type = 'image/' + mime_type
+                    else:
+                        mime_type = 'image/svg+xml'
+                elif mime_type == 'js':
+                    mime_type = 'text/javascript'
+                elif mime_type == 'txt':
+                    mime_type = 'text/plain'
+                else:
+                    mime_type = 'text/' + mime_type
+
+            return flask.send_from_directory(
+                dir_name, file_name, 
+                mimetype = mime_type
+            )

+ 21 - 8
route/main_view_file.py

@@ -2,12 +2,25 @@ from .tool.func import *
 from .main_error_404 import main_error_404
 from .main_error_404 import main_error_404
 
 
 def main_view_file(data = ''):
 def main_view_file(data = ''):
-    if data == 'robots.txt' and not os.path.exists('robots.txt'):
-        return flask.Response('User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/', mimetype = 'text/plain')
-    elif os.path.exists(data):
-        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')
+    with get_db_connect() as conn:
+        if data == 'robots.txt':
+            curs = conn.cursor()
 
 
-    return main_error_404()
+            curs.execute(db_change("select data from other where name = 'robot_default'"))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                return flask.Response(get_default_robots_txt(), mimetype = 'text/plain')
+            else:
+                curs.execute(db_change("select data from other where name = 'robot'"))
+                db_data = curs.fetchall()
+                if db_data:
+                    return flask.Response(db_data[0][0], mimetype = 'text/plain')
+                else:
+                    return flask.Response(get_default_robots_txt(), 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')
+        else:
+            return main_error_404()

+ 13 - 12
route/main_view_image.py

@@ -2,15 +2,16 @@ from .tool.func import *
 from .main_error_404 import main_error_404
 from .main_error_404 import main_error_404
 
 
 def main_view_image(name = ''):
 def main_view_image(name = ''):
-    mime_type = re.search(r'([^.]+)$', name)
-    if mime_type:
-        mime_type = mime_type.group(1).lower()
-        if mime_type == 'svg':
-            mime_type = 'svg+xml'
-        
-        return flask.send_from_directory(
-            './' + load_image_url(), name, 
-            mimetype = 'image/' + mime_type
-        )
-    else:
-        return main_error_404()
+    with get_db_connect() as conn:
+        mime_type = re.search(r'([^.]+)$', name)
+        if mime_type:
+            mime_type = mime_type.group(1).lower()
+            if mime_type == 'svg':
+                mime_type = 'svg+xml'
+
+            return flask.send_from_directory(
+                './' + load_image_url(), name, 
+                mimetype = 'image/' + mime_type
+            )
+        else:
+            return main_error_404()

+ 138 - 137
route/recent_app_submit.py

@@ -1,145 +1,146 @@
 from .tool.func import *
 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>'
-                
+def recent_app_submit_2():
+    with get_db_connect() as 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 += '''
                 div += '''
-                    <form method="post">
-                        <tr>
-                            <td>''' + application['id'] + '''</td>
-                            <td>''' + email + '''</td>
+                    <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>
-                        <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>
+                        <tr id="main_table_top_tr">
+                            <td>''' + load_lang('approval_question') + '''</td>
+                            <td>''' + load_lang('answer') + '''</td>
+                        </tr>                        
                 '''
                 '''
-                
-            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')
+
+                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="opennamu_save_button"
+                                            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:
             else:
-                application = json.loads(application[0][0])
-            
-            add_user(
-                application['id'], 
-                application['pw'],
-                application['email'],
-                application['encode']
-            )
+                div += load_lang('no_applications_now')
 
 
-            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 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')
+            return redirect('/app_submit')

+ 128 - 129
route/recent_block.py

@@ -1,150 +1,149 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def recent_block_2(conn, name, tool):
-    curs = conn.cursor()
-
-    num = int(number_check(flask.request.args.get('num', '1')))
-    sql_num = (num * 50 - 50) if num * 50 > 0 else 0
-
-    div = '''
-        <table id="main_table_set">
-            <tbody>
-                <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>
-                </tr>
-    '''
-
-    curs.execute(db_change("update rb set ongoing = '' where end < ? and end != '' and ongoing = '1'"), [get_time()])
-    conn.commit()
+def recent_block_2(name, tool):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        num = int(number_check(flask.request.args.get('num', '1')))
+        sql_num = (num * 50 - 50) if num * 50 > 0 else 0
+
+        div = '''
+            <table id="main_table_set">
+                <tbody>
+                    <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>
+                    </tr>
+        '''
 
 
-    get_type = flask.request.args.get('type', '')
-    sub_type = flask.request.args.get('s_type', '')
-    if tool == 'all':
-        if get_type == 'ongoing':
-            sub = ' (' + load_lang('in_progress') + ')'
+        curs.execute(db_change("update rb set ongoing = '' where end < ? and end != '' and ongoing = '1'"), [get_time()])
+        conn.commit()
+
+        get_type = flask.request.args.get('type', '')
+        sub_type = flask.request.args.get('s_type', '')
+        if tool == 'all':
+            if get_type == 'ongoing':
+                sub = ' (' + load_lang('in_progress') + ')'
+
+                if sub_type == '':
+                    div = '' + \
+                        '<a href="?type=ongoing&s_type=regex">(' + load_lang('regex') + ')</a> ' + \
+                        '<a href="?type=ongoing&s_type=normal">(' + load_lang('normal') + ')</a>' + \
+                        '<hr class="main_hr">' + \
+                    '' + div
+                    menu = [['block_log', load_lang('return')]]
+                    plus_sql = ''
+                else:
+                    menu = [['block_log?type=ongoing', load_lang('return')]]
+
+                    if sub_type == 'regex':
+                        sub += ' (' + load_lang('regex') + ')'
+                        plus_sql = 'and band = \'regex\' '
+                    else:
+                        sub += ' (' + load_lang('normal') + ')'
+                        plus_sql = 'and band = \'\' '
+
+                curs.execute(db_change("" + \
+                    "select why, block, blocker, end, today, band, ongoing from rb " + \
+                    "where ((end > ? and end like '2%') or end = '') and ongoing = '1' " + plus_sql + \
+                    "order by end desc limit ?, 50" + \
+                ""), [
+                    get_time(),
+                    sql_num
+                ])
+            else:
+                sub = 0
+                menu = 0
 
 
-            if sub_type == '':
                 div = '' + \
                 div = '' + \
-                    '<a href="?type=ongoing&s_type=regex">(' + load_lang('regex') + ')</a> ' + \
-                    '<a href="?type=ongoing&s_type=normal">(' + load_lang('normal') + ')</a>' + \
+                    '<a href="/manager/11">(' + load_lang('blocked') + ')</a> ' + \
+                    '<a href="/manager/12">(' + load_lang('admin') + ')</a> ' + \
+                    '<a href="?type=ongoing">(' + load_lang('in_progress') + ')</a>' + \
                     '<hr class="main_hr">' + \
                     '<hr class="main_hr">' + \
                 '' + div
                 '' + div
-                menu = [['block_log', load_lang('return')]]
-                plus_sql = ''
-            else:
-                menu = [['block_log?type=ongoing', load_lang('return')]]
-                
-                if sub_type == 'regex':
-                    sub += ' (' + load_lang('regex') + ')'
-                    plus_sql = 'and band = \'regex\' '
-                else:
-                    sub += ' (' + load_lang('normal') + ')'
-                    plus_sql = 'and band = \'\' '
+
+                curs.execute(db_change("" + \
+                    "select why, block, blocker, end, today, band, ongoing " + \
+                    "from rb order by today desc limit ?, 50" + \
+                ""), [sql_num])
+        elif tool == 'user':
+            sub = ' (' + load_lang('blocked') + ')'
+            menu = [['block_log', load_lang('normal')]]
 
 
             curs.execute(db_change("" + \
             curs.execute(db_change("" + \
-                "select why, block, blocker, end, today, band, ongoing from rb " + \
-                "where ((end > ? and end like '2%') or end = '') and ongoing = '1' " + plus_sql + \
-                "order by end desc limit ?, 50" + \
+                "select why, block, blocker, end, today, band, ongoing " + \
+                "from rb where block = ? order by today desc limit ?, 50" + \
             ""), [
             ""), [
-                get_time(),
+                name, 
                 sql_num
                 sql_num
             ])
             ])
         else:
         else:
-            sub = 0
-            menu = 0
-
-            div = '' + \
-                '<a href="/manager/11">(' + load_lang('blocked') + ')</a> ' + \
-                '<a href="/manager/12">(' + load_lang('admin') + ')</a> ' + \
-                '<a href="?type=ongoing">(' + load_lang('in_progress') + ')</a>' + \
-                '<hr class="main_hr">' + \
-            '' + div
+            sub = ' (' + load_lang('admin') + ')'
+            menu = [['block_log', load_lang('normal')]]
 
 
             curs.execute(db_change("" + \
             curs.execute(db_change("" + \
                 "select why, block, blocker, end, today, band, ongoing " + \
                 "select why, block, blocker, end, today, band, ongoing " + \
-                "from rb order by today desc limit ?, 50" + \
-            ""), [sql_num])
-    elif tool == 'user':
-        sub = ' (' + load_lang('blocked') + ')'
-        menu = [['block_log', load_lang('normal')]]
-
-        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
-        ])
-
-    data_list = curs.fetchall()
-    all_ip = ip_pas([i[1] for i in data_list] + [i[2] for i in data_list])
-    for data in data_list:
-        why = '<br>' if data[0] == '' else html.escape(data[0])
-
-        if data[5] == 'regex':
-            ip = data[1]
-            if data[6] == '1':
-                ip = '<s>' + ip + '</s> <a href="/ban/' + url_pas(data[1]) + '?type=regex">(' + load_lang('release') + ')</a>'
+                "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])
+        for data in data_list:
+            why = '<br>' if data[0] == '' else html.escape(data[0])
+
+            if data[5] == 'regex':
+                ip = data[1]
+                if data[6] == '1':
+                    ip = '<s>' + ip + '</s> <a href="/auth/give/ban_regex/' + url_pas(data[1]) + '">(' + load_lang('release') + ')</a>'
+                else:
+                    ip += ' <a href="/auth/give/ban_regex/' + url_pas(data[1]) + '">(' + load_lang('ban') + ')</a>'
+
+                ip += ' (' + load_lang('regex') + ')'
             else:
             else:
-                ip += ' <a href="/ban/' + url_pas(data[1]) + '?type=regex">(' + load_lang('ban') + ')</a>'
-                
-            ip += ' (' + load_lang('regex') + ')'
-        else:
-            ip = all_ip[data[1]]
+                ip = all_ip[data[1]]
 
 
-        if data[3] == '':
-            end = load_lang('limitless')
-        elif data[3] == 'release':
-            end = load_lang('release')
-        else:
-            end = data[3]
+            if data[3] == '':
+                end = load_lang('limitless')
+            elif data[3] == 'release':
+                end = load_lang('release')
+            else:
+                end = data[3]
 
 
-        if data[2] == '':
-            admin = ''
-        elif re.search(r'^tool:', data[2]):
-            admin = data[2]
+            if data[2] == '':
+                admin = ''
+            else:
+                admin = all_ip[data[2]]
+
+            start = load_lang('start') + ' : ' + (data[4] if data[4] != '' else '0')
+            div += '''
+                <tr>
+                    <td>''' + ip + '''</td>
+                    <td>''' + admin + '''</td>
+                    <td>
+                        ''' + start + '''
+                        <br>
+                        ''' + load_lang('end') + ' : ' + end + '''
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="3">''' + why + '''</td>
+                </tr>
+            '''
+
+        div += '</tbody>'
+        div += '</table>'
+
+        if tool == 'all':
+            div += next_fix('/block_log?num=', num, data_list)
         else:
         else:
-            admin = all_ip[data[2]]
-
-        start = load_lang('start') + ' : ' + (data[4] if data[4] != '' else '0')
-        div += '''
-            <tr>
-                <td>''' + ip + '''</td>
-                <td>''' + admin + '''</td>
-                <td>
-                    ''' + start + '''
-                    <br>
-                    ''' + load_lang('end') + ' : ' + end + '''
-                </td>
-            </tr>
-            <tr>
-                <td colspan="3">''' + why + '''</td>
-            </tr>
-        '''
+            div += next_fix('/block_log/' + 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(), wiki_custom(), wiki_css([sub, 0])],
-        data = div,
-        menu = menu
-    ))
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('recent_ban'), wiki_set(), wiki_custom(), wiki_css([sub, 0])],
+            data = div,
+            menu = menu
+        ))

+ 19 - 7
route/recent_change.py

@@ -1,5 +1,20 @@
 from .tool.func import *
 from .tool.func import *
 
 
+def recent_change_send_render(data):
+    def send_render_href_replace(match):
+        match = match.group(1)
+        data_unescape = html.unescape(match)
+
+        return '<a href="/w/' + url_pas(data_unescape) + '">' + match + '</a>'
+
+    if data == '&lt;br&gt;' or data == '':
+        data = '<br>'
+    else:
+        data = data.replace('javascript:', '')
+        data = re.sub(r'&lt;a(?:(?:(?!&gt;).)*)&gt;((?:(?!&lt;\/a&gt;).)+)&lt;\/a&gt;', send_render_href_replace, data)
+
+    return data
+
 def recent_change(name = None, tool = ''):
 def recent_change(name = None, tool = ''):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
@@ -105,8 +120,8 @@ def recent_change(name = None, tool = ''):
 
 
                 if data[6] == 'O':
                 if data[6] == 'O':
                     if admin == 1:
                     if admin == 1:
-                        style[0] = 'id="toron_color_grey"'
-                        style[1] = 'id="toron_color_grey"'
+                        style[0] = 'class="opennamu_history_blind"'
+                        style[1] = 'class="opennamu_history_blind"'
                     else:
                     else:
                         ip = ''
                         ip = ''
                         ban = ''
                         ban = ''
@@ -114,7 +129,7 @@ def recent_change(name = None, tool = ''):
                         send = ''
                         send = ''
 
 
                         style[0] = 'style="display: none;"'
                         style[0] = 'style="display: none;"'
-                        style[1] = 'id="toron_color_grey"'
+                        style[1] = 'class="opennamu_history_blind"'
 
 
                 if tool == 'history':
                 if tool == 'history':
                     title = '<a href="/w_rev/' + data[0] + '/' + url_pas(name) + '">r' + data[0] + '</a> '
                     title = '<a href="/w_rev/' + data[0] + '/' + url_pas(name) + '">r' + data[0] + '</a> '
@@ -132,16 +147,13 @@ def recent_change(name = None, tool = ''):
                         <td>''' + date + '''</td>
                         <td>''' + date + '''</td>
                     </tr>
                     </tr>
                     <tr ''' + style[1] + '''>
                     <tr ''' + style[1] + '''>
-                        <td class="send_content" colspan="3">
-                            ''' + (html.escape(send) if send != '' else '<br>') + '''
-                        </td>
+                        <td colspan="3">''' + recent_change_send_render(html.escape(send)) + '''</td>
                     </tr>
                     </tr>
                 '''
                 '''
 
 
             div += '''
             div += '''
                     </tbody>
                     </tbody>
                 </table>
                 </table>
-                <script>send_render();</script>
             '''
             '''
 
 
             if name:
             if name:

+ 27 - 4
route/recent_discuss.py

@@ -5,6 +5,7 @@ def recent_discuss(tool):
         curs = conn.cursor()
         curs = conn.cursor()
 
 
         div = ''
         div = ''
+        admin_auth = admin_check(3)
 
 
         if tool == 'normal':
         if tool == 'normal':
             div += '<a href="/recent_discuss/close">(' + load_lang('close_discussion') + ')</a> '
             div += '<a href="/recent_discuss/close">(' + load_lang('close_discussion') + ')</a> '
@@ -25,8 +26,9 @@ def recent_discuss(tool):
                 <table id="main_table_set">
                 <table id="main_table_set">
                     <tbody>
                     <tbody>
                         <tr id="main_table_top_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>
+                            <td id="main_table_width">''' + load_lang('discussion_name') + '''</td>
+                            <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                            <td id="main_table_width">''' + load_lang('time') + '''</td>
                         </tr>
                         </tr>
                 '''
                 '''
 
 
@@ -37,18 +39,39 @@ def recent_discuss(tool):
         else:
         else:
             curs.execute(db_change('select title, sub, date, code from rd where stop != "O" order by date asc limit 50'))
             curs.execute(db_change('select title, sub, date, code from rd where stop != "O" order by date asc limit 50'))
 
 
-        for data in curs.fetchall():
+        db_data = curs.fetchall()
+
+        last_editor = []
+        for for_a in db_data:
+            curs.execute(db_change("select ip from topic where code = ? order by id + 0 desc limit 1"), [for_a[3]])
+            db_data_2 = curs.fetchall()
+            if db_data_2:
+                last_editor += [db_data_2[0][0]]
+            else:
+                last_editor += ['']
+
+        last_editor_ip_pas = ip_pas(last_editor)
+
+        count = 0
+        for data in db_data:
             div += '' + \
             div += '' + \
                 '<tr>' + \
                 '<tr>' + \
                     '<td>' + \
                     '<td>' + \
                         '<a href="/thread/' + data[3] + '">' + html.escape(data[1]) + '</a> ' + \
                         '<a href="/thread/' + data[3] + '">' + html.escape(data[1]) + '</a> ' + \
                         '<a href="/topic/' + url_pas(data[0]) + '">(' + html.escape(data[0]) + ')</a>' + \
                         '<a href="/topic/' + url_pas(data[0]) + '">(' + html.escape(data[0]) + ')</a>' + \
+                        (' <a href="/thread/' + data[3] + '/tool">(' + load_lang('tool') + ')</a>' if admin_auth == 1 else '') + \
                     '</td>' + \
                     '</td>' + \
+                    '<td>' + last_editor_ip_pas[last_editor[count]] + '</td>' + \
                     '<td>' + data[2] + '</td>' + \
                     '<td>' + data[2] + '</td>' + \
                 '</tr>' + \
                 '</tr>' + \
             ''
             ''
 
 
-        div += '</tbody></table>'
+            count += 1
+
+        div += '' + \
+                '</tbody>' + \
+            '</table>' + \
+        ''
 
 
         return easy_minify(flask.render_template(skin_check(),
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('recent_discussion'), wiki_set(), wiki_custom(), wiki_css([m_sub, 0])],
             imp = [load_lang('recent_discussion'), wiki_set(), wiki_custom(), wiki_css([m_sub, 0])],

+ 36 - 11
route/recent_history_add.py

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

+ 7 - 7
route/recent_history_tool.py

@@ -8,13 +8,13 @@ def recent_history_tool(name = 'Test', rev = 1):
 
 
         data = '' + \
         data = '' + \
             '<h2>' + load_lang('tool') + '</h2>' + \
             '<h2>' + load_lang('tool') + '</h2>' + \
-            '<ul class="inside_ul">' + \
+            '<ul class="opennamu_ul">' + \
                 '<li><a href="/raw_rev/' + num + '/' + url_pas(name) + '">' + load_lang('raw') + '</a></li>' + \
                 '<li><a href="/raw_rev/' + num + '/' + url_pas(name) + '">' + load_lang('raw') + '</a></li>' + \
         ''
         ''
 
 
-        data += '<li><a href="/revert/' + num + '/' + url_pas(name) + '">' + load_lang('revert') + ' | r' + num + '</a></li>'
+        data += '<li><a href="/revert/' + num + '/' + url_pas(name) + '">' + load_lang('revert') + ' (r' + num + ')</a></li>'
         if rev - 1 > 0:
         if rev - 1 > 0:
-            data += '<li><a href="/revert/' + str(rev - 1) + '/' + url_pas(name) + '">' + load_lang('revert') + ' | r' + str(rev - 1) + '</a></li>'
+            data += '<li><a href="/revert/' + str(rev - 1) + '/' + url_pas(name) + '">' + load_lang('revert') + ' (r' + str(rev - 1) + ')</a></li>'
 
 
         if rev - 1 > 0:
         if rev - 1 > 0:
             data += '<li><a href="/diff/' + str(rev - 1) + '/' + num + '/' + url_pas(name) + '">' + load_lang('compare') + '</a></li>'
             data += '<li><a href="/diff/' + str(rev - 1) + '/' + num + '/' + url_pas(name) + '">' + load_lang('compare') + '</a></li>'
@@ -23,8 +23,8 @@ def recent_history_tool(name = 'Test', rev = 1):
         data += '</ul>'
         data += '</ul>'
 
 
         if admin_check(6) == 1:
         if admin_check(6) == 1:
-            data += '<h3>admin</h3>'
-            data += '<ul class="inside_ul">'
+            data += '<h3>' + load_lang('admin') + '</h3>'
+            data += '<ul class="opennamu_ul">'
             curs.execute(db_change('' + \
             curs.execute(db_change('' + \
                 'select title from history ' + \
                 'select title from history ' + \
                 'where title = ? and id = ? and hide = "O"' + \
                 'where title = ? and id = ? and hide = "O"' + \
@@ -39,8 +39,8 @@ def recent_history_tool(name = 'Test', rev = 1):
             data += '</ul>'
             data += '</ul>'
 
 
         if admin_check() == 1:
         if admin_check() == 1:
-            data += '<h3>owner</h3>'
-            data += '<ul class="inside_ul">'
+            data += '<h3>' + load_lang('owner') + '</h3>'
+            data += '<ul class="opennamu_ul">'
             data += '<li><a href="/history_delete/' + num + '/' + url_pas(name) + '">' + load_lang('history_delete') + '</li>'
             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 += '<li><a href="/history_send/' + num + '/' + url_pas(name) + '">' + load_lang('send_edit') + '</li>'
             data += '</ul>'
             data += '</ul>'

File diff suppressed because it is too large
+ 499 - 192
route/tool/func.py


+ 53 - 163
route/tool/func_render.py

@@ -3,182 +3,72 @@ from .func_render_namumark import *
 # 커스텀 마크 언젠간 다시 추가 예정
 # 커스텀 마크 언젠간 다시 추가 예정
 
 
 class class_do_render:
 class class_do_render:
-    def __init__(self, conn):
+    def __init__(self, conn, lang_data = {}):
         self.conn = conn
         self.conn = conn
-    
-    def do_backlink_generate(self, data_markup, doc_data, doc_name):
-        conn = self.conn
-        curs = self.conn.cursor()
-
-        if data_markup == 'namumark':
-            # Link
-            link_re = re.compile(r'\[\[(?!https?:\/\/|inter:|외부:|out:|#)((?:(?!\[\[|\]\]|\|).)+)(?:\]\]|\|)', 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.startswith('분류:') or \
-                    data_link_in.startswith('category:'):
-                    data_link_in = re.sub(r'\\(.)', r'\1', data_link_in)
-                    data_link_end['cat'] += [re.sub(r'^분류:', 'category:', data_link_in)]
-                elif data_link_in.startswith('파일:') or \
-                    data_link_in.startswith('file:'):
-                    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'^:분류:', 'category:', data_link_in)
-                        data_link_in = re.sub(r'^:category:', 'category:', data_link_in)
-
-                        data_link_in = re.sub(r'^:file:', 'file:', data_link_in)
-                        data_link_in = re.sub(r'^:파일:', 'file:', 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))
+        if lang_data == '{}':
+            lang_data = {
+                'toc' : 'toc',
+                'category' : 'category'
+            }
 
 
-            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
+        self.lang_data = lang_data
 
 
     def do_render(self, doc_name, doc_data, data_type, data_in):
     def do_render(self, doc_name, doc_data, data_type, data_in):
-        conn = self.conn
         curs = self.conn.cursor()
         curs = self.conn.cursor()
 
 
-        data_in = None if data_in == '' else data_in
+        doc_set = {}
+        if data_in == 'from':
+            data_in = ''
+            doc_set['doc_from'] = 'O'
+        
+        data_in = (data_in + '_') if data_in != '' else ''
+        doc_set['doc_include'] = data_in
 
 
-        curs.execute(db_change('select data from other where name = "markup"'))
+        curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'document_markup'"), [doc_name])
         rep_data = curs.fetchall()
         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 ''
-                doc_data = html.escape(doc_data)
-                doc_name = html.escape(doc_name)
-                
-                data_end = [
-                    '<pre class="render_content_load" id="' + data_in + 'render_content_load">' + doc_data + '</pre>' + \
-                    '<div class="render_content" id="' + data_in + 'render_content" style="display: none;"></div>', 
-                    '''
-                        do_onmark_render(
-                            test_mode = "normal", 
-                            name_id = "''' + data_in + '''render_content",
-                            name_include = "''' + data_in + '''",
-                            name_doc = "''' + doc_name + '''"
-                        );
-                    ''',
-                    []
-                ]
-            elif rep_data == 'namumark_beta':
-                doc_include = (data_in + '_') if data_in else ''
-                data_end = class_do_render_namumark(
-                    curs,
-                    doc_name,
-                    doc_data,
-                    doc_include
-                )()
-            elif rep_data == 'markdown':
-                data_in = (data_in + '_') if data_in else ''
-                doc_data = html.escape(doc_data)
-                doc_name = html.escape(doc_name)
-                
-                data_end = [
-                    '<pre class="render_content_load" id="' + data_in + 'render_content_load">' + html.escape(doc_data) + '</pre>' + \
-                    '<div class="render_content" id="' + data_in + 'render_content" style="display: none;"></div>', 
-                    'new opennamu_render_markdown(' + \
-                        'render_part_id = "render_content_load",' + \
-                        'render_part_id_after = "render_content",' + \
-                        'render_part_id_add = "' + data_in + '",' + \
-                        'doc_name = "' + doc_name + '"' + \
-                    ').do_main();',
-                    []
-                ]
-            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>'
+        if rep_data and rep_data[0][0] != '':
+            rep_data = rep_data[0][0]
+        else:
+            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 rep_data == 'namumark' or rep_data == 'namumark_beta':
+            data_end = class_do_render_namumark(
+                curs,
+                doc_name,
+                doc_data,
+                doc_set,
+                self.lang_data
+            )()
+        elif rep_data == 'raw':
+            data_end = [
+                html.escape(doc_data).replace('\n', '<br>'), 
+                '', 
+                {}
+            ]
         else:
         else:
-            if rep_data == 'namumark':
-                backlink = self.do_backlink_generate(
-                    rep_data, 
-                    doc_data, 
-                    doc_name
-                )
+            data_end = [
+                doc_data, 
+                '', 
+                {}
+            ]
+
+        if data_type == 'backlink':
+            if 'backlink' in data_end[2]:
+                backlink = data_end[2]['backlink']
             else:
             else:
                 backlink = []
                 backlink = []
 
 
             if backlink != []:
             if backlink != []:
-                curs.executemany(db_change("insert into back (link, title, type) values (?, ?, ?)"), backlink)
+                curs.executemany(db_change("insert into back (link, title, type) values (?, ?, ?)"), data_end[2]['backlink'])
                 curs.execute(db_change("delete from back where title = ? and type = 'no'"), [doc_name])
                 curs.execute(db_change("delete from back where title = ? and type = 'no'"), [doc_name])
 
 
-            conn.commit()
+            self.conn.commit()
+        else:
+            return [
+                data_end[0], 
+                data_end[1],
+                data_end[2]
+            ]

+ 1897 - 80
route/tool/func_render_namumark.py

@@ -1,115 +1,1932 @@
 from .func_tool import *
 from .func_tool import *
 
 
 class class_do_render_namumark:
 class class_do_render_namumark:
-    def __init__(
-        self,
-        curs,
-        doc_name, 
-        doc_data, 
-        doc_include
-    ):
+    def __init__(self, curs, doc_name, doc_data, doc_set, lang_data):
         self.curs = curs
         self.curs = curs
         
         
-        self.doc_data = doc_data
+        self.doc_data = doc_data.replace('\r', '')
         self.doc_name = doc_name
         self.doc_name = doc_name
-        self.doc_include = doc_include
-        
-        self.data_nowiki = {}
+        self.doc_set = doc_set
+        self.doc_include = self.doc_set['doc_include'] if 'doc_include' in self.doc_set else ''
+
+        self.lang_data = lang_data
+        try:
+            self.ip = ip_check()
+        except:
+            self.ip = '0.0.0.0'
+
+        try:
+            if 'main_css_bold' in self.flask_session:
+                pass    
+                
+            self.flask_session = flask.session
+        except:
+            self.flask_session = ''
+
+        try:
+            self.darkmode = flask.request.cookies.get('main_css_darkmode', '0')
+        except:
+            self.darkmode = '0'
+
+
+        self.data_temp_storage = {}
+        self.data_temp_storage_count = 0
+
         self.data_backlink = []
         self.data_backlink = []
+        self.data_include = []
+
+        self.data_math_count = 0
+        self.data_redirect = 0
         
         
         self.data_toc = ''
         self.data_toc = ''
-        self.data_footnote = ''
+        self.data_footnote = {}
         self.data_category = ''
         self.data_category = ''
+        self.data_category_list = []
+
+        self.render_data = self.doc_data
+        self.render_data = html.escape(self.render_data)
+        self.render_data = '<back_br>\n' + self.render_data + '\n<front_br>'
+        self.render_data_js = ''
+
+    def get_tool_lang(self, name):
+        if name in self.lang_data:
+            return self.lang_data[name]
+        else:
+            return name + ' (RENDER LANG)'
+
+    def get_tool_js_safe(self, data):
+        data = data.replace('\n', '\\\\n')
+        data = data.replace('\\', '\\\\')
+        data = data.replace("'", "\\'")
+        data = data.replace('"', '\\"')
+
+        return data
+
+    def get_tool_css_safe(self, data):
+        return data.replace(';', '')
+
+    def get_tool_data_storage(self, data_A = '', data_B = '', data_C = '', do_type = 'render'):
+        self.data_temp_storage_count += 1
+        if do_type == 'render':
+            data_name = 'render_' + str(self.data_temp_storage_count)
+
+            self.data_temp_storage[data_name] = data_A
+            self.data_temp_storage['/' + data_name] = data_B
+            self.data_temp_storage['revert_' + data_name] = data_C
+        else:
+            data_name = 'slash_' + str(self.data_temp_storage_count)
+
+            self.data_temp_storage[data_name] = data_A
+
+        return data_name
+
+    def get_tool_data_restore(self, data, do_type = 'all'):
+        storage_count = self.data_temp_storage_count * 3
+        if do_type == 'all':
+            storage_regex = r'<(\/?(?:render|slash)_(?:[0-9]+))>'
+        elif do_type == 'render':
+            storage_regex = r'<(\/?(?:render)_(?:[0-9]+))>'
+        else:
+            storage_regex = r'<(\/?(?:slash)_(?:[0-9]+))>'
+
+        while 1:
+            if not re.search(storage_regex, data):
+                break
+            if storage_count < 0:
+                print('Error : render restore count overflow')
+
+                break
+            else:
+                data = re.sub(storage_regex, lambda match : self.data_temp_storage[match.group(1)], data, 1)
+
+            storage_count -= 1
+
+        return data
+
+    def get_tool_data_revert(self, data, do_type = 'all'):
+        storage_count = self.data_temp_storage_count * 3
+        if do_type == 'all':
+            storage_regex = r'(?:<((slash)_(?:[0-9]+))>|<((render)_(?:[0-9]+))>(?:(?:(?!<(?:\/?render_(?:[0-9]+))>).|\n)*)<\/render_(?:[0-9]+)>)'
+        elif do_type == 'render':
+            storage_regex = r'<((render)_(?:[0-9]+))>(?:(?:(?!<(?:\/?render_(?:[0-9]+))>).)*)<\/render_(?:[0-9]+)>'
+        else:
+            storage_regex = r'<((slash)_(?:[0-9]+))>'
+
+        while 1:
+            match = re.search(storage_regex, data)
+            if not match:
+                break
+            if storage_count < 0:
+                print('Error : render restore count overflow')
+
+                break
+            else:
+                match = match.groups()
+                if match[1] and match[1] == 'render':
+                    if ('revert_' + match[0]) in self.data_temp_storage:
+                        data_revert = self.data_temp_storage['revert_' + match[0]]
+                    else:
+                        data_revert = ''
+                else:
+                    if len(match) > 3 and match[3] == 'render':
+                        if ('revert_' + match[2]) in self.data_temp_storage:
+                            data_revert = self.data_temp_storage['revert_' + match[2]]
+                        else:
+                            data_revert = ''
+                    else:
+                        data_revert = '\\' + self.data_temp_storage[match[0]]
+
+                data = re.sub(storage_regex, lambda x : data_revert, data, 1)
+
+            storage_count -= 1
+
+        data = re.sub(r'<front_br>', '', data)
+        data = re.sub(r'<back_br>', '', data)
+
+        return data
+
+    def get_tool_footnote_make(self):
+        data = ''
+        for for_a in self.data_footnote:
+            if data == '':
+                data += '<div class="opennamu_footnote">'
+            else:
+                data += '<br>'
+
+            if len(self.data_footnote[for_a]['list']) > 1:
+                data += '(' + for_a + ') '
+
+                for for_b in self.data_footnote[for_a]['list']:
+                    data += '<sup><a id="' + self.doc_include + 'fn_' + for_b + '" href="#' + self.doc_include + 'rfn_' + for_b + '">(' + for_b + ')</a></sup> '
+            else:
+                data += '<a id="' + self.doc_include + 'fn_' + self.data_footnote[for_a]['list'][0] + '" href="#' + self.doc_include + 'rfn_' + self.data_footnote[for_a]['list'][0] + '">(' + for_a + ') </a> '
+
+            data += '<footnote_title target="' + self.doc_include + 'fn_' + self.data_footnote[for_a]['list'][0] + '">' + self.data_footnote[for_a]['data'] + '</footnote_title>'
+
+        if data != '':
+            data += '</div>'
+
+        self.data_footnote = {}
+
+        return data
+
+    def get_tool_px_add_check(self, data):
+        if re.search(r'^[0-9]+$', data):
+            return data + 'px'
+        else:
+            return data
+
+    def get_tool_dark_mode_split(self, data):
+        data = data.split(',')
+        if len(data) == 1:
+            return data[0]
+        else:
+            if self.darkmode == '0':
+                return data[0]
+            else:
+                return data[1]
 
 
     def do_render_text(self):
     def do_render_text(self):
+        # <b> function
+        if ip_or_user(self.ip) == 0:
+            self.curs.execute(db_change('select data from user_set where name = "main_css_bold" and id = ?'), [self.ip])
+            db_data = self.curs.fetchall()
+            bold_user_set = db_data[0][0] if db_data else 'normal'
+        else:
+            bold_user_set = self.flask_session['main_css_bold'] if 'main_css_bold' in self.flask_session else 'normal'
+
+        def do_render_text_bold(match):
+            data = match.group(1)
+            if bold_user_set == 'normal':
+                data_name = self.get_tool_data_storage('<b>', '</b>', match.group(0))
+            elif bold_user_set == 'change':
+                data_name = self.get_tool_data_storage('', '', match.group(0))
+            else:
+                return ''
+            
+            return '<' + data_name + '>' + data + '</' + data_name + '>'
+
         # <b>
         # <b>
-        self.render_data = re.sub(
-            r"&#x27;&#x27;&#x27;((?:(?!&#x27;&#x27;&#x27;).)+)&#x27;&#x27;&#x27;",
-            '<b>\g<1></b>',
-            self.render_data
-        )
+        self.render_data = re.sub(r"&#x27;&#x27;&#x27;((?:(?!&#x27;&#x27;&#x27;).)+)&#x27;&#x27;&#x27;", do_render_text_bold, self.render_data)
+
+        # <i> function
+        def do_render_text_italic(match):
+            data = match.group(1)
+            data_name = self.get_tool_data_storage('<i>', '</i>', match.group(0))
+            
+            return '<' + data_name + '>' + data + '</' + data_name + '>'
+
         # <i>
         # <i>
-        self.render_data = re.sub(
-            r"&#x27;&#x27;((?:(?!&#x27;&#x27;).)+)&#x27;&#x27;",
-            '<i>\g<1></i>',
-            self.render_data
-        )
+        self.render_data = re.sub(r"&#x27;&#x27;((?:(?!&#x27;&#x27;).)+)&#x27;&#x27;", do_render_text_italic, self.render_data)
+
+        # <u> function
+        def do_render_text_under(match):
+            data = match.group(1)
+            data_name = self.get_tool_data_storage('<u>', '</u>', match.group(0))
+            
+            return '<' + data_name + '>' + data + '</' + data_name + '>'
+
         # <u>
         # <u>
-        self.render_data = re.sub(
-            r"__((?:(?!__).)+)__",
-            '<u>\g<1></u>',
-            self.render_data
-        )
+        self.render_data = re.sub(r"__((?:(?!__).)+)__", do_render_text_under, self.render_data)
         
         
+        # <sup> function
+        def do_render_text_sup(match):
+            data = match.group(1)
+            data_name = self.get_tool_data_storage('<sup>', '</sup>', match.group(0))
+            
+            return '<' + data_name + '>' + data + '</' + data_name + '>'
+
         # <sup>
         # <sup>
-        self.render_data = re.sub(
-            r"\^\^\^((?:(?!\^\^\^).)+)\^\^\^",
-            '<sup>\g<1></sup>',
-            self.render_data
-        )
+        self.render_data = re.sub(r"\^\^\^((?:(?!\^\^\^).)+)\^\^\^", do_render_text_sup, self.render_data)
         # <sup> 2
         # <sup> 2
-        self.render_data = re.sub(
-            r"\^\^((?:(?!\^\^).)+)\^\^",
-            '<sup>\g<1></sup>',
-            self.render_data
-        )
+        self.render_data = re.sub(r"\^\^((?:(?!\^\^).)+)\^\^", do_render_text_sup, self.render_data)
+
+        # <sub> function
+        def do_render_text_sub(match):
+            data = match.group(1)
+            data_name = self.get_tool_data_storage('<sub>', '</sub>', match.group(0))
+            
+            return '<' + data_name + '>' + data + '</' + data_name + '>'
         
         
         # <sub>
         # <sub>
-        self.render_data = re.sub(
-            r",,,((?:(?!,,,).)+),,,",
-            '<sub>\g<1></sub>',
-            self.render_data
-        )
+        self.render_data = re.sub(r",,,((?:(?!,,,).)+),,,", do_render_text_sub, self.render_data)
         # <sub> 2
         # <sub> 2
-        self.render_data = re.sub(
-            r",,((?:(?!,,).)+),,",
-            '<sub>\g<1></sub>',
-            self.render_data
-        )
+        self.render_data = re.sub(r",,((?:(?!,,).)+),,", do_render_text_sub, self.render_data)
+
+        # <s> function
+        if ip_or_user(self.ip) == 0:
+            self.curs.execute(db_change('select data from user_set where name = "main_css_strike" and id = ?'), [self.ip])
+            db_data = self.curs.fetchall()
+            strike_user_set = db_data[0][0] if db_data else 'normal'
+        else:
+            strike_user_set = self.flask_session['main_css_strike'] if 'main_css_strike' in self.flask_session else 'normal'
+
+        def do_render_text_strike(match):
+            data = match.group(1)
+            if strike_user_set == 'normal':
+                data_name = self.get_tool_data_storage('<s>', '</s>', match.group(0))
+            elif strike_user_set == 'change':
+                data_name = self.get_tool_data_storage('', '', match.group(0))
+            else:
+                return ''
+            
+            return '<' + data_name + '>' + data + '</' + data_name + '>'
         
         
         # <s>
         # <s>
-        self.render_data = re.sub(
-            r"--((?:(?!--).)+)--",
-            '<s>\g<1></s>',
-            self.render_data
-        )
+        self.render_data = re.sub(r"--((?:(?!--).)+)--", do_render_text_strike, self.render_data)
         # <s> 2
         # <s> 2
-        self.render_data = re.sub(
-            r"~~((?:(?!~~).)+)~~",
-            '<s>\g<1></s>',
-            self.render_data
-        )
+        self.render_data = re.sub(r"~~((?:(?!~~).)+)~~", do_render_text_strike, self.render_data)
+    
+    def do_render_heading(self):
+        toc_list = []
+
+        # make heading base
+        heading_regex = r'\n((={1,6})(#?) ?([^\n]+))\n'
+        heading_count_all = len(re.findall(heading_regex, self.render_data)) * 3
+        heading_stack = [0, 0, 0, 0, 0, 0]
+        heading_count = 0
+        while 1:
+            heading_count += 1
+
+            if not re.search(heading_regex, self.render_data):
+                break
+            elif heading_count_all < 0:
+                print('Error : render heading count overflow')
+
+                break
+            else:
+                heading_data = re.search(heading_regex, self.render_data)
+                heading_data_org = heading_data.group(0)
+                heading_data = heading_data.groups()
+
+                heading_data_last_regex = r' ?(#?={1,6}[^=]*)$'
+                heading_data_last = re.search(heading_data_last_regex, heading_data[3])
+                if heading_data_last:
+                    heading_data_last = heading_data_last.group(1)
+                else:
+                    heading_data_last = ''
+
+                heading_data_text = re.sub(heading_data_last_regex, '', heading_data[3])
+
+                heading_data_diff = heading_data[2] + heading_data[1]
+                if heading_data_diff != heading_data_last:
+                    # front != back -> restore
+
+                    heading_data_all = heading_data[0]
+
+                    for for_a in reversed(range(1, 7)):
+                        for_a_str = str(for_a)
+
+                        heading_restore_regex = re.compile('^={' + for_a_str + '}|={' + for_a_str + '}$')
+
+                        heading_data_all = re.sub(heading_restore_regex, '<heading_' + for_a_str + '>', heading_data_all)
+
+                    self.render_data = re.sub(heading_regex, '\n' + heading_data_all + '\n', self.render_data, 1)
+                else:
+                    heading_level = len(heading_data[1])
+                    heading_level_str = str(heading_level)
+
+                    heading_stack[heading_level - 1] += 1
+                    for for_a in range(heading_level, 6):
+                        heading_stack[for_a] = 0
+
+                    heading_stack_str = '.'.join([str(for_a) for for_a in heading_stack])
+                    heading_stack_str = re.sub(r'(\.0)+$', '', heading_stack_str)
+
+                    toc_list += [['', heading_data_text]]
+
+                    self.render_data_js += '''
+                        function opennamu_heading_folding(data, element = '') {
+                            let fol = document.getElementById(data);
+                            if(fol.style.display === '' || fol.style.display === 'inline-block' || fol.style.display === 'block') {
+                                document.getElementById(data).style.display = 'none';
+                            } else {
+                                document.getElementById(data).style.display = 'block';
+                            }
+                            
+                            if(element !== '') {
+                                console.log(element.innerHTML);
+                                if(element.innerHTML !== '⊖') {
+                                    element.innerHTML = '⊖';
+                                } else {
+                                    element.innerHTML = '⊕';
+                                }
+                            }
+                        }\n
+                    '''
+
+                    heading_folding = ['⊖', 'block']
+                    if heading_data[2]:
+                        heading_folding = ['⊕', 'none']
+
+                    data_name = self.get_tool_data_storage(
+                        '<h' + heading_level_str + '>', 
+                        '' + \
+                            ' <sub>' + \
+                                '<a id="' + self.doc_include + 'edit_load_' + str(heading_count) + '" href="/edit_section/' + str(heading_count) + '/' + url_pas(self.doc_name) + '">✎</a> ' + \
+                                '<a href="javascript:void(0);" onclick="javascript:opennamu_heading_folding(\'' + self.doc_include + 'opennamu_heading_' + str(heading_count) + '\', this);">' + \
+                                    heading_folding[0] + \
+                                '</a>'
+                            '</sub>' + \
+                            '</h' + heading_level_str + '>' + \
+                        '', 
+                        heading_data_org
+                    )
+
+                    heading_data_complete = '' + \
+                        '\n<front_br>' + \
+                        ('</div>' if heading_count != 1 else '') + \
+                        '<' + data_name + '>' + \
+                            '<heading_stack>' + \
+                                heading_stack_str + \
+                            '</heading_stack>' + \
+                            ' ' + heading_data_text + \
+                        '</' + data_name + '>' + \
+                        '<div id="' + self.doc_include + 'opennamu_heading_' + str(heading_count) + '" style="display: ' + heading_folding[1] + ';">' + \
+                        '<back_br>\n' + \
+                    ''
+
+                    self.render_data = re.sub(heading_regex, heading_data_complete, self.render_data, 1)
+
+            heading_count_all -= 1
+
+        # heading id adjust
+        heading_end_count = len(re.findall(r'<heading_stack>', self.render_data))
+        for for_a in reversed(range(0, 6)):
+            heading_end_stack_regex = re.compile('<heading_stack>' + ('0\\.' * for_a))
+
+            heading_end_match_count = len(re.findall(heading_end_stack_regex, self.render_data))
+            if heading_end_match_count == heading_end_count:
+                self.render_data = re.sub(heading_end_stack_regex, '<heading_stack>', self.render_data)
+
+                break
+
+        # heading id -> inline id
+        heading_id_regex = r'<heading_stack>([^<>]+)<\/heading_stack>'
+        heading_id_data = re.findall(heading_id_regex, self.render_data)
+        for for_a in range(len(heading_id_data)):
+            self.render_data = re.sub(heading_id_regex, '<a href="#toc" id="s-' + heading_id_data[for_a] + '">' + heading_id_data[for_a] + '.</a>', self.render_data, 1)
+            
+            toc_list[for_a][0] = heading_id_data[for_a]
+
+        # not heading restore
+        for for_a in range(1, 7):
+            for_a_str = str(for_a)
+
+            heading_restore_regex = re.compile('<heading_' + for_a_str + '>')
+
+            self.render_data = re.sub(heading_restore_regex, ('=' * for_a), self.render_data)
+
+        # make toc
+        if len(toc_list) == 0:
+            toc_data = ''
+        else:
+            toc_data = '' + \
+                '<div class="opennamu_TOC" id="toc">' + \
+                    '<span class="opennamu_TOC_title">' + self.get_tool_lang('toc') + '</span>' + \
+                    '<br>' + \
+                ''
+
+        for for_a in toc_list:
+            toc_data += '' + \
+                '<br>' + \
+                ('<span style="margin-left: 10px;"></span>' * for_a[0].count('.')) + \
+                '<span class="opennamu_TOC_list">' + \
+                    '<a href="#s-' + for_a[0] + '">' + \
+                        for_a[0] + '. ' + \
+                    '</a>' + \
+                    '<toc_inside>' + for_a[1] + '</toc_inside>' + \
+                '</span>' + \
+            ''
+
+        if toc_data != '':
+            toc_data += '</div>'
+
+            self.data_toc = toc_data
+            self.render_data += '<toc_data>' + toc_data + '</toc_data>'
+        else:
+            self.data_toc = ''
+
+    def do_render_macro(self):
+        # double macro function
+        def do_render_macro_double(match):
+            match_org = match
+            match = match.groups()
+
+            name_data = match[0]
+            name_data = name_data.lower()
+
+            macro_split_regex = r'(?:^|,) *([^,]+)'
+            macro_split_sub_regex = r'(^[^=]+) *= *([^=]+)'
+            if name_data in ('youtube', 'nicovideo', 'navertv', 'kakaotv', 'vimeo'):
+                data = re.findall(macro_split_regex, match[1])
+
+                # get option
+                video_code = ''
+                video_start = ''
+                video_end = ''
+                video_width = '640px'
+                video_height = '360px'
+                for for_a in data:
+                    data_sub = re.search(macro_split_sub_regex, for_a)
+                    if data_sub:
+                        data_sub = data_sub.groups()
+                        data_sub = [data_sub[0].lower(), data_sub[1]]
+
+                        if data_sub[0] == 'width':
+                            video_width = self.get_tool_px_add_check(data_sub[1])
+                        elif data_sub[0] == 'height':
+                            video_height = self.get_tool_px_add_check(data_sub[1])
+                        elif data_sub[0] == 'start':
+                            video_start = data_sub[1]
+                        elif data_sub[0] == 'end':
+                            video_end = data_sub[1]
+                        elif data_sub[0] == 'https://www.youtube.com/watch?v' and name_data == 'youtube':
+                            video_code = data_sub[1]
+                    else:
+                        video_code = for_a
+
+                # code to url
+                if name_data == 'youtube':
+                    video_code = re.sub(r'^https:\/\/youtu\.be\/', '', video_code)
+
+                    video_code = 'https://www.youtube.com/embed/' + video_code
+
+                    if video_start != '':
+                        if video_end != '':
+                            video_code += '?start=' + video_start + '&end=' + video_end
+                        else:
+                            video_code += '?start=' + video_start
+                    else:
+                        if video_end != '':
+                            video_code += '?end=' + video_end
+                elif name_data == 'kakaotv':
+                    video_code = re.sub(r'^https:\/\/tv\.kakao\.com\/v\/', '', video_code)
+
+                    video_code = 'https://tv.kakao.com/embed/player/cliplink/' + video_code +'?service=kakao_tv'
+                elif name_data == 'navertv':
+                    video_code = re.sub(r'^https:\/\/tv\.naver\.com\/v\/', '', video_code)
+
+                    video_code = 'https://tv.naver.com/embed/' + video_code
+                elif name_data == 'nicovideo':
+                    video_code = 'https://embed.nicovideo.jp/watch/' + video_code
+                else:
+                    video_code = 'https://player.vimeo.com/video/' + video_code
+
+                video_width = self.get_tool_css_safe(video_width)
+                video_height = self.get_tool_css_safe(video_height)
+
+                data_name = self.get_tool_data_storage(
+                    '<iframe style="width: ' + video_width + '; height: ' + video_height + ';" src="' + video_code + '" frameborder="0" allowfullscreen>',
+                    '</iframe>', 
+                    match_org.group(0)
+                )
+
+                return '<' + data_name + '></' + data_name + '>'
+            elif name_data == 'toc':
+                return '<toc_no_auto>'
+            elif name_data == 'ruby':
+                data = re.findall(macro_split_regex, match[1])
+
+                # get option
+                main_text = ''
+                sub_text = ''
+                color = ''
+                for for_a in data:
+                    data_sub = re.search(macro_split_sub_regex, for_a)
+                    if data_sub:
+                        data_sub = data_sub.groups()
+                        data_sub = [data_sub[0].lower(), data_sub[1]]
+
+                        if data_sub[0] == 'ruby':
+                            sub_text = data_sub[1]
+                        elif data_sub[0] == 'color':
+                            color = data_sub[1]
+                    else:
+                        main_text = for_a
+
+                main_text = self.get_tool_data_revert(main_text, do_type = 'render')
+                sub_text = self.get_tool_data_revert(sub_text, do_type = 'render')
+
+                color = self.get_tool_css_safe(color)
+
+                # add color
+                if color != '':
+                    sub_text = '<span style="color:' + color + ';">' + sub_text + '</span>'
+
+                data_name = self.get_tool_data_storage('<ruby>' + main_text + '<rp>(</rp><rt>' + sub_text + '</rt><rp>)</rp></ruby>', '', match_org.group(0))
+
+                return '<' + data_name + '></' + data_name + '>'
+            elif name_data == 'anchor':
+                main_text = self.get_tool_data_revert(match[1], do_type = 'render')
+
+                data_name = self.get_tool_data_storage('<span id="' + main_text + '">', '</span>', match_org.group(0))
+
+                return '<' + data_name + '></' + data_name + '>'
+            elif name_data == 'age':
+                if re.search(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$', match[1]):
+                    try:
+                        date = datetime.datetime.strptime(match[1], '%Y-%m-%d')
+                        data_text = ''
+                    except:
+                        data_text = 'invalid date'
+
+                    date_now = datetime.datetime.today()
+
+                    if data_text == '':
+                        if date > date_now:
+                            data_text = 'invalid date'
+                        else:
+                            data_text = str((date_now - date).days // 365)
+                else:
+                    data_text = 'invalid date'
+
+                data_name = self.get_tool_data_storage(data_text, '', match_org.group(0))
+
+                return '<' + data_name + '></' + data_name + '>'
+            elif name_data == 'dday':
+                if re.search(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$', match[1]):
+                    try:
+                        date = datetime.datetime.strptime(match[1], '%Y-%m-%d')
+                        data_text = ''
+                    except:
+                        data_text = 'invalid date'
+
+                    date_now = datetime.datetime.today()
+                    
+                    if data_text == '':
+                        date_end = (date_now - date).days
+                        if date_end > 0:
+                            data_text = '+' + str(date_end)
+                        else:
+                            if date_end == 0:
+                                data_text = '-' + str(date_end)
+                            else:
+                                data_text = str(date_end)
+                else:
+                    data_text = 'invalid date'
+
+                data_name = self.get_tool_data_storage(data_text, '', match_org.group(0))
+
+                return '<' + data_name + '></' + data_name + '>'
+            elif name_data == 'pagecount':
+                return '0'
+            else:
+                return '<macro>' + match[0] + '(' + match[1] + ')' + '</macro>'
+
+        # double macro replace
+        self.render_data = re.sub(r'\[([^[(]+)\(([^()]+)\)\]', do_render_macro_double, self.render_data)
+
+        # single macro function
+        def do_render_macro_single(match):
+            match_org = match
+
+            match = match.group(1)
+            match = match.lower()
+
+            if match in ('date', 'datetime'):
+                data_name = self.get_tool_data_storage(get_time(), '', match_org.group(0))
+
+                return '<' + data_name + '></' + data_name + '>'
+            elif match == 'br':
+                data_name = self.get_tool_data_storage('<br>', '', match_org.group(0))
+
+                return '<' + data_name + '></' + data_name + '>'
+            elif match == 'clearfix':
+                data_name = self.get_tool_data_storage('<div style="clear: both;"></div>', '', match_org.group(0))
+
+                return '<' + data_name + '></' + data_name + '>'
+            elif match in ('목차', 'toc', 'tableofcontents'):
+                return '<toc_need_part>'
+            elif match == 'pagecount':
+                self.curs.execute(db_change('select data from other where name = "count_all_title"'))
+                db_data = self.curs.fetchall()
+                if db_data:
+                    return db_data[0][0]
+                else:
+                    return '0'
+            else:
+                return '<macro>' + match_org.group(1) + '</macro>'
+
+        # single macro replace
+        self.render_data = re.sub(r'\[([^[\]]+)\]', do_render_macro_single, self.render_data)
+
+        # macro safe restore
+        self.render_data = re.sub(r'<macro>', '[', self.render_data)
+        self.render_data = re.sub(r'<\/macro>', ']', self.render_data)
+
+    def do_render_math(self):
+        def do_render_math_sub(match):
+            data = match.group(1)
+
+            data = re.sub(r'\n', '', data)
+            data = self.get_tool_data_revert(data)
+
+            data_html = self.get_tool_js_safe(data)
+
+            data = html.unescape(data)
+            data = self.get_tool_js_safe(data)
+
+            name_ob = 'opennamu_math_' + str(self.data_math_count)
+
+            data_name = self.get_tool_data_storage('<span id="' + name_ob + '">', '</span>', match.group(0))
+
+            self.render_data_js += '' + \
+                'try {\n' + \
+                    'katex.render("' + data + '", document.getElementById(\"' + name_ob + '\"));\n' + \
+                '} catch {\n' + \
+                    'if(document.getElementById(\"' + name_ob + '\")) {\n' + \
+                        'document.getElementById(\"' + name_ob + '\").innerHTML = "<span style=\'color: red;\'>' + data_html + '</span>";\n' + \
+                    '}\n' + \
+                '}\n' + \
+            ''
+
+            self.data_math_count += 1
+
+            return '<' + data_name + '></' + data_name + '>'
+
+        math_regex = re.compile('\[math\(((?:(?!\[math\(|\)\]).|\n)+)\)\]', re.I)
+        self.render_data = re.sub(math_regex, do_render_math_sub, self.render_data)
+
+    def do_render_link(self):
+        link_regex = r'\[\[((?:(?!\[\[|\]\]|\||<|>).|<slash_[0-9]+>)+)(?:\|((?:(?!\[\[|\]\]|\|).)+))?\]\]'
+        link_count_all = len(re.findall(link_regex, self.render_data)) * 4
+        while 1:
+            if not re.search(link_regex, self.render_data):
+                break
+            elif link_count_all < 0:
+                print('Error : render link count overflow')
+
+                break
+            else:
+                # link split
+                link_data = re.search(link_regex, self.render_data)
+                link_data_full = link_data.group(0)
+                link_data = link_data.groups()
+
+                link_main = link_data[0]
+                link_main_org = link_main
+
+                # file link
+                if re.search(r'^(파일|file|외부|out):', link_main, flags = re.I):
+                    file_width = ''
+                    file_height = ''
+                    file_align = ''
+                    file_bgcolor = ''
+                    file_turn = ''
+
+                    file_split_regex = r'(?:^|&amp;) *((?:(?!&amp;).)+)'
+                    file_split_sub_regex = r'(^[^=]+) *= *([^=]+)'
+                    if link_data[1]:
+                        data = re.findall(file_split_regex, link_data[1])
+                        for for_a in data:
+                            data_sub = re.search(file_split_sub_regex, for_a)
+                            if data_sub:
+                                data_sub = data_sub.groups()
+                                if data_sub[0] == 'width':
+                                    file_width = self.get_tool_px_add_check(data_sub[1])
+                                elif data_sub[0] == 'height':
+                                    file_height = self.get_tool_px_add_check(data_sub[1])
+                                elif data_sub[0] == 'align':
+                                    if data_sub[1] in ('center', 'left', 'right'):
+                                        file_align = data_sub[1]
+                                elif data_sub[0] == 'bgcolor':
+                                    file_bgcolor = data_sub[1]
+                                elif data_sub[0] == 'theme':
+                                    if data_sub[1] == 'dark':
+                                        file_turn = 'dark'
+                                    elif data_sub[1] == 'light':
+                                        file_turn = 'light'
+
+                    link_main_org = ''
+                    link_sub = link_main
+                    file_out = 0
+
+                    link_out_regex = re.compile('^(외부|out):', re.I)
+                    link_in_regex = re.compile('^(파일|file):', re.I)
+                    if re.search(link_out_regex, link_main):
+                        link_main = re.sub(link_out_regex, '', link_main)
+
+                        link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                        link_main = html.unescape(link_main)
+                        link_main = re.sub(r'"', '&quot;', link_main)
+                        
+                        link_exist = ''
+                        file_out = 1
+                    else:
+                        link_main = re.sub(link_in_regex, '', link_main)
+
+                        link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                        link_main = html.unescape(link_main)
+
+                        self.curs.execute(db_change("select title from data where title = ?"), ['file:' + link_main])
+                        db_data = self.curs.fetchall()
+                        if db_data:
+                            link_exist = ''
+                            self.data_backlink += [[self.doc_name, 'file:' + link_main, 'file']]
+                        else:
+                            link_exist = 'opennamu_not_exist_link'
+                            self.data_backlink += [[self.doc_name, 'file:' + link_main, 'no']]
+                            self.data_backlink += [[self.doc_name, 'file:' + link_main, 'file']]
+                        
+                        link_extension_regex = r'\.([^.]+)$'
+                        link_extension = re.search(link_extension_regex, link_main)
+                        if link_extension:
+                            link_extension = link_extension.group(1)
+                        else:
+                            link_extension = 'jpg'
+
+                        link_main = re.sub(link_extension_regex, '', link_main)
+                        link_main_org = link_main
+
+                        link_main = '/image/' + url_pas(sha224_replace(link_main)) + '.' + link_extension
+
+                    if file_width != '':
+                        file_width = 'width:' + self.get_tool_css_safe(file_width) + ';'
+                    
+                    if file_height != '':
+                        file_height = 'height:' + self.get_tool_css_safe(file_height) + ';'
+
+                    file_align_style = ''
+                    if file_align in ('left', 'right'):
+                        file_align_style = 'float:' + file_align + ';'
+
+                    if file_bgcolor != '':
+                        file_bgcolor = 'background:' + self.get_tool_css_safe(file_bgcolor) + ';'
+
+                    file_end = '<img style="' + file_width + file_height + file_align_style + file_bgcolor + '" alt="' + link_sub + '" src="' + link_main + '">'
+                    if file_align == 'center':
+                        file_end = '<div style="text-align:center;">' + file_end + '</div>'
+
+                    if link_exist != '':
+                        data_name = self.get_tool_data_storage('<a class="' + link_exist + '" title="' + link_sub + '" href="/upload?name=' + url_pas(link_main_org) + '">' + link_sub, '</a>', link_data_full)
+                        self.render_data = re.sub(link_regex, '<' + data_name + '></' + data_name + '>', self.render_data, 1)
+                    else:
+                        file_pass = 0
+                        if file_turn != '':
+                            if file_turn == 'dark' and self.darkmode == '1':
+                                file_pass = 1
+                            elif file_turn == 'light' and self.darkmode == '0':
+                                file_pass = 1
+                        else:
+                            file_pass = 1
+
+                        if file_pass == 1:
+                            if file_out == 0:
+                                data_name = self.get_tool_data_storage('<a title="' + link_sub + '" href="/w/file:' + url_pas(link_main_org) + '.' + url_pas(link_extension) + '">' + file_end, '</a>', link_data_full)
+                            else:
+                                data_name = self.get_tool_data_storage('<a title="' + link_sub + '" href="' + link_main + '">' + file_end, '</a>', link_data_full)
+                        else:
+                            data_name = self.get_tool_data_storage('', '', link_data_full)
+                        
+                        self.render_data = re.sub(link_regex, '<' + data_name + '></' + data_name + '>', self.render_data, 1)
+                # category
+                elif re.search(r'^(분류|category):', link_main, flags = re.I):
+                    link_main = re.sub(r'^(분류|category):', '', link_main, flags = re.I)
+
+                    if link_data[1]:
+                        link_main += link_data[1]
+
+                    category_blur = ''
+                    if re.search(r'#blur$', link_main, flags = re.I):
+                        link_main = re.sub(r'#blur$', '', link_main, flags = re.I)
+
+                        category_blur = 'opennamu_category_blur'
+                    
+                    link_sub = link_main
+
+                    link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                    link_main = html.unescape(link_main)
+
+                    if not link_main in self.data_category_list:
+                        self.data_category_list += [link_main]
+                        
+                        self.curs.execute(db_change("select title from data where title = ?"), ['category:' + link_main])
+                        db_data = self.curs.fetchall()
+                        if db_data:
+                            link_exist = ''
+                            self.data_backlink += [[self.doc_name, 'category:' + link_main, 'cat']]
+                        else:
+                            link_exist = 'opennamu_not_exist_link'
+                            self.data_backlink += [[self.doc_name, 'category:' + link_main, 'no']]
+                            self.data_backlink += [[self.doc_name, 'category:' + link_main, 'cat']]
+
+                        link_main = url_pas(link_main)
+
+                        if self.data_category == '':
+                            self.data_category = '<div class="opennamu_category">' + self.get_tool_lang('category') + ' : '
+                        else:
+                            self.data_category += ' | '
+
+                        self.data_category += '<a class="' + category_blur + ' ' + link_exist + '" title="' + link_sub + '" href="/w/category:' + link_main + '">' + link_sub + '</a>'
+
+                    if self.render_data.find('\n' + link_data_full + '\n') != -1:
+                        self.render_data = self.render_data.replace('\n' + link_data_full + '\n', '\n', 1)
+                    else:
+                        self.render_data = re.sub(link_regex, '', self.render_data, 1)
+                # inter link
+                elif re.search(r'^(?:inter|인터):([^:]+):', link_main, flags = re.I):
+                    link_inter_regex = re.compile('^(?:inter|인터):([^:]+):', flags = re.I)
+
+                    link_inter_name = re.search(link_inter_regex, link_main)
+                    link_inter_name = link_inter_name.group(1)
+
+                    link_main = re.sub(link_inter_regex, '', link_main)
+                    link_title = link_inter_name + ':' + link_main
+
+                    # sharp
+                    link_main = link_main.replace('&#x27;', '<link_single>')
+                    link_data_sharp_regex = r'#([^#]+)$'
+                    link_data_sharp = re.search(link_data_sharp_regex, link_main)
+                    if link_data_sharp:
+                        link_data_sharp = link_data_sharp.group(1)
+                        link_data_sharp = html.unescape(link_data_sharp)
+                        link_data_sharp = '#' + url_pas(link_data_sharp)
+
+                        link_main = re.sub(link_data_sharp_regex, '', link_main)
+                    else:
+                        link_data_sharp = ''
+                    
+                    link_main = link_main.replace('<link_single>', '&#x27;')
+
+                    # main link fix
+                    link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                    link_main = html.unescape(link_main)
+                    
+                    link_main = url_pas(link_main)
+
+                    self.curs.execute(db_change("select plus, plus_t from html_filter where kind = 'inter_wiki' and html = ?"), [link_inter_name])
+                    db_data = self.curs.fetchall()
+                    if db_data:
+                        link_main = db_data[0][0] + link_main
+
+                        # sub not exist -> sub = main
+                        if link_data[1]:
+                            link_sub = link_data[1]
+                            link_sub_storage = ''
+                        else:
+                            link_sub = ''
+                            link_sub_storage = link_main_org
+                            link_sub_storage = re.sub(link_inter_regex, '', link_sub_storage)
+
+                        link_inter_icon = link_inter_name + ':'
+                        if db_data[0][1] != '':
+                            link_inter_icon = db_data[0][1]
+
+                        link_sub_storage = link_inter_icon + link_sub_storage
+
+                        data_name = self.get_tool_data_storage('<a class="opennamu_link_inter" title="' + link_title + '" href="' + link_main + link_data_sharp + '">' + link_sub_storage, '</a>', link_data_full)
+                    
+                        self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
+                    else:
+                        self.render_data = re.sub(link_regex, '', self.render_data, 1)
+                # out link
+                elif re.search(r'^https?:\/\/', link_main, flags = re.I):
+                    link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                    link_title = link_main
+                    link_main = html.unescape(link_main)
+                    link_main = re.sub(r'"', '&quot;', link_main)
+                    
+                    # sub not exist -> sub = main
+                    if link_data[1]:
+                        link_sub = link_data[1]
+                        link_sub_storage = ''
+                    else:
+                        link_sub = ''
+                        link_sub_storage = link_main_org
+
+                    data_name = self.get_tool_data_storage('<a class="opennamu_link_out" target="_blank" title="' + link_title + '" href="' + link_main + '">' + link_sub_storage, '</a>', link_data_full)
+
+                    self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
+                # in link
+                else:
+                    # under page & fix url
+                    if link_main == '../':
+                        link_main = self.doc_name
+                        link_main = re.sub(r'(\/[^/]+)$', '', link_main)
+                    elif re.search(r'^\/', link_main):
+                        link_main = re.sub(r'^\/', lambda x : (self.doc_name + '/'), link_main)
+                    elif re.search(r'^:(분류|category):', link_main, flags = re.I):
+                        link_main = re.sub(r'^:(분류|category):', 'category:', link_main, flags = re.I)
+                    elif re.search(r'^:(파일|file):', link_main, flags = re.I):
+                        link_main = re.sub(r'^:(파일|file):', 'file:', link_main, flags = re.I)
+                    elif re.search(r'^사용자:', link_main, flags = re.I):
+                        link_main = re.sub(r'^사용자:', 'user:', link_main, flags = re.I)
+
+                    # sharp
+                    link_main = link_main.replace('&#x27;', '<link_single>')
+                    link_data_sharp_regex = r'#([^#]+)$'
+                    link_data_sharp = re.search(link_data_sharp_regex, link_main)
+                    if link_data_sharp:
+                        link_data_sharp = link_data_sharp.group(1)
+                        link_data_sharp = html.unescape(link_data_sharp)
+                        link_data_sharp = '#' + url_pas(link_data_sharp)
+
+                        link_main = re.sub(link_data_sharp_regex, '', link_main)
+                    else:
+                        link_data_sharp = ''
+                    
+                    link_main = link_main.replace('<link_single>', '&#x27;')
+
+                    # main link fix
+                    link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                    link_main = html.unescape(link_main)
+
+                    # link_title
+                    link_title = html.escape(link_main + link_data_sharp)
+
+                    link_exist = ''
+                    if link_main != '':
+                        self.curs.execute(db_change("select title from data where title = ?"), [link_main])
+                        db_data = self.curs.fetchall()
+                        if not db_data:
+                            self.data_backlink += [[self.doc_name, link_main, 'no']]
+                            self.data_backlink += [[self.doc_name, link_main, '']]
+                            link_exist = 'opennamu_not_exist_link'
+                        else:
+                            self.data_backlink += [[self.doc_name, link_main, '']]
+
+                    link_same = ''
+                    if link_main == self.doc_name and self.doc_include == '':
+                        link_same = 'opennamu_same_link'
+
+                    link_main = url_pas(link_main)
+
+                    if link_main != '':
+                        link_main = '/w/' + link_main
+
+                    # sub not exist -> sub = main
+                    if link_data[1]:
+                        link_sub = link_data[1]
+                        link_sub_storage = ''
+                    else:
+                        link_sub = ''
+                        link_sub_storage = link_main_org
+
+                    data_name = self.get_tool_data_storage('<a class="' + link_exist + ' ' + link_same + '" title="' + link_title + '" href="' + link_main + link_data_sharp + '">' + link_sub_storage, '</a>', link_data_full)
+
+                    self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
+
+            link_count_all -= 1
+
+    def do_render_slash(self):
+        # slash text -> <slash_n>
+        
+        def do_render_slash_sub(match):
+            if match.group(1) == '<':
+                return '<'
+            else:
+                data_name = self.get_tool_data_storage(match.group(1), do_type = 'slash')
+
+                return '<' + data_name + '>'
+
+        self.render_data = re.sub(r'\\(&lt;|&gt;|&#x27;|&quot;|&amp;|.)', do_render_slash_sub, self.render_data)
+
+    def do_render_include_default(self):
+        def do_render_include_default_sub(match):
+            match_org = match.group(0)
+            match = match.groups()
+
+            if len(match) < 3:
+                match = list(match) + ['']
+
+            if match[2] == '\\':
+                return match_org
+            else:
+                slash_add = ''
+                if match[0]:
+                    if len(match[0]) % 2 == 1:
+                        slash_add = '\\' * (len(match[0]) - 1)
+                    else:
+                        slash_add = match[0]
+
+                return slash_add + match[2]
+
+        self.render_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z]+)=((?:\\@|[^@\n])+)@', do_render_include_default_sub, self.render_data)
+        self.render_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z]+)@', do_render_include_default_sub, self.render_data)
+
+    def do_render_include(self):
+        def do_render_include_default_sub(match):
+            match_org = match.group(0)
+            match = match.groups()
+
+            if len(match) < 3:
+                match = list(match) + ['']
+
+            if match[2] == '\\':
+                return match_org
+            else:
+                slash_add = ''
+                if match[0]:
+                    if len(match[0]) % 2 == 1:
+                        slash_add = '\\' * (len(match[0]) - 1)
+                    else:
+                        slash_add = match[0]
+
+                if match[1] in include_change_list:
+                    return slash_add + include_change_list[match[1]]
+                else:
+                    return slash_add + match[2]
+
+        include_num = 0
+        include_regex = re.compile('\[include\(((?:(?!\[include\(|\)\]|<\/div>).)+)\)\]', re.I)
+        include_count_max = len(re.findall(include_regex, self.render_data)) * 2
+        include_change_list = {}
+        while 1:
+            include_num += 1
+            include_change_list = {}
+
+            match = re.search(include_regex, self.render_data)
+            if include_count_max < 0:
+                break
+            elif not match:
+                break
+            else:
+                if self.doc_include != '':
+                    self.render_data = re.sub(include_regex, '', self.render_data, 1)
+                else:
+                    match_org = match.group(0)
+                    match = match.groups()
+
+                    macro_split_regex = r'(?:^|,) *([^,]+)'
+                    macro_split_sub_regex = r'^([^=]+) *= *(.*)$'
+
+                    include_name = ''
+
+                    data = re.findall(macro_split_regex, match[0])
+                    for for_a in data:
+                        data_sub = re.search(macro_split_sub_regex, for_a)
+                        if data_sub:
+                            data_sub = data_sub.groups()
+                            
+                            data_sub_name = data_sub[0]
+                            data_sub_data = self.get_tool_data_restore(data_sub[1], do_type = 'slash')
+                            
+                            data_sub_data = re.sub(r'^분류:', ':분류:', data_sub_data)
+                            data_sub_data = re.sub(r'^파일:', ':파일:', data_sub_data)
+
+                            include_change_list[data_sub_name] = data_sub_data
+                        else:
+                            include_name = for_a
+
+                    include_name_org = include_name
+                    
+                    include_name = self.get_tool_data_restore(include_name, do_type = 'slash')
+                    include_name = html.unescape(include_name)
+
+                    # load include db data
+                    self.curs.execute(db_change("select data from data where title = ?"), [include_name])
+                    db_data = self.curs.fetchall()
+                    if db_data:
+                        self.data_backlink += [[self.doc_name, include_name, 'include']]
+                        include_data = db_data[0][0].replace('\r', '')
+
+                        # include link func
+                        if ip_or_user(self.ip) == 0:
+                            self.curs.execute(db_change('select data from user_set where name = "main_css_include_link" and id = ?'), [self.ip])
+                            db_data = self.curs.fetchall()
+                            include_set_data = db_data[0][0] if db_data else 'normal'
+                        else:
+                            include_set_data = self.flask_session['main_css_include_link'] if 'main_css_include_link' in self.flask_session else 'normal'
+
+                        include_link = ''
+                        if include_set_data == 'use':
+                            include_link = '<div><a href="/w/' + url_pas(include_name) + '">(' + include_name_org + ')</a></div>'
+
+                        # parameter replace
+                        include_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z]+)=((?:\\@|[^@\n])+)@', do_render_include_default_sub, include_data)
+                        include_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z]+)@', do_render_include_default_sub, include_data)
+
+                        # remove end br
+                        include_data = re.sub('^\n+', '', include_data)
+
+                        self.data_include += [[self.doc_include + 'opennamu_include_' + str(include_num), include_name, include_data, 'style="display: inline;"']]
+
+                        data_name = self.get_tool_data_storage('' + \
+                            include_link + \
+                            '<div id="' + self.doc_include + 'opennamu_include_' + str(include_num) + '"></div>' + \
+                        '', '', match_org)
+                    else:
+                        self.data_backlink += [[self.doc_name, include_name, 'no']]
+
+                        include_link = '<div><a class="opennamu_not_exist_link" href="/w/' + url_pas(include_name) + '">(' + include_name_org + ')</a></div>'
+
+                        data_name = self.get_tool_data_storage(include_link, '', match_org)
+
+                    self.render_data = re.sub(include_regex, '<' + data_name + '></' + data_name + '>', self.render_data, 1)
+
+            include_count_max -= 1
+
+    def do_render_list(self):
+        pass
+
+    def do_redner_footnote(self):
+        footnote_num = 0
+        footnote_regex = re.compile('(?:\[\*((?:(?!\[\*|\]| ).)+)?(?: ((?:(?!\[\*|\]).)+))?\]|\[(각주|footnote)\])', re.I)
+        footnote_count_all = len(re.findall(footnote_regex, self.render_data)) * 4
+        while 1:
+            footnote_num += 1
+
+            footnote_data = re.search(footnote_regex, self.render_data)
+            if footnote_count_all < 0:
+                break
+            elif not footnote_data:
+                break
+            else:
+                footnote_data_org = footnote_data.group(0)
+                footnote_data = footnote_data.groups()
+                if footnote_data[2]:
+                    self.render_data = re.sub(footnote_regex, lambda x : self.get_tool_footnote_make(), self.render_data, 1)
+                else:
+                    footnote_num_str = str(footnote_num)
+
+                    if not footnote_data[0]:
+                        footnote_name = footnote_num_str
+                        footnote_name_add = ''
+                    else:
+                        footnote_name = footnote_data[0]
+                        footnote_name_add = ' (' + footnote_num_str + ')'
+
+                    if not footnote_data[1]:
+                        footnote_text_data = ''
+                    else:
+                        footnote_text_data = footnote_data[1]
+
+                    if footnote_name in self.data_footnote:
+                        self.data_footnote[footnote_name]['list'] += [footnote_num_str]
+                        footnote_first = self.data_footnote[footnote_name]['list'][0]
+
+                        data_name = self.get_tool_data_storage('<sup><a fn_target="' + self.doc_include + 'fn_' + footnote_first + '" id="' + self.doc_include + 'rfn_' + footnote_num_str + '" href="#' + self.doc_include + 'fn_' + footnote_first + '">(' + footnote_name + ' (' + footnote_num_str + ')' + ')</a></sup>', '', footnote_data_org)
+
+                        self.render_data = re.sub(footnote_regex, '<' + data_name + '></' + data_name + '>', self.render_data, 1)
+                    else:
+                        self.data_footnote[footnote_name] = {}
+                        self.data_footnote[footnote_name]['list'] = [footnote_num_str]
+                        self.data_footnote[footnote_name]['data'] = footnote_text_data
+
+                        data_name = self.get_tool_data_storage('<sup><a fn_target="' + self.doc_include + 'fn_' + footnote_num_str + '" id="' + self.doc_include + 'rfn_' + footnote_num_str + '" href="#' + self.doc_include + 'fn_' + footnote_num_str + '">(' + footnote_name + footnote_name_add + ')</a></sup>', '', footnote_data_org)
+
+                        self.render_data = re.sub(footnote_regex, '<' + data_name + '></' + data_name + '>', self.render_data, 1)
+
+            footnote_count_all -= 1
+
+        self.render_data += '<footnote_category>'
+        self.render_data += self.get_tool_footnote_make()
+
+    def do_render_redirect(self):
+        match = re.search(r'^<back_br>\n#(?:redirect|넘겨주기) ([^\n]+)', self.render_data, flags = re.I)
+        if match and self.doc_include == '':
+            link_data_full = match.group(0)
+            link_main = match.group(1)
+
+            # under page & fix url
+            if link_main == '../':
+                link_main = self.doc_name
+                link_main = re.sub(r'(\/[^/]+)$', '', link_main)
+            elif re.search(r'^\/', link_main):
+                link_main = re.sub(r'^\/', lambda x : (self.doc_name + '/'), link_main)
+            elif re.search(r'^분류:', link_main):
+                link_main = re.sub(r'^분류:', 'category:', link_main)
+            elif re.search(r'^사용자:', link_main):
+                link_main = re.sub(r'^사용자:', 'user:', link_main)
+
+            # sharp
+            link_main = link_main.replace('&#x27;', '<link_single>')
+            link_data_sharp_regex = r'#([^#]+)$'
+            link_data_sharp = re.search(link_data_sharp_regex, link_main)
+            if link_data_sharp:
+                link_data_sharp = link_data_sharp.group(1)
+                link_data_sharp = html.unescape(link_data_sharp)
+                link_data_sharp = '#' + url_pas(link_data_sharp)
+
+                link_main = re.sub(link_data_sharp_regex, '', link_main)
+            else:
+                link_data_sharp = ''
+            
+            link_main = link_main.replace('<link_single>', '&#x27;')
+
+            # main link fix
+            link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+            link_main = html.unescape(link_main)
+
+            self.data_backlink += [[self.doc_name, link_main, 'redirect']]
+
+            link_main = url_pas(link_main)
+
+            self.data_redirect = 1
+            if link_main != '':
+                link_main = '/w_from/' + link_main
+
+            if 'doc_from' in self.doc_set:
+                data_name = self.get_tool_data_storage('<a href="' + link_main + link_data_sharp + '">(GO)</a>', '', link_data_full)
+            else:
+                data_name = self.get_tool_data_storage('<meta http-equiv="refresh" content="0; url=' + link_main + link_data_sharp + '">', '', link_data_full)
+                
+            self.render_data = '<' + data_name + '></' + data_name + '>'
+
+    def do_render_table(self):
+        self.render_data = re.sub(r'\n +\|\|', '\n||', self.render_data)
+
+        # get_tool_dark_mode_split
+        # get_tool_px_add_check
+        # get_tool_css_safe
+        # todo : after text render text not use to make table
+        def do_render_table_parameter(cell_count, parameter, data, option = {}):
+            table_parameter_all = { "div" : "", "class" : "", "table" : "", "tr" : "", "td" : "", "col" : "", "colspan" : "", "rowspan" : "", "data" : "" }
+            
+            table_align_auto = 1
+            table_colspan_auto = 1
+
+            # todo : useless parameter return
+            table_parameter_regex = r'&lt;((?:(?!&lt;|&gt;).)+)&gt;'
+            for table_parameter in re.findall(table_parameter_regex, parameter):
+                table_parameter_split = table_parameter.split('=')
+                if len(table_parameter_split) == 2:
+                    table_parameter_name = table_parameter_split[0].replace(' ', '')
+                    table_parameter_name = table_parameter_name.lower()
+                    
+                    table_parameter_data = self.get_tool_css_safe(table_parameter_split[1])
+
+                    if table_parameter_name == 'tablebgcolor':
+                        table_parameter_all['table'] += 'background:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'tablewidth':
+                        table_parameter_all['table'] += 'width:' + self.get_tool_px_add_check(table_parameter_data) + ';'
+                    elif table_parameter_name == 'tableheight':
+                        table_parameter_all['table'] += 'height:' + self.get_tool_px_add_check(table_parameter_data) + ';'
+                    elif table_parameter_name == 'tablealign':
+                        if table_parameter_data == 'right':
+                            table_parameter_all['div'] += 'float:right;'
+                        elif table_parameter_data == 'center':
+                            table_parameter_all['div'] += 'margin:auto;'
+                            table_parameter_all['table'] += 'margin:auto;'
+                    elif table_parameter_name == 'tableclass':
+                        table_parameter_all['class'] = table_parameter_split[1]
+                    elif table_parameter_name == 'tabletextalign':
+                        table_parameter_all['table'] += 'text-align:' + table_parameter_data + ';'
+                    elif table_parameter_name == 'tablecolor':
+                        table_parameter_all['table'] += 'color:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'tablebordercolor':
+                        table_parameter_all['table'] += 'border:2px solid ' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'rowbgcolor':
+                        table_parameter_all['tr'] += 'background:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'rowtextalign':
+                        table_parameter_all['tr'] += 'text-align:' + table_parameter_data + ';'
+                    elif table_parameter_name == 'rowcolor':
+                        table_parameter_all['tr'] += 'color:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'colcolor':
+                        table_parameter_all['col'] += 'color:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'colbgcolor':
+                        table_parameter_all['col'] += 'background:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'bgcolor':
+                        table_parameter_all['td'] += 'background:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'color':
+                        table_parameter_all['td'] += 'color:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+                    elif table_parameter_name == 'width':
+                        table_parameter_all['td'] += 'width:' + self.get_tool_px_add_check(table_parameter_data) + ';'
+                    elif table_parameter_name == 'height':
+                        table_parameter_all['td'] += 'height:' + self.get_tool_px_add_check(table_parameter_data) + ';'
+                elif len(table_parameter_split) == 1:
+                    if re.search(r'^-[0-9]+$', table_parameter):
+                        table_colspan_auto = 0
+                        table_parameter_all['colspan'] = re.sub(r'[^0-9]+', '', table_parameter)
+                    elif re.search(r'^(\^|v)?\|[0-9]+$', table_parameter):
+                        if table_parameter[0] == '^':
+                            table_parameter_all['td'] += 'vertical-align: top;'
+                        elif table_parameter[0] == 'v':
+                            table_parameter_all['td'] += 'vertical-align: bottom;'
+
+                        table_parameter_all['rowspan'] = re.sub(r'[^0-9]+', '', table_parameter)
+                    elif table_parameter in ('(', ':', ')'):
+                        table_align_auto = 0
+                        if table_parameter == '(':
+                            table_parameter_all['td'] += 'text-align: left;'
+                        elif table_parameter == ':':
+                            table_parameter_all['td'] += 'text-align: center;'
+                        elif table_parameter == ':':
+                            table_parameter_all['td'] += 'text-align: right;'
+                    else:
+                        table_parameter_data = self.get_tool_css_safe(table_parameter)
+                        table_parameter_all['td'] += 'background:' + self.get_tool_dark_mode_split(table_parameter_data) + ';'
+            
+            if table_align_auto == 1:
+                if re.search(r'^ ', data):
+                    data = re.sub(r'^ ', '', data)
+                    if re.search(r' $', data):
+                        table_parameter_all['td'] += 'text-align: center;'
+
+                        data = re.sub(r' $', '', data)
+                    else:
+                        table_parameter_all['td'] += 'text-align: right;'
+                else:
+                    if re.search(r' $', data):
+                        data = re.sub(r' $', '', data)
+
+            if table_colspan_auto == 1:
+                table_parameter_all['colspan'] = str(len(cell_count) // 2)
+
+            table_parameter_all['data'] = data
+
+            return table_parameter_all
+
+        table_regex = re.compile('\n((?:(?:(?:(?:\|\|)+)|(?:\|[^|]+\|(?:\|\|)*))\n?(?:(?:(?!\|\|).)+))(?:(?:\|\||\|\|\n|(?:\|\|)+(?!\n)(?:(?:(?!\|\|).)+)\n*)*)\|\|)\n', re.DOTALL)
+        table_sub_regex = r'(\n?)((?:\|\|)+)((?:&lt;(?:(?:(?!&lt;|&gt;).)+)&gt;)*)((?:\n*(?:(?:(?:(?!\|\|).)+)\n*)+)|(?:(?:(?!\|\|).)*))'
+        table_caption_regex = r'^\|([^|]+)\|'
+        table_count_all = len(re.findall(table_regex, self.render_data)) * 2
+        while 1:
+            table_data = re.search(table_regex, self.render_data)
+            if table_count_all < 0:
+                print('Error : render table count overflow')
+
+                break
+            elif not table_data:
+                break
+            else:
+                table_data_org = table_data.group(0)
+                table_data = table_data.group(1)
+                
+                table_caption = re.search(table_caption_regex, table_data)
+                if table_caption:
+                    table_caption = table_caption.group(1)
+                    table_caption = '<caption>' + table_caption + '</caption>'
+
+                    table_data = re.sub(table_caption_regex, '||', table_data)
+                else:
+                    table_caption = ''
+
+                table_parameter = { "div" : "", "class" : "", "table" : "", "col" : {}, "rowspan" : {} }
+                table_data_end = ''
+                table_col_num = 0
+                table_tr_change = 0
+                for table_sub in re.findall(table_sub_regex, table_data):
+                    table_data_in = table_sub[3]
+                    table_data_in = re.sub(r'^\n+', '', table_data_in)
+
+                    table_sub_parameter = do_render_table_parameter(table_sub[1], table_sub[2], table_data_in)
+
+                    if table_data_end == '':
+                        table_data_end += '<tr style="' + table_sub_parameter['tr'] + '">'
+
+                    if table_sub[0] != '' and table_tr_change == 1:
+                        table_col_num = 0
+                        table_data_end += '</tr><tr style="' + table_sub_parameter['tr'] + '">'
+
+                    if not table_col_num in table_parameter['rowspan']:
+                        table_parameter['rowspan'][table_col_num] = 0
+                    else:
+                        if table_parameter['rowspan'][table_col_num] != 0:
+                            table_parameter['rowspan'][table_col_num] -= 1
+                            table_col_num += 1
+
+                    if table_sub_parameter['rowspan'] != '':
+                        rowspan_int = int(table_sub_parameter['rowspan'])
+                        if rowspan_int > 1:
+                            table_parameter['rowspan'][table_col_num] = rowspan_int - 1
+
+                    if not table_col_num in table_parameter['col']:
+                        table_parameter['col'][table_col_num] = ''
+
+                    table_parameter['div'] += table_sub_parameter['div']
+                    table_parameter['class'] = table_sub_parameter['class'] if table_sub_parameter['class'] != '' else table_parameter['class']
+                    table_parameter['table'] += table_sub_parameter['table']
+                    table_parameter['col'][table_col_num] += table_sub_parameter['col']
+
+                    if table_sub[2] == '' and table_sub[3] == '':
+                        table_tr_change = 1
+                    else:
+                        table_tr_change = 0
+                    
+                        table_data_end += '<td colspan="' + table_sub_parameter['colspan'] + '" rowspan="' + table_sub_parameter['rowspan'] + '" style="' + table_parameter['col'][table_col_num] + table_sub_parameter['td'] + '"><back_br>\n' + table_sub_parameter['data'] + '\n<front_br></td>'
+                    
+                    table_col_num += 1
+
+                table_data_end += '</tr>'
+                table_data_end = '<table class="' + table_parameter['class'] + '" style="' + table_parameter['table'] + '">' + table_caption + table_data_end + '</table>'
+                table_data_end = '<div class="table_safe" style="' + table_parameter['div'] + '">' + table_data_end + '</div>'
+
+                self.render_data = re.sub(table_regex, lambda x : ('\n<front_br>' + table_data_end + '<back_br>\n'), self.render_data, 1)
+
+            table_count_all -= 1
+    
+    def do_render_middle(self):
+        middle_regex = r'{{{([^{](?:(?!{{{|}}}).|\n)*)?(?:}|<(\/?(?:slash)_(?:[0-9]+))>)}}'
+        wiki_count = 0
+        syntax_count = 0
+        folding_count = 0
+        middle_count_all = len(re.findall(middle_regex, self.render_data)) * 10
+        while 1:
+            middle_data = re.search(middle_regex, self.render_data)
+            if middle_count_all < 0:
+                break
+            elif not middle_data:
+                break
+            else:
+                middle_data_org = middle_data.group(0)
+                middle_slash = middle_data.group(2)
+                if middle_slash:
+                    if self.data_temp_storage[middle_slash] != '}':
+                        middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                        self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                        continue
+
+                middle_data = middle_data.group(1)
+                if not middle_data:
+                    middle_data = ''
+
+                middle_name = re.search(r'^([^ \n]+)', middle_data)
+                middle_data_pass = ''
+                if middle_name:
+                    middle_name = middle_name.group(1)
+                    middle_name = middle_name.lower()
+                    if middle_name == '#!wiki':
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_regex = re.compile('^#!wiki(?:(?: style=(&quot;(?:(?:(?!&quot;).)*)&quot;|&#x27;(?:(?:(?!&#x27;).)*)&#x27;))| [^\n]*)?\n', re.I)
+                        wiki_data_style = re.search(wiki_regex, middle_data)
+                        wiki_data = re.sub(wiki_regex, '', middle_data)
+                        if wiki_data_style:
+                            wiki_data_style = wiki_data_style.group(1)
+                            if wiki_data_style:
+                                wiki_data_style = wiki_data_style.replace('&#x27;', '\'')
+                                wiki_data_style = wiki_data_style.replace('&quot;', '"')
+                                wiki_data_style = 'style=' + wiki_data_style
+                            else:
+                                wiki_data_style = ''
+                        else:
+                            wiki_data_style = ''
+
+                        wiki_data = self.get_tool_data_revert(wiki_data)
+                        wiki_data = re.sub('(^\n|\n$)', '', wiki_data)
+                        wiki_data = html.unescape(wiki_data)
+
+                        self.data_include += [[self.doc_include + 'opennamu_wiki_' + str(wiki_count), self.doc_name, wiki_data, wiki_data_style]]
+
+                        data_name = self.get_tool_data_storage('<div id="' + self.doc_include + 'opennamu_wiki_' + str(wiki_count) + '"></div>', '', middle_data_org)
+                        wiki_count += 1
+                    elif middle_name == '#!html':
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        data_name = self.get_tool_data_storage('', '', middle_data_org)
+                    elif middle_name == '#!folding':
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_regex = re.compile('^#!folding(?: ([^\n]*))?\n', re.I)
+                        wiki_data_folding = re.search(wiki_regex, middle_data)
+                        wiki_data = re.sub(wiki_regex, '', middle_data)
+                        if wiki_data_folding:
+                            wiki_data_folding = wiki_data_folding.group(1)
+                            if not wiki_data_folding:
+                                wiki_data_folding = 'test'
+                        else:
+                            wiki_data_folding = 'test'
+
+                        wiki_data = self.get_tool_data_revert(wiki_data)
+                        wiki_data = html.unescape(wiki_data)
+                        wiki_data = re.sub('\n$', '', wiki_data)
+
+                        self.data_include += [[self.doc_include + 'opennamu_folding_' + str(folding_count), self.doc_name, wiki_data]]
+
+                        middle_data_pass = wiki_data_folding
+                        data_name = self.get_tool_data_storage(
+                            '<details><summary>',
+                            '</summary><div id="' + self.doc_include + 'opennamu_folding_' + str(folding_count) + '"></div></details>', 
+                            middle_data_org
+                        )
+                        folding_count += 1
+                    elif middle_name == '#!syntax':
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_regex = re.compile('^#!syntax(?: ([^\n]*))?\n', re.I)
+                        wiki_data_syntax = re.search(wiki_regex, middle_data)
+                        wiki_data = re.sub(wiki_regex, '', middle_data)
+                        if wiki_data_syntax:
+                            wiki_data_syntax = wiki_data_syntax.group(1)
+                            if not wiki_data_syntax:
+                                wiki_data_syntax = 'python'
+                        else:
+                            wiki_data_syntax = 'python'
+
+                        if syntax_count == 0:
+                            self.render_data_js += 'hljs.highlightAll();\n'
+
+                        data_name = self.get_tool_data_storage('<pre id="syntax"><code class="' + wiki_data_syntax + '">' + wiki_data, '</code></pre>', middle_data_org)
+                        syntax_count += 1
+                    elif middle_name in ('+5', '+4', '+3', '+2', '+1'):
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_data = re.sub(r'^\+[1-5] ', '', middle_data)
+                        if middle_name == '+5':
+                            wiki_size = '200'
+                        elif middle_name == '+4':
+                            wiki_size = '180'
+                        elif middle_name == '+3':
+                            wiki_size = '160'
+                        elif middle_name == '+2':
+                            wiki_size = '140'
+                        else:
+                            wiki_size = '120'
+
+                        middle_data_pass = wiki_data
+                        data_name = self.get_tool_data_storage('<span style="font-size:' + wiki_size + '%">', '</span>', middle_data_org)
+                    elif middle_name in ('-5', '-4', '-3', '-2', '-1'):
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_data = re.sub(r'^\-[1-5] ', '', middle_data)
+                        if middle_name == '-5':
+                            wiki_size = '50'
+                        elif middle_name == '-4':
+                            wiki_size = '60'
+                        elif middle_name == '-3':
+                            wiki_size = '70'
+                        elif middle_name == '-2':
+                            wiki_size = '80'
+                        else:
+                            wiki_size = '90'
+
+                        middle_data_pass = wiki_data
+                        data_name = self.get_tool_data_storage('<span style="font-size:' + wiki_size + '%">', '</span>', middle_data_org)
+                    elif re.search(r'^@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))', middle_name):
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_color = re.search(r'^@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))(,@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+)))?', middle_name)
+                        wiki_color_data = ''
+                        if wiki_color:
+                            wiki_color = wiki_color.groups()
+                            if wiki_color[0]:
+                                wiki_color_data += '#' + wiki_color[0]
+                            else:
+                                wiki_color_data += wiki_color[1]
+
+                            if wiki_color[2]:
+                                if wiki_color[3]:
+                                    wiki_color_data += ',#' + wiki_color[3]
+                                elif wiki_color[4]:
+                                    wiki_color_data += ',' + wiki_color[4]
+                        else:
+                            wiki_color_data += 'red'
+
+                        wiki_color = self.get_tool_css_safe(wiki_color_data)
+                        wiki_color = self.get_tool_dark_mode_split(wiki_color)
+
+                        wiki_data = re.sub(r'^@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))(?:,@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+)))? ?', '', middle_data)
+
+                        middle_data_pass = wiki_data
+                        data_name = self.get_tool_data_storage('<span style="background-color:' + wiki_color + '">', '</span>', middle_data_org)
+                    elif re.search(r'^#(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))', middle_name):
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_color = re.search(r'^#(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))(,#(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+)))?', middle_name)
+                        wiki_color_data = ''
+                        if wiki_color:
+                            wiki_color = wiki_color.groups()
+                            if wiki_color[0]:
+                                wiki_color_data += '#' + wiki_color[0]
+                            else:
+                                wiki_color_data += wiki_color[1]
+
+                            if wiki_color[2]:
+                                if wiki_color[3]:
+                                    wiki_color_data += ',#' + wiki_color[3]
+                                elif wiki_color[4]:
+                                    wiki_color_data += ',' + wiki_color[4]
+                        else:
+                            wiki_color_data += 'red'
+
+                        wiki_color = self.get_tool_css_safe(wiki_color_data)
+                        wiki_color = self.get_tool_dark_mode_split(wiki_color)
+
+                        wiki_data = re.sub(r'^#(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))(?:,#(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+)))? ?', '', middle_data)
+
+                        middle_data_pass = wiki_data
+                        data_name = self.get_tool_data_storage('<span style="color:' + wiki_color + '">', '</span>', middle_data_org)
+                    else:
+                        if middle_slash:
+                            middle_data += '\\'
+
+                        data_revert = self.get_tool_data_revert(middle_data)
+                        data_revert = re.sub('^\n', '', data_revert)
+                        data_revert = re.sub('\n$', '', data_revert)
+
+                        data_name = self.get_tool_data_storage(data_revert, '', middle_data_org)
+                else:
+                    if middle_slash:
+                        middle_data += '\\'
+
+                    data_revert = self.get_tool_data_revert(middle_data)
+                    data_revert = re.sub('^\n', '', data_revert)
+                    data_revert = re.sub('\n$', '', data_revert)
+
+                    data_name = self.get_tool_data_storage(data_revert, '', middle_data_org)
+
+                self.render_data = re.sub(middle_regex, lambda x : ('<' + data_name + '>' + middle_data_pass + '</' + data_name + '>'), self.render_data, 1)
+
+            middle_count_all -= 1
+
+        self.render_data = re.sub(r'<temp_(?P<in>(?:slash)_(?:[0-9]+))>', '<\g<in>>', self.render_data)
+
+    def do_render_hr(self):
+        hr_regex = r'\n-{4,9}\n'
+        hr_count_max = len(re.findall(hr_regex, self.render_data)) * 3
+        while 1:
+            hr_data = re.search(hr_regex, self.render_data)
+            if hr_count_max < 0:
+                break
+            elif not hr_data:
+                break
+            else:
+                self.render_data = re.sub(hr_regex, '\n<front_br><hr><back_br>\n', self.render_data, 1)
+
+            hr_count_max -= 1
+
+    def do_render_list(self):        
+        quote_regex = r'((?:\n&gt; *[^\n]*)+)\n'
+        quote_count = 0
+        quote_count_max = len(re.findall(quote_regex, self.render_data)) * 10
+        while 1:
+            quote_data = re.search(quote_regex, self.render_data)
+            if quote_count_max < 0:
+                break
+            elif not quote_data:
+                break
+            else:
+                quote_data_org = quote_data.group(0)
+                
+                quote_data = quote_data.group(1)
+                quote_data = re.sub(r'\n&gt; *(?P<in>[^\n]*)', '\g<in>\n', quote_data)
+                quote_data = re.sub(r'\n$', '', quote_data)
+                quote_data = self.get_tool_data_revert(quote_data)
+                quote_data = html.unescape(quote_data)
+
+                self.data_include += [[self.doc_include + 'opennamu_quote_' + str(quote_count), self.doc_name, quote_data, '']]
+
+                data_name = self.get_tool_data_storage('<div id="' + self.doc_include + 'opennamu_quote_' + str(quote_count) + '"></div>', '', quote_data_org)
+
+                self.render_data = re.sub(quote_regex, lambda x : ('\n<front_br><blockquote><back_br>\n<' + data_name + '></' + data_name + '><front_br></blockquote><back_br>\n'), self.render_data, 1)
+
+            quote_count_max -= 1
+            quote_count += 1
+
+        def do_render_list_sub(match):
+            list_data = match.group(2)
+            list_len = len(match.group(1))
+            if list_len == 0:
+                list_len = 1
+
+            list_style = {
+                1 : 'list-style: unset;',
+                2 : 'list-style: circle;',
+                3 : 'list-style: square;',
+            }
+            list_style_data = 'list-style: square;'
+            if list_len in list_style:
+                list_style_data = list_style[list_len]
+
+            return '<li style="margin-left: ' + str(list_len * 20) + 'px;' + list_style_data + '">' + list_data + '</li>'
+
+        list_regex = r'((?:\n *\* ?[^\n]*)+)\n'
+        list_count_max = len(re.findall(list_regex, self.render_data)) * 3
+        while 1:
+            list_data = re.search(list_regex, self.render_data)
+            if list_count_max < 0:
+                break
+            elif not list_data:
+                break
+            else:
+                list_data = list_data.group(1)
+                list_sub_regex = r'\n( *)\* ?([^\n]*)'
+
+                list_data = re.sub(list_sub_regex, do_render_list_sub, list_data)
+
+                self.render_data = re.sub(list_regex, lambda x : ('\n<front_br><ul class="opennamu_ul">' + list_data + '</ul><back_br>\n'), self.render_data, 1)
+
+            list_count_max -= 1
+
+    def do_render_remark(self):
+        self.render_data = re.sub(r'\n##[^\n]+', '\n<front_br>', self.render_data)
 
 
     def do_render_last(self):
     def do_render_last(self):
+        # add category
+        if self.doc_include == '':
+            if self.data_category != '':
+                data_name = self.get_tool_data_storage(self.data_category, '</div>', '')
+
+                if ip_or_user(self.ip) == 0:
+                    self.curs.execute(db_change('select data from user_set where name = "main_css_category_set" and id = ?'), [self.ip])
+                    db_data = self.curs.fetchall()
+                    category_set_data = db_data[0][0] if db_data else 'normal'
+                else:
+                    category_set_data = self.flask_session['main_css_category_set'] if 'main_css_category_set' in self.flask_session else 'normal'
+
+                if category_set_data == 'normal':
+                    if re.search(r'<footnote_category>', self.render_data):
+                        self.render_data = re.sub(r'<footnote_category>', '<hr><' + data_name + '></' + data_name + '>', self.render_data, 1)
+                    else:
+                        self.render_data += '<hr><' + data_name + '></' + data_name + '>'
+                else:
+                    self.render_data = re.sub(r'<footnote_category>', '', self.render_data, 1)
+                    self.render_data = '<' + data_name + '></' + data_name + '><hr class="main_hr">' + self.render_data
+            else:
+                self.render_data = re.sub(r'<footnote_category>', '', self.render_data, 1)
+        else:
+            self.render_data = re.sub(r'<footnote_category>', '', self.render_data, 1)
+
         # remove front_br and back_br
         # remove front_br and back_br
-        self.render_data = re.sub(
-            r'\n<front_br>',
-            '',
-            self.render_data
-        )
-        self.render_data = re.sub(
-            r'<back_br>\n',
-            '',
-            self.render_data
-        )
+        self.render_data = re.sub(r'\n?<front_br>', '', self.render_data)
+        self.render_data = re.sub(r'<back_br>\n?', '', self.render_data)
         
         
         # \n to <br>
         # \n to <br>
-        self.render_data = re.sub(
-            r'\n',
-            '<br>',
-            self.render_data
-        )
+        self.render_data = re.sub(r'\n', '<br>', self.render_data)
 
 
-    def __call__(self):
-        self.render_data = html.escape(self.doc_data)
+        # <render_n> restore
+        self.render_data = self.get_tool_data_restore(self.render_data)
+
+        # a fix
+        self.temp_a_link_count = 0
+        def do_render_last_a_link(match):
+            data = match.group(1)
+            if data == '</a>':
+                if self.temp_a_link_count == 0:
+                    return ''
+                elif self.temp_a_link_count > 1:
+                    self.temp_a_link_count -= 1
+                    
+                    return ''
+                else:
+                    self.temp_a_link_count -= 1
+                    
+                    return match.group(0)
+            else:
+                if self.temp_a_link_count > 0:
+                    self.temp_a_link_count += 1
+                    
+                    return ''
+                else:
+                    self.temp_a_link_count += 1
+                    
+                    return match.group(0)
+            
+        self.render_data = re.sub(r'(<a(?: [^<>]*)?>|<\/a>)', do_render_last_a_link, self.render_data)
         
         
-        self.render_data_js = ''
+        # add toc
+        def do_render_last_toc(match):
+            data = match.group(1)
+
+            data = re.sub(r'<[^<>]*>', '', data)
+
+            heading_regex = r'<h([1-6])>'
+            heading_data = re.search(heading_regex, self.render_data)
+            if heading_data:
+                heading_data = heading_data.group(1)
+                self.render_data = re.sub(heading_regex, lambda x : ('<h' + heading_data + ' id="' + data + '">'), self.render_data, 1)
+            
+            return data
+
+        if self.data_toc != '':
+            self.render_data += '</div>'
+            toc_search_regex = r'<toc_data>((?:(?!<toc_data>|<\/toc_data>).)*)<\/toc_data>'
+
+            toc_data_on = 0
+
+            toc_data = re.search(toc_search_regex, self.render_data)
+            toc_data = toc_data.group(1)
+            self.data_toc = toc_data
+            self.data_toc = re.sub(r'<toc_inside>((?:(?!<toc_inside>|<\/toc_inside>).)*)<\/toc_inside>', do_render_last_toc, self.data_toc)
+
+            if ip_or_user(self.ip) == 0:
+                self.curs.execute(db_change('select data from user_set where name = "main_css_toc_set" and id = ?'), [self.ip])
+                db_data = self.curs.fetchall()
+                toc_set_data = db_data[0][0] if db_data else 'normal'
+            else:
+                toc_set_data = self.flask_session['main_css_toc_set'] if 'main_css_toc_set' in self.flask_session else 'normal'
+
+            self.render_data = re.sub(toc_search_regex, '', self.render_data)
+            if toc_set_data != 'off':
+                if re.search(r'<toc_need_part>', self.render_data):
+                    toc_data_on = 1
+
+                self.render_data = re.sub(r'<toc_need_part>', lambda x : (self.data_toc), self.render_data, 20)
+                self.render_data = re.sub(r'<toc_need_part>', '', self.render_data)
+            else:
+                self.render_data = re.sub(r'<toc_need_part>', '', self.render_data)
 
 
-        self.do_render_text()
+            if  self.doc_include != '' or \
+                re.search(r'<toc_no_auto>', self.render_data) or \
+                toc_set_data != 'normal' or \
+                toc_data_on == 1:
+                self.render_data = re.sub(r'<toc_no_auto>', '', self.render_data)
+            else:
+                self.render_data = re.sub(r'(?P<in><h[1-6] id="[^"]*">)', '<br>' + self.data_toc + '\g<in>', self.render_data, 1)
+        else:
+            self.render_data = re.sub(r'<toc_need_part>', '', self.render_data)
+            self.render_data = re.sub(r'<toc_no_auto>', '', self.render_data)
+
+        def do_render_last_footnote(match):
+            match = match.group(1)
+
+            find_regex = re.compile('<footnote_title target="' + match + '">((?:(?!<footnote_title|<\/footnote_title>).)*)<\/footnote_title>')
+            find_data = re.search(find_regex, self.render_data)
+            if find_data:
+                find_data = find_data.group(1)
+                find_data = re.sub(r'<[^<>]*>', '', find_data)
+            else:
+                find_data = ''
+
+            return '<a title="' + find_data + '"'
+
+        self.render_data = re.sub(r'<a fn_target="([^"]+)"', do_render_last_footnote, self.render_data)
+
+        self.render_data = '<div class="opennamu_render_complete">' + self.render_data + '</div>'
+
+    def __call__(self):
+        self.do_render_remark()
+        self.do_render_include_default()
+        self.do_render_slash()
+        self.do_render_redirect()
+        if self.data_redirect == 0:
+            self.do_render_middle()
+            self.do_render_include()
+            self.do_render_math()
+            self.do_render_table()
+            self.do_render_list()
+            self.do_render_macro()
+            self.do_render_link()
+            self.do_redner_footnote()
+            self.do_render_text()
+            self.do_render_hr()
+            self.do_render_heading()
+            
         self.do_render_last()
         self.do_render_last()
-        
+
+        # print(self.data_temp_storage)
+
         return [
         return [
-            self.render_data, # HTML
-            self.render_data_js, # JS
-            [] # Other
+            self.render_data, # html
+            self.render_data_js, # js
+            {
+                'backlink' : self.data_backlink, # backlink
+                'include' : self.data_include # include data
+            } # other
         ]
         ]

+ 14 - 0
route/tool/func_tool.py

@@ -43,6 +43,20 @@ def ip_check(d_type = 0):
 
 
     return ip
     return ip
 
 
+def ip_or_user(data = ''):
+    # without_DB
+
+    # 1 == ip
+    # 0 == reg
+    
+    if data == '':
+        data = ip_check()
+
+    if re.search(r'(\.|:)', data):
+        return 1
+    else:
+        return 0
+
 def url_pas(data):
 def url_pas(data):
     return urllib.parse.quote(data).replace('/','%2F')
     return urllib.parse.quote(data).replace('/','%2F')
 
 

+ 138 - 60
route/topic.py

@@ -1,34 +1,30 @@
 from .tool.func import *
 from .tool.func import *
 
 
-def topic(topic_num = 0):
+def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
         topic_num = str(topic_num)
         topic_num = str(topic_num)
 
 
-        if flask.request.method == 'POST':
+        topic_acl = acl_check('', 'topic', topic_num)
+        topic_view_acl = acl_check('', 'topic_view', topic_num)
+        if topic_view_acl == 1:
+            return re_error('/ban')
+
+        if flask.request.method == 'POST' and do_type == '':
             name = flask.request.form.get('topic', 'Test')
             name = flask.request.form.get('topic', 'Test')
             sub = flask.request.form.get('title', 'Test')
             sub = flask.request.form.get('title', 'Test')
             
             
+            if do_title_length_check(name) == 1:
+                return re_error('/error/38')
+            
+            if do_title_length_check(sub, 'topic') == 1:
+                return re_error('/error/38')
+            
             if topic_num == '0':
             if topic_num == '0':
                 curs.execute(db_change("select code from topic order by code + 0 desc limit 1"))
                 curs.execute(db_change("select code from topic order by code + 0 desc limit 1"))
                 t_data = curs.fetchall()
                 t_data = curs.fetchall()
                 topic_num = str(int(t_data[0][0]) + 1) if t_data else '1'
                 topic_num = str(int(t_data[0][0]) + 1) if t_data else '1'
-        else:
-            if topic_num == '0':
-                name = load_lang('make_new_topic')
-                sub = load_lang('make_new_topic')
-            else:
-                curs.execute(db_change("select title, sub from rd where code = ?"), [topic_num])
-                name = curs.fetchall()
-                if name:
-                    sub = name[0][1]
-                    name = name[0][0]
-                else:
-                    return redirect('/')
-
-        ban = acl_check(name, 'topic', topic_num)
-
-        if flask.request.method == 'POST':
+            
             if flask.request.form.get('content', 'Test') == '':
             if flask.request.form.get('content', 'Test') == '':
                 return redirect('/thread/' + topic_num)
                 return redirect('/thread/' + topic_num)
 
 
@@ -40,7 +36,7 @@ def topic(topic_num = 0):
             ip = ip_check()
             ip = ip_check()
             today = get_time()
             today = get_time()
 
 
-            if ban == 1:
+            if topic_acl == 1:
                 return re_error('/ban')
                 return re_error('/ban')
 
 
             curs.execute(db_change("select id from topic where code = ? order by id + 0 desc limit 1"), [topic_num])
             curs.execute(db_change("select id from topic where code = ? order by id + 0 desc limit 1"), [topic_num])
@@ -68,78 +64,160 @@ def topic(topic_num = 0):
                         y_check = 1
                         y_check = 1
 
 
                 if y_check == 1:
                 if y_check == 1:
-                    add_alarm(match, ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
+                    add_alarm(match, ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + html.escape(name) + ' | ' + html.escape(sub) + ' | #' + num + '</a>')
 
 
             cate_re = re.compile(r'\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
             cate_re = re.compile(r'\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
             data = cate_re.sub('[br]', flask.request.form.get('content', 'Test').replace('\r', ''))
             data = cate_re.sub('[br]', flask.request.form.get('content', 'Test').replace('\r', ''))
 
 
-            for rd_data in re.findall(r"(?: |\n|^)(#(?:[0-9]+))(?: |\n|$)", data):
-                curs.execute(db_change("select ip from topic where code = ? and id = ?"), [topic_num, rd_data])
-                ip_data = curs.fetchall()
-                if ip_data and ip_or_user(ip_data[0][0]) == 0:
-                    add_alarm(ip_data[0][0], ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
-
-            for rd_data in re.findall(r"(?: |\n|^)@((?:[^ ]+))(?: |\n|$)", data):
-                curs.execute(db_change("select ip from history where ip = ? limit 1"), [rd_data])
-                ip_data = curs.fetchall()
-                if not ip_data:
-                    curs.execute(db_change("select ip from topic where ip = ? limit 1"), [rd_data])
+            call_thread_regex = r"( |\n|^)(?:#([0-9]+))( |\n|$)"
+            call_thread_count = len(re.findall(call_thread_regex, data)) * 3
+            while 1:
+                rd_data = re.search(call_thread_regex, data)
+                if call_thread_count < 0:
+                    break
+                elif not rd_data:
+                    break
+                else:
+                    rd_data = rd_data.groups()
+
+                    curs.execute(db_change("select ip from topic where code = ? and id = ?"), [topic_num, rd_data[1]])
                     ip_data = curs.fetchall()
                     ip_data = curs.fetchall()
+                    if ip_data and ip_or_user(ip_data[0][0]) == 0 and ip != ip_data[0][0]:
+                        add_alarm(ip_data[0][0], ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + html.escape(name) + ' | ' + html.escape(sub) + ' | #' + num + '</a>')
+
+                    data = re.sub(call_thread_regex, rd_data[0] + '<topic_a>#' + rd_data[1] + '</topic_a>' + rd_data[2], data, 1)
 
 
-                if ip_data and ip_or_user(ip_data[0][0]) == 0:
-                    add_alarm(ip_data[0][0], ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>')
+                call_thread_count -= 1
 
 
-            data = re.sub(r"( |\n|^)(#(?:[0-9]+))( |\n|$)", '\g<1><topic_a>\g<2></topic_a>\g<3>', data)
-            data = re.sub(r"( |\n|^)(@(?:[^ ]+))( |\n|$)", '\g<1><topic_call>\g<2></topic_call>\g<3>', data)
+            call_user_regex = r"( |\n|^)(?:@([^ ]+))( |\n|$)"
+            call_user_count = len(re.findall(call_user_regex, data)) * 3
+            while 1:
+                rd_data = re.search(call_user_regex, data)
+                if call_user_count < 0:
+                    break
+                elif not rd_data:
+                    break
+                else:
+                    rd_data = rd_data.groups()
+
+                    curs.execute(db_change("select ip from history where ip = ? limit 1"), [rd_data[1]])
+                    ip_data = curs.fetchall()
+                    if not ip_data:
+                        curs.execute(db_change("select ip from topic where ip = ? limit 1"), [rd_data[1]])
+                        ip_data = curs.fetchall()
 
 
-            rd_plus(topic_num, today, name, sub)
-            curs.execute(db_change("insert into topic (id, data, date, ip, code) values (?, ?, ?, ?, ?)"), [
-                num,
+                    if ip_data and ip_or_user(ip_data[0][0]) == 0 and ip != ip_data[0][0]:
+                        add_alarm(ip_data[0][0], ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + html.escape(name) + ' | ' + html.escape(sub) + ' | #' + num + '</a>')
+
+                    data = re.sub(call_user_regex, rd_data[0] + '<topic_call>@' + rd_data[1] + '</topic_call>' + rd_data[2], data, 1)
+
+                call_user_count -= 1
+
+            do_add_thread(
+                topic_num,
                 data,
                 data,
-                today,
-                ip,
-                topic_num
-            ])
+                '',
+                num
+            )
+            do_reload_recent_thread(
+                topic_num, 
+                today, 
+                name, 
+                sub
+            )
+
             conn.commit()
             conn.commit()
 
 
             return redirect('/thread/' + topic_num + '#' + num)
             return redirect('/thread/' + topic_num + '#' + num)
         else:
         else:
-            display = 'display: none;' if ban == 1 else ''
-            data_input_topic_name = ''
+            thread_data = ''
+            thread_data_preview = ''
+
             if topic_num == '0':
             if topic_num == '0':
-                data_input_topic_name = '' + \
-                    '<input placeholder="' + load_lang('discussion_name') + '" name="title">' + \
-                    '<hr class="main_hr">' + \
-                    '<input placeholder="' + load_lang('document_name') + '" name="topic">' + \
-                    '<hr class="main_hr">' + \
-                ''
+                name = load_lang('make_new_topic')
+                sub = load_lang('make_new_topic')
+
+                if do_type == 'preview':
+                    name_value = flask.request.form.get('topic', '')
+                    sub_value = flask.request.form.get('title', '')
+                else:
+                    name_value = doc_name
+                    sub_value = ''
+            else:
+                curs.execute(db_change("select title, sub from rd where code = ?"), [topic_num])
+                name = curs.fetchall()
+                if name:
+                    sub = name[0][1]
+                    name = name[0][0]
+
+                    name_value = name
+                    sub_value = sub
+                else:
+                    return redirect('/')
+
+            if do_type == 'preview':
+                thread_data = flask.request.form.get('content', 'Test')
+                thread_data = thread_data.replace('\r', '')
+
+                thread_data_preview = render_set(
+                    doc_name = '', 
+                    doc_data = thread_data,
+                    data_in = ''
+                )
+
+            acl_display = 'display: none;' if topic_acl == 1 else ''
+            name_display = 'display: none;' if topic_num != '0' else ''
                 
                 
             curs.execute(db_change('select data from other where name = "topic_text"'))
             curs.execute(db_change('select data from other where name = "topic_text"'))
             sql_d = curs.fetchall()
             sql_d = curs.fetchall()
             topic_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('content')
             topic_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('content')
 
 
+            shortcut = '<div class="opennamu_thread_shortcut" id="thread_shortcut">'
+            curs.execute(db_change(
+                "select id from topic where code = ? order by id + 0 asc"
+            ), [topic_num])
+            db_data = curs.fetchall()
+            for for_a in db_data:
+                shortcut += '<a href="#' + for_a[0] + '">#' + for_a[0] + '</a> '
+            
+            shortcut += '</div>'
+
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('discussion') + ')', 0])],
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('discussion') + ')', 0])],
                 data = '''
                 data = '''
+                    ''' + shortcut + '''
                     <h2 id="topic_top_title">''' + html.escape(sub) + '''</h2>
                     <h2 id="topic_top_title">''' + html.escape(sub) + '''</h2>
+                    
                     <div id="top_topic"></div>
                     <div id="top_topic"></div>
                     <div id="main_topic"></div>
                     <div id="main_topic"></div>
                     <div id="plus_topic"></div>
                     <div id="plus_topic"></div>
-                    <script>opennamu_do_thread_make("''' + topic_num + '''");</script>
+                    
                     <a href="/thread/''' + topic_num + '/tool">(' + load_lang('topic_tool') + ''')</a>
                     <a href="/thread/''' + topic_num + '/tool">(' + load_lang('topic_tool') + ''')</a>
                     <hr class="main_hr">
                     <hr class="main_hr">
-                    <form style="''' + display + '''" method="post">
-                        ''' + data_input_topic_name + '''
-                        <textarea id="textarea_edit_view" class="opennamu_comment_textarea" placeholder="''' + topic_text + '''" name="content"></textarea>
+                    
+                    <form style="''' + acl_display + '''" method="post">
+                        <div style="''' + name_display + '''">
+                            <input placeholder="''' + load_lang('document_name') + '''" name="topic" value="''' + html.escape(name_value) + '''">
+                            <hr class="main_hr">
+                            <input placeholder="''' + load_lang('discussion_name') + '''" name="title" value="''' + html.escape(sub_value) + '''">
+                            <hr class="main_hr">
+                        </div>
+                        
+                        <div>''' + edit_button('opennamu_edit_textarea') + '''</div>
+
+                        <textarea id="opennamu_edit_textarea" class="opennamu_textarea_200" placeholder="''' + topic_text + '''" name="content">''' + html.escape(thread_data) + '''</textarea>
                         <hr class="main_hr">
                         <hr class="main_hr">
-                        ''' + captcha_get() + (ip_warning() if display == '' else '') + '''
-                        <input style="display: none;" name="topic" value="''' + name + '''">
-                        <input style="display: none;" name="title" value="''' + sub + '''">
-                        <button id="save" type="submit">''' + load_lang('send') + '''</button>
-                        <button id="preview" type="button" onclick="load_preview(\'\')">''' + load_lang('preview') + '''</button>
+                        
+                        ''' + captcha_get() + ip_warning() + '''
+                        
+                        <button id="opennamu_save_button" formaction="/thread/''' + topic_num + '''" type="submit">''' + load_lang('send') + '''</button>
+                        <button id="opennamu_preview_button" formaction="/thread_preview/''' + topic_num + '''#opennamu_edit_textarea" type="submit">''' + load_lang('preview') + '''</button>
                     </form>
                     </form>
                     <hr class="main_hr">
                     <hr class="main_hr">
-                    <div id="see_preview"></div>
+                    
+                    <div id="opennamu_preview_area">''' + thread_data_preview + '''</div>
+                    
+                    <!-- JS : opennamu_do_thread_make -->
                 ''',
                 ''',
                 menu = [['topic/' + url_pas(name), load_lang('list')]]
                 menu = [['topic/' + url_pas(name), load_lang('list')]]
             ))
             ))

+ 6 - 3
route/topic_comment_blind.py

@@ -3,10 +3,10 @@ from .tool.func import *
 def topic_comment_blind(topic_num = 1, num = 1):
 def topic_comment_blind(topic_num = 1, num = 1):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
-
+        
         topic_num = str(topic_num)
         topic_num = str(topic_num)
         num = str(num)
         num = str(num)
-
+        
         if admin_check(3, 'blind (code ' + topic_num + '#' + num + ')') != 1:
         if admin_check(3, 'blind (code ' + topic_num + '#' + num + ')') != 1:
             return re_error('/error/3')
             return re_error('/error/3')
 
 
@@ -18,7 +18,10 @@ def topic_comment_blind(topic_num = 1, num = 1):
             else:
             else:
                 curs.execute(db_change("update topic set block = 'O' where code = ? and id = ?"), [topic_num, num])
                 curs.execute(db_change("update topic set block = 'O' where code = ? and id = ?"), [topic_num, num])
 
 
-            rd_plus(topic_num, get_time())
+            do_reload_recent_thread(
+                topic_num, 
+                get_time()
+            )
 
 
             conn.commit()
             conn.commit()
 
 

+ 7 - 3
route/topic_comment_notice.py

@@ -3,10 +3,10 @@ from .tool.func import *
 def topic_comment_notice(topic_num = 1, num = 1):
 def topic_comment_notice(topic_num = 1, num = 1):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
-
+        
         topic_num = str(topic_num)
         topic_num = str(topic_num)
         num = str(num)
         num = str(num)
-
+        
         if admin_check(3, 'notice (code ' + topic_num + '#' + num + ')') != 1:
         if admin_check(3, 'notice (code ' + topic_num + '#' + num + ')') != 1:
             return re_error('/error/3')
             return re_error('/error/3')
 
 
@@ -20,7 +20,11 @@ def topic_comment_notice(topic_num = 1, num = 1):
                 else:
                 else:
                     curs.execute(db_change("update topic set top = 'O' where code = ? and id = ?"), [topic_num, num])
                     curs.execute(db_change("update topic set top = 'O' where code = ? and id = ?"), [topic_num, num])
 
 
-            rd_plus(topic_num, get_time())
+            do_reload_recent_thread(
+                topic_num, 
+                get_time()
+            )
+            
             conn.commit()
             conn.commit()
 
 
         return redirect('/thread/' + topic_num + '#' + num)
         return redirect('/thread/' + topic_num + '#' + num)

+ 8 - 5
route/topic_comment_tool.py

@@ -3,9 +3,12 @@ from .tool.func import *
 def topic_comment_tool(topic_num = 1, num = 1):
 def topic_comment_tool(topic_num = 1, num = 1):
     with get_db_connect() as conn:
     with get_db_connect() as conn:
         curs = conn.cursor()
         curs = conn.cursor()
-
+        
         num = str(num)
         num = str(num)
         topic_num = str(topic_num)
         topic_num = str(topic_num)
+        
+        if acl_check('', 'topic_view', topic_num) == 1:
+            return re_error('/ban')
 
 
         curs.execute(db_change("select block, ip, date from topic where code = ? and id = ?"), [topic_num, num])
         curs.execute(db_change("select block, ip, date from topic where code = ? and id = ?"), [topic_num, num])
         data = curs.fetchall()
         data = curs.fetchall()
@@ -14,12 +17,12 @@ def topic_comment_tool(topic_num = 1, num = 1):
 
 
         ban = '''
         ban = '''
             <h2>''' + load_lang('state') + '''</h2>
             <h2>''' + load_lang('state') + '''</h2>
-            <ul class="inside_ul">
+            <ul class="opennamu_ul">
                 <li>''' + load_lang('writer') + ' : ''' + ip_pas(data[0][1]) + '''</li>
                 <li>''' + load_lang('writer') + ' : ''' + ip_pas(data[0][1]) + '''</li>
                 <li>''' + load_lang('time') + ' : ' + data[0][2] + '''</li>
                 <li>''' + load_lang('time') + ' : ' + data[0][2] + '''</li>
             </ul>
             </ul>
             <h2>''' + load_lang('other_tool') + '''</h2>
             <h2>''' + load_lang('other_tool') + '''</h2>
-            <ul class="inside_ul">
+            <ul class="opennamu_ul">
                 <li>
                 <li>
                     <a href="/thread/''' + topic_num + '/comment/' + num + '''/raw">''' + load_lang('raw') + '''</a>
                     <a href="/thread/''' + topic_num + '/comment/' + num + '''/raw">''' + load_lang('raw') + '''</a>
                 </li>
                 </li>
@@ -39,9 +42,9 @@ def topic_comment_tool(topic_num = 1, num = 1):
 
 
             ban += '''
             ban += '''
                 <h2>''' + load_lang('admin_tool') + '''</h2>
                 <h2>''' + load_lang('admin_tool') + '''</h2>
-                <ul class="inside_ul">
+                <ul class="opennamu_ul">
                     <li>
                     <li>
-                        <a href="/ban/''' + url_pas(data[0][1]) + '''">
+                        <a href="/auth/give/ban/''' + url_pas(data[0][1]) + '''">
                             ''' + (load_lang('release') if user_ban_d else load_lang('ban')) + '''
                             ''' + (load_lang('release') if user_ban_d else load_lang('ban')) + '''
                         </a>
                         </a>
                     </li>
                     </li>

+ 5 - 10
route/topic_list.py

@@ -26,7 +26,7 @@ def topic_list(name = 'Test'):
                 <a href="/topic/''' + url_pas(name) + '?tool=close">(' + load_lang('closed_discussion') + ''')</a>
                 <a href="/topic/''' + url_pas(name) + '?tool=close">(' + load_lang('closed_discussion') + ''')</a>
                 <a href="/topic/''' + url_pas(name) + '?tool=agree">(' + load_lang('agreed_discussion') + ''')</a>
                 <a href="/topic/''' + url_pas(name) + '?tool=agree">(' + load_lang('agreed_discussion') + ''')</a>
                 <hr class="main_hr">
                 <hr class="main_hr">
-                <a href="/thread/0">(''' + load_lang('make_new_topic') + ''')</a>
+                <a href="/thread/0/''' + url_pas(name) + '''">(''' + load_lang('make_new_topic') + ''')</a>
             '''
             '''
 
 
             curs.execute(db_change("select code, sub from rd where title = ? and stop != 'O' order by date desc"), [name])
             curs.execute(db_change("select code, sub from rd where title = ? and stop != 'O' order by date desc"), [name])
@@ -36,15 +36,10 @@ def topic_list(name = 'Test'):
             t_data = curs.fetchall()
             t_data = curs.fetchall()
 
 
             div += '''
             div += '''
-                <h2><a href="/thread/''' + data[0] + '">' + html.escape(data[0] + '. ' + data[1]) + '''</a></h2>
-                <div id="topic_pre_''' + data[0] + '''"></div>
-                <div id="topic_back_pre_''' + data[0] + '''"></div>
-                <script>
-                    opennamu_do_thread_make(''' + data[0] + ', "list", "/normal/1", "topic_pre_' + data[0] + '''");
-                    if(''' + t_data[0][0] + ''' !== 1) {
-                        opennamu_do_thread_make(''' + data[0] + ', "list", "/normal/' + t_data[0][0] + '", "topic_back_pre_' + data[0] + '''");
-                    }
-                </script>
+                <h2><a href="/thread/''' + data[0] + '">' + data[0] + '. ' + html.escape(data[1]) + '''</a></h2>
+                <div class="topic_pre" id="opennamu_thread_''' + data[0] + '''"></div>
+                <div class="topic_back_pre" id="opennamu_thread_back_''' + data[0] + '''"></div>
+                <!-- JS : opennamu_do_thread_make -->
             '''
             '''
 
 
         if div == '':
         if div == '':

+ 31 - 10
route/topic_tool.py

@@ -11,37 +11,58 @@ def topic_tool(topic_num = 1):
         close_data = curs.fetchall()
         close_data = curs.fetchall()
         if close_data:
         if close_data:
             if close_data[0][0] == 'S':
             if close_data[0][0] == 'S':
-                t_state = 'Stop'
+                t_state = load_lang('topic_stop')
             elif close_data[0][0] == 'O':
             elif close_data[0][0] == 'O':
-                t_state = 'Close'
+                t_state = load_lang('topic_close')
             else:
             else:
-                t_state = 'Normal'
+                t_state = load_lang('topic_normal')
+                
+            if close_data[0][1] == 'O':
+                t_state += ' (' + load_lang('topic_agree') + ')'
         else:
         else:
-            t_state = 'Normal'
+            t_state = load_lang('topic_normal')
 
 
         curs.execute(db_change("select acl from rd where code = ?"), [topic_num])
         curs.execute(db_change("select acl from rd where code = ?"), [topic_num])
-        topic_acl_get = curs.fetchall()
+        db_data = curs.fetchall()
+        if db_data:
+            if db_data[0][0] == '':
+                acl_state = 'normal'
+            else:
+                acl_state = db_data[0][0]
+        else:
+            acl_state = 'normal'
+        
+        curs.execute(db_change("select set_data from topic_set where thread_code = ? and set_name = 'thread_view_acl'"), [topic_num])
+        db_data = curs.fetchall()
+        if db_data:
+            if db_data[0][0] == '':
+                acl_view_state = 'normal'
+            else:
+                acl_view_state = db_data[0][0]
+        else:
+            acl_view_state = 'normal'
 
 
         if admin_check(3) == 1:
         if admin_check(3) == 1:
             data = '''
             data = '''
                 <h2>''' + load_lang('admin_tool') + '''</h2>
                 <h2>''' + load_lang('admin_tool') + '''</h2>
-                <ul class="inside_ul">
+                <ul class="opennamu_ul">
                     <li><a href="/thread/''' + topic_num + '/setting">' + load_lang('topic_setting') + '''</a></li>
                     <li><a href="/thread/''' + topic_num + '/setting">' + load_lang('topic_setting') + '''</a></li>
                     <li><a href="/thread/''' + topic_num + '/acl">' + load_lang('topic_acl_setting') + '''</a></li>
                     <li><a href="/thread/''' + topic_num + '/acl">' + load_lang('topic_acl_setting') + '''</a></li>
                 </ul>
                 </ul>
             '''
             '''
         data += '''
         data += '''
             <h2>''' + load_lang('tool') + '''</h2>
             <h2>''' + load_lang('tool') + '''</h2>
-            <ul class="inside_ul">
-                <li>''' + load_lang('topic_state') + ''' : ''' + t_state + '' + (' (Agree)' if close_data and (close_data[0][1] == 'O') else '') + '''</li>
-                <li>''' + load_lang('topic_acl') + ''' : <a href="/acl/TEST#exp">''' + ('Normal' if not topic_acl_get or (topic_acl_get[0][0] == '') else topic_acl_get[0][0]) + '''</a></li>
+            <ul class="opennamu_ul">
+                <li>''' + load_lang('topic_state') + ''' : ''' + t_state + '''</li>
+                <li>''' + load_lang('topic_acl') + ''' : <a href="/acl/TEST#exp">''' + acl_state + '''</a></li>
+                <li>''' + load_lang('topic_view_acl') + ''' : <a href="/acl/TEST#exp">''' + acl_view_state + '''</a></li>
             </ul>
             </ul>
         '''
         '''
 
 
         if admin_check(None) == 1:
         if admin_check(None) == 1:
             data += '''
             data += '''
                 <h2>''' + load_lang('owner') + '''</h2>
                 <h2>''' + load_lang('owner') + '''</h2>
-                <ul class="inside_ul">
+                <ul class="opennamu_ul">
                     <li>
                     <li>
                         <a href="/thread/''' + topic_num + '''/delete">
                         <a href="/thread/''' + topic_num + '''/delete">
                             ''' + load_lang('topic_delete') + '''
                             ''' + load_lang('topic_delete') + '''

+ 42 - 13
route/topic_tool_acl.py

@@ -23,26 +23,41 @@ def topic_tool_acl(topic_num = 1):
             topic_check = curs.fetchall()
             topic_check = curs.fetchall()
             if topic_check:
             if topic_check:
                 acl_data = flask.request.form.get('acl', '')
                 acl_data = flask.request.form.get('acl', '')
+                acl_data_view = flask.request.form.get('acl_view', '')
 
 
                 curs.execute(db_change("update rd set acl = ? where code = ?"), [
                 curs.execute(db_change("update rd set acl = ? where code = ?"), [
-                    acl_data,
-                    topic_num
-                ])
-
-                curs.execute(db_change("insert into topic (id, data, date, ip, top, code) values (?, ?, ?, ?, '1', ?)"), [
-                    str(int(topic_check[0][0]) + 1),
-                    'acl change ' + acl_data,
-                    time,
-                    ip,
+                    acl_data, 
                     topic_num
                     topic_num
                 ])
                 ])
+                
+                curs.execute(db_change("select set_data from topic_set where thread_code = ? and set_name = 'thread_view_acl'"), [topic_num])
+                db_data = curs.fetchall()
+                if db_data:
+                    curs.execute(db_change("update topic_set set set_data = ? where thread_code = ?"), [
+                        acl_data_view,
+                        topic_num
+                    ])
+                else:
+                    curs.execute(db_change("insert into topic_set (thread_code, set_name, set_id, set_data) values (?, 'thread_view_acl', '1', ?)"), [
+                        topic_num,
+                        acl_data_view
+                    ])
 
 
-                rd_plus(topic_num, time)
+                do_add_thread(
+                    topic_num,
+                    load_lang('acl_thread_change') + ' : ' + acl_data,
+                    '1'
+                )
+                do_reload_recent_thread(
+                    topic_num, 
+                    time
+                )
 
 
             return redirect('/thread/' + topic_num)
             return redirect('/thread/' + topic_num)
         else:
         else:
             acl_list = get_acl_list()
             acl_list = get_acl_list()
             acl_html_list = ''
             acl_html_list = ''
+            acl_html_list_view = ''
 
 
             curs.execute(db_change("select acl from rd where code = ?"), [topic_num])
             curs.execute(db_change("select acl from rd where code = ?"), [topic_num])
             topic_acl_get = curs.fetchall()
             topic_acl_get = curs.fetchall()
@@ -54,16 +69,30 @@ def topic_tool_acl(topic_num = 1):
 
 
                 acl_html_list += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
                 acl_html_list += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
 
 
+            curs.execute(db_change("select set_data from topic_set where thread_code = ? and set_name = 'thread_view_acl'"), [topic_num])
+            db_data = curs.fetchall()
+            for data_list in acl_list:
+                if db_data and db_data[0][0] == data_list:
+                    check = 'selected="selected"'
+                else:
+                    check = ''
+
+                acl_html_list_view += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
+
             return easy_minify(flask.render_template(skin_check(),
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('topic_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 imp = [load_lang('topic_acl_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                 data = '''
                     <form method="post">
                     <form method="post">
                         <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
                         <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
-                        <hr>
+                        <h2>''' + load_lang('thread_acl') + '''</h2>
                         <select name="acl">
                         <select name="acl">
-                        ''' + acl_html_list + '''
+                            ''' + acl_html_list + '''
+                        </select>
+                        <h2>''' + load_lang('view_acl') + ''' (''' + load_lang('beta') + ''')</h2>
+                        <select name="acl_view">
+                            ''' + acl_html_list_view + '''
                         </select>
                         </select>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <button type="submit">''' + load_lang('save') + '''</button>
                         <button type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     </form>
                 ''',
                 ''',

+ 9 - 9
route/topic_tool_change.py

@@ -31,15 +31,15 @@ def topic_tool_change(topic_num = 1):
                     topic_num
                     topic_num
                 ])
                 ])
 
 
-                curs.execute(db_change("insert into topic (id, data, date, ip, top, code) values (?, ?, ?, ?, '1', ?)"), [
-                    str(int(topic_check[0][0]) + 1),
-                    'change name to ' + sub_d + '(' + title_d + ')',
-                    time,
-                    ip,
-                    topic_num
-                ])
-
-                rd_plus(topic_num, time)
+                do_add_thread(
+                    topic_num,
+                    load_lang('topic_name_change') + ' : ' + sub_d + ' (' + title_d + ')',
+                    '1'
+                )
+                do_reload_recent_thread(
+                    topic_num, 
+                    time
+                )
 
 
             return redirect('/thread/' + topic_num)
             return redirect('/thread/' + topic_num)
         else:
         else:

Some files were not shown because too many files changed in this diff