Sfoglia il codice sorgente

Merge pull request #936 from 2du/master

st
잉여개발기 (SPDV) 6 anni fa
parent
commit
64c0b88824
71 ha cambiato i file con 1550 aggiunte e 1381 eliminazioni
  1. 34 37
      app.py
  2. 10 14
      emergency_tool.py
  3. 10 2
      language/en-US.json
  4. 1 1
      language/help_tool.py
  5. 14 6
      language/ko-KR.json
  6. 0 2
      requirements.txt
  7. 2 2
      route/api_skin_info.py
  8. 17 7
      route/api_topic_sub.py
  9. 1 4
      route/api_user_info.py
  10. 3 3
      route/api_w.py
  11. 74 55
      route/edit.py
  12. 18 0
      route/edit_backlink_reset.py
  13. 1 1
      route/edit_delete.py
  14. 2 2
      route/edit_many_delete.py
  15. 0 177
      route/edit_req.py
  16. 34 25
      route/func_upload.py
  17. 13 6
      route/give_acl.py
  18. 1 2
      route/give_history_add.py
  19. 1 1
      route/give_user_ban.py
  20. 1 1
      route/inter_wiki_del.py
  21. 1 1
      route/inter_wiki_plus.py
  22. 1 1
      route/list_acl.py
  23. 1 1
      route/list_block.py
  24. 1 1
      route/list_old_page.py
  25. 22 6
      route/list_user_topic.py
  26. 1 1
      route/login_need_email.py
  27. 1 1
      route/login_register.py
  28. 2 2
      route/main_file.py
  29. 1 1
      route/main_image_view.py
  30. 2 1
      route/main_manager.py
  31. 3 3
      route/main_views.py
  32. 34 28
      route/recent_changes.py
  33. 198 137
      route/setting.py
  34. 0 66
      route/setting_adsense.py
  35. 70 87
      route/tool/func.py
  36. 1 1
      route/tool/init.py
  37. 7 4
      route/tool/mark.py
  38. 73 0
      route/tool/set_mark/markdown.py
  39. 248 238
      route/tool/set_mark/namumark.py
  40. 0 10
      route/tool/set_mark/tool.py
  41. 26 9
      route/topic.py
  42. 1 1
      route/topic_close_list.py
  43. 1 0
      route/user_info.py
  44. 6 6
      route/view_diff_data.py
  45. 3 2
      route/view_raw.py
  46. 12 23
      route/view_read.py
  47. 27 15
      route/view_xref.py
  48. 36 7
      route/watch_list.py
  49. 17 9
      route/watch_list_name.py
  50. 4 4
      version.json
  51. 13 15
      views/main_css/css/main.css
  52. 102 0
      views/main_css/js/do_editor.js
  53. 0 18
      views/main_css/js/do_insert_data.js
  54. 0 10
      views/main_css/js/do_open_folding.js
  55. 0 13
      views/main_css/js/do_open_foot.js
  56. 0 15
      views/main_css/js/do_stop_exit.js
  57. 0 59
      views/main_css/js/do_upload_paste.js
  58. 136 37
      views/main_css/js/load_namumark.js
  59. 6 5
      views/main_css/js/load_preview.js
  60. 0 6
      views/main_css/js/load_raw_preview.js
  61. 201 131
      views/main_css/js/load_skin_set.js
  62. 26 0
      views/main_css/js/load_something.js
  63. 7 10
      views/main_css/js/load_topic.js
  64. 0 15
      views/main_css/js/load_user_info.js
  65. 0 16
      views/main_css/js/load_ver.js
  66. 1 1
      views/main_css/js/render_html.js
  67. 17 9
      views/marisa/css/main.css
  68. 1 1
      views/marisa/index.html
  69. 1 1
      views/marisa/info.json
  70. 1 3
      views/marisa/js/main.js
  71. 1 2
      views/marisa/js/skin_set.js

+ 34 - 37
app.py

@@ -2,7 +2,7 @@ import os
 import re
 
 for i_data in os.listdir("route"):
-    f_src = re.search("(.+)\.py$", i_data)
+    f_src = re.search(r"(.+)\.py$", i_data)
     if f_src:
         f_src = f_src.group(1)
 
@@ -54,7 +54,7 @@ while 1:
 
             all_src = []
             for i_data in os.listdir("."):
-                f_src = re.search("(.+)\.db$", i_data)
+                f_src = re.search(r"(.+)\.db$", i_data)
                 if f_src:
                     all_src += [f_src.group(1)]
 
@@ -190,7 +190,7 @@ if setup_tool != 0:
     create_data['alarm'] = ['name', 'data', 'date']
     create_data['ua_d'] = ['name', 'ip', 'ua', 'today', 'sub']
     create_data['filter'] = ['name', 'regex', 'sub']
-    create_data['scan'] = ['user', 'title']
+    create_data['scan'] = ['user', 'title', 'type']
     create_data['acl'] = ['title', 'decu', 'dis', 'view', 'why']
     create_data['inter'] = ['title', 'link', 'icon']
     create_data['html_filter'] = ['html', 'kind', 'plus']
@@ -225,9 +225,6 @@ app.config['JSON_AS_ASCII'] = False
 
 flask_reggie.Reggie(app)
 
-compress = flask_compress.Compress()
-compress.init_app(app)
-
 class EverythingConverter(werkzeug.routing.PathConverter):
     regex = '.*?'
 
@@ -247,6 +244,7 @@ if not os.path.exists(app_var['path_data_image']):
 if not os.path.exists('views'):
     os.makedirs('views')
 
+print('----')
 import route.tool.init as server_init
 
 dislay_set_key = ['Host', 'Port', 'Language', 'Markup', 'Encryption method']
@@ -277,17 +275,22 @@ if not rep_data:
 else:
     rep_key = rep_data[0][0]
 
-curs.execute(db_change('select data from other where name = "adsense"'))
-adsense_result = curs.fetchall()
-if not adsense_result:
-    curs.execute(db_change('insert into other (name, data) values ("adsense", "False")'))
-    curs.execute(db_change('insert into other (name, data) values ("adsense_code", "")'))
-
 if set_data['db_type'] == 'sqlite':
     def back_up():
         print('----')
+
+        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_' + set_data['db'] + '.db'
+        
         try:
-            shutil.copyfile(set_data['db'] + '.db', 'back_' + set_data['db'] + '.db')
+            shutil.copyfile(
+                set_data['db'] + '.db', 
+                back_up_where
+            )
 
             print('Back up : OK')
         except:
@@ -311,17 +314,15 @@ if set_data['db_type'] == 'sqlite':
     else:
         print('Back up state : Turn off')
 
-if set_data['db_type'] == 'mysql':
-    def mysql_dont_off():
-        try:
-            urllib.request.urlopen('http://localhost:' + server_set['port'] + '/')
-        except:
-            pass
-
-        threading.Timer(60 * 60 * 6, mysql_dont_off).start()
+def mysql_dont_off():
+    try:
+        urllib.request.urlopen('http://localhost:' + server_set['port'] + '/')
+    except:
+        pass
 
-    mysql_dont_off()
+    threading.Timer(60 * 60 * 6, mysql_dont_off).start()
 
+mysql_dont_off()
 
 curs.execute(db_change('select data from other where name = "count_all_title"'))
 if not curs.fetchall():
@@ -361,7 +362,7 @@ def inter_wiki_plus(tools = None, name = None):
 @app.route('/setting')
 @app.route('/setting/<int:num>', methods=['POST', 'GET'])
 def setting(num = 0):
-    return setting_2(conn, num)
+    return setting_2(conn, num, set_data['db_type'])
 
 @app.route('/not_close_topic')
 def list_not_close_topic():
@@ -419,10 +420,6 @@ def server_restart():
 def server_now_update():
     return server_now_update_2(conn, version_list['master']['r_ver'])
 
-@app.route('/adsense_setting', methods=['GET', 'POST'])
-def setting_adsense():
-    return setting_adsense_2(conn)
-
 @app.route('/xref/<everything:name>')
 def view_xref(name = None):
     return view_xref_2(conn, name)
@@ -466,9 +463,9 @@ def edit_revert(name = None):
 def edit(name = 'Test'):
     return edit_2(conn, name)
 
-@app.route('/edit_req/<everything:name>', methods=['POST', 'GET'])
-def edit_req(name = 'Test'):
-    return edit_req_2(conn, name)
+@app.route('/backlink_reset/<everything:name>')
+def edit_backlink_reset(name = 'Test'):
+    return edit_backlink_reset_2(conn, name)
 
 @app.route('/delete/<everything:name>', methods=['POST', 'GET'])
 def edit_delete(name = None):
@@ -601,7 +598,7 @@ def view_read(name = None):
     return view_read_2(conn, name)
 
 @app.route('/topic_record/<name>')
-def list_user_topic(name = None):
+def list_user_topic(name = 'test'):
     return list_user_topic_2(conn, name)
 
 @app.route('/recent_changes')
@@ -626,13 +623,13 @@ def func_upload():
 def user_info():
     return user_info_2(conn)
 
-@app.route('/watch_list')
-def watch_list():
-    return watch_list_2(conn)
+@app.route('/<regex("watch_list|star_doc"):tool>')
+def watch_list(tool = 'star_doc'):
+    return watch_list_2(conn, tool)
 
-@app.route('/watch_list/<everything:name>')
-def watch_list_name(name = None):
-    return watch_list_name_2(conn, name)
+@app.route('/<regex("watch_list|star_doc"):tool>/<everything:name>')
+def watch_list_name(tool = 'star_doc', name = 'Test'):
+    return watch_list_name_2(conn, tool, name)
 
 @app.route('/custom_head', methods=['GET', 'POST'])
 def user_custom_head_view():

+ 10 - 14
emergency_tool.py

@@ -48,7 +48,7 @@ while 1:
 
             all_src = []
             for i_data in os.listdir("."):
-                f_src = re.search("(.+)\.db$", i_data)
+                f_src = re.search(r"(.+)\.db$", i_data)
                 if f_src:
                     all_src += [f_src.group(1)]
 
@@ -186,19 +186,15 @@ elif what_i_do == '3':
     print('IP or Name : ', end = '')
     user_data = input()
 
-    if re.search("^([0-9]{1,3}\.[0-9]{1,3})$", user_data):
-        band = 'O'
-    else:
-        band = ''
-
-        curs.execute(db_change("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)"),
-            [user_data,
-            'release',
-            get_time(),
-            'tool:emergency',
-            '',
-            band
-        ])
+    curs.execute(db_change("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)"),
+        [user_data,
+        'release',
+        get_time(),
+        'tool:emergency',
+        '',
+        ''
+    ])
+
     curs.execute(db_change("delete from ban where block = ?"), [user_data])
 elif what_i_do == '4':
     print('----')

+ 10 - 2
language/en-US.json

@@ -99,6 +99,7 @@
         "off" : "Off",
         "unset" : "Unset",
         "extension" : "Extension",
+        "empty" : "Empty",
         "_comment_1.1_" : "Time",
             "second" : "Second(s)",
             "hour" : "Hour(s)",
@@ -181,7 +182,7 @@
         "last_edit_time" : "Last edited time",
         "admin_group" : "Administrator groups",
         "topic_setting" : "Discussion settings",
-        "old_page" : "Old decument(s)",
+        "old_page" : "Document(s) modified a long time ago",
         "skin_set" : "Skin setting(s)",
         "many_delete" : "Document bulk delete",
         "edit_req" : "Edit request",
@@ -202,6 +203,10 @@
         "topic_acl" : "Discussion ACL",
         "delete_admin_group": "Delete admin group",
         "main_skin_set" : "Main skin setting(s)",
+        "reset_backlink" : "Reset backlink",
+        "link_in_this" : "Links in this document",
+        "star_doc" : "Document(s) of interest",
+        "add_star_doc" : "Add document(s) of interest",
         "_comment_2.1_" : "Filter",
             "_comment_2.1.1_" : "List",
                 "interwiki_list" : "Interwiki(s) list",
@@ -254,6 +259,7 @@
                 "slow_edit" : "Continuous edit limit",
                 "requires_approval" : "Requires approval for register",
                 "approval_question": "Registeration questions",
+                "backup_where" : "Backup location",
             "_comment_2.2.3_" : "Text",
                 "register_text" : "Terms of sign-up",
                 "non_login_alert" : "Non-login alert",
@@ -345,13 +351,15 @@
         "no_login_warring" : "You are not logged in. The IP address will be logged when editing or discussing with non-login.",
         "user_reset_sign" : "Your account information has changed like this.",
         "update_warring" : "Manual updates are recommended if your version is 0.2 or lower than the latest version. For Windows, the contents of the route folder disappear.",
-        "defalut_edit_help" : "Describe it here",
+        "default_edit_help" : "Describe it here",
         "markup_enabled" : "Markup enabled",
         "many_delete_help" : "Please write down the document[s] name one by one on the line.",
         "sqlite_only" : "SQLite only",
         "approval_question_visible_only_when_approval_on" : "Approval questions are visible only when approval requirement is on",
         "oauth_explain" : "To use the OAuth login feature, you must set the 'publish_url' value to a domain address that includes the HTTPS protocol, and actually support HTTPS connections.",
         "msg_whatchlist_lmt": "You can add as many as",
+        "enter_html" : "Please enter HTML",
+        "exp_edit_conflict" : "Editing conflict occurred",
         "_comment_3.1_" : "Error",
             "update_error" : "Auto update is not supported.",
             "inter_error" : "Internal error.",

+ 1 - 1
language/help_tool.py

@@ -13,7 +13,7 @@ for i in list(n_json):
         del n_json[i]
 
 for i in list(o_json):
-    if not re.search('^_', i[0]):
+    if not re.search(r'^_', i[0]):
         if not i in n_json:
             print('o_title : ' + i)
             print('o_text : ' + o_json[i])

+ 14 - 6
language/ko-KR.json

@@ -107,7 +107,7 @@
     "reset_user_ok": "검사 성공",
     "in_progress": "진행 중",
     "under_category": "하위 분류",
-    "range": "범위",
+    "range": "대역",
     "edit_filter_rule": "편집 필터 규칙",
     "oauth_connection": "Oauth 연결",
     "hide_ip": "IP 주소 숨기기",
@@ -267,7 +267,7 @@
     "count": "기여 횟수",
     "main_head": "메인 <HEAD>",
     "recent_ban": "차단 기록",
-    "smtp_password": "SMTP Password",
+    "smtp_password": "SMTP 비밀번호",
     "id_filter_list": "ID 필터 목록",
     "other": "기타",
     "edit": "편집",
@@ -303,10 +303,10 @@
     "link": "링크",
     "icon": "아이콘",
     "topic_setting": "토론 설정",
-    "old_page": "오래된 문서",
+    "old_page": "편집된 지 오래된 문서",
     "skin_set": "스킨 설정",
     "edit_help": "편집 창 문구",
-    "defalut_edit_help": "이곳에 내용을 입력해주세요.",
+    "default_edit_help": "이곳에 내용을 입력해주세요.",
     "many_delete": "문서 대량 삭제",
     "many_delete_help": "한 줄에 문서명을 한 개씩 적어주세요.",
     "content": "내용",
@@ -345,7 +345,7 @@
     "blocked_admin": "차단한 관리자",
     "invalid_password_error": "비밀번호 또는 아이디가 없습니다.",
     "accept_edit_request": "편집 요청 승인",
-    "msg_whatchlist_lmt": "다음 개수만큼 추가할 수 있습니다",
+    "msg_whatchlist_lmt": "최대 추가 가능 갯수",
     "watchlist_overflow_error": "추가 한도를 초과했으므로 더 이상 추가할 수 없습니다. 필요없는 항목을 삭제하십시오.",
     "unset": "미설정",
     "copyright_disagreed": "저작권 동의문구에 동의하여야 합니다.",
@@ -359,5 +359,13 @@
     "topic_acl" : "토론 ACL",
     "main_skin_set" : "기본 스킨 설정",
     "image_file_list" : "이미지 파일 목록",
-    "many_upload_acl" : "다중 파일 업로드 ACL"
+    "many_upload_acl" : "다중 파일 업로드 ACL",
+    "reset_backlink" : "역링크 초기화",
+    "link_in_this" : "이 문서의 링크",
+    "star_doc" : "관심 문서",
+    "add_star_doc" : "관심 문서 추가",
+    "enter_html" : "HTML을 입력하세요.",
+    "exp_edit_conflict" : "편집 충돌 발생",
+    "backup_where" : "백업 위치",
+    "empty" : "빈칸"
 }

+ 0 - 2
requirements.txt

@@ -1,8 +1,6 @@
 tornado
-bcrypt
 flask
 flask-Reggie
-flask-compress
 requests
 pymysql
 diff-match-patch

+ 2 - 2
route/api_skin_info.py

@@ -9,7 +9,7 @@ def api_skin_info_2(conn, name):
         name = './views/' + name + '/index.html'
 
     if not flask.request.args.get('all', None):
-        json_address = re.sub("(((?!\.|\/).)+)\.html$", "info.json", name)
+        json_address = re.sub(r"(((?!\.|\/).)+)\.html$", "info.json", name)
         try:
             json_data = json.loads(open(json_address, encoding='utf8').read())
         except:
@@ -28,7 +28,7 @@ def api_skin_info_2(conn, name):
         }
 
         for i in load_skin(skin_check(1), 1):
-            json_address = re.sub("(((?!\.|\/).)+)\.html$", "info.json", './views/' + i + '/index.html')
+            json_address = re.sub(r"(((?!\.|\/).)+)\.html$", "info.json", './views/' + i + '/index.html')
             try:
                 json_data = json.loads(open(json_address, encoding='utf8').read())
             except:

+ 17 - 7
route/api_topic_sub.py

@@ -27,14 +27,13 @@ def api_topic_sub_2(conn, topic_num):
                 t_data_f = i[1]
                 b_color = 'toron_color'
             else:
-                if admin == 1:
-                    t_data_f = i[1]
-                    b_color = 'toron_color_grey'
-                else:
-                    t_data_f = ''
-                    b_color = 'toron_color_not'
+                t_data_f = ''
+                b_color = 'toron_color_not'
 
-                ip += ' (B)'
+                ip += ' <a href="/admin_log?search=blind%20(code%20' + topic_num + '#' + i[0] + '">(B)</a>'
+
+                if admin == 1:
+                    ip += ' <a href="/thread/' + topic_num + '/raw/' + i[0] + '">(R)</a>'
 
             if flask.request.args.get('render', None):
                 if i[0] == '1':
@@ -67,6 +66,17 @@ def api_topic_sub_2(conn, topic_num):
                 t_plus_data = t_data_f[1]
                 t_data_f = t_data_f[0]
 
+                t_data_f = re.sub(
+                    r'&lt;topic_a&gt;((?:(?!&lt;\/topic_a&gt;).)+)&lt;\/topic_a&gt;', 
+                    '<a href="\g<1>">\g<1></a>', 
+                    t_data_f
+                )
+                t_data_f = re.sub(
+                    r'&lt;topic_call&gt;@((?:(?!&lt;\/topic_call&gt;).)+)&lt;\/topic_call&gt;', 
+                    '<a href="/w/user:\g<1>">@\g<1></a>', 
+                    t_data_f
+                )
+
                 all_data = '' + \
                     '<table id="toron">' + \
                         '<tbody>' + \

+ 1 - 4
route/api_user_info.py

@@ -47,9 +47,6 @@ def api_user_info_2(conn, name):
             plus_t += [load_lang('normal')]
         else:
             plus_t += [load_lang('blocked') + '<br>']
-
-            match = re.search("^([0-9]{1,3}\.[0-9]{1,3})", name)
-            match = match.group(1) if match else '-'
             regex_ban = 0
 
             curs.execute(db_change("select login, block, end, why from ban where band = 'regex'"))
@@ -62,7 +59,7 @@ def api_user_info_2(conn, name):
                     regex_ban = 1
 
             if regex_ban == 0:
-                curs.execute(db_change("select end, login, band, why from ban where block = ? or block = ?"), [name, match])
+                curs.execute(db_change("select end, login, band, why from ban where block = ?"), [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'))

+ 3 - 3
route/api_w.py

@@ -20,13 +20,13 @@ def api_w_2(conn, name):
                 data = curs.fetchall()
                 if data:
                     if flask.request.args.get('include', 'include_1'):
-                        include_re = re.compile('\[include\(((?:(?!\)\]).)+)\)\]', re.I)
-                        category_re = re.compile('\[\[(?:(?:category|분류):(?:(?!\[\[|\]\]).)+)\]\]', re.I)
+                        include_re = re.compile(r'\[include\(((?:(?!\)\]).)+)\)\]', re.I)
+                        category_re = re.compile(r'\[\[(?:(?:category|분류):(?:(?!\[\[|\]\]).)+)\]\]', re.I)
 
                         json_data = include_re.sub('', data[0][0])
                         json_data = category_re.sub('', json_data)
 
-                        get_all_change = re.findall('(@(?:[^@]*)@),([^,]*),', flask.request.args.get('change', ''))
+                        get_all_change = re.findall(r'(@(?:[^@]*)@),([^,]*),', flask.request.args.get('change', ''))
                         for i in get_all_change:
                             json_data = json_data.replace(
                                 i[0].replace('<amp>', '&'), 

+ 74 - 55
route/edit.py

@@ -1,5 +1,18 @@
 from .tool.func import *
 
+class run_count_section:
+    def __init__(self, key, change):
+        self.counter = key
+        self.change = change
+
+    def __call__(self, match):
+        self.counter -= 1
+
+        if self.counter == 0:
+            return '\n' + self.change + '\n'
+        else:
+            return '\n' + match[1]
+
 def edit_2(conn, name):
     curs = conn.cursor()
 
@@ -8,13 +21,18 @@ def edit_2(conn, name):
     if section:
         section = int(number_check(section))
 
-    curs.execute(db_change("select data from data where title = ?"), [name])
-    old = curs.fetchall()
-
     if acl_check(name) == 1:
-        return redirect('/edit_req/' + url_pas(name))
+        return re_error('/ban')
     
+    edit_repeat = 0
     if flask.request.method == 'POST':
+        edit_repeat = 1
+        curs.execute(db_change("select id from history where title = ? order by id + 0 desc"), [name])
+        old = curs.fetchall()
+        if old and flask.request.form.get('ver', '') != old[0][0]:
+            edit_repeat = 2
+    
+    if edit_repeat == 1:
         if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
             return re_error('/error/13')
         else:
@@ -37,49 +55,35 @@ def edit_2(conn, name):
         copyright_checkbox_text_d = curs.fetchall()
         if copyright_checkbox_text_d and copyright_checkbox_text_d[0][0] != '' and flask.request.form.get('copyright_agreement', '') != 'yes':
             return re_error('/error/29')
-
-        content = savemark(content)
         
+        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')
 
             if section:
-                class run_count_section:
-                    def __init__(self, key, change):
-                        self.counter = key
-                        self.change = change
-
-                    def __call__(self, match):
-                        self.counter -= 1
-
-                        if self.counter == 0:
-                            return '\n' + self.change
-                        else:
-                            return '\n' + match[1]
-
                 run_count = run_count_section(section, content)
 
                 c_data = html.escape('\n' + o_data)
-                c_data = re.sub('\n(?P<in>={1,6})', '<br>\g<in>', c_data)
-                c_data = re.sub('<br>((?:(?:(?!<br>).)*\n*)*)', run_count, c_data)
-                c_data = re.sub('^\n', '', c_data)
+                c_data = re.sub(r'\n(?P<in>={1,6})', '<br>\g<in>', c_data)
+                c_data = re.sub(r'<br>((?:(?:(?!<br>).)*\n*)*)', run_count, c_data)
+                c_data = re.sub(r'^\n', '', c_data)
                 c_data = html.unescape(c_data)
 
                 content = c_data
 
             leng = leng_check(len(o_data), len(content))
+            
+            curs.execute(db_change("update data set data = ? where title = ?"), [content, name])
         else:
             leng = '+' + str(len(content))
 
-        if old:
-            curs.execute(db_change("update data set data = ? where title = ?"), [content, name])
-        else:
             curs.execute(db_change("insert into data (title, data) values (?, ?)"), [name, content])
 
             curs.execute(db_change('select data from other where name = "count_all_title"'))
             curs.execute(db_change("update other set data = ? where name = 'count_all_title'"), [str(int(curs.fetchall()[0][0]) + 1)])
 
-        curs.execute(db_change("select user from scan where title = ?"), [name])
+        curs.execute(db_change("select user from scan where title = ? and type = ''"), [name])
         for scan_user in curs.fetchall():
             curs.execute(db_change("insert into alarm (name, data, date) values (?, ?, ?)"), [
                 scan_user[0],
@@ -109,36 +113,51 @@ def edit_2(conn, name):
         
         return redirect('/w/' + url_pas(name))
     else:
+        curs.execute(db_change("select data, id from history where title = ? order by id + 0 desc"), [name])
+        old = curs.fetchall()
         if old:
             if section:
                 data = html.escape('\n' + old[0][0].replace('\r\n', '\n'))
-                
-                data = re.sub('\n(?P<in>={1,6})', '<br>\g<in>', data)
+                data = re.sub(r'\n(?P<in>={1,6})', '<br>\g<in>', data)
 
-                section_data = re.findall('<br>((?:(?:(?!<br>).)*\n*)*)', data)
+                section_data = re.findall(r'<br>((?:(?:(?!<br>).)*\n*)*)', data)
                 if len(section_data) >= section:
-                    data = section_data[section - 1]
+                    data = html.unescape(section_data[section - 1])
                 else:
                     return redirect('/edit/' + url_pas(name))
             else:
                 data = old[0][0].replace('\r\n', '\n')
         else:
             data = ''
-
+            
         data_old = data
+        if edit_repeat == 2:
+            data = flask.request.form.get('content', '')
+        
+            warring_edit = load_lang('exp_edit_conflict') + ' '
 
-        if section:
-            get_name = '' + \
-                '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>' + \
-                '<hr class=\"main_hr\">' + \
-            ''
+            if flask.request.form.get('ver', '0') == '0':
+                warring_edit += '<a href="/raw/' + url_pas(name) + '">(r' + old[0][1] + ')</a>'
+            else:
+                warring_edit += '' + \
+                    '<a href="/diff/' + url_pas(name) + '?first=' + flask.request.form.get('ver', '1') + '&second=' + old[0][1] + '">(r' + old[0][1] + ')</a>' + \
+                ''
+
+            warring_edit += '<hr class="main_hr">'
         else:
-            get_name = '' + \
+            warring_edit = ''
+
+        get_name = ''
+        if not section and not flask.request.args.get('plus', None):
+            get_name += '' + \
                 '<a href="/manager/15?plus=' + url_pas(name) + '">(' + load_lang('load') + ')</a> ' + \
-                '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>' + \
-                '<hr class=\"main_hr\">' + \
             ''
             
+        get_name += '' + \
+            '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>' + \
+            '<hr class="main_hr">' + \
+        ''
+            
         if flask.request.args.get('plus', None):
             curs.execute(db_change("select data from data where title = ?"), [flask.request.args.get('plus', 'test')])
             get_data = curs.fetchall()
@@ -155,48 +174,48 @@ def edit_2(conn, name):
 
         curs.execute(db_change('select data from other where name = "edit_bottom_text"'))
         sql_d = curs.fetchall()
-        if sql_d and sql_d[0][0] != '':
-            b_text = '<hr class=\"main_hr\">' + sql_d[0][0]
-        else:
-            b_text = ''
+        b_text = ('<hr class="main_hr">' + sql_d[0][0]) if sql_d and sql_d[0][0] != '' else ''
         
         curs.execute(db_change('select data from other where name = "copyright_checkbox_text"'))
         sql_d = curs.fetchall()
         if sql_d and sql_d[0][0] != '':
             cccb_text = '' + \
-                '<hr class=\"main_hr\">' + \
+                '<hr class="main_hr">' + \
                 '<input type="checkbox" name="copyright_agreement" value="yes"> ' + sql_d[0][0] + \
-                '<hr class=\"main_hr\">' + \
+                '<hr class="main_hr">' + \
             ''
         else:
             cccb_text = ''
 
         curs.execute(db_change('select data from other where name = "edit_help"'))
         sql_d = curs.fetchall()
-        if sql_d and sql_d[0][0] != '':
-            p_text = sql_d[0][0]
-        else:
-            p_text = load_lang('defalut_edit_help')
+        p_text = sql_d[0][0] if sql_d and sql_d[0][0] != '' else load_lang('default_edit_help')
 
-        data = re.sub('\n$', '', data)
-        data_old = re.sub('\n$', '', data_old)
+        data = re.sub(r'\n+$', '', data)
+        data_old = re.sub(r'\n+$', '', data_old)
 
         return easy_minify(flask.render_template(skin_check(), 
             imp = [name, wiki_set(), custom(), other2([' (' + sub + ')', 0])],
             data =  get_name + '''
                 <form method="post">
+                    <script>
+                        do_paste_image();
+                        do_not_out();
+                    </script>
                     ''' + edit_button() + '''
-                    <textarea id="content" placeholder="''' + p_text + '''" name="content">''' + html.escape(data) + '''</textarea>
+                    ''' + warring_edit + '''
+                    <textarea id="content" class="content" placeholder="''' + p_text + '''" name="content">''' + html.escape(data) + '''</textarea>
                     <textarea id="origin" name="o_content">''' + html.escape(data_old) + '''</textarea>
-                    <hr class=\"main_hr\">
+                    <hr class="main_hr">
                     <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
-                    <hr class=\"main_hr\">
+                    <input id="origin" name="ver" value="''' + (old[0][1] if old else '0') + '''">
+                    <hr class="main_hr">
                     ''' + captcha_get() + ip_warring() + cccb_text + '''
                     <button id="save" type="submit" onclick="save_stop_exit();">''' + save_button + '''</button>
                     <button id="preview" type="button" onclick="load_preview(\'''' + url_pas(name) + '\')">' + load_lang('preview') + '''</button>
                 </form>
                 ''' + b_text + '''
-                <hr class=\"main_hr\">
+                <hr class="main_hr">
                 <div id="see_preview"></div>
             ''',
             menu = [['w/' + url_pas(name), load_lang('return')]] + menu_plus

+ 18 - 0
route/edit_backlink_reset.py

@@ -0,0 +1,18 @@
+from .tool.func import *
+
+def edit_backlink_reset_2(conn, name):
+    curs = conn.cursor()
+
+    curs.execute(db_change("select data from data where title = ?"), [name])
+    old = curs.fetchall()
+    if old:
+        curs.execute(db_change("delete from back where link = ?"), [name])
+        curs.execute(db_change("delete from back where title = ? and type = 'no'"), [name])
+        
+        render_set(
+            title = name,
+            data = old[0][0],
+            num = 1
+        )
+
+    return redirect('/xref/' + url_pas(name))

+ 1 - 1
route/edit_delete.py

@@ -40,7 +40,7 @@ def edit_delete_2(conn, name, app_var):
             curs.execute(db_change("delete from data where title = ?"), [name])
             conn.commit()
 
-        file_check = re.search('^file:(.+)\.(.+)$', name)
+        file_check = re.search(r'^file:(.+)\.(.+)$', name)
         if file_check:
             file_check = file_check.groups()
             file_directory = os.path.join(

+ 2 - 2
route/edit_many_delete.py

@@ -8,7 +8,7 @@ def edit_many_delete_2(conn, app_var):
         return re_error('/ban')
 
     if flask.request.method == 'POST':
-        all_title = re.findall('([^\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', '\n') + '\n')
         for name in all_title:
             curs.execute(db_change("select data from data where title = ?"), [name])
             data = curs.fetchall()
@@ -34,7 +34,7 @@ def edit_many_delete_2(conn, app_var):
                 curs.execute(db_change("delete from data where title = ?"), [name])
                 conn.commit()
 
-            file_check = re.search('^file:(.+)\.(.+)$', name)
+            file_check = re.search(r'^file:(.+)\.(.+)$', name)
             if file_check:
                 file_check = file_check.groups()
                 file_directory = os.path.join(

+ 0 - 177
route/edit_req.py

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

+ 34 - 25
route/func_upload.py

@@ -16,7 +16,12 @@ def func_upload_2(conn):
         if not file_data:
             return re_error('/error/9')
 
-        if len(file_data) == 1:
+        file_len = len(file_data)
+
+        if int(wiki_set(3)) * 1024 * 1024 * file_len < flask.request.content_length:
+            return re_error('/error/17')
+
+        if file_len == 1:    
             file_num = None
         else:
             if acl_check(None, 'many_upload') == 1:
@@ -25,14 +30,11 @@ def func_upload_2(conn):
             file_num = 1
 
         for data in file_data:
-            if int(wiki_set(3)) * 1024 * 1024 < flask.request.content_length:
-                return re_error('/error/17')
-
             value = os.path.splitext(data.filename)[1]
             
             curs.execute(db_change("select html from html_filter where kind = 'extension'"))
             extension = [i[0].lower() for i in curs.fetchall()]
-            if not re.sub('^\.', '', value).lower() in extension:
+            if not re.sub(r'^\.', '', value).lower() in extension:
                 return re_error('/error/14')
 
             if flask.request.form.get('f_name', None):
@@ -41,7 +43,7 @@ def func_upload_2(conn):
                 name = data.filename
 
             piece = os.path.splitext(name)
-            if re.search('[^ㄱ-힣0-9a-zA-Z_\- ]', piece[0]):
+            if re.search(r'[^ㄱ-힣0-9a-zA-Z_\- ]', piece[0]):
                 return re_error('/error/22')
 
             e_data = sha224_replace(piece[0]) + piece[1]
@@ -57,30 +59,36 @@ def func_upload_2(conn):
                 if t_re.search(name):
                     return redirect('/file_filter')
 
-            ip = ip_check()
-
-            if flask.request.form.get('f_lice_sel', 'direct_input') == 'direct_input':
-                lice = flask.request.form.get('f_lice', '') + '[br][br]'
-                if ip_or_user(ip) != 0:
-                    lice += ip
-                else:
-                    lice += '[[user:' + ip + ']]'
-
-                lice += '[[category:direct_input]]'
-            else:
-                lice = flask.request.form.get('f_lice_sel', '')
-                lice += '[br][br]'  + flask.request.form.get('f_lice', '')
-                lice += '[[category:' + re.sub('\]', '_', flask.request.form.get('f_lice_sel', '')) + ']]'
-
             if os.path.exists(os.path.join(app_var['path_data_image'], e_data)):
-
                 os.remove(os.path.join(app_var['path_data_image'], e_data))
-
                 data.save(os.path.join(app_var['path_data_image'], e_data))
             else:
                 data.save(os.path.join(app_var['path_data_image'], e_data))
 
-            file_d = '[[file:' + name + ']][br][br]{{{[[file:' + name + ']]}}}[br][br]' + lice
+            ip = ip_check()
+            g_lice = flask.request.form.get('f_lice', '')
+            file_size = os.stat(os.path.join(app_var['path_data_image'], e_data)).st_size
+
+            curs.execute(db_change("select data from other where name = 'markup'"))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] == 'namumark':
+                file_d = '' + \
+                    '[[file:' + name + ']]\n' + \
+                    '{{{[[file:' + name + ']]}}}\n\n' + \
+                    (g_lice + '\n' if g_lice != '' else '') + \
+                    flask.request.form.get('f_lice_sel', 'direct_input') + '\n' + \
+                    (ip if ip_or_user(ip) != 0 else '[[user:' + ip + ']]') + '\n' + \
+                    str(file_size) + ' Byte\n' + \
+                    '[[category:' + re.sub(r'\]', '_', flask.request.form.get('f_lice_sel', '')) + ']]' + \
+                ''
+            else:
+                file_d = '' + \
+                    '/image/' + e_data + '\n\n' + \
+                    (g_lice + '\n' if g_lice != '' else '') + \
+                    flask.request.form.get('f_lice_sel', 'direct_input') + '\n' + \
+                    ip + \
+                    str(file_size) + ' Byte\n' + \
+                ''
 
             curs.execute(db_change("insert into data (title, data) values (?, ?)"), ['file:' + name, file_d])
             curs.execute(db_change("insert into acl (title, decu, dis, why, view) values (?, 'admin', '', '', '')"), ['file:' + name])
@@ -101,7 +109,8 @@ def func_upload_2(conn):
                 'upload'
             )
 
-            if file_num: file_num += 1
+            if file_num:
+                file_num += 1
 
         conn.commit()
 

+ 13 - 6
route/give_acl.py

@@ -11,7 +11,7 @@ def give_acl_2(conn, name):
     else:
         check_data = None
 
-    user_data = re.search('^user:(.+)$', name)
+    user_data = re.search(r'^user:(.+)$', name)
     if user_data:
         if check_data and ip_or_user(ip) != 0:
             return redirect('/login')
@@ -68,7 +68,7 @@ def give_acl_2(conn, name):
     else:
         data = '<h2>' + load_lang('document_acl') + '</h2><hr class=\"main_hr\"><select name="decu" ' + check_ok + '>'
 
-        if re.search('^user:', name):
+        if re.search(r'^user:', name):
             acl_list = get_acl_list('user')
         else:
             acl_list = get_acl_list()
@@ -85,7 +85,7 @@ def give_acl_2(conn, name):
 
         data += '</select>'
 
-        if not re.search('^user:', name):
+        if not re.search(r'^user:', name):
             data += '<hr class=\"main_hr\"><h2>' + load_lang('discussion_acl') + '</h2><hr class=\"main_hr\"><select name="dis" ' + check_ok + '>'
 
             curs.execute(db_change("select dis, why, view from acl where title = ?"), [name])
@@ -127,14 +127,21 @@ def give_acl_2(conn, name):
 
             if check_ok == '':
                 if acl_data:
-                    data += '<hr class=\"main_hr\"><input value="' + html.escape(acl_data[0][1]) + '" placeholder="' + load_lang('why') + '" name="why" type="text" ' + check_ok + '>'
+                    data += '' + \
+                        '<hr class=\"main_hr\">' + \
+                        '<input value="' + html.escape(acl_data[0][1]) + '" placeholder="' + load_lang('why') + '" name="why" type="text" ' + check_ok + '>' + \
+                    ''
                 else:
-                    data += '<hr class=\"main_hr\"><input placeholder="' + load_lang('why') + '" name="why" type="text" ' + check_ok + '>'
+                    data += '' + \
+                        '<hr class=\"main_hr\">' + \
+                        '<input placeholder="' + load_lang('why') + '" name="why" type="text" ' + check_ok + '>' + \
+                    ''
 
         return easy_minify(flask.render_template(skin_check(),
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('acl') + ')', 0])],
-            data =  '''
+            data = '''
                 <form method="post">
+                    <a href="/setting/8">(''' + load_lang('main_acl_setting') + ''')</a>
                     ''' + data + '''
                     <hr class=\"main_hr\">
                     <button type="submit" ''' + check_ok + '''>''' + load_lang('save') + '''</button>

+ 1 - 2
route/give_history_add.py

@@ -12,7 +12,6 @@ def give_history_add_2(conn, name):
 
         today = get_time()
         content = flask.request.form.get('content', '')
-        content = savemark(content)
         leng = '+' + str(len(content))
 
         history_plus(
@@ -40,7 +39,7 @@ def give_history_add_2(conn, name):
         if sql_d and sql_d[0][0] != '':
             p_text = sql_d[0][0]
         else:
-            p_text = load_lang('defalut_edit_help')
+            p_text = load_lang('default_edit_help')
 
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('history_add'), wiki_set(), custom(), other2([' (' + name + ')', 0])],

+ 1 - 1
route/give_user_ban.py

@@ -73,7 +73,7 @@ def give_user_ban_2(conn, name):
             if name:
                 main_name = name
 
-                if name and re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name):
+                if name and re.search(r"^([0-9]{1,3}\.[0-9]{1,3})$", name):
                     b_now = load_lang('band_ban')
                 else:
                     b_now = load_lang('ban')

+ 1 - 1
route/inter_wiki_del.py

@@ -23,6 +23,6 @@ def inter_wiki_del_2(conn, tools, name):
 
         conn.commit()
 
-        return redirect('/' + re.sub('^del_', '', tools))
+        return redirect('/' + re.sub(r'^del_', '', tools))
     else:
         return re_error('/error/3')

+ 1 - 1
route/inter_wiki_plus.py

@@ -88,7 +88,7 @@ def inter_wiki_plus_2(conn, tools, name):
 
         conn.commit()
 
-        return redirect('/' + re.sub('^plus_', '', tools))
+        return redirect('/' + re.sub(r'^plus_', '', tools))
     else:
         if admin_check(1) != 1:
             stat = 'disabled'

+ 1 - 1
route/list_acl.py

@@ -8,7 +8,7 @@ def list_acl_2(conn):
     curs.execute(db_change("select title, why from acl where decu != '' or dis != '' or view != '' order by title desc"))
     list_data = curs.fetchall()
     for data in list_data:
-        if not re.search('^user:', data[0]) and not re.search('^file:', data[0]):
+        if not re.search(r'^user:', data[0]) and not re.search(r'^file:', data[0]):
             curs.execute(db_change("select time from re_admin where what like ? order by time desc limit 1"), ['acl (' + data[0] + ')%'])
             time_data = curs.fetchall()
             if time_data:

+ 1 - 1
route/list_block.py

@@ -79,7 +79,7 @@ def list_block_2(conn, name, tool):
 
         if data[2] == '':
             admin = ''
-        elif re.search('^tool:', data[2]):
+        elif re.search(r'^tool:', data[2]):
             admin = data[2]
         else:
             admin = ip_pas(data[2])

+ 1 - 1
route/list_old_page.py

@@ -26,7 +26,7 @@ def list_old_page_2(conn):
     ''), [sql_num])
     n_list = curs.fetchall()
     for data in n_list:
-        div += '<li><a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a> (' + re.sub(' .*$', '', data[1]) + ')</li>'
+        div += '<li><a href="/w/' + url_pas(data[0]) + '">' + html.escape(data[0]) + '</a> (' + re.sub(r' .*$', '', data[1]) + ')</li>'
 
     div += '</ul>' + next_fix('/old_page?num=', num, n_list)
 

+ 22 - 6
route/list_user_topic.py

@@ -18,24 +18,40 @@ def list_user_topic_2(conn, name):
                     <td id="main_table_width">''' + load_lang('time') + '''</td>
                 </tr>
     '''
+    sub = '(' + html.escape(name) + ')'
+    pas_name = ip_pas(name)
 
-    curs.execute(db_change("select code, id, ip, date from topic where ip = ? order by date desc limit ?, 50"), [name, sql_num])
+    curs.execute(db_change("select code, id, date from topic where ip = ? order by date desc limit ?, 50"), [name, sql_num])
     data_list = curs.fetchall()
     for data in data_list:
         title = html.escape(data[0])
-        sub = html.escape(data[2])
 
         curs.execute(db_change("select title, sub from rd where code = ?"), [data[0]])
         other_data = curs.fetchall()
         
-        div += '<tr><td><a href="/thread/' + data[0] + '#' + data[1] + '">' + other_data[0][1] + '#' + data[1] + '</a> (' + other_data[0][0] + ')</td>'
-        div += '<td>' + ip_pas(data[2]) + '</td><td>' + data[3] + '</td></tr>'
+        div += '' + \
+            '<tr>' + \
+                '<td>' + \
+                    '<a href="/thread/' + data[0] + '#' + data[1] + '">' + other_data[0][1] + '#' + data[1] + '</a> (' + other_data[0][0] + ')' + \
+                '</td>' + \
+                '<td>' + pas_name + '</td>' + \
+                '<td>' + data[2] + '</td>' + \
+            '</tr>' + \
+        ''
 
-    div += '</tbody></table>'
+    div += '' + \
+            '</tbody>' + \
+        '</table>' + \
+    ''
     div += next_fix('/topic_record/' + url_pas(name) + '?num=', num, data_list)
     
     return easy_minify(flask.render_template(skin_check(),
         imp = [load_lang('discussion_record'), wiki_set(), custom(), other2([sub, 0])],
         data = div,
-        menu = [['other', load_lang('other')], ['user', load_lang('user')], ['count/' + url_pas(name), load_lang('count')], ['record/' + url_pas(name), load_lang('record')]]
+        menu = [
+            ['other', load_lang('other')], 
+            ['user', load_lang('user')], 
+            ['count/' + url_pas(name), load_lang('count')], 
+            ['record/' + url_pas(name), load_lang('record')]
+        ]
     ))

+ 1 - 1
route/login_need_email.py

@@ -39,7 +39,7 @@ def login_need_email_2(conn, tool):
                 flask.session['c_pw'] = ''
 
             if 'c_id' in flask.session:
-                data = re.search('@([^@]+)$', flask.request.form.get('email', ''))
+                data = re.search(r'@([^@]+)$', flask.request.form.get('email', ''))
                 if data:
                     data = data.group(1)
 

+ 1 - 1
route/login_register.py

@@ -28,7 +28,7 @@ def login_register_2(conn):
         if flask.request.form.get('pw', None) != flask.request.form.get('pw2', None):
             return re_error('/error/20')
 
-        if re.search('(?:[^A-Za-zㄱ-힣0-9 ])', flask.request.form.get('id', None)):
+        if re.search(r'(?:[^A-Za-zㄱ-힣0-9 ])', flask.request.form.get('id', None)):
             return re_error('/error/8')
 
         curs.execute(db_change('select html from html_filter where kind = "name"'))

+ 2 - 2
route/main_file.py

@@ -10,11 +10,11 @@ def main_file_2(conn, data):
             data = open('./views/main_css/file/easter_egg.html', encoding='utf8').read(),
             menu = 0
         ))
-    elif re.search('\.txt$', data, flags = re.I) or data == 'sitemap.xml':
+    elif re.search(r'\.txt$', data, flags = re.I) or data == 'sitemap.xml':
         if data == 'robots.txt' and not os.path.exists('robots.txt'):
             return flask.Response('User-agent: *\nDisallow: /\nAllow: /$\nAllow: /w/', mimetype = 'text/plain')
         elif os.path.exists(data):
-            if re.search('\.txt$', data, flags = re.I):
+            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')

+ 1 - 1
route/main_image_view.py

@@ -6,7 +6,7 @@ def main_image_view_2(conn, name, app_var):
     if os.path.exists(os.path.join(app_var['path_data_image'], name)):
         return flask.send_from_directory(
             './' + app_var['path_data_image'], name, 
-            mimetype = 'image/' + re.search('\.([^\.]+)$', name).group(1)
+            mimetype = 'image/' + re.search(r'\.([^\.]+)$', name).group(1)
         )
     else:
         return redirect()

+ 2 - 1
route/main_manager.py

@@ -17,7 +17,8 @@ def main_manager_2(conn, num, r_ver):
         10 : [0, 'block_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')]
+        13 : [load_lang('document_name'), 'edit', load_lang('load')],
+        14 : [load_lang('document_name'), 'star_doc', load_lang('add_star_doc')]
     }
 
     if num == 1:

+ 3 - 3
route/main_views.py

@@ -3,8 +3,8 @@ from .tool.func import *
 def main_views_2(conn, name):
     curs = conn.cursor()
 
-    if re.search('\/', name):
-        m = re.search('^(.*)\/(.*)$', name)
+    if re.search(r'\/', name):
+        m = re.search(r'^(.*)\/(.*)$', name)
         if m:
             n = m.groups()
             plus = '/' + n[0]
@@ -16,7 +16,7 @@ def main_views_2(conn, name):
         plus = ''
         rename = name
 
-    mime_type = re.search('\.([^\.]+)$', rename).group(1)
+    mime_type = re.search(r'\.([^\.]+)$', rename).group(1)
     if mime_type:
         if mime_type in ['.jpeg', '.jpg', '.gif', '.png', '.webp', '.JPEG', '.JPG', '.GIF', '.PNG', '.WEBP']:
             mime_type = 'image/' + mime_type

+ 34 - 28
route/recent_changes.py

@@ -78,21 +78,28 @@ def recent_changes_2(conn, name, tool):
                 <td id="main_table_width">''' + load_lang('editor') + '''</td>
                 <td id="main_table_width">''' + load_lang('time') + '''</td>
             '''
-
+            sub = ''
             set_type = flask.request.args.get('set', 'normal')
-            if set_type == 'normal':
-                div = '' + \
-                    '<a href="?set=user">(' + load_lang('user_document') + ')</a> ' + \
-                    '<a href="?set=req">(' + load_lang('edit_req') + ')</a>' + \
-                    '<hr class="main_hr">' + div + \
-                ''
-
-            if set_type == 'req':
-                plus_sql = "where type = 'req' "
-            elif set_type == 'user':
-                plus_sql = "where title like 'user:%' and type = '' "
+
+            if set_type == 'move':
+                plus_sql = 'where send >= "" and send like "%</a> move)" and '
+                sub += ' (' + load_lang('move') + ')'
+            elif set_type == 'delete':
+                plus_sql = 'where send like "%(delete)" and '
+                sub += ' (' + load_lang('delete') + ')'
+            elif set_type == 'revert':
+                plus_sql = 'where send >= "" and send like "%(r%)" and '
+                sub += ' (' + load_lang('revert') + ')'
+            else:
+                plus_sql = 'where '
+
+            plus_sql += 'type = "" '
+            
+            if set_type == 'user':
+                plus_sql = 'where title like "user:%" '
+                sub += ' (' + load_lang('user') + ')'
             else:
-                plus_sql = "where not title like 'user:%' and type = '' "
+                plus_sql += 'and not title like "user:%" '
 
             curs.execute(db_change('' + \
                 'select id, title, date, ip, send, leng, hide from history ' + \
@@ -109,12 +116,12 @@ def recent_changes_2(conn, name, tool):
             send = '<br>'
 
             if data[4]:
-                if not re.search("^(?: *)$", data[4]):
+                if not re.search(r"^(?: *)$", data[4]):
                     send = data[4]
 
-            if re.search("\+", data[5]):
+            if re.search(r"\+", data[5]):
                 leng = '<span style="color:green;">(' + data[5] + ')</span>'
-            elif re.search("\-", data[5]):
+            elif re.search(r"\-", data[5]):
                 leng = '<span style="color:red;">(' + data[5] + ')</span>'
             else:
                 leng = '<span style="color:gray;">(' + data[5] + ')</span>'
@@ -147,11 +154,8 @@ def recent_changes_2(conn, name, tool):
             if tool == 'history':
                 title = '<a href="/w/' + url_pas(name) + '?num=' + data[0] + '">r' + data[0] + '</a> '
             else:
-                if not name and set_type == 'req':
-                    title = '<a href="/edit_req/' + url_pas(data[1]) + '?r=' + data[0] + '">' + html.escape(data[1]) + ' (r' + data[0] + ')</a> '
-                else:
-                    title = '<a href="/w/' + url_pas(data[1]) + '">' + html.escape(data[1]) + '</a> '
-                    title += '<a href="/history/' + url_pas(data[1]) + '">(r' + data[0] + ')</a> '
+                title = '<a href="/w/' + url_pas(data[1]) + '">' + html.escape(data[1]) + '</a> '
+                title += '<a href="/history/' + url_pas(data[1]) + '">(r' + data[0] + ')</a> '
 
             div += '''
                 <tr ''' + style[0] + '''>
@@ -201,17 +205,19 @@ def recent_changes_2(conn, name, tool):
                 menu = [['other', load_lang('other')], ['user', load_lang('user')], ['count/' + url_pas(name), load_lang('count')]]
                 div += next_fix('/record/' + url_pas(name) + '?num=', num, data_list)
         else:
+            div = '' + \
+                '<a href="?set=normal">(' + load_lang('normal') + ')</a> ' + \
+                '<a href="?set=user">(' + load_lang('user_document') + ')</a> ' + \
+                '<a href="?set=move">(' + load_lang('move') + ')</a> ' + \
+                '<a href="?set=delete">(' + load_lang('delete') + ')</a> ' + \
+                '<a href="?set=revert">(' + load_lang('revert') + ')</a>' + \
+                '<hr class="main_hr">' + div + \
+            ''
+
             menu = 0
             title = load_lang('recent_change')
             div += next_fix('/recent_changes?set=' + set_type + '&num=', num, data_list)
 
-            if set_type == 'user':
-                sub = ' (' + load_lang('user') + ')'
-                menu = [['recent_changes', load_lang('return')]]
-            elif set_type == 'req':
-                sub = ' (' + load_lang('edit_req') + ')'
-                menu = [['recent_changes', load_lang('return')]]
-
         if sub == '':
             sub = 0
 

+ 198 - 137
route/setting.py

@@ -1,9 +1,9 @@
 from .tool.func import *
 
-def setting_2(conn, num):
+def setting_2(conn, num, db_set):
     curs = conn.cursor()
 
-    if num != 0 and admin_check() != 1:
+    if not (num == 0 or num == 8) and admin_check() != 1:
         return re_error('/ban')
 
     if num == 0:
@@ -16,7 +16,8 @@ def setting_2(conn, num):
             'Google',
             load_lang('main_bottom_body'),
             load_lang('main_acl_setting'),
-            load_lang('oauth_setting')
+            load_lang('oauth_setting'),
+            load_lang('wiki_logo')
         ]
 
         x = 0
@@ -26,8 +27,6 @@ def setting_2(conn, num):
             x += 1
             li_data += '<li><a href="/setting/' + str(x) + '">' + li + '</a></li>'
 
-        li_data += '<li><a href="/adsense_setting">'+ load_lang('adsense_setting') + '</a></li>'
-
         return easy_minify(flask.render_template(skin_check(),
             imp = [load_lang('setting'), wiki_set(), custom(), other2([0, 0])],
             data = '<h2>' + load_lang('list') + '</h2><ul>' + li_data + '</ul>',
@@ -52,6 +51,7 @@ def setting_2(conn, num):
             16 : 'host',
             19 : 'slow_edit',
             20 : 'requires_approval',
+            21 : 'backup_where'
         }
         n_list = {
             0 : 'Wiki',
@@ -70,7 +70,8 @@ def setting_2(conn, num):
             15 : 'sha3',
             16 : '0.0.0.0',
             19 : '0',
-            20 : ''
+            20 : '',
+            21 : ''
         }
 
         if flask.request.method == 'POST':
@@ -82,7 +83,7 @@ def setting_2(conn, num):
 
             conn.commit()
 
-            admin_check(None, 'edit_set')
+            admin_check(None, 'edit_set (' + str(num) + ')')
 
             return redirect('/setting/1')
         else:
@@ -130,70 +131,79 @@ def setting_2(conn, num):
                 branch_div += '<option value="master">master</option>'
                 branch_div += '<option value="stable">stable</option>'
 
+            if db_set != 'sqlite':
+                sqlite_only = 'style="display:none;"'
+            else:
+                sqlite_only = ''
+
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('main_setting'), wiki_set(), custom(), other2([0, 0])],
                 data = '''
                     <form method="post">
                         <span>''' + load_lang('wiki_name') + '''</span>
-                        <hr class=\"main_hr\">
-                        <input type="text" name="name" value="''' + html.escape(d_list[0]) + '''">
-                        <hr>
-                        <span>''' + load_lang('wiki_logo') + ''' (HTML)</span>
-                        <hr class=\"main_hr\">
-                        <input type="text" name="logo" value="''' + html.escape(d_list[1]) + '''">
-                        <hr>
+                        <hr class="main_hr">
+                        <input name="name" value="''' + html.escape(d_list[0]) + '''">
+                        <hr class="main_hr">
+                        <span><a href="/setting/10">(''' + load_lang('wiki_logo') + ''')</a></span>
+                        <hr class="main_hr">
                         <span>''' + load_lang('main_page') + '''</span>
-                        <hr class=\"main_hr\">
-                        <input type="text" name="frontpage" value="''' + html.escape(d_list[2]) + '''">
-                        <hr>
+                        <hr class="main_hr">
+                        <input name="frontpage" value="''' + html.escape(d_list[2]) + '''">
+                        <hr class="main_hr">
                         <span>''' + load_lang('bottom_text') + ''' (HTML)</span>
-                        <hr class=\"main_hr\">
-                        <input type="text" name="license" value="''' + html.escape(d_list[3]) + '''">
-                        <hr>
+                        <hr class="main_hr">
+                        <input name="license" value="''' + html.escape(d_list[3]) + '''">
+                        <hr class="main_hr">
                         <span>''' + load_lang('max_file_size') + ''' (MB)</span>
-                        <hr class=\"main_hr\">
-                        <input type="text" name="upload" value="''' + html.escape(d_list[4]) + '''">
-                        <hr>
-                        <span>''' + load_lang('backup_interval') + ' (' + load_lang('hour') + ') (' + load_lang('off') + ' : 0) (' + load_lang('sqlite_only') + ') (' + load_lang('restart_required') + ''')</span>
-                        <hr class=\"main_hr\">
-                        <input type="text" name="back_up" value="''' + html.escape(d_list[9]) + '''">
-                        <hr>
+                        <hr class="main_hr">
+                        <input name="upload" value="''' + html.escape(d_list[4]) + '''">
+                        <hr class="main_hr">
+                        <span ''' + sqlite_only + '''>
+                            <span>''' + load_lang('backup_interval') + ' (' + load_lang('hour') + ') (' + load_lang('off') + ' : 0) (' + load_lang('restart_required') + ''')</span>
+                            <hr class="main_hr">
+                            <input name="back_up" value="''' + html.escape(d_list[9]) + '''">
+                            <hr class="main_hr">
+                            <span>''' + load_lang('backup_where') + ' (' + load_lang('empty') + ' : ' + load_lang('default') + ') (' + load_lang('restart_required') + ''') (EX : ./data/backup.db)</span>
+                            <hr class="main_hr">
+                            <input name="backup_where" value="''' + html.escape(d_list[21]) + '''">
+                            <hr class="main_hr">
+                        </span>
                         <span>''' + load_lang('wiki_skin') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <select name="skin">''' + load_skin(d_list[5]) + '''</select>
-                        <hr>
+                        <hr class="main_hr">
                         <input type="checkbox" name="reg" ''' + check_box_div[0] + '''> ''' + load_lang('no_register') + '''
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input type="checkbox" name="ip_view" ''' + check_box_div[1] + '''> ''' + load_lang('hide_ip') + '''
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input type="checkbox" name="email_have" ''' + check_box_div[2] + '''> ''' + load_lang('email_required') + ' <a href="/setting/6">(' + load_lang('smtp_setting_required') + ''')</a>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input type="checkbox" name="requires_approval" ''' + check_box_div[3] + '''> ''' + load_lang('requires_approval') + '''
-                        <hr>
+                        <hr class="main_hr">
                         <span>''' + load_lang('wiki_host') + '''</span>
-                        <hr class=\"main_hr\">
-                        <input type="text" name="host" value="''' + html.escape(d_list[16]) + '''">
-                        <hr>
+                        <hr class="main_hr">
+                        <input name="host" value="''' + html.escape(d_list[16]) + '''">
+                        <hr class="main_hr">
                         <span>''' + load_lang('wiki_port') + '''</span>
-                        <hr class=\"main_hr\">
-                        <input type="text" name="port" value="''' + html.escape(d_list[10]) + '''">
-                        <hr>
+                        <hr class="main_hr">
+                        <input name="port" value="''' + html.escape(d_list[10]) + '''">
+                        <hr class="main_hr">
                         <span>''' + load_lang('wiki_secret_key') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input type="password" name="key" value="''' + html.escape(d_list[11]) + '''">
-                        <hr>
+                        <hr class="main_hr">
                         <span>''' + load_lang('update_branch') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <select name="update">''' + branch_div + '''</select>
-                        <hr>
+                        <hr class="main_hr">
                         <span>''' + load_lang('encryption_method') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <select name="encode">''' + acl_div[0] + '''</select>
-                        <hr>
+                        <hr class="main_hr">
                         <span>''' + load_lang('slow_edit') + ' (' + load_lang('second') + ') (' + load_lang('off') + ''' : 0)</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[19] + '''" value="''' + html.escape(d_list[19]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
@@ -225,7 +235,7 @@ def setting_2(conn, num):
 
             conn.commit()
 
-            admin_check(None, 'edit_set')
+            admin_check(None, 'edit_set (' + str(num) + ')')
 
             return redirect('/setting/2')
         else:
@@ -248,63 +258,63 @@ def setting_2(conn, num):
                 data = '''
                     <form method="post">
                         <span>''' + load_lang('register_text') + ''' (HTML)</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[0] + '''" value="''' + html.escape(d_list[0]) + '''">
-                        <hr>
+                        <hr class="main_hr">
                         <span>''' + load_lang('non_login_alert') + ''' (HTML)</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[1] + '''" value="''' + html.escape(d_list[1]) + '''">
-                        <hr>
+                        <hr class="main_hr">
                         <span>''' + load_lang('edit_bottom_text') + ''' (HTML)</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[2] + '''" value="''' + html.escape(d_list[2]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('copyright_checkbox_text') + ''' (HTML)</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[3] + '''" value="''' + html.escape(d_list[3]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('check_key_text') + ''' (HTML)</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[4] + '''" value="''' + html.escape(d_list[4]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('email_title') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[5] + '''" value="''' + html.escape(d_list[5]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('email_text') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[6] + '''" value="''' + html.escape(d_list[6]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('email_insert_text') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[7] + '''" value="''' + html.escape(d_list[7]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('password_search_text') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[8] + '''" value="''' + html.escape(d_list[8]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('reset_user_text') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[9] + '''" value="''' + html.escape(d_list[9]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('error_401') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[10] + '''" value="''' + html.escape(d_list[10]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('error_404') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[11] + '''" value="''' + html.escape(d_list[11]) + '''">
-                        <hr>
+                        <hr class="main_hr">
                         <span>''' + load_lang('approval_question') + '''</span><sup><a href="#rfn-1" id="fn-1">(1)</a></sup>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[12] + '''" value="''' + html.escape(d_list[12]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('edit_help') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="''' + i_list[12] + '''" value="''' + html.escape(d_list[12]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                        <hr>
+                        <hr class="main_hr">
                         <ul>
                             <li><a href="#fn-1" id="rfn-1">(1)</a> <span>''' + load_lang('approval_question_visible_only_when_approval_on') + '''</span></li>
                         </ul>
@@ -342,7 +352,7 @@ def setting_2(conn, num):
 
             conn.commit()
 
-            admin_check(None, 'edit_set')
+            admin_check(None, 'edit_set (' + str(num) + ')')
 
             return redirect('/setting/' + end_r + '?skin=' + flask.request.args.get('skin', ''))
         else:
@@ -352,7 +362,7 @@ def setting_2(conn, num):
                 start = ''
                 plus = '''
                     <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
-                    <hr class=\"main_hr\">
+                    <hr class="main_hr">
                     <div id="see_preview"></div>
                 '''
             elif num == 7:
@@ -361,7 +371,7 @@ def setting_2(conn, num):
                 start = ''
                 plus = '''
                     <button id="preview" type="button" onclick="load_raw_preview(\'content\', \'see_preview\')">''' + load_lang('preview') + '''</button>
-                    <hr class=\"main_hr\">
+                    <hr class="main_hr">
                     <div id="see_preview"></div>
                 '''
             else:
@@ -370,9 +380,9 @@ def setting_2(conn, num):
                 start = '' + \
                     '<a href="?">(' + load_lang('all') + ')</a> ' + \
                     ' '.join(['<a href="?skin=' + i + '">(' + 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>
-                    <hr class=\"main_hr\">
+                    <hr class="main_hr">
                 '''
                 plus = ''
 
@@ -392,8 +402,8 @@ def setting_2(conn, num):
                 data = '''
                     <form method="post">
                         ''' + start + '''
-                        <textarea rows="25" name="content" id="content">''' + html.escape(data) + '''</textarea>
-                        <hr class=\"main_hr\">
+                        <textarea rows="25" placeholder="''' + load_lang('enter_html') + '''" name="content" id="content">''' + html.escape(data) + '''</textarea>
+                        <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
                         ''' + plus + '''
                     </form>
@@ -414,7 +424,7 @@ def setting_2(conn, num):
             fw.write(re.sub('\r\n', '\n', flask.request.form.get('content', '')))
             fw.close()
 
-            admin_check(None, 'edit_set')
+            admin_check(None, 'edit_set (' + str(num) + ')')
 
             return redirect('/setting/5')
         else:
@@ -450,10 +460,10 @@ def setting_2(conn, num):
                 imp = ['robots.txt', wiki_set(), custom(), other2([0, 0])],
                 data = '''
                     <a href="/robots.txt">(''' + load_lang('view') + ''')</a>
-                    <hr class=\"main_hr\">
+                    <hr class="main_hr">
                     <form method="post">
                         <textarea rows="25" name="content">''' + html.escape(data) + '''</textarea>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
@@ -479,7 +489,7 @@ def setting_2(conn, num):
 
             conn.commit()
 
-            admin_check(None, 'edit_set')
+            admin_check(None, 'edit_set (' + str(num) + ')')
 
             return redirect('/setting/6')
         else:
@@ -517,38 +527,38 @@ def setting_2(conn, num):
                     <form method="post">
                         <h2><a href="https://www.google.com/recaptcha/admin">''' + load_lang('recaptcha') + '''</a></h2>
                         <span>''' + load_lang('public_key') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="recaptcha" value="''' + html.escape(d_list[0]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('secret_key') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="sec_re" value="''' + html.escape(d_list[1]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <select name="recaptcha_ver">
                             ''' + re_ver + '''
                         </select>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <h2>''' + load_lang('smtp_setting') + ' (' + load_lang('restart_required') + ''')</h1>
                         <span>''' + load_lang('smtp_server') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="smtp_server" value="''' + html.escape(d_list[2]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('smtp_port') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="smtp_port" value="''' + html.escape(d_list[3]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('smtp_security') + '''</span>
-                        <hr class=\"main_hr\">'''
+                        <hr class="main_hr">'''
                         + security_radios +
-                        '''<hr class=\"main_hr\">
+                        '''<hr class="main_hr">
                         <span>''' + load_lang('smtp_username') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input name="smtp_email" value="''' + html.escape(d_list[5]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <span>''' + load_lang('smtp_password') + '''</span>
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <input type="password" name="smtp_pass" value="''' + html.escape(d_list[6]) + '''">
-                        <hr class=\"main_hr\">
+                        <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
@@ -560,25 +570,30 @@ def setting_2(conn, num):
             2 : 'discussion',
             3 : 'upload_acl',
             4 : 'all_view_acl',
-            5 : 'edit_req_acl',
             6 : 'many_upload_acl'
         }
 
         if flask.request.method == 'POST':
-            for i in i_list:
-                curs.execute(db_change("update other set data = ? where name = ?"), [
-                    flask.request.form.get(i_list[i], 'normal'),
-                    i_list[i]
-                ])
-
-            conn.commit()
+            if admin_check(None, 'edit_set (' + str(num) + ')') != 1:
+                return re_error('/ban')
+            else:
+                for i in i_list:
+                    curs.execute(db_change("update other set data = ? where name = ?"), [
+                        flask.request.form.get(i_list[i], 'normal'),
+                        i_list[i]
+                    ])
 
-            admin_check(None, 'edit_set')
+                conn.commit()
 
-            return redirect('/setting/8')
+                return redirect('/setting/8')
         else:
             d_list = {}
 
+            if admin_check() != 1:
+                disable = 'disabled'
+            else:
+                disable = ''
+
             for i in i_list:
                 curs.execute(db_change('select data from other where name = ?'), [i_list[i]])
                 sql_d = curs.fetchall()
@@ -610,31 +625,27 @@ def setting_2(conn, num):
                 data = '''
                     <form method="post">
                         <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
-                        <hr>
+                        <hr class="main_hr">
                         <span>''' + load_lang('document_acl') + '''</span> 
-                        <hr class=\"main_hr\">
-                        <select name="edit">''' + acl_div[0] + '''</select>
-                        <hr>
+                        <hr class="main_hr">
+                        <select ''' + disable + ''' name="edit">''' + acl_div[0] + '''</select>
+                        <hr class="main_hr">
                         <span>''' + load_lang('discussion_acl') + '''</span>
-                        <hr class=\"main_hr\">
-                        <select name="discussion">''' + acl_div[1] + '''</select>
-                        <hr>
+                        <hr class="main_hr">
+                        <select ''' + disable + ''' name="discussion">''' + acl_div[1] + '''</select>
+                        <hr class="main_hr">
                         <span>''' + load_lang('upload_acl') + '''</span>
-                        <hr class=\"main_hr\">
-                        <select name="upload_acl">''' + acl_div[2] + '''</select>
-                        <hr>
+                        <hr class="main_hr">
+                        <select ''' + disable + ''' name="upload_acl">''' + acl_div[2] + '''</select>
+                        <hr class="main_hr">
                         <span>''' + load_lang('view_acl') + '''</span>
-                        <hr class=\"main_hr\">
-                        <select name="all_view_acl">''' + acl_div[3] + '''</select>
-                        <hr>
-                        <span>''' + load_lang('edit_req_acl') + '''</span>
-                        <hr class=\"main_hr\">
-                        <select name="edit_req_acl">''' + acl_div[4] + '''</select>
-                        <hr>
+                        <hr class="main_hr">
+                        <select ''' + disable + ''' name="all_view_acl">''' + acl_div[3] + '''</select>
+                        <hr class="main_hr">
                         <span>''' + load_lang('many_upload_acl') + '''</span>
-                        <hr class=\"main_hr\">
-                        <select name="many_upload_acl">''' + acl_div[5] + '''</select>
-                        <hr>
+                        <hr class="main_hr">
+                        <select ''' + disable + ''' name="many_upload_acl">''' + acl_div[5] + '''</select>
+                        <hr class="main_hr">
                         <button id="save" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
@@ -675,10 +686,10 @@ def setting_2(conn, num):
 
             return redirect('/oauth_setting')
         else:
-            body_content = load_lang('oauth_explain') + '<hr>'
+            body_content = load_lang('oauth_explain') + '<hr class="main_hr">'
             body_content += '''
                 <input placeholder="publish_url" id="publish_url_box" name="publish_url_box">
-                <hr>
+                <hr class="main_hr">
                 <script>
                     function check_value (target) {
                         target_box = document.getElementById(target.id + "_box");
@@ -710,10 +721,10 @@ def setting_2(conn, num):
                                 id="''' + oauth_supported[i] + '''_client_''' + load_target + '''" 
                                 name="''' + oauth_supported[i] + '''_client_''' + load_target + '''" 
                                 value="''' + oauth_data['client_' + load_target] + '''" 
-                                type="text" 
+                                
                                 onChange="check_value(this)" 
                                 style="width: 80%;">
-                        ''' + ('<hr>' if j == 1 else '<hr class=\"main_hr\">') + '''
+                        ''' + ('<hr class="main_hr">' if j == 1 else '<hr class="main_hr">') + '''
                     '''
 
             body_content += '<button id="save" type="submit">' + load_lang('save') + '</button></form>'
@@ -724,5 +735,55 @@ def setting_2(conn, num):
                 data = body_content,
                 menu = [['other', load_lang('return')]]
             ))
+    elif num == 10:
+        skin_list = [0] + load_skin('', 1)
+        i_list = []
+        for i in skin_list:
+            i_list += [['logo', '' if i == 0 else i]]
+        
+        if flask.request.method == 'POST':
+            for i in i_list:
+                curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [
+                    flask.request.form.get(('main_css' if i[1] == '' else i[1]), ''),
+                    i[0], 
+                    i[1]
+                ])
+
+            conn.commit()
+
+            admin_check(None, 'edit_set (' + str(num) + ')')
+
+            return redirect('/setting/10')
+        else:
+            d_list = []
+            for i in i_list:
+                curs.execute(db_change('select data from other where name = ? and coverage = ?'), [i[0], i[1]])
+                sql_d = curs.fetchall()
+                if sql_d:
+                    d_list += [sql_d[0][0]]
+                else:
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, ?)'), [i[0], '', i[1]])
+
+                    d_list += ['']
+            
+            end_data = ''
+            for i in range(0, len(skin_list)):
+                end_data += '' + \
+                    '<span>' + load_lang('wiki_logo') + ' ' + ('(' + skin_list[i] + ')' if skin_list[i] != 0 else '') + ' (HTML)' + \
+                    '<hr class="main_hr">' + \
+                    '<input name="' + (skin_list[i] if skin_list[i] != 0 else 'main_css') + '" value="' + html.escape(d_list[i]) + '">' + \
+                    '<hr class="main_hr">' + \
+                ''
+            
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('wiki_logo'), wiki_set(), custom(), other2([0, 0])],
+                data = '''
+                    <form method="post">
+                        ''' + end_data + '''
+                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
+                menu = [['setting', load_lang('return')]]
+            ))
     else:
         return redirect()

+ 0 - 66
route/setting_adsense.py

@@ -1,66 +0,0 @@
-from .tool.func import *
-
-def setting_adsense_2(conn):
-    curs = conn.cursor()
-
-    if admin_check(None, 'adsense setting') != 1:
-        return re_error('/error/3')
-
-    if flask.request.method == 'POST':
-        try:
-            adsense_enabled = flask.request.form.get('adsense_enabled')
-            adsense_code = flask.request.form['adsense_code']
-        except:
-            return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('inter_error'), wiki_set(), custom(), other2([0, 0])],
-                data = '<h2>ie_no_data_required</h2>' + load_lang('ie_no_data_required'),
-                menu = [['setting', load_lang('return')]]
-            ))
-
-        if adsense_enabled == 'on':
-            curs.execute(db_change('update other set data = "True" where name = "adsense"'))
-        else:
-            curs.execute(db_change('update other set data = "False" where name = "adsense"'))
-
-        curs.execute(db_change('update other set data = ? where name = "adsense_code"'), [adsense_code])
-        conn.commit()
-
-        return redirect('/adsense_setting')
-
-    body_content = ''
-
-    curs.execute(db_change('select data from other where name = "adsense"'))
-    adsense_enabled = curs.fetchall()[0][0]
-
-    curs.execute(db_change('select data from other where name = "adsense_code"'))
-    adsense_code = curs.fetchall()[0][0]
-
-    template = '''
-        <form action="" accept-charset="utf-8" method="post">
-            <div class="form-check">
-                <label class="form-check-label">
-                    <input class="form-check-input" name="adsense_enabled" type="checkbox" {}>
-                    {}
-                </label>
-            </div>
-            <hr class=\"main_hr\">
-            <div class="form-group">
-                <textarea class="form-control" id="adsense_code" name="adsense_code" rows="12">{}</textarea>
-            </div>
-            <hr class=\"main_hr\">
-            <button type="submit" value="publish">{}</button>
-        </form>
-    '''
-
-    body_content += template.format(
-        'checked' if adsense_enabled == 'True' else '',
-        load_lang('adsense_enable'),
-        adsense_code,
-        load_lang('save')
-    )
-
-    return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('adsense_setting'), wiki_set(), custom(), other2([0, 0])],
-        data = body_content,
-        menu = [['setting', load_lang('return')]]
-    ))

+ 70 - 87
route/tool/func.py

@@ -7,7 +7,6 @@ for i in range(0, 2):
         from diff_match_patch import diff_match_patch
         import werkzeug.routing
         import werkzeug.debug
-        import flask_compress
         import flask_reggie
         import tornado.ioloop
         import tornado.httpserver
@@ -18,7 +17,6 @@ for i in range(0, 2):
         import pymysql
         import hashlib
         import smtplib
-        import bcrypt
         import zipfile
         import shutil
         import threading
@@ -73,7 +71,10 @@ def load_conn(data):
 
 def send_email(who, title, data):
     try:
-        curs.execute(db_change('select name, data from other where name = "smtp_email" or name = "smtp_pass" or name = "smtp_server" or name = "smtp_port" or name = "smtp_security"'))
+        curs.execute(db_change('' + \
+            'select name, data from other ' + \
+            'where name = "smtp_email" or name = "smtp_pass" or name = "smtp_server" or name = "smtp_port" or name = "smtp_security"' + \
+        ''))
         rep_data = curs.fetchall()
 
         smtp_email = ''
@@ -119,7 +120,7 @@ def send_email(who, title, data):
         print('Error : Email send error')
 
 def last_change(data):
-    json_address = re.sub("(((?!\.|\/).)+)\.html$", "set.json", skin_check())
+    json_address = re.sub(r"(((?!\.|\/).)+)\.html$", "set.json", skin_check())
     try:
         json_data = json.loads(open(json_address, encoding='utf8').read())
     except:
@@ -191,7 +192,7 @@ def update(ver_num, set_data):
         curs.execute(db_change("select data from other where name = 'recaptcha'"))
         change_rec = curs.fetchall()
         if change_rec and change_rec[0][0] != '':
-            new_rec = re.search('data-sitekey="([^"]+)"', change_rec[0][0])
+            new_rec = re.search(r'data-sitekey="([^"]+)"', change_rec[0][0])
             if new_rec:
                 curs.execute(db_change("update other set data = ? where name = 'recaptcha'"), [new_rec.group(1)])
             else:
@@ -203,11 +204,29 @@ def update(ver_num, set_data):
         
         with open('data/mysql.json', 'w') as f:
             f.write('{ "user" : "' + get_data_mysql['user'] + '", "password" : "' + get_data_mysql['password'] + '", "host" : "localhost" }')
+
+    if ver_num < 3183603:
+        curs.execute(db_change("select block from ban where band = 'O'"))
+        change_band = curs.fetchall()
+        for i in change_band:
+            curs.execute(db_change("update ban set block = ?, band = 'regex' where block = ? and band = 'O'"), [
+                '^' + i[0].replace('.', '\\.'),
+                i[0]
+            ])
+
+        curs.execute(db_change("select block from rb where band = 'O'"))
+        change_band = curs.fetchall()
+        for i in change_band:
+            curs.execute(db_change("update rb set block = ?, band = 'regex' where block = ? and band = 'O'"), [
+                '^' + i[0].replace('.', '\\.'),
+                i[0]
+            ])
             
-    if ver_num < 3180200:
+    if ver_num < 3184400:
         curs.execute(db_change('delete from cache_data'))
 
     conn.commit()
+
     print('Update pass')
 
 def set_init():
@@ -236,18 +255,11 @@ def pw_encode(data, data2 = '', type_d = ''):
 
     if type_d == 'sha256':
         return hashlib.sha256(bytes(data, 'utf-8')).hexdigest()
-    elif type_d == 'sha3':
+    else:
         if sys.version_info < (3, 6):
             return sha3.sha3_256(bytes(data, 'utf-8')).hexdigest()
         else:
             return hashlib.sha3_256(bytes(data, 'utf-8')).hexdigest()
-    else:
-        if data2 != '':
-            salt_data = bytes(data2, 'utf-8')
-        else:
-            salt_data = bcrypt.gensalt(11)
-
-        return bcrypt.hashpw(bytes(data, 'utf-8'), salt_data).decode()
 
 def pw_check(data, data2, type_d = 'no', id_d = ''):
     curs.execute(db_change('select data from other where name = "encode"'))
@@ -255,31 +267,16 @@ def pw_check(data, data2, type_d = 'no', id_d = ''):
 
     if type_d != 'no':
         if type_d == '':
-            set_data = 'bcrypt'
+            set_data = 'sha3'
         else:
             set_data = type_d
     else:
         set_data = db_data[0][0]
 
-    while 1:
-        if set_data in ['sha256', 'sha3']:
-            data3 = pw_encode(data = data, type_d = set_data)
-            if data3 == data2:
-                re_data = 1
-            else:
-                re_data = 0
-
-            break
-        else:
-            try:
-                if pw_encode(data, data2, 'bcrypt') == data2:
-                    re_data = 1
-                else:
-                    re_data = 0
-
-                break
-            except:
-                set_data = db_data[0][0]
+    if pw_encode(data = data, type_d = set_data) == data2:
+        re_data = 1
+    else:
+        re_data = 0
 
     if db_data[0][0] != set_data and re_data == 1 and id_d != '':
         curs.execute(db_change("update user set pw = ?, encode = ? where id = ?"), [pw_encode(data), db_data[0][0], id_d])
@@ -426,7 +423,7 @@ def ip_or_user(data = ''):
     if data == '':
         data = ip_check()
 
-    if re.search('(\.|:)', data):
+    if re.search(r'(\.|:)', data):
         return 1
     else:
         return 0
@@ -499,9 +496,11 @@ def other2(data):
         data += ['']
 
     req_list = ''
-    main_css_ver = 30
+    main_css_ver = 47
 
-    if not 'main_css_load' in flask.session or not 'main_css_ver' in flask.session or flask.session['main_css_ver'] != main_css_ver:
+    if  not 'main_css_load' in flask.session or \
+        not 'main_css_ver' in flask.session or \
+        flask.session['main_css_ver'] != main_css_ver:
         for i_data in os.listdir(os.path.join("views", "main_css", "css")):
             req_list += '<link rel="stylesheet" href="/views/main_css/css/' + i_data + '?ver=' + str(main_css_ver) + '">'
 
@@ -514,7 +513,8 @@ def other2(data):
         req_list = flask.session['main_css_load']
 
     data = data[0:2] + ['', '''
-        <link   rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
+        <link   rel="stylesheet"
+                href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.1/styles/default.min.css">
         <link   rel="stylesheet"
                 href="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.css"
                 integrity="sha384-dbVIfZGuN1Yq7/1Ocstc1lUEm+AT+/rCkibIcC/OmWo5f0EA48Vf8CytHzGrSwbQ"
@@ -522,22 +522,22 @@ def other2(data):
         <script src="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.js"
                 integrity="sha384-2BKqo+exmr9su6dir+qCw08N2ZKRucY4PrGQPPWU1A7FtlCGjmEGFqXCv5nyM5Ij"
                 crossorigin="anonymous"></script>
-        <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
-    ''' + req_list + '<script>main_css_skin_load();</script>'] + data[2:]
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.1/highlight.min.js"></script>
+    ''' + req_list + '<script>window.addEventListener(\'DOMContentLoaded\', function() { main_css_skin_load(); });</script>'] + data[2:]
 
     return data
 
 def cut_100(data):
-    if re.search('^\/w\/', flask.request.path):
-        data = re.sub('<script>((\n*(((?!<\/script>).)+)\n*)+)<\/script>', '', data)
-        data = re.sub('<hr class="main_hr">((\n*((.+)\n*))+)$', '', data)
-        data = re.sub('<div id="cate_all">((\n*((.+)\n*))+)$', '', data)        
-
-        data = re.sub('<(((?!>).)*)>', ' ', data)
-        data = re.sub('\n', ' ', data)
-        data = re.sub('^ +', '', data)
-        data = re.sub(' +$', '', data)
-        data = re.sub(' {2,}', ' ', data)
+    if re.search(r'^\/w\/', flask.request.path):
+        data = re.sub(r'<script>((\n*(((?!<\/script>).)+)\n*)+)<\/script>', '', data)
+        data = re.sub(r'<hr class="main_hr">((\n*((.+)\n*))+)$', '', data)
+        data = re.sub(r'<div id="cate_all">((\n*((.+)\n*))+)$', '', data)        
+
+        data = re.sub(r'<(((?!>).)*)>', ' ', data)
+        data = re.sub(r'\n', ' ', data)
+        data = re.sub(r'^ +', '', data)
+        data = re.sub(r' +$', '', data)
+        data = re.sub(r' {2,}', ' ', data)
     
         return data[0:100] + '...'
     else:
@@ -546,6 +546,7 @@ def cut_100(data):
 def wiki_set(num = 1):
     if num == 1:
         data_list = []
+        skin_name = skin_check(1)
 
         curs.execute(db_change('select data from other where name = ?'), ['name'])
         db_data = curs.fetchall()
@@ -563,12 +564,17 @@ def wiki_set(num = 1):
 
         data_list += ['', '']
 
-        curs.execute(db_change('select data from other where name = "logo"'))
+        curs.execute(db_change('select data from other where name = "logo" and coverage = ?'), [skin_name])
         db_data = curs.fetchall()
         if db_data and db_data[0][0] != '':
             data_list += [db_data[0][0]]
         else:
-            data_list += [data_list[0]]
+            curs.execute(db_change('select data from other where name = "logo" and coverage = ""'))
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                data_list += [db_data[0][0]]
+            else:
+                data_list += [data_list[0]]
 
         head_data = ''
 
@@ -577,7 +583,7 @@ def wiki_set(num = 1):
         if db_data and db_data[0][0] != '':
             head_data += db_data[0][0]
 
-        curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [skin_check(1)])
+        curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [skin_name])
         db_data = curs.fetchall()
         if db_data and db_data[0][0] != '':
             head_data += db_data[0][0]
@@ -660,10 +666,10 @@ def ip_pas(raw_ip, type_d = 0):
         curs.execute(db_change("select data from other where name = 'ip_view'"))
         data = curs.fetchall()
         if data and data[0][0] != '':
-            if re.search('\.', raw_ip):
-                ip = re.sub('\.([^.]*)\.([^.]*)$', '.*.*', raw_ip)
+            if re.search(r'\.', raw_ip):
+                ip = re.sub(r'\.([^.]*)\.([^.]*)$', '.*.*', raw_ip)
             else:
-                ip = re.sub(':([^:]*):([^:]*)$', ':*:*', raw_ip)
+                ip = re.sub(r':([^:]*):([^:]*)$', ':*:*', raw_ip)
 
             if not admin_check(1):
                 hide = 1
@@ -837,7 +843,7 @@ def acl_check(name = 'test', tool = '', topic_num = '1'):
     get_ban = ban_check()
     
     if name:
-        acl_c = re.search("^user:((?:(?!\/).)*)", name)
+        acl_c = re.search(r"^user:((?:(?!\/).)*)", name)
     else:
         acl_c = None
 
@@ -865,9 +871,8 @@ def acl_check(name = 'test', tool = '', topic_num = '1'):
 
         return 1
 
-    if tool == '' or tool == 'edit_req':
-        if acl_check(name, 'render') == 1:
-            return 1
+    if tool == '' and acl_check(name, 'render') == 1:
+        return 1
     
     if tool == '':
         end = 3
@@ -912,10 +917,6 @@ def acl_check(name = 'test', tool = '', topic_num = '1'):
         elif tool == 'many_upload':
             curs.execute(db_change("select data from other where name = 'many_upload_acl'"))
 
-            num = 5
-        elif tool == 'edit_req':
-            curs.execute(db_change("select data from other where name = 'edit_req_acl'"))
-
             num = 5
         else:
             if i == 0:
@@ -988,12 +989,6 @@ def ban_check(ip = None, tool = None):
     if admin_check(None, None, ip) == 1:
         return 0
 
-    band = re.search("^([0-9]{1,3}\.[0-9]{1,3})", ip)
-    if band:
-        band_it = band.group(1)
-    else:
-        band_it = '-'
-
     curs.execute(db_change("delete from ban where (end < ? and end like '2%')"), [get_time()])
     conn.commit()
 
@@ -1008,15 +1003,6 @@ def ban_check(ip = None, tool = None):
             else:
                 return 1
 
-    curs.execute(db_change("select login from ban where ((end > ? and end like '2%') or end = '') and block = ? and band = 'O'"), [get_time(), band_it])
-    band_d = curs.fetchall()
-    if band_d:
-        if tool and tool == 'login':
-            if band_d[0][0] != 'O':
-                return 1
-        else:
-            return 1
-
     curs.execute(db_change("select login from ban where ((end > ? and end like '2%') or end = '') and block = ? and band = ''"), [get_time(), ip])
     ban_d = curs.fetchall()
     if ban_d:
@@ -1034,10 +1020,7 @@ def ban_insert(name, end, why, login, blocker, type_d = None):
     if type_d:
         band = type_d
     else:
-        if re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name):
-            band = 'O'
-        else:
-            band = ''
+        band = ''
 
     curs.execute(db_change("delete from ban where (end < ? and end like '2%')"), [get_time()])
 
@@ -1107,7 +1090,7 @@ def history_plus(title, data, date, ip, send, leng, t_check = '', d_type = ''):
                 id_data
             ])
 
-    send = re.sub('\(|\)|<|>', '', send)
+    send = re.sub(r'\(|\)|<|>', '', send)
     send = send[:128] if len(send) > 128 else send
     send = send + ' (' + t_check + ')' if t_check != '' else send
 
@@ -1181,7 +1164,7 @@ def re_error(data):
             imp = [load_lang('error'), wiki_set(1), custom(), other2([0, 0])],
             data = '<h2>' + load_lang('error') + '</h2>' + end,
             menu = 0
-        ))
+        )), 401
     else:
         num = int(number_check(data.replace('/error/', '')))
         if num == 1:
@@ -1254,7 +1237,7 @@ def re_error(data):
                     '<div id="main_skin_set">' + \
                         '<h2>' + load_lang('error') + '</h2>' + \
                         '<ul>' + \
-                            '<li>' + data + '</li>' + \
+                            '<li>' + data + ' <a href="/main_skin_set">(' + load_lang('main_skin_set') + ')</a></li>' + \
                         '</ul>' + \
                     '</div>' + \
                     ('<script>window.addEventListener(\'DOMContentLoaded\', function() { main_css_skin_set(); });</script>' if get_url == '/main_skin_set' else ''),
@@ -1265,4 +1248,4 @@ def re_error(data):
                 imp = [load_lang('error'), wiki_set(1), custom(), other2([0, 0])],
                 data = '<h2>' + load_lang('error') + '</h2><ul><li>' + data + '</li></ul>',
                 menu = 0
-            )), 401
+            )), 400

+ 1 - 1
route/tool/init.py

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

+ 7 - 4
route/tool/mark.py

@@ -1,4 +1,5 @@
-from .set_mark.namumark import namumark, link_fix
+from .set_mark.namumark import namumark
+from .set_mark.markdown import markdown
 
 from .set_mark.tool import *
 
@@ -25,13 +26,13 @@ def load_conn2(data):
     curs = conn.cursor()
 
 def send_parser(data):
-    if not re.search('^<br>$', data):
+    if not re.search(r'^<br>$', data):
         data = html.escape(data)
 
-        data = re.sub('javascript:', '', data, flags = re.I)
+        data = re.sub(r'javascript:', '', data, flags = re.I)
         data = data.replace('&lt;br&gt;', '')
 
-    link_re = re.compile('&lt;a(?: (?:(?:(?!&gt;).)*))?&gt;(?P<in>(?:(?!&lt;).)*)&lt;\/a&gt;')
+    link_re = re.compile(r'&lt;a(?: (?:(?:(?!&gt;).)*))?&gt;(?P<in>(?:(?!&lt;).)*)&lt;\/a&gt;')
     link_data = link_re.findall(data)
     for i in link_data:
         data = link_re.sub('<a href="/w/' + urllib.parse.quote(i).replace('/','%2F') + '">' + i + '</a>', data, 1)
@@ -49,6 +50,8 @@ def render_do(title, data, num, include):
     rep_data = curs.fetchall()
     if rep_data[0][0] == 'namumark':
         data = namumark(conn, data, title, include)
+    elif rep_data[0][0] == 'markdown':
+        data = markdown(conn, data, title, include)
     elif rep_data[0][0] == 'custom':
         data = custom_mark(conn, data, title, include)
     elif rep_data[0][0] == 'raw':

+ 73 - 0
route/tool/set_mark/markdown.py

@@ -0,0 +1,73 @@
+from . import tool
+
+import datetime
+import html
+import re
+
+class head_render:
+    def __init__(self):
+        pass
+
+    def __call__(self, match):
+        head_len = str(len(match[1]))
+        head_data = match[2]
+
+        return '<h' + head_len + '>' + head_data + '</h' + head_len + '>'
+
+class link_render:
+    def __init__(self):
+        pass
+
+    def __call__(self, match):
+        if match[1] == '!':
+            if re.search(r'^http(s)?:\/\/', match[3], flags = re.I):
+                return '<img alt="' + match[2] + '" src="' + match[3] + '">'
+            else:
+                file_name = re.search(r'^([^.]+)\.([^.]+)$', match[3])
+                if file_name:
+                    file_end = file_name.group(2)
+                    file_name = file_name.group(1)
+                else:
+                    file_name = 'Test'
+                    file_end = 'jpg'
+
+                file_src = '/image/' + tool.sha224_replace(file_name) + '.' + file_end
+                file_alt = 'file:' + file_name + '.' + file_end
+
+                return '' + \
+                    '<img class="' + include_num + 'file_finder_1" alt="' + match[2] + '" src="' + file_src + '">' + \
+                    '<a class="' + include_num + 'file_finder_2" id="not_thing" href="/upload?name=' + tool.url_pas(file_name) + '">' + file_alt + '</a>' + \
+                ''
+        else:
+            if re.search(r'^http(s)?:\/\/', match[3], flags = re.I):
+                return '<a id="out_link" href="' + match[3] + '">' + match[2] + '</a>'
+            else:
+                return '<a class="' + include_num + 'link_finder" href="/w/' + match[3] + '">' + match[2] + '</a>'
+
+def markdown(conn, data, title, include_num):
+    backlink = []
+    include_num = include_num + '_' if include_num else ''
+    plus_data = '' + \
+        'get_link_state("' + include_num + '");\n' + \
+        'get_file_state("' + include_num + '");\n' + \
+    ''
+
+    data = html.escape(data)
+    data = data.replace('\r\n', '\n')
+    data = '\n' + data
+
+    head_r = r'\n(#{1,6}) ?([^\n]+)'
+    head_do = head_render()
+    data = re.sub(head_r, head_do, data)
+
+    link_r = r'(!)?\[((?:(?!\]\().)+)\]\(([^\]]+)\)'
+    link_do = link_render()
+    data = re.sub(link_r, link_do, data)
+
+    data = re.sub(r'\*\*((?:(?!\*\*).)+)\*\*', '<b>\1</b>', data)
+    data = re.sub(r'__((?:(?!__).)+)__', '<i>\1</i>', data)
+
+    data = re.sub('^\n', '', data)
+    data = re.sub('\n', '<br>', data)
+    
+    return [data, plus_data, backlink]

File diff suppressed because it is too large
+ 248 - 238
route/tool/set_mark/namumark.py


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

@@ -37,16 +37,6 @@ def ip_check(d_type = 0):
 
     return str(ip)
 
-def savemark(data):
-    data = re.sub("\[date\(now\)\]", get_time(), data)
-
-    ip = ip_check()
-    name = '[[user:' + ip + '|' + ip + ']]' if not re.search("\.|:", ip) else ip
-
-    data = re.sub("\[name\]", name, data)
-
-    return data
-
 def url_pas(data):
     return urllib.parse.quote(data).replace('/','%2F')
 

+ 26 - 9
route/topic.py

@@ -21,6 +21,9 @@ def topic_2(conn, topic_num):
     ban = acl_check(name, 'topic', topic_num)
 
     if flask.request.method == 'POST':
+        if flask.request.form.get('content', 'Test') == '':
+            return redirect('/thread/' + topic_num)
+
         if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
             return re_error('/error/13')
         else:
@@ -41,7 +44,7 @@ def topic_2(conn, topic_num):
 
         num = str(num)
 
-        match = re.search('^user:([^/]+)', name)
+        match = re.search(r'^user:([^/]+)', name)
         if match:
             y_check = 0
             if ip_or_user(match.group(1)) == 1:
@@ -67,10 +70,10 @@ def topic_2(conn, topic_num):
                     today
                 ])
 
-        cate_re = re.compile('\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
-        data = cate_re.sub('[br]', flask.request.form.get('content', 'Test'))
+        cate_re = re.compile(r'\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
+        data = cate_re.sub('[br]', flask.request.form.get('content', 'Test').replace('\r', ''))
 
-        for rd_data in re.findall("(?:#([0-9]+))", data):
+        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:
@@ -80,8 +83,22 @@ def topic_2(conn, topic_num):
                     today
                 ])
 
-        data = re.sub("(?P<in>#(?:[0-9]+))", '[[\g<in>]]', data)
-        data = savemark(data)
+        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])
+                ip_data = curs.fetchall()
+
+            if ip_data and ip_or_user(ip_data[0][0]) == 0:
+                curs.execute(db_change('insert into alarm (name, data, date) values (?, ?, ?)'), [
+                    ip_data[0][0],
+                    ip + ' | <a href="/thread/' + topic_num + '#' + num + '">' + name + ' | ' + sub + ' | #' + num + '</a>',
+                    today
+                ])
+
+        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)
 
         rd_plus(topic_num, today, name, sub)
         curs.execute(db_change("insert into topic (id, data, date, ip, code) values (?, ?, ?, ?, ?)"), [
@@ -93,7 +110,7 @@ def topic_2(conn, topic_num):
         ])
         conn.commit()
 
-        return redirect('/thread/' + topic_num + '?where=bottom')
+        return redirect('/thread/' + topic_num + '#' + num)
     else:
         data = ''
 
@@ -110,12 +127,12 @@ def topic_2(conn, topic_num):
             <a href="/thread/''' + topic_num + '/tool">(' + load_lang('topic_tool') + ''')</a>
             <hr class=\"main_hr\">
             <form style="''' + display + '''" method="post">
-                <textarea rows="10" id="content" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
+                <textarea id="content" class="topic_content" placeholder="''' + load_lang('content') + '''" name="content"></textarea>
                 <hr class=\"main_hr\">
                 ''' + captcha_get() + (ip_warring() if display == '' else '') + '''
                 <input style="display: none;" name="topic" value="''' + name + '''">
                 <input style="display: none;" name="title" value="''' + sub + '''">
-                <button type="submit">''' + load_lang('send') + '''</button>
+                <button id="save" type="submit">''' + load_lang('send') + '''</button>
                 <button id="preview" type="button" onclick="load_preview(\'\')">''' + load_lang('preview') + '''</button>
             </form>
             <hr class=\"main_hr\">

+ 1 - 1
route/topic_close_list.py

@@ -73,7 +73,7 @@ def topic_close_list_2(conn, name):
         '''
 
     if div == '':
-        plus = re.sub('^<br>', '', plus)
+        plus = re.sub(r'^<br>', '', plus)
 
     return easy_minify(flask.render_template(skin_check(),
         imp = [name, wiki_set(), custom(), other2([' (' + sub + ')', 0])],

+ 1 - 0
route/user_info.py

@@ -19,6 +19,7 @@ def user_info_2(conn):
         '''
 
         plus2 += '<li><a href="/watch_list">' + load_lang('watchlist') + '</a></li>'
+        plus2 += '<li><a href="/star_doc">' + load_lang('star_doc') + '</a></li>'
         plus3 = '<li><a href="/acl/user:' + url_pas(ip) + '">' + load_lang('user_document_acl') + '</a></li>'
     else:
         plus = '''

+ 6 - 6
route/view_diff_data.py

@@ -33,19 +33,19 @@ def view_diff_data_2(conn, name):
                 diff_data = diff_match_patch().diff_prettyHtml(diff_match_patch().diff_main(first_raw_data, second_raw_data))
                 end_data = ''
 
-                re_data = re.findall('(?:(?:(?:(?!&para;<br>).)*)(?:&para;<br>)|(?:(?:(?!&para;<br>).)+)$)', diff_data)
+                re_data = re.findall(r'(?:(?:(?:(?!&para;<br>).)*)(?:&para;<br>)|(?:(?:(?!&para;<br>).)+)$)', diff_data)
                 for re_in_data in re_data:
-                    re_in_data = re.sub('&para;<br>$', '', re_in_data)
-                    if re.search('<ins (((?!<\/ins>).)+)<\/ins>', re_in_data):
+                    re_in_data = re.sub(r'&para;<br>$', '', re_in_data)
+                    if re.search(r'<ins (((?!<\/ins>).)+)<\/ins>', re_in_data):
                         end_data += str(i) + ' : ' + re_in_data + '\n'
                         include_ins = 0
-                    elif re.search('(<ins |<del )', re_in_data) and re.search('(<\/ins>|<\/del>)', re_in_data):
+                    elif re.search(r'(<ins |<del )', re_in_data) and re.search(r'(<\/ins>|<\/del>)', re_in_data):
                         end_data += str(i) + ' : ' + re_in_data + '\n'
                         include_ins = 1
-                    elif re.search('(<\/ins>|<\/del>)', re_in_data):
+                    elif re.search(r'(<\/ins>|<\/del>)', re_in_data):
                         end_data += str(i) + ' : ' + re_in_data + '\n'
                         include_ins = 0
-                    elif re.search('(<ins |<del )', re_in_data) or include_ins == 1:
+                    elif re.search(r'(<ins |<del )', re_in_data) or include_ins == 1:
                         end_data += str(i) + ' : ' + re_in_data + '\n'
                         include_ins = 1
                     else:

+ 3 - 2
route/view_raw.py

@@ -12,10 +12,11 @@ def view_raw_2(conn, name, topic_num, num):
     if not num:
         num = flask.request.args.get('num', None)
         if num:
-            num = int(number_check(num))
+            num = number_check(num)
+    else:
+        num = str(num)
 
     v_name = name
-    num = str(num)
     sub = ' (' + load_lang('raw') + ')'
 
     if not topic_num and num:

+ 12 - 23
route/view_read.py

@@ -7,18 +7,14 @@ def view_read_2(conn, name):
     acl = 0
     div = ''
     ip = ip_check()
+    run_redirect = ''
 
     num = flask.request.args.get('num', None)
     if num:
         num = int(number_check(num))
     else:
         if not flask.request.args.get('from', None):
-            curs.execute(db_change("select title from back where link = ? and type = 'redirect'"), [name])
-            r_db = curs.fetchall()
-            if r_db:
-                r_data = link_fix(r_db[0][0])
-
-                return redirect('/w/' + url_pas(r_data[0]) + '?from=' + name + r_data[1])
+            run_redirect = '<script>not_from_exist();</script>'
 
     curs.execute(db_change("select sub from rd where title = ? and not stop = 'O' order by date desc"), [name])
     if curs.fetchall():
@@ -34,13 +30,13 @@ def view_read_2(conn, name):
     else:
         down = 0
 
-    m = re.search("^(.*)\/(.*)$", name)
+    m = re.search(r"^(.*)\/(.*)$", name)
     if m:
         uppage = m.group(1)
     else:
         uppage = 0
 
-    if re.search('^category:', name):
+    if re.search(r'^category:', name):
         curs.execute(db_change("select link from back where title = ? and type = 'cat' order by link asc"), [name])
         back = curs.fetchall()
         if back:
@@ -50,7 +46,7 @@ def view_read_2(conn, name):
                 if div == '':
                     div = '<br><h2 id="cate_normal">' + load_lang('category_title') + '</h2><ul>'
 
-                if re.search('^category:', data[0]):
+                if re.search(r'^category:', data[0]):
                     u_div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a></li>'
                 else:
                     curs.execute(db_change("select title from back where title = ? and type = 'include'"), [data[0]])
@@ -95,8 +91,8 @@ def view_read_2(conn, name):
             else_data = None
 
         if flask.request.args.get('from', None) and else_data:
-            else_data = re.sub('^\r\n', '', else_data)
-            else_data = re.sub('\r\n$', '', else_data)
+            else_data = re.sub(r'^\r\n', '', else_data)
+            else_data = re.sub(r'\r\n$', '', else_data)
 
         end_data = render_set(
             title = name,
@@ -140,9 +136,9 @@ def view_read_2(conn, name):
         if sql_d:
             end_data += '<h2>' + load_lang('history') + '</h2><ul>'
             for i in sql_d:
-                if re.search("\+", i[2]):
+                if re.search(r"\+", i[2]):
                     leng = '<span style="color:green;">(' + i[2] + ')</span>'
-                elif re.search("\-", i[2]):
+                elif re.search(r"\-", i[2]):
                     leng = '<span style="color:red;">(' + i[2] + ')</span>'
                 else:
                     leng = '<span style="color:gray;">(' + i[2] + ')</span>'
@@ -196,16 +192,7 @@ def view_read_2(conn, name):
 
     div = end_data + div
 
-    curs.execute(db_change("select data from other where name = 'adsense'"))
-    if curs.fetchall()[0][0] == 'True':
-        curs.execute(db_change("select data from other where name = 'adsense_code'"))
-        adsense_code = '<div align="center" style="display: block;">' + curs.fetchall()[0][0] + '</div><hr class=\"main_hr\">'
-    else:
-        adsense_code = ''
-
-    div = adsense_code + '<div>' + div + '</div>'
-
-    match = re.search("^user:([^/]*)", name)
+    match = re.search(r"^user:([^/]*)", name)
     if match:
         user_name = match.group(1)
         div = '''
@@ -232,6 +219,8 @@ def view_read_2(conn, name):
     else:
         watch_list = 0
 
+    div += run_redirect
+
     return easy_minify(flask.render_template(skin_check(),
         imp = [flask.request.args.get('show', name), wiki_set(), custom(), other2([sub, r_date, watch_list])],
         data = div,

+ 27 - 15
route/view_xref.py

@@ -12,20 +12,32 @@ def view_xref_2(conn, name):
     else:
         sql_num = 0
 
-    div = '<ul>'
-
-    if re.search('#', name):
-        name = re.sub('#', '\\\\#', name)
-
-    curs.execute(db_change("" + \
-        "select link, type from back " + \
-        "where (title = ? and not type = 'cat' and not type = 'no') or (title like ? and type = 'redirect')" + \
-        "order by link asc limit ?, 50" + \
-    ""), [
-        name,
-        name + '#s-%',
-        sql_num
-    ])
+    if flask.request.args.get('change', '1') == '1':
+        div = '<a href="?change=2">(' + load_lang('link_in_this') + ')</a><hr class="main_hr">'
+    else:
+        div = '<a href="?change=1">(' + load_lang('normal') + ')</a><hr class="main_hr">'
+
+    div += '<ul>'
+
+    if flask.request.args.get('change', '1') == '1':
+        curs.execute(db_change("" + \
+            "select distinct link, type from back " + \
+            "where title = ? and not type = 'cat' and not type = 'no'" + \
+            "order by link asc limit ?, 50" + \
+        ""), [
+            name,
+            sql_num
+        ])
+    else:
+        curs.execute(db_change("" + \
+            "select distinct title, type from back " + \
+            "where link = ? and not type = 'cat' and not type = 'no'" + \
+            "order by link asc limit ?, 50" + \
+        ""), [
+            name,
+            sql_num
+        ])
+
     data_list = curs.fetchall()
     for data in data_list:
         div += '<li><a href="/w/' + url_pas(data[0]) + '">' + data[0] + '</a>'
@@ -45,5 +57,5 @@ def view_xref_2(conn, name):
     return easy_minify(flask.render_template(skin_check(),
         imp = [name, wiki_set(), custom(), other2([' (' + load_lang('backlink') + ')', 0])],
         data = div,
-        menu = [['w/' + url_pas(name), load_lang('return')]]
+        menu = [['w/' + url_pas(name), load_lang('return')], ['backlink_reset/' + url_pas(name), load_lang('reset_backlink')]]
     ))

+ 36 - 7
route/watch_list.py

@@ -1,29 +1,58 @@
 from .tool.func import *
 
-def watch_list_2(conn):
+def watch_list_2(conn, tool):
     curs = conn.cursor()
 
-    div = load_lang("msg_whatchlist_lmt") + ': 10 <hr class=\"main_hr\">'
+    if tool == 'watch_list':
+        div = load_lang("msg_whatchlist_lmt") + ' : 10 <hr class=\"main_hr\">'
+    else:
+        div = ''
+
     ip = ip_check()
 
     if ip_or_user(ip) != 0:
         return redirect('/login')
 
+
     curs.execute(db_change("delete from scan where user = ? and title = ''"), [ip])
     conn.commit()
 
-    curs.execute(db_change("select title from scan where user = ?"), [ip])
+    if tool == 'watch_list':
+        curs.execute(db_change("select title from scan where type = '' and user = ?"), [ip])
+
+        title_name = load_lang('watchlist')
+    else:
+        curs.execute(db_change("select title from scan where type = 'star' and user = ?"), [ip])
+
+        title_name = load_lang('star_doc')
+
     data = curs.fetchall()
     for data_list in data:
-        div += '<li><a href="/w/' + url_pas(data_list[0]) + '">' + data_list[0] + '</a> <a href="/watch_list/' + url_pas(data_list[0]) + '">(' + load_lang('delete') + ')</a></li>'
+        if tool == 'star_doc':
+            curs.execute(db_change("select date from history where title = ? order by id + 0 desc limit 1"), [data_list[0]])
+            get_data = curs.fetchall()
+            if get_data:
+                plus = '(' + get_data[0][0] + ') '
+            else:
+                plus = ''
+        else:
+            plus = ''
+
+        div += '' + \
+            '<li>' + \
+                '<a href="/w/' + url_pas(data_list[0]) + '">' + data_list[0] + '</a> ' + \
+                plus + \
+                '<a href="/' + ('star_doc' if tool == 'star_doc' else 'watch_list') + '/' + url_pas(data_list[0]) + '">(' + load_lang('delete') + ')</a>' + \
+            '</li>' + \
+        ''
 
     if data:
         div = '<ul>' + div + '</ul><hr class=\"main_hr\">'
 
-    div += '<a href="/manager/13">(' + load_lang('add') + ')</a>'
+    div += '<a href="/manager/' + ('13' if tool == 'watch_list' else '16') + '">(' + load_lang('add') + ')</a>'
 
     return easy_minify(flask.render_template(skin_check(),
-        imp = [load_lang('watchlist'), wiki_set(), custom(), other2([0, 0])],
+        imp = [title_name, wiki_set(), custom(), other2([0, 0])],
         data = div,
-        menu = [['manager', load_lang('return')]]
+        menu = [['user', load_lang('return')]]
     ))

+ 17 - 9
route/watch_list_name.py

@@ -1,23 +1,31 @@
 from .tool.func import *
 
-def watch_list_name_2(conn, name):
+def watch_list_name_2(conn, tool, name):
     curs = conn.cursor()
 
     ip = ip_check()
     if ip_or_user(ip) != 0:
         return redirect('/login')
 
-    curs.execute(db_change("select count(title) from scan where user = ?"), [ip])
-    count = curs.fetchall()
-    if count and count[0][0] > 9:
-        return re_error('/error/28')
+    if tool == 'watch_list':
+        curs.execute(db_change("select count(title) from scan where user = ?"), [ip])
+        count = curs.fetchall()
+        if count and count[0][0] > 9:
+            return re_error('/error/28')
 
-    curs.execute(db_change("select title from scan where user = ? and title = ?"), [ip, name])
+        type_data = ''
+    else:
+        type_data = 'star'
+
+    curs.execute(db_change("select title from scan where user = ? and title = ? and type = ?"), [ip, name, type_data])
     if curs.fetchall():
-        curs.execute(db_change("delete from scan where user = ? and title = ?"), [ip, name])
+        curs.execute(db_change("delete from scan where user = ? and title = ? and type = ?"), [ip, name, type_data])
     else:
-        curs.execute(db_change("insert into scan (user, title) values (?, ?)"), [ip, name])
+        curs.execute(db_change("insert into scan (user, title, type) values (?, ?, ?)"), [ip, name, type_data])
 
     conn.commit()
 
-    return redirect('/watch_list')
+    if tool == 'watch_list':
+        return redirect('/watch_list')
+    else:
+        return redirect('/star_doc')

+ 4 - 4
version.json

@@ -1,11 +1,11 @@
 {
     "master" : {
-        "r_ver" : "v3.1.7-stable-04",
-        "c_ver" : "3180200",
+        "r_ver" : "v3.1.8-stable-01",
+        "c_ver" : "3184400",
         "s_ver" : "8"
     }, "stable" : {
-        "r_ver" : "v3.1.7-stable-04",
-        "c_ver" : "3180200",
+        "r_ver" : "v3.1.8-stable-01",
+        "c_ver" : "3184400",
         "s_ver" : "8"
     }
 }

+ 13 - 15
views/main_css/css/main.css

@@ -1,7 +1,8 @@
+body, html, video, table, div, iframe, input, textarea, img, hr, blockquote, pre { max-width: 100%;}
 textarea { width: 100%; }
-input { width: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; }
+input { width: 100%; box-sizing: border-box; }
 #last { margin-top: 30px; }
-#toc { border: 1px solid; padding: 20px; width: fit-content; width: -moz-fit-content; clear: both; margin-top: 10px; }
+#toc { border: 1px solid; padding: 20px; width: fit-content; clear: both; margin-top: 10px; }
 #toc-name { font-size: 18px; }
 table { border-collapse: collapse; }
 td { border: 1px solid; padding: 5px; }
@@ -10,12 +11,11 @@ a { text-decoration: none; }
 #inside, #out_link, #open { color: green; }
 #out_link::before { background: green; color: white; content: "E"; }
 input[type="checkbox"], input[type="radio"] { width: auto; }
-.popup { position: fixed; bottom: 0; padding: 10px; left: 0; background: lightgray; width: 100%; }
 #list { padding: 10px; }
 #toron { width: 100%; }
-#toron_color_green { background: lightgreen; }
-#toron_color_blue { background: skyblue; }
-#toron_color_red { background: indianred; }
+#toron_color_green { background: #99ffcd; }
+#toron_color_blue { background: #ffcbf9; }
+#toron_color_red { background: #fecabf; }
 #toron_color_grey { background: gainsboro; }
 #toron_color_not { display: none; }
 #cate { border: 1px solid; padding: 5px; }
@@ -32,22 +32,20 @@ s:hover, strike:hover, del:hover { color: gray; background-color: gainsboro; tex
 #main_table_width_quarter { width: 25%; }
 #redirect { border: 1px solid; padding: 10px; }
 body { word-break: break-all; overflow: auto; }
-hr.main_hr { border: none; margin-top: 8px; margin-bottom: 8px; }
+.main_hr { border: none; margin-top: 8px; margin-bottom: 8px; }
 #include_link { display: none; }
-.foot_plus { background: white; border: 5px solid gainsboro; padding: 5px; width: 300px; height: 300px; position: fixed; top: calc(50% - 150px); right: calc(50% - 150px); display: none; z-index: 100; }
 #toc_title { font-size: 18px; }
-blockquote { background-image: url(/views/acme/img/quote.png); background-position: calc(100% - 10px) 10px; background-repeat: no-repeat; background-size: 25px; }
+blockquote { background-image: url(/views/main_css/file/quote.png); background-position: calc(100% - 10px) 10px; background-repeat: no-repeat; background-size: 25px; }
 #admin_log_search { width: 100px; }
 @media (max-width: 768px) { table { min-width: 100%; } .table_safe { min-width: 100%; }}
-@media (max-width: 400px) { .foot_plus { width: 80%; right: calc(100% - 92%); }}
-@media (max-height: 400px) { .foot_plus { height: 80%; top: calc(100% - 92%); }}
-.foot_in { overflow-y: scroll; height: calc(100% - 20px); }
 #origin { display: none; }
 .all_in_data { display: block; width: 100%; white-space: pre-wrap; }
 .table_safe { max-width: 100%; }
 .change_space { white-space: pre-line; }
-div#topic_scroll { max-height: 500px; overflow: scroll; -ms-overflow-style: none; scrollbar-width: none; }
-div#topic_scroll::-webkit-scrollbar { display: none; }
+#topic_scroll { max-height: 500px; overflow: scroll; -ms-overflow-style: none; scrollbar-width: none; }
+#topic_scroll::-webkit-scrollbar { display: none; }
 .hidden_link { filter: blur(3px); }
 .hidden_link:hover { filter: none; }
-#content { height: 500px; }
+.content { height: 500px; }
+.topic_content { height: 200px; }
+.spead_footnote { background-color: #efefef; color: #555; border: 1px solid #cecece; }

+ 102 - 0
views/main_css/js/do_editor.js

@@ -0,0 +1,102 @@
+function do_insert_data(name, data) {
+    // https://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript
+    if(document.selection) {
+        document.getElementById(name).focus();
+
+        var sel = document.selection.createRange();
+        sel.text = data;
+    } else if(document.getElementById(name).selectionStart || document.getElementById(name).selectionStart == '0') {
+        var startPos = document.getElementById(name).selectionStart;
+        var endPos = document.getElementById(name).selectionEnd;
+        var myPos = document.getElementById(name).value;
+
+        document.getElementById(name).value = myPos.substring(0, startPos) + data + myPos.substring(endPos, myPos.length);
+    } else {
+        document.getElementById(name).value += data;
+    }
+}
+
+function do_not_out() {
+    window.addEventListener('DOMContentLoaded', function() {
+        window.onbeforeunload = function() {
+            data = document.getElementById('content').value;
+            origin = document.getElementById('origin').value;
+            if(data !== origin) {
+                return '';
+            }
+        }
+    });
+}
+
+function save_stop_exit() {
+    window.onbeforeunload = function () {}
+}
+
+function do_paste_image() {
+    window.addEventListener('DOMContentLoaded', function() {
+        if(
+            document.cookie.match(main_css_regex_data('main_css_image_paste')) &&
+            document.cookie.match(main_css_regex_data('main_css_image_paste'))[1] === '1'
+        ) {
+            const textarea = document.querySelector("textarea");
+            if (textarea) {
+                textarea.addEventListener("paste", pasteListener);
+            }
+        }
+    });
+}
+
+function pasteListener(e) {
+    // find file
+    if (e.clipboardData && e.clipboardData.items) {
+        const items = e.clipboardData.items;
+        let haveImageInClipboard = false;
+        const formData = new FormData();
+        for (let i = 0; i < items.length; i++) {
+            if (items[i].type.indexOf("image") !== -1) {
+                const file = items[i].getAsFile();
+                const customName = prompt("파일 이름을 설정해주세요. (확장자는 생략)");
+                
+                if (!customName) {
+                    return alert("취소되었습니다.");
+                }
+                
+                const customFile = new File([file], customName + ".png", { type: file.type });
+                formData.append("f_data[]", customFile);
+                haveImageInClipboard = true;
+                e.preventDefault();
+                
+                break;
+            }
+        }
+        if (!haveImageInClipboard) {
+            return;
+        }
+
+        // send to server
+        fetch("/upload", {
+            method: "POST",
+            body: formData,
+        }).then((res) => {
+            if (res.status === 200 || res.status === 201) {
+                const url = res.url;
+                alert(
+                    '클립보드의 이미지를 성공적으로 업로드했습니다. 아래 텍스트로 본문에 삽입할 수 있습니다. ' +
+                    '[[' + decodeURIComponent(url.replace(/.*\/w\/file/, "file")) + ']]'
+                );
+            } else {
+                console.error("[ERROR] PasteUpload Fail :", res.statusText);
+                if(res.status === 400) {
+                    alert("클립보드의 이미지를 업로드하는데 실패했습니다. 파일 이름 중복일 수 있습니다.");
+                } else if(res.status === 401) {
+                    alert("클립보드의 이미지를 업로드하는데 실패했습니다. 권한 부족일 수 있습니다.");    
+                } else {
+                    alert("클립보드의 이미지를 업로드하는데 실패했습니다.");        
+                }
+            }
+        }).catch((err) => {
+            console.error("[ERROR] PasteUpload Fail :", JSON.stringify(err), err);
+            alert("클립보드의 이미지를 업로드하는데 실패했습니다. 서버가 응답하지 않습니다.");
+        });
+    }
+}

+ 0 - 18
views/main_css/js/do_insert_data.js

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

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

@@ -1,10 +0,0 @@
-function do_open_folding(data, element) {
-    var fol = document.getElementById(data);
-    if(fol.style.display === '' || (fol.style.display === 'inline-block' || fol.style.display === 'block')) {
-        document.getElementById(data).style.display = 'none';
-        element.innerHTML = '(+)'
-    } else {
-        document.getElementById(data).style.display = 'block';
-        element.innerHTML = '(-)'
-    }
-}

+ 0 - 13
views/main_css/js/do_open_foot.js

@@ -1,13 +0,0 @@
-function do_open_foot(name, num = 0) {
-    var found_include = name.match(/^(include_(?:[0-9]+)\-)/);
-    if(found_include) {
-        var include_name = name.replace(/^(?:include_(?:[0-9]+)\-)/, '');
-        var front_data = found_include[1];
-    } else {
-        var include_name = name;
-        var front_data = '';
-    }
-
-    document.getElementById(front_data + 'r' + include_name).style.color = 'red';
-    document.getElementById(front_data + 'c' + include_name).style.color = (num === 1 ? 'inherit' : 'red');
-}

+ 0 - 15
views/main_css/js/do_stop_exit.js

@@ -1,15 +0,0 @@
-window.addEventListener('DOMContentLoaded', function() {
-    if(window.location.pathname.match(/^\/edit\//i)) {
-        window.onbeforeunload = function() {
-            data = document.getElementById('content').value;
-            origin = document.getElementById('origin').value;
-            if(data !== origin) {
-                return '';
-            }
-        }
-    }
-});
-
-function save_stop_exit() {
-    window.onbeforeunload = function () { }
-}

+ 0 - 59
views/main_css/js/do_upload_paste.js

@@ -1,59 +0,0 @@
-/*
-window.addEventListener('DOMContentLoaded', function() {
-    if(window.location.pathname.match(/^\/edit\//i)) {
-        const textarea = document.querySelector("textarea");
-        if (textarea) {
-            textarea.addEventListener("paste", pasteListener);
-        }
-    }
-});
-
-function pasteListener(e) {
-    // find file
-    if (e.clipboardData && e.clipboardData.items) {
-        const items = e.clipboardData.items;
-        let haveImageInClipboard = false;
-        const formData = new FormData();
-        for (let i = 0; i < items.length; i++) {
-            if (items[i].type.indexOf("image") !== -1) {
-                const file = items[i].getAsFile();
-                const customName = prompt("파일 이름을 설정해주세요. (확장자는 생략)");
-                
-                if (!customName) {
-                    return alert("취소되었습니다.");
-                }
-                
-                const customFile = new File([file], customName + ".png", { type: file.type });
-                formData.append("f_data[]", customFile);
-                haveImageInClipboard = true;
-                e.preventDefault();
-                
-                break;
-            }
-        }
-        if (!haveImageInClipboard) {
-            return;
-        }
-
-        // send to server
-        fetch("/upload", {
-            method: "POST",
-            body: formData,
-        }).then((res) => {
-            if (res.status === 200 || res.status === 201) {
-                const url = res.url;
-                alert(
-                    '클립보드의 이미지를 성공적으로 업로드했습니다. 아래 텍스트로 본문에 삽입할 수 있습니다.' +
-                    '[[' + decodeURIComponent(url.replace(/.*\/w\/file/, "file")) + ']]'
-                );
-            } else {
-                console.error("[ERROR] PasteUpload Fail :", res.statusText);
-                alert("클립보드의 이미지를 업로드하는데 실패했습니다. 파일 이름 중복일 수 있습니다.");
-            }
-        }).catch((err) => {
-            console.error("[ERROR] PasteUpload Fail :", JSON.stringify(err), err);
-            alert("클립보드의 이미지를 업로드하는데 실패했습니다. 파일 이름 중복일 수 있습니다.");
-        });
-    }
-}
-*/

+ 136 - 37
views/main_css/js/load_namumark.js

@@ -1,11 +1,12 @@
 function get_link_state(data, i = 0) { 
-    if(document.getElementsByClassName(data + 'link_finder')[i]) {
-        var link_data = document.getElementsByClassName(data + 'link_finder')[i];
-        
-        get_link_state(data, i + 1);
-
+    var get_class = document.getElementsByClassName(data + 'link_finder')[i];
+    if(get_class) {
         var xhr = new XMLHttpRequest();
-        xhr.open("GET", link_data.href.replace('/w/', '/api/w/').replace(/#([^#]*)/, '') + "?exist=1", true);
+        xhr.open(
+            "GET", 
+            get_class.href.replace('/w/', '/api/w/').replace(/#([^#]*)/, '') + "?exist=1", 
+            true
+        );
         xhr.send(null);
 
         xhr.onreadystatechange = function() {
@@ -17,34 +18,76 @@ function get_link_state(data, i = 0) {
                 }
             }
         }
+
+        get_link_state(data, i + 1);
     }
 }
 
 function get_file_state(data, i = 0) {       
-    if(document.getElementsByClassName(data + 'file_finder_1')[i]) {
-        var file_data = document.getElementsByClassName(data + 'file_finder_1')[i];
-        
-        get_file_state(data, i + 1);
-
-        var xhr = new XMLHttpRequest();
-        xhr.open("GET", file_data.src.replace('/image/', '/api/image/'), true);
-        xhr.send(null);
-        
-        xhr.onreadystatechange = function() {
-            if(this.readyState === 4 && this.status === 200) {
-                if(JSON.parse(this.responseText)['exist'] !== '1') {
-                    document.getElementsByClassName(data + 'file_finder_1')[i].style = "display: none;";
-                } else {
-                    document.getElementsByClassName(data + 'file_finder_2')[i].innerHTML = "";
+    var get_class = document.getElementsByClassName(data + 'file_finder')[i];
+    if(get_class) {            
+        if(get_class.getAttribute('under_href') === 'out_link') {
+            if(
+                document.cookie.match(main_css_regex_data('main_css_image_set')) &&
+                document.cookie.match(main_css_regex_data('main_css_image_set'))[1] === '1'
+            ) {
+                document.getElementsByClassName(data + 'file_finder')[i].innerHTML = '' +
+                    '<a href="' + get_class.getAttribute('under_src') + '">(' +
+                        get_class.getAttribute('under_src') +
+                    ')</a>' +
+                '';
+            } else {
+                document.getElementsByClassName(data + 'file_finder')[i].innerHTML = '' +
+                    '<img   style="' + get_class.getAttribute('under_style') + '" ' + 
+                            'alt="' + get_class.getAttribute('under_alt') + '" ' + 
+                            'src="' + get_class.getAttribute('under_src') + '">' +
+                '';
+            }
+        } else {
+            var xhr = new XMLHttpRequest();
+            xhr.open(
+                "GET", 
+                get_class.getAttribute('under_src').replace('/image/', '/api/image/'), 
+                true
+            );
+            xhr.send(null);
+            
+            xhr.onreadystatechange = function() {
+                if(this.readyState === 4 && this.status === 200) {
+                    if(JSON.parse(this.responseText)['exist'] !== '1') {
+                        document.getElementsByClassName(data + 'file_finder')[i].innerHTML = '' +
+                            '<a href="' + get_class.getAttribute('under_href') + '" ' + 
+                                'id="not_thing">' +
+                                get_class.getAttribute('under_alt') +
+                            '</a>' +
+                        '';
+                    } else {
+                        if(
+                            document.cookie.match(main_css_regex_data('main_css_image_set')) &&
+                            document.cookie.match(main_css_regex_data('main_css_image_set'))[1] === '1'
+                        ) {
+                            document.getElementsByClassName(data + 'file_finder')[i].innerHTML = '' +
+                                '<a href="' + get_class.getAttribute('under_src') + '">(' +
+                                    get_class.getAttribute('under_alt') +
+                                ')</a>' +
+                            '';
+                        } else {
+                            document.getElementsByClassName(data + 'file_finder')[i].innerHTML = '' +
+                                '<img   style="' + get_class.getAttribute('under_style') + '" ' + 
+                                        'alt="' + get_class.getAttribute('under_alt') + '" ' + 
+                                        'src="' + get_class.getAttribute('under_src') + '">' +
+                            '';
+                        }
+                    }
                 }
             }
         }
+
+        get_file_state(data, i + 1);
     }
 }
 
 function load_include(title, name, p_data) {
-    var o_data = document.getElementById(name);
-
     var change = '';
     for(key in p_data) {
         change += '@' + p_data[key][0].replace('&', '<amp>') + '@,' + p_data[key][1].replace(',', '<comma>').replace('&', '<amp>') + ','
@@ -59,15 +102,13 @@ function load_include(title, name, p_data) {
     xhr.onreadystatechange = function() {
         if(this.readyState === 4 && this.status === 200) {
             if(this.responseText === "{}\n") {
-                o_data.innerHTML = "";
-
+                document.getElementById(name).innerHTML = "";
                 document.getElementsByClassName(name)[0].id = "not_thing";
             } else {
                 var o_p_data = JSON.parse(this.responseText);
                 
-                var g_data = o_p_data['data'];
-                o_data.innerHTML = g_data;
-
+                document.getElementById(name).innerHTML = o_p_data['data'];
+                
                 eval(o_p_data['js_data']);
             }
         }
@@ -75,8 +116,6 @@ function load_include(title, name, p_data) {
 }
 
 function page_count() {
-    var n_ver = document.getElementsByClassName('all_page_count');
-
     var url = "/api/title_index";
 
     var xhr = new XMLHttpRequest();
@@ -86,14 +125,74 @@ function page_count() {
     xhr.onreadystatechange = function() {
         if(this.readyState === 4 && this.status === 200) {
             var i = 0;
-            while(1) {
-                if(n_ver[i]) {
-                    n_ver[i].innerHTML = JSON.parse(this.responseText)['count'];
-                    i += 1;
-                } else {
-                    break;
-                }
+            while(document.getElementsByClassName('all_page_count')[i]) {
+                document.getElementsByClassName('all_page_count')[i].innerHTML = JSON.parse(this.responseText)['count'];
+                
+                i += 1;
+            }
+        }
+    }
+}
+
+function not_from_exist() {
+    window.addEventListener('DOMContentLoaded', function() {
+        if(document.getElementById('go_redirect_link')) {
+            var r_link = document.getElementById('go_redirect_link').href;
+            if(r_link.match(/#([^#]+)$/)) {
+                var s_link = '#' + r_link.match(/#([^#]+)$/)[1];
+                r_link = r_link.replace(/#([^#]+)$/, '');
+            } else {
+                var s_link = '';
+            }
+
+            window.location.href = r_link + '?from=' + location.pathname.replace(/^\/w\//, '') + s_link;
+        }
+    });
+}
+
+function do_open_folding(data, element) {
+    var fol = document.getElementById(data);
+    if(fol.style.display === '' || (fol.style.display === 'inline-block' || fol.style.display === 'block')) {
+        document.getElementById(data).style.display = 'none';
+        element.innerHTML = '(+)'
+    } else {
+        document.getElementById(data).style.display = 'block';
+        element.innerHTML = '(-)'
+    }
+}
+
+function do_open_foot(name, num = 0) {
+    var found_include = name.match(/^(include_(?:[0-9]+)\-)/);
+    if(found_include) {
+        var include_name = name.replace(/^(?:include_(?:[0-9]+)\-)/, '');
+        var front_data = found_include[1];
+    } else {
+        var include_name = name;
+        var front_data = '';
+    }
+
+    if(
+        document.cookie.match(main_css_regex_data('main_css_footnote_set')) &&
+        document.cookie.match(main_css_regex_data('main_css_footnote_set'))[1] === '1'
+    ) {
+        if(num === 1) {
+            document.getElementById(front_data + 'r' + include_name).focus();
+        } else {
+            var get_data = document.getElementById(front_data + include_name).innerHTML;
+            var org_data = document.getElementById(front_data + 'd' + include_name).innerHTML;
+            if(org_data === '') {
+                document.getElementById(front_data + 'd' + include_name).innerHTML = '' +
+                    '<a href="#' + front_data + 'c' + include_name + '">(Go)</a> ' + get_data +
+                '';
+                document.getElementById(front_data + 'd' + include_name).className = 'spead_footnote';
+            } else {
+                document.getElementById(front_data + 'd' + include_name).innerHTML = '';
+                document.getElementById(front_data + 'd' + include_name).className = '';
             }
         }
+    } else {
+        document.getElementById(front_data + 'r' + include_name).style.color = 'red';
+        document.getElementById(front_data + 'c' + include_name).style.color = (num === 1 ? 'inherit' : 'red');
+        document.getElementById(front_data + (num === 1 ? 'r' : 'c') + include_name).focus();
     }
 }

+ 6 - 5
views/main_css/js/load_preview.js

@@ -1,9 +1,6 @@
 function load_preview(name) {
-    var o_data = document.getElementById('content');
-    var p_data = document.getElementById('see_preview');
-
     var s_data = new FormData();
-    s_data.append('data', o_data.value);
+    s_data.append('data', document.getElementById('content').value);
 
     var url = "/api/w/" + name;
     var url_2 = "/api/markup";
@@ -19,8 +16,12 @@ function load_preview(name) {
     xhr.onreadystatechange = function() {
         if(xhr.readyState === 4 && xhr.status === 200) {
             var o_p_data = JSON.parse(xhr.responseText);
-            p_data.innerHTML = o_p_data['data'];
+            document.getElementById('see_preview').innerHTML = o_p_data['data'];
             eval(o_p_data['js_data'])
         }
     }
+}
+
+function load_raw_preview(name_1, name_2) {
+    document.getElementById(name_2).innerHTML = document.getElementById(name_1).value;
 }

+ 0 - 6
views/main_css/js/load_raw_preview.js

@@ -1,6 +0,0 @@
-function load_raw_preview(name_1, name_2) {
-    var get = document.getElementById(name_1);
-    var send = document.getElementById(name_2);
-
-    send.innerHTML = get.value;
-}

+ 201 - 131
views/main_css/js/load_skin_set.js

@@ -1,3 +1,7 @@
+function main_css_regex_data(data) {
+    return new RegExp('(?:^|; )' + data + '=([^;]*)');
+}
+
 function main_css_get_post() {    
     var check = document.getElementById('strike');
     if(check.value === 'normal') {
@@ -18,7 +22,7 @@ function main_css_get_post() {
     }
 
     check = document.getElementById('include');
-    if(check.checked === true) {
+    if(check.checked) {
         document.cookie = 'main_css_include_link=1;';
     } else {
         document.cookie = 'main_css_include_link=0;';
@@ -31,6 +35,27 @@ function main_css_get_post() {
         document.cookie = 'main_css_category_set=1;';
     }
 
+    check = document.getElementById('footnote');
+    if(check.value === 'spread') {
+        document.cookie = 'main_css_footnote_set=1;';
+    } else {
+        document.cookie = 'main_css_footnote_set=0;';
+    }
+
+    check = document.getElementById('image');
+    if(check.value === 'click') {
+        document.cookie = 'main_css_image_set=1;';
+    } else {
+        document.cookie = 'main_css_image_set=0;';
+    }
+
+    check = document.getElementById('image_paste');
+    if(check.checked) {
+        document.cookie = 'main_css_image_paste=1;';
+    } else {
+        document.cookie = 'main_css_image_paste=0;';
+    }
+
     history.go(0);
 }
 
@@ -76,151 +101,196 @@ function main_css_skin_load() {
     }
 }
 
-function main_css_regex_data(data) {
-    return new RegExp('(?:^|; )' + data + '=([^;]*)');
-}
-
 function main_css_skin_set() {    
-    if(window.location.pathname === '/main_skin_set') {
-        var set_language = {
-            "en-US" : {
-                "default" : "Default",
-                "change_to_normal" : "Change to normal text",
-                "delete" : "Delete",
-                "include_link" : "Using include link",
-                "save" : "Save",
-                "strike" : "Strike",
-                "bold" : "Bold",
-                "other" : "Other",
-                "where_category" : "Set category location",
-                "bottom" : "Bottom",
-                "top" : "Top"
-            }, "ko-KR" : {
-                "default" : "기본값",
-                "change_to_normal" : "일반 텍스트로 변경",
-                "delete" : "삭제",
-                "include_link" : "틀 링크 사용",
-                "save" : "저장",
-                "strike" : "취소선",
-                "bold" : "볼드체",
-                "other" : "기타",
-                "where_category" : "분류 위치 설정",
-                "bottom" : "아래",
-                "top" : "위"
-            }
+    var set_language = {
+        "en-US" : {
+            "default" : "Default",
+            "change_to_normal" : "Change to normal text",
+            "delete" : "Delete",
+            "include_link" : "Using include link",
+            "save" : "Save",
+            "strike" : "Strike",
+            "bold" : "Bold",
+            "other" : "Other",
+            "where_category" : "Set category location",
+            "bottom" : "Bottom",
+            "top" : "Top",
+            "set_footnote" : "Set footnote",
+            "renderer" : "Renderer",
+            "spread" : "Spread",
+            "set_image" : "Set image"
+        }, "ko-KR" : {
+            "default" : "기본값",
+            "change_to_normal" : "일반 텍스트로 변경",
+            "delete" : "삭제",
+            "include_link" : "틀 링크 사용",
+            "save" : "저장",
+            "strike" : "취소선",
+            "bold" : "볼드체",
+            "other" : "기타",
+            "where_category" : "분류 위치 설정",
+            "bottom" : "아래",
+            "top" : "위",
+            "set_footnote" : "각주 설정",
+            "renderer" : "렌더러",
+            "spread" : "펼치기",
+            "set_image" : "이미지 설정"
         }
+    }
 
-        var language = document.cookie.match(main_css_regex_data('language'))[1];
-        var user_language = document.cookie.match(main_css_regex_data('user_language'))[1];
-        if(user_language in set_language) {
-            language = user_language;
-        }
+    var language = document.cookie.match(main_css_regex_data('language'))[1];
+    var user_language = document.cookie.match(main_css_regex_data('user_language'))[1];
+    if(user_language in set_language) {
+        language = user_language;
+    }
 
-        if(!language in set_language) {
-            language = "en-US";
-        }
+    if(!language in set_language) {
+        language = "en-US";
+    }
 
-        var data = document.getElementById("main_skin_set");
-        var set_data = {};
-
-        var strike_list = [
-            ['0', 'normal', set_language[language]['default']],
-            ['1', 'change', set_language[language]['change_to_normal']],
-            ['2', 'delete', set_language[language]['delete']]
-        ];
-        set_data["strike"] = '';
-        var i = 0;
-        while(1) {
-            if(strike_list[i]) {
-                if(
-                    document.cookie.match(main_css_regex_data('main_css_del_strike')) && 
-                    document.cookie.match(main_css_regex_data('main_css_del_strike'))[1] === strike_list[i][0]
-                ) {
-                    set_data["strike"] = '<option value="' + strike_list[i][1] + '">' + strike_list[i][2] + '</option>' + set_data["strike"];
-                } else {
-                    set_data["strike"] += '<option value="' + strike_list[i][1] + '">' + strike_list[i][2] + '</option>';
-                }
-
-                i += 1;
-            } else {
-                break;
-            }
+    var set_data = {};
+    var strike_list = [
+        ['0', 'normal', set_language[language]['default']],
+        ['1', 'change', set_language[language]['change_to_normal']],
+        ['2', 'delete', set_language[language]['delete']]
+    ];
+    set_data["strike"] = '';
+    var i = 0;
+    while(strike_list[i]) {
+        if(
+            document.cookie.match(main_css_regex_data('main_css_del_strike')) && 
+            document.cookie.match(main_css_regex_data('main_css_del_strike'))[1] === strike_list[i][0]
+        ) {
+            set_data["strike"] = '<option value="' + strike_list[i][1] + '">' + strike_list[i][2] + '</option>' + set_data["strike"];
+        } else {
+            set_data["strike"] += '<option value="' + strike_list[i][1] + '">' + strike_list[i][2] + '</option>';
         }
 
-        var bold_list = [
-            ['0', 'normal', set_language[language]['default']],
-            ['1', 'change', set_language[language]['change_to_normal']],
-            ['2', 'delete', set_language[language]['delete']]
-        ];
-        set_data["bold"] = '';
-        var i = 0;
-        while(1) {
-            if(bold_list[i]) {
-                if(
-                    document.cookie.match(main_css_regex_data('main_css_del_bold')) && 
-                    document.cookie.match(main_css_regex_data('main_css_del_bold'))[1] === bold_list[i][0]
-                ) {
-                    set_data["bold"] = '<option value="' + bold_list[i][1] + '">' + bold_list[i][2] + '</option>' + set_data["bold"];
-                } else {
-                    set_data["bold"] += '<option value="' + bold_list[i][1] + '">' + bold_list[i][2] + '</option>';
-                }
-
-                i += 1;
-            } else {
-                break;
-            }
+        i += 1;
+    }
+
+    var bold_list = [
+        ['0', 'normal', set_language[language]['default']],
+        ['1', 'change', set_language[language]['change_to_normal']],
+        ['2', 'delete', set_language[language]['delete']]
+    ];
+    set_data["bold"] = '';
+    i = 0;
+    while(bold_list[i]) {
+        if(
+            document.cookie.match(main_css_regex_data('main_css_del_bold')) && 
+            document.cookie.match(main_css_regex_data('main_css_del_bold'))[1] === bold_list[i][0]
+        ) {
+            set_data["bold"] = '<option value="' + bold_list[i][1] + '">' + bold_list[i][2] + '</option>' + set_data["bold"];
+        } else {
+            set_data["bold"] += '<option value="' + bold_list[i][1] + '">' + bold_list[i][2] + '</option>';
         }
 
+        i += 1;
+    }
+
+    if(
+        document.cookie.match(main_css_regex_data('main_css_include_link')) &&
+        document.cookie.match(main_css_regex_data('main_css_include_link'))[1] === '1'
+    ) {
+        set_data["include"] = "checked";
+    } else {
+        set_data["include"] = "";
+    }
+
+    if(
+        document.cookie.match(main_css_regex_data('main_css_image_paste')) &&
+        document.cookie.match(main_css_regex_data('main_css_image_paste'))[1] === '1'
+    ) {
+        set_data["image_paste"] = "checked";
+    } else {
+        set_data["image_paste"] = "";
+    }
+
+    var category_list = [
+        ['0', 'bottom', set_language[language]['bottom']],
+        ['1', 'top', set_language[language]['top']],
+    ];
+    set_data["category"] = '';
+    i = 0;
+    while(category_list[i]) {
         if(
-            document.cookie.match(main_css_regex_data('main_css_include_link')) &&
-            document.cookie.match(main_css_regex_data('main_css_include_link'))[1] === '1'
+            document.cookie.match(main_css_regex_data('main_css_category_set')) && 
+            document.cookie.match(main_css_regex_data('main_css_category_set'))[1] === category_list[i][0]
         ) {
-            set_data["include"] = "checked";
+            set_data["category"] = '<option value="' + category_list[i][1] + '">' + category_list[i][2] + '</option>' + set_data["category"];
+        } else {
+            set_data["category"] += '<option value="' + category_list[i][1] + '">' + category_list[i][2] + '</option>';
         }
 
-        var category_list = [
-            ['0', 'bottom', set_language[language]['bottom']],
-            ['1', 'top', set_language[language]['top']],
-        ];
-        set_data["category"] = '';
-        var i = 0;
-        while(1) {
-            if(category_list[i]) {
-                if(
-                    document.cookie.match(main_css_regex_data('main_css_category_set')) && 
-                    document.cookie.match(main_css_regex_data('main_css_category_set'))[1] === category_list[i][0]
-                ) {
-                    set_data["category"] = '<option value="' + category_list[i][1] + '">' + category_list[i][2] + '</option>' + set_data["category"];
-                } else {
-                    set_data["category"] += '<option value="' + category_list[i][1] + '">' + category_list[i][2] + '</option>';
-                }
-
-                i += 1;
-            } else {
-                break;
-            }
+        i += 1;
+    }
+
+    var footnote_list = [
+        ['0', 'normal', set_language[language]['default']],
+        ['1', 'spread', set_language[language]['spread']]
+    ];
+    set_data["footnote"] = '';
+    i = 0;
+    while(footnote_list[i]) {
+        if(
+            document.cookie.match(main_css_regex_data('main_css_footnote_set')) && 
+            document.cookie.match(main_css_regex_data('main_css_footnote_set'))[1] === footnote_list[i][0]
+        ) {
+            set_data["footnote"] = '<option value="' + footnote_list[i][1] + '">' + footnote_list[i][2] + '</option>' + set_data["footnote"];
+        } else {
+            set_data["footnote"] += '<option value="' + footnote_list[i][1] + '">' + footnote_list[i][2] + '</option>';
         }
 
+        i += 1;
+    }
+
+    var image_list = [
+        ['0', 'normal', set_language[language]['default']],
+        ['1', 'click', 'click (beta)']
+    ];
+    set_data["image"] = '';
+    i = 0;
+    while(image_list[i]) {
+        if(
+            document.cookie.match(main_css_regex_data('main_css_image_set')) && 
+            document.cookie.match(main_css_regex_data('main_css_image_set'))[1] === image_list[i][0]
+        ) {
+            set_data["image"] = '<option value="' + image_list[i][1] + '">' + image_list[i][2] + '</option>' + set_data["image"];
+        } else {
+            set_data["image"] += '<option value="' + image_list[i][1] + '">' + image_list[i][2] + '</option>';
+        }
 
-        data.innerHTML = ' \
-            <h2>' + set_language[language]['strike'] + '</h2> \
-            <hr class="main_hr"> \
-            <select id="strike" name="strike"> \
-                ' + set_data["strike"] + ' \
-            </select> \
-            <h2>' + set_language[language]['bold'] + '</h2> \
-            <select id="bold" name="bold"> \
-                ' + set_data["bold"] + ' \
-            </select> \
-            <h2>' + set_language[language]['where_category'] + '</h2> \
-            <select id="category" name="category"> \
-                ' + set_data["category"] + ' \
-            </select> \
-            <hr class="main_hr"> \
-            <h2>' + set_language[language]['other'] + '</h2> \
-            <input ' + set_data["include"] + ' type="checkbox" id="include" name="include" value="include"> ' + set_language[language]['include_link'] + ' \
-            <hr class="main_hr"> \
-            <button onclick="main_css_get_post();">' + set_language[language]['save'] + '</button> \
-        ';
+        i += 1;
     }
+
+    document.getElementById("main_skin_set").innerHTML = ' \
+        <h2>1. ' + set_language[language]['renderer'] + '</h2> \
+        <h3>1.1. ' + set_language[language]['strike'] + '</h3> \
+        <select id="strike" name="strike"> \
+            ' + set_data["strike"] + ' \
+        </select> \
+        <h3>1.2. ' + set_language[language]['bold'] + '</h3> \
+        <select id="bold" name="bold"> \
+            ' + set_data["bold"] + ' \
+        </select> \
+        <h3>1.3. ' + set_language[language]['where_category'] + '</h3> \
+        <select id="category" name="category"> \
+            ' + set_data["category"] + ' \
+        </select> \
+        <h3>1.4. ' + set_language[language]['set_footnote'] + '</h3> \
+        <select id="footnote" name="footnote"> \
+            ' + set_data["footnote"] + ' \
+        </select> \
+        <h3>1.5. ' + set_language[language]['set_image'] + '</h3> \
+        <select id="image" name="image"> \
+            ' + set_data["image"] + ' \
+        </select> \
+        <h3>1.6. ' + set_language[language]['other'] + '</h3> \
+        <input ' + set_data["include"] + ' type="checkbox" id="include" name="include" value="include"> ' + set_language[language]['include_link'] + ' \
+        <hr class="main_hr"> \
+        <input ' + set_data["image_paste"] + ' type="checkbox" id="image_paste" name="image_paste" value="image_paste"> 클립보드 이미지 업로드 (ko-KR) \
+        <hr class="main_hr"> \
+        <button onclick="main_css_get_post();">' + set_language[language]['save'] + '</button> \
+    ';
 }

+ 26 - 0
views/main_css/js/load_something.js

@@ -0,0 +1,26 @@
+function load_user_info(name) {
+    var url = "/api/user_info/" + encodeURI(name) + "?render=1";
+    var xhr = new XMLHttpRequest();
+    xhr.open("GET", url, true);
+    xhr.send(null);
+
+    xhr.onreadystatechange = function() {
+        if(this.readyState === 4 && this.status === 200) {
+            document.getElementById('get_user_info').innerHTML += JSON.parse(this.responseText)['data'];
+        }
+    }
+}
+
+function load_ver() {
+    var url = "/api/version";
+    var xhr = new XMLHttpRequest();
+    xhr.open("GET", url, true);
+    xhr.send(null);
+
+    xhr.onreadystatechange = function() {
+        if(this.readyState === 4 && this.status === 200) {
+            document.getElementById('ver_send').innerHTML += JSON.parse(this.responseText)['lastest_version'];
+            document.getElementById('ver_send').style.display = "list-item";
+        }
+    }
+}

+ 7 - 10
views/main_css/js/load_topic.js

@@ -1,5 +1,4 @@
 function topic_list_load(topic_num, s_num, where) {
-    var o_data = document.getElementById(where);
     var url = "/api/thread/" + String(topic_num) + "?render=1&num=" + String(s_num);
     var n_data = "";
 
@@ -17,7 +16,7 @@ function topic_list_load(topic_num, s_num, where) {
                 t_plus_data += t_data[key]['plus_data'];
             }
 
-            o_data.innerHTML = n_data;
+            document.getElementById(where).innerHTML = n_data;
             eval(t_plus_data);
         }
     }
@@ -26,7 +25,6 @@ function topic_list_load(topic_num, s_num, where) {
 function topic_plus_load(topic_num, num) {
     var test = setInterval(function() {
         var url = "/api/thread/" + String(topic_num) + "?num=" + num + "&render=1";
-        var p_data = document.getElementById("plus_topic");
         var n_data = '';
         var n_num = 1;
 
@@ -46,7 +44,7 @@ function topic_plus_load(topic_num, num) {
                     t_plus_data += t_data[key]['plus_data'];
                 }
 
-                p_data.innerHTML += n_data;
+                document.getElementById("plus_topic").innerHTML += n_data;
                 eval(t_plus_data);
 
                 topic_plus_load(topic_num, String(Number(num) + 1));
@@ -57,7 +55,6 @@ function topic_plus_load(topic_num, num) {
 }
 
 function topic_main_load(topic_num, s_num) {
-    var o_data = document.getElementById('main_topic');
     if(s_num) {
         var url = "/api/thread/" + String(topic_num) + "?render=1&num=" + s_num;
     } else {
@@ -82,10 +79,11 @@ function topic_main_load(topic_num, s_num) {
                 t_plus_data += t_data[key]['plus_data'];
             }
 
-            o_data.innerHTML = n_data;
+            document.getElementById('main_topic').innerHTML = n_data;
             eval(t_plus_data);
-            if(window.location.search === "?where=bottom") {
-                document.getElementById(num).focus();
+
+            if(window.location.hash) {
+                document.getElementById(window.location.hash.replace(/^#/, '')).focus();
             }
             
             if(!s_num) {
@@ -96,7 +94,6 @@ function topic_main_load(topic_num, s_num) {
 }
 
 function topic_top_load(topic_num) {
-    var o_data = document.getElementById('top_topic');
     var url = "/api/thread/" + String(topic_num) + "?top=1&render=1";
     var n_data = "";
     var num = 1;
@@ -117,7 +114,7 @@ function topic_top_load(topic_num) {
                 t_plus_data += t_data[key]['plus_data'];
             }
 
-            o_data.innerHTML = n_data;
+            document.getElementById('top_topic').innerHTML = n_data;
             eval(t_plus_data);
 
             topic_main_load(topic_num, null);

+ 0 - 15
views/main_css/js/load_user_info.js

@@ -1,15 +0,0 @@
-function load_user_info(name) {
-    var n_ver = document.getElementById('get_user_info');
-
-    var url = "/api/user_info/" + encodeURI(name) + "?render=1";
-
-    var xhr = new XMLHttpRequest();
-    xhr.open("GET", url, true);
-    xhr.send(null);
-
-    xhr.onreadystatechange = function() {
-        if(this.readyState === 4 && this.status === 200) {
-            n_ver.innerHTML += JSON.parse(this.responseText)['data'];
-        }
-    }
-}

+ 0 - 16
views/main_css/js/load_ver.js

@@ -1,16 +0,0 @@
-function load_ver() {
-    var n_ver = document.getElementById('ver_send');
-
-    var url = "/api/version";
-
-    var xhr = new XMLHttpRequest();
-    xhr.open("GET", url, true);
-    xhr.send(null);
-
-    xhr.onreadystatechange = function() {
-        if(this.readyState === 4 && this.status === 200) {
-            n_ver.innerHTML += JSON.parse(this.responseText)['lastest_version'];
-            n_ver.style.display = "list-item";
-        }
-    }
-}

+ 1 - 1
views/main_css/js/render_html.js

@@ -95,7 +95,7 @@ function render_html(name = '') {
                             height_data = '';
                         }
 
-                        return '<' + t_data[key] + ' src="' + src_data + '" width="' + width_data + '" height="' + height_data + '">' + in_data_2 + '</' + t_data[key] + '>';
+                        return '<' + t_data[key] + ' controls src="' + src_data + '" width="' + width_data + '" height="' + height_data + '">' + in_data_2 + '</' + t_data[key] + '>';
                     }
                 });
             }

+ 17 - 9
views/marisa/css/main.css

@@ -1,11 +1,9 @@
-@import url(https://fonts.googleapis.com/earlyaccess/nanumgothic.css);
-
 body {
     max-width: 100%;
     word-break: break-all;
     word-wrap: break-word;
     margin: 0;
-    font-family: "나눔고딕", "Nanum Gothic", sans-serif;
+    font-family: 'Apple SD Gothic', '맑은고딕', 'Nanum Gothic', 'Noto Sans KR', sans-serif;
     font-size: 14px;
 }
 
@@ -25,7 +23,7 @@ hr {
 
 button {
     padding: 10px;
-    border: 1px solid gainsboro;
+    border: 1px solid #aaa;
     background: white;
     cursor: pointer;
 }
@@ -85,7 +83,7 @@ li {
 
 @media (min-width: 780px) and (max-width: 1350px) {
     #main {
-        width: 90%;
+        width: calc(100% - 45px);
     }
 
     #top_main {
@@ -213,7 +211,7 @@ h6 {
 }
 
 .cel_in_cel {
-    border: 1px solid gainsboro;
+    border: 1px solid #aaa;
     padding: 10px;
     position: absolute;
     background: white;
@@ -309,12 +307,12 @@ a {
 }
 
 pre, #toc, #cate, #redirect {
-    border: 1px solid gainsboro;
+    border: 1px solid #aaa;
 }
 
 textarea, input {
-    border: 1px solid gainsboro;
-    font-family: '나눔고딕', 'Nanum Gothic', 'Noto Sans KR', 'Malgun Gothic', '맑은 고딕', sans-serif;
+    font-family: 'Apple SD Gothic', '맑은고딕', 'Nanum Gothic', 'Noto Sans KR', sans-serif;
+    border: 1px solid #aaa;
     padding: 5px;
     margin-left: -5px;
 }
@@ -351,6 +349,7 @@ textarea, input {
     border: 1px solid #4a4a4a;
     background: #4a4a4a;
     text-align: center;
+    height: 45px;
 }
 
 #nav_bar a {
@@ -426,4 +425,13 @@ button#save {
 
 div#top_tool_cel a:hover, #logo a:hover, #search button:hover, div#nav_bar a:hover {
     color: #aaa;
+}
+
+div#main {
+    border-left: 1px solid #aaa;
+    border-right: 1px solid #aaa;
+}
+
+#bottom {   
+    border-top: 1px solid #aaa;   
 }

+ 1 - 1
views/marisa/index.html

@@ -8,7 +8,7 @@
             <title>{{imp[0]}} - {{imp[1][0]}}</title>
         {% endif %}
         {{imp[3][3]|safe}}
-        <link rel="stylesheet" href="/views/marisa/css/main.css?ver=9">
+        <link rel="stylesheet" href="/views/marisa/css/main.css?ver=14">
         <script src="/views/marisa/js/skin_set.js?ver=4"></script>
         <script src="/views/marisa/js/main.js?ver=3"></script>
         <script>main_load(); window.addEventListener('DOMContentLoaded', function() { skin_set(); });</script>

+ 1 - 1
views/marisa/info.json

@@ -1,5 +1,5 @@
 {
     "name" : "Marisa",
-    "skin_ver" : "v1.2.1",
+    "skin_ver" : "v1.2.6",
     "require_ver" : "8"
 }

+ 1 - 3
views/marisa/js/main.js

@@ -23,14 +23,12 @@ function opening(data) {
 }
 
 document.onclick = function(event) {
-    var element = document.getElementById(save_data);
-
     for(var node = event.target; node != document.body; node = node.parentNode) {
         if(save_data !== '' && open == 0) {
             if(node.id === save_data) {
                 break;
             } else {
-                element.style.display = 'none';
+                document.getElementById(save_data).style.display = 'none';
             }
         }
     }

+ 1 - 2
views/marisa/js/skin_set.js

@@ -47,7 +47,6 @@ function skin_set() {
             language = "en-US";
         }
 
-        var data = document.getElementById("main_skin_set");
         var set_data = {};
 
         if(
@@ -57,7 +56,7 @@ function skin_set() {
             set_data["invert"] = "checked";
         }
 
-        data.innerHTML = ' \
+        document.getElementById("main_skin_set").innerHTML = ' \
             <input ' + set_data["invert"] + ' type="checkbox" id="invert" name="invert" value="invert"> ' + set_language[language]['darkmode'] + ' \
             <hr class="main_hr"> \
             <button onclick="get_post();">' + set_language[language]['save'] + '</button> \

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