2DU 9 år sedan
förälder
incheckning
437b67a44d
4 ändrade filer med 3359 tillägg och 1 borttagningar
  1. 299 0
      func.py
  2. 2047 1
      main.py
  3. 1013 0
      mark.py
  4. 0 0
      parser.py

+ 299 - 0
func.py

@@ -0,0 +1,299 @@
+from flask import Flask, session, request
+
+from urllib import parse
+import json
+import pymysql
+import time
+import re
+import json
+
+json_data = open('set.json').read()
+set_data = json.loads(json_data)
+
+conn = pymysql.connect(host = set_data['host'], user = set_data['user'], password = set_data['pw'], charset = 'utf8mb4')
+curs = conn.cursor(pymysql.cursors.DictCursor)
+
+def db_com():
+    conn.commit()
+
+def url_pas(data):
+    return parse.quote(data).replace('/','%2F')
+    
+def db_get():
+    return curs.fetchall()
+    
+db_ex = curs.execute
+db_pas = pymysql.escape_string
+
+db_ex("use " + set_data['db'])
+
+def diff(seqm):
+    output= []
+    for opcode, a0, a1, b0, b1 in seqm.get_opcodes():
+        if(opcode == 'equal'):
+            output.append(seqm.a[a0:a1])
+        elif(opcode == 'insert'):
+            output.append("<span style='background:#CFC;'>" + seqm.b[b0:b1] + "</span>")
+        elif(opcode == 'delete'):
+            output.append("<span style='background:#FDD;'>" + seqm.a[a0:a1] + "</span>")
+        elif(opcode == 'replace'):
+            output.append("<span style='background:#CFC;'>" + seqm.b[b0:b1] + "</span><span style='background:#FDD;'>" + seqm.a[a0:a1] + "</span>")
+        else:
+            output.append(seqm.a[a0:a1])
+    return ''.join(output)
+           
+def admin_check():
+    if(session.get('Now') == True):
+        ip = ip_check()
+        db_ex("select * from user where id = '" + db_pas(ip) + "'")
+        user = db_get()
+        if(user):
+            if(user[0]['acl'] == 'owner' or user[0]['acl'] == 'admin'):
+                return 1
+                
+def owner_check():
+    if(session.get('Now') == True):
+        ip = ip_check()
+        db_ex("select * from user where id = '" + db_pas(ip) + "'")
+        user = db_get()
+        if(user):
+            if(user[0]['acl'] == 'owner'):
+                return 1
+                
+def include_check(name, data):
+    if(re.search('^틀:', name)):
+        db_ex("select * from back where title = '" + db_pas(name) + "' and type = 'include'")
+        back = db_get()
+        if(back):
+            i = 0
+
+            while(True):
+                try:
+                    namumark(back[i]['link'], data)
+                except:
+                    break
+                    
+                i += 1
+    
+def login_check():
+    if(session.get('Now') == True):
+        return 1
+    else:
+        return 0
+
+def ip_pas(raw_ip):
+    yes = re.search("([^-]*)\s\-\s(Close|Reopen|Stop|Restart|Admin|Agreement|Settlement)$", raw_ip)
+    if(yes):
+        results = yes.groups()
+        
+        db_ex("select * from data where title = '사용자:" + db_pas(results[0]) + "'")
+        row = db_get()
+        if(row):
+            ip = '<a href="/w/' + url_pas('사용자:' + results[0]) + '">' + results[0] + '</a> - ' + results[1] + ' <a href="/record/' + url_pas(results[0]) + '/n/1">(기록)</a>'
+        else:
+            ip = '<a class="not_thing" href="/w/' + url_pas('사용자:' + results[0]) + '">' + results[0] + '</a> - ' + results[1] + ' <a href="/record/' + url_pas(results[0]) + '/n/1">(기록)</a>'
+    elif(re.search("\.", raw_ip)):
+        ip = raw_ip + ' <a href="/record/' + url_pas(raw_ip) + '/n/1">(기록)</a>'
+    else:
+        db_ex("select * from data where title = '사용자:" + db_pas(raw_ip) + "'")
+        row = db_get()
+        if(row):
+            ip = '<a href="/w/' + url_pas('사용자:' + raw_ip) + '">' + raw_ip + '</a> <a href="/record/' + url_pas(raw_ip) + '/n/1">(기록)</a>'
+        else:
+            ip = '<a class="not_thing" href="/w/' + url_pas('사용자:' + raw_ip) + '">' + raw_ip + '</a> <a href="/record/' + url_pas(raw_ip) + '/n/1">(기록)</a>'
+
+    return ip
+
+def ip_check():
+    if(session.get('Now') == True):
+        ip = format(session['DREAMER'])
+    else:
+        if(request.headers.getlist("X-Forwarded-For")):
+            ip = request.headers.getlist("X-Forwarded-For")[0]
+        else:
+            ip = request.remote_addr
+            
+    return ip
+
+def acl_check(ip, name):
+    m = re.search("^사용자:(.*)", name)
+    n = re.search("^파일:(.*)", name)
+    if(m):
+        g = m.groups()
+        if(ip == g[0]):
+            if(re.search("\.", g[0])):
+                return 1
+            else:
+                db_ex("select * from ban where block = '" + db_pas(ip) + "'")
+                rows = db_get()
+                if(rows):
+                    return 1
+                else:
+                    return 0
+        else:
+            return 1
+    elif(n):
+        if(not owner_check() == 1):
+            return 1
+    else:
+        b = re.search("^([0-9](?:[0-9]?[0-9]?)\.[0-9](?:[0-9]?[0-9]?))", ip)
+        if(b):
+            results = b.groups()
+            db_ex("select * from ban where block = '" + db_pas(results[0]) + "' and band = 'O'")
+            rowss = db_get()
+            if(rowss):
+                return 1
+            else:
+                db_ex("select * from ban where block = '" + db_pas(ip) + "'")
+                rows = db_get()
+                if(rows):
+                    return 1
+                else:
+                    db_ex("select * from data where title = '" + db_pas(name) + "'")
+                    row = db_get()
+                    if(row):
+                        db_ex("select * from user where id = '" + db_pas(ip) + "'")
+                        rows = db_get()
+                        if(row[0]['acl'] == 'user'):
+                            if(rows):
+                                return 0
+                            else:
+                                return 1
+                        elif(row[0]['acl'] == 'admin'):
+                            if(rows):
+                                if(rows[0]['acl'] == 'admin' or rows[0]['acl'] == 'owner'):
+                                    return 0
+                                else:
+                                    return 1
+                            else:
+                                return 1
+                        else:
+                            return 0
+                    else:
+                        return 0
+        else:
+            db_ex("select * from ban where block = '" + db_pas(ip) + "'")
+            rows = db_get()
+            if(rows):
+                return 1
+            else:
+                db_ex("select * from data where title = '" + db_pas(name) + "'")
+                row = db_get()
+                if(row):
+                    db_ex("select * from user where id = '" + db_pas(ip) + "'")
+                    rows = db_get()
+                    if(row[0]['acl'] == 'user'):
+                        if(rows):
+                            return 0
+                        else:
+                            return 1
+                    elif(row[0]['acl'] == 'admin'):
+                        if(rows):
+                            if(rows[0]['acl'] == 'admin' or rows[0]['acl'] == 'owner'):
+                                return 0
+                            else:
+                                return 1
+                        else:
+                            return 1
+                    else:
+                        return 0
+                else:
+                    return 0
+
+def ban_check(ip):
+    b = re.search("^([0-9](?:[0-9]?[0-9]?)\.[0-9](?:[0-9]?[0-9]?))", ip)
+    if(b):
+        results = b.groups()
+        db_ex("select * from ban where block = '" + db_pas(results[0]) + "' and band = 'O'")
+        rowss = db_get()
+        if(rowss):
+            return 1
+        else:
+            db_ex("select * from ban where block = '" + db_pas(ip) + "'")
+            rows = db_get()
+            if(rows):
+                return 1
+            else:
+                return 0
+    else:
+        db_ex("select * from ban where block = '" + db_pas(ip) + "'")
+        rows = db_get()
+        if(rows):
+            return 1
+        else:
+            return 0
+        
+def topic_check(ip, name, sub):
+    b = re.search("^([0-9](?:[0-9]?[0-9]?)\.[0-9](?:[0-9]?[0-9]?))", ip)
+    if(b):
+        results = b.groups()
+        db_ex("select * from ban where block = '" + db_pas(results[0]) + "' and band = 'O'")
+        rowss = db_get()
+        if(rowss):
+            return 1
+        else:
+            db_ex("select * from ban where block = '" + db_pas(ip) + "'")
+            rows = db_get()
+            if(rows):
+                return 1
+            else:
+                db_ex("select * from stop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "'")
+                rows = db_get()
+                if(rows):
+                    return 1
+                else:
+                    return 0
+    else:
+        db_ex("select * from ban where block = '" + db_pas(ip) + "'")
+        rows = db_get()
+        if(rows):
+            return 1
+        else:
+            db_ex("select * from stop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "'")
+            rows = db_get()
+            if(rows):
+                return 1
+            else:
+                return 0
+
+def get_time():
+    now = time.localtime()
+    date = "%04d-%02d-%02d %02d:%02d:%02d" % (now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec)
+    
+    return date
+
+def rd_plus(title, sub, date):
+    db_ex("select * from rd where title = '" + db_pas(title) + "' and sub = '" + db_pas(sub) + "'")
+    rd = db_get()
+    if(rd):
+        db_ex("update rd set date = '" + db_pas(date) + "' where title = '" + db_pas(title) + "' and sub = '" + db_pas(sub) + "'")
+    else:
+        db_ex("insert into rd (title, sub, date) value ('" + db_pas(title) + "', '" + db_pas(sub) + "', '" + db_pas(date) + "')")
+    db_com()
+    
+def rb_plus(block, end, today, blocker, why):
+    db_ex("insert into rb (block, end, today, blocker, why) value ('" + db_pas(block) + "', '" + db_pas(end) + "', '" + today + "', '" + db_pas(blocker) + "', '" + db_pas(why) + "')")
+    db_com()
+
+def history_plus(title, data, date, ip, send, leng):
+    db_ex("select * from history where title = '" + db_pas(title) + "' order by id+0 desc limit 1")
+    rows = db_get()
+    if(rows):
+        number = int(rows[0]['id']) + 1
+        db_ex("insert into history (id, title, data, date, ip, send, leng) value ('" + str(number) + "', '" + db_pas(title) + "', '" + db_pas(data) + "', '" + date + "', '" + db_pas(ip) + "', '" + db_pas(send) + "', '" + leng + "')")
+        db_com()
+    else:
+        db_ex("insert into history (id, title, data, date, ip, send, leng) value ('1', '" + db_pas(title) + "', '" + db_pas(data) + "', '" + date + "', '" + db_pas(ip) + "', '" + db_pas(send + ' (새 문서)') + "', '" + leng + "')")
+        db_com()
+
+def leng_check(a, b):
+    if(a < b):
+        c = b - a
+        c = '+' + str(c)
+    elif(b < a):
+        c = a - b
+        c = '-' + str(c)
+    else:
+        c = '0'
+        
+    return c

+ 2047 - 1
main.py

@@ -147,7 +147,7 @@ def upload():
                         
                         
                         history_plus('파일:' + filename, '[[파일:' + filename + ']][br][br]{{{[[파일:' + filename + ']]}}}', get_time(), ip, '파일:' + filename + ' 업로드', '0')
                         history_plus('파일:' + filename, '[[파일:' + filename + ']][br][br]{{{[[파일:' + filename + ']]}}}', get_time(), ip, '파일:' + filename + ' 업로드', '0')
                         
                         
-                        return '<meta http-equiv="refresh" content="0;url=/w/' + URL_인코딩('파일:' + filename) + '" />'
+                        return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas('파일:' + filename) + '" />'
                 else:
                 else:
                     return '<meta http-equiv="refresh" content="0;url=/error/15" />'
                     return '<meta http-equiv="refresh" content="0;url=/error/15" />'
             else:
             else:
@@ -157,4 +157,2050 @@ def upload():
             return '<meta http-equiv="refresh" content="0;url=/ban" />'
             return '<meta http-equiv="refresh" content="0;url=/ban" />'
         else:
         else:
             return web_render('index.html', login = login_check(), logo = set_data['name'], title = '업로드', tn = 21, number = set_data['upload'])
             return web_render('index.html', login = login_check(), logo = set_data['name'], title = '업로드', tn = 21, number = set_data['upload'])
+            
+@app.route('/image/<path:name>')
+def image_get(name = None):
+    if(os.path.exists(os.path.join('image', name))):
+        return send_file(os.path.join('image', name), mimetype='image')
+    else:
+        return web_render('index.html', login = login_check(), logo = set_data['name'], data = '이미지 없음.', title = '이미지 보기'), 404
+        
+@app.route('/adminlist')
+def admin_list():
+    i = 0
+    div = '<div>'
+    
+    db_ex("select * from user where acl = 'admin' or acl = 'owner'")
+    user_data = db_get()
+    if(user_data):
+        while(True):
+            try:
+                a = user_data[i]
+            except:
+                div = div + '</div>'
+                break
+
+            if(user_data[i]['acl'] == 'owner'):
+                acl = '소유자'
+            else:
+                acl = '관리자'
+
+            db_ex("select * from data where title = '사용자:" + user_data[i]['id'] + "'")
+            user = db_get()
+            if(user):
+                name = '<a href="/w/' + url_pas('사용자:' + user_data[i]['id']) + '">' + user_data[i]['id'] + '</a> (' + acl + ')'
+            else:
+                name = '<a class="not_thing" href="/w/' + url_pas('사용자:' + user_data[i]['id']) + '">' + user_data[i]['id'] + '</a> (' + acl + ')'
+
+            div = div + '<li>' + str(i + 1) + '. ' + name + '</li>'
+            
+            i += 1
+            
+        return web_render('index.html', login = login_check(), logo = set_data['name'], data = div, title = '관리자 목록')
+    else:
+        return web_render('index.html', login = login_check(), logo = set_data['name'], title = '관리자 목록')
+        
+@app.route('/recentchanges')
+def recent_changes():
+    i = 0
+    div = '<div>'
+    
+    db_ex("select * from history order by date desc limit 50")
+    rows = db_get()
+    if(rows):
+        while(True):
+            try:
+                a = rows[i]
+            except:
+                div = div + '</div>'
+                break
+                
+            if(rows[i]['send']):
+                send = rows[i]['send']
+                send = re.sub('<a href="\/w\/(?P<in>[^"]*)">(?P<out>[^&]*)<\/a>', '<a href="/w/\g<in>">\g<out></a>', send)
+            else:
+                send = '<br>'
+                
+            title = rows[i]['title']
+            title = re.sub('<', '&lt;', title)
+            title = re.sub('>', '&gt;', title)
+            
+            m = re.search("\+", rows[i]['leng'])
+            n = re.search("\-", rows[i]['leng'])
+            
+            if(m):
+                leng = '<span style="color:green;">' + rows[i]['leng'] + '</span>'
+            elif(n):
+                leng = '<span style="color:red;">' + rows[i]['leng'] + '</span>'
+            else:
+                leng = '<span style="color:gray;">' + rows[i]['leng'] + '</span>'
+                
+            if(admin_check() == 1):
+                db_ex("select * from ban where block = '" + db_pas(rows[i]['ip']) + "'")
+                row = db_get()
+                if(row):
+                    ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(해제)</a>'
+                else:
+                    ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(차단)</a>'
+            else:
+                ban = ''
+                
+            if(re.search('\.', rows[i]['ip'])):
+                ip = rows[i]['ip'] + ' <a href="/record/' + url_pas(rows[i]['ip']) + '/n/1">(기록)</a>'
+            else:
+                db_ex("select * from data where title = '사용자:" + db_pas(rows[i]['ip']) + "'")
+                row = db_get()
+                if(row):
+                    ip = '<a href="/w/' + url_pas('사용자:' + rows[i]['ip']) + '">' + rows[i]['ip'] + '</a> <a href="/record/' + url_pas(rows[i]['ip']) + '/n/1">(기록)</a>'
+                else:
+                    ip = '<a class="not_thing" href="/w/' + url_pas('사용자:' + rows[i]['ip']) + '">' + rows[i]['ip'] + '</a> <a href="/record/' + url_pas(rows[i]['ip']) + '/n/1">(기록)</a>'
+                    
+            if((int(rows[i]['id']) - 1) == 0):
+                revert = ''
+            else:
+                revert = '<a href="/revert/' + url_pas(rows[i]['title']) + '/r/' + str(int(rows[i]['id']) - 1) + '">(되돌리기)</a>'
+                
+            div = div + '<table style="width: 100%;"><tbody><tr><td style="text-align: center;width:33.33%;"><a href="/w/' + url_pas(rows[i]['title']) + '">' + title + '</a> <a href="/history/' + url_pas(rows[i]['title']) + '/n/1">(역사)</a> ' + revert + ' (' + leng + ')</td><td style="text-align: center;width:33.33%;">' + ip + ban + '</td><td style="text-align: center;width:33.33%;">' + rows[i]['date'] + '</td></tr><tr><td colspan="3" style="text-align: center;width:100%;">' + send + '</td></tr></tbody></table>'
+            
+            i += 1
+            
+        return web_render('index.html', login = login_check(), logo = set_data['name'], rows = div, tn = 3, title = '최근 변경내역')
+    else:
+        return web_render('index.html', login = login_check(), logo = set_data['name'], rows = '', tn = 3, title = '최근 변경내역')
+        
+@app.route('/history/<path:name>/r/<int:num>/hidden')
+def history_hidden(name = None, num = None):
+    if(owner_check() == 1):
+        db_ex("select * from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(str(num)) + "'")
+        exist = db_get()
+        if(exist):
+            db_ex("delete from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(str(num)) + "'")
+        else:
+            db_ex("insert into hidhi (title, re) value ('" + db_pas(name) + "', '" + db_pas(str(num)) + "')")
+            
+        db_com()
+        
+        return '<meta http-equiv="refresh" content="0;url=/history/' + url_pas(name) + '/n/1" />'
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/history/' + url_pas(name) + '/n/1" />'
+        
+@app.route('/record/<path:name>/n/<int:num>')
+def user_record(name = None, num = None):
+    v = num * 50
+    i = v - 50
+    div = '<div>'
+    
+    db_ex("select * from history where ip = '" + db_pas(name) + "' order by date desc")
+    rows = db_get()
+    if(rows):
+        while(True):
+            try:
+                a = rows[i]
+            except:
+                div = div + '</div>'
+                if(num != 1):
+                    div = div + '<br><a href="/record/' + url_pas(name) + '/n/' + str(num - 1) + '">(이전)'
+                break
+                
+            if(rows[i]['send']):
+                send = rows[i]['send']
+                send = re.sub('<a href="\/w\/(?P<in>[^"]*)">(?P<out>[^&]*)<\/a>', '<a href="/w/\g<in>">\g<out></a>', send)
+            else:
+                send = '<br>'
+                
+            title = rows[i]['title']
+            title = re.sub('<', '&lt;', title)
+            title = re.sub('>', '&gt;', title)
+            
+            m = re.search("\+", rows[i]['leng'])
+            n = re.search("\-", rows[i]['leng'])
+            
+            if(m):
+                leng = '<span style="color:green;">' + rows[i]['leng'] + '</span>'
+            elif(n):
+                leng = '<span style="color:red;">' + rows[i]['leng'] + '</span>'
+            else:
+                leng = '<span style="color:gray;">' + rows[i]['leng'] + '</span>'
+                
+            if(admin_check() == 1):
+                db_ex("select * from ban where block = '" + db_pas(rows[i]['ip']) + "'")
+                row = db_get()
+                if(row):
+                    ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(해제)</a>'
+                else:
+                    ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(차단)</a>'
+            else:
+                ban = ''
+                
+            if(re.search('\.', rows[i]['ip'])):
+                ip = rows[i]['ip']
+            else:
+                db_ex("select * from data where title = '사용자:" + db_pas(rows[i]['ip']) + "'")
+                row = db_get()
+                if(row):
+                    ip = '<a href="/w/' + url_pas('사용자:' + rows[i]['ip']) + '">' + rows[i]['ip'] + '</a>'
+                else:
+                    ip = '<a class="not_thing" href="/w/' + url_pas('사용자:' + rows[i]['ip']) + '">' + rows[i]['ip'] + '</a>'
+                    
+            if((int(rows[i]['id']) - 1) == 0):
+                revert = ''
+            else:
+                revert = '<a href="/revert/' + url_pas(rows[i]['title']) + '/r/' + str(int(rows[i]['id']) - 1) + '">(되돌리기)</a>'
+                
+            div = div + '<table style="width: 100%;"><tbody><tr><td style="text-align: center;width:33.33%;"><a href="/w/' + url_pas(rows[i]['title']) + '">' + title + '</a> r' + rows[i]['id'] + ' <a href="/history/' + url_pas(rows[i]['title']) + '/n/1">(역사)</a> ' + revert + ' (' + leng + ')</td><td style="text-align: center;width:33.33%;">' + ip + ban +  '</td><td style="text-align: center;width:33.33%;">' + rows[i]['date'] + '</td></tr><tr><td colspan="3" style="text-align: center;width:100%;">' + send + '</td></tr></tbody></table>'
+            
+            if(i == v):
+                div = div + '</div>'
+                if(num == 1):
+                    div = div + '<br><a href="/record/' + url_pas(name) + '/n/' + str(num + 1) + '">(다음)'
+                else:
+                    div = div + '<br><a href="/record/' + url_pas(name) + '/n/' + str(num - 1) + '">(이전) <a href="/record/' + url_pas(name) + '/n/' + str(num + 1) + '">(다음)'
+                break
+
+            i += 1
+                
+        return web_render('index.html', login = login_check(), logo = set_data['name'], rows = div, tn = 3, title = '유저 기록')
+    else:
+        return web_render('index.html', login = login_check(), logo = set_data['name'], rows = '', tn = 3, title = '유저 기록')
+        
+@app.route('/userlog/n/<int:number>')
+def user_log(number = None):
+    i = number * 50
+    j = i - 50
+    list = ''
+    
+    db_ex("select * from user")
+    user_list = db_get()
+    if(user_list):        
+        while(True):
+            try:
+                a = user_list[j]
+            except:
+                if(number != 1):
+                    list = list + '<br><a href="/userlog/n/' + str(number - 1) + '">(이전)'
+                break
+                
+            if(admin_check() == 1):
+                db_ex("select * from ban where block = '" + db_pas(user_list[j]['id']) + "'")
+                ban_exist = db_get()
+                if(ban_exist):
+                    ban_button = ' <a href="/ban/' + url_pas(user_list[j]['id']) + '">(해제)</a>'
+                else:
+                    ban_button = ' <a href="/ban/' + url_pas(user_list[j]['id']) + '">(차단)</a>'
+            else:
+                ban_button = ''
+                
+            db_ex("select * from data where title = '사용자:" + db_pas(user_list[j]['id']) + "'")
+            file = db_get()
+            if(file):
+                ip = '<a href="/w/' + url_pas('사용자:' + user_list[j]['id']) + '">' + user_list[j]['id'] + '</a> <a href="/record/' + url_pas(user_list[j]['id']) + '/n/1">(기록)</a>'
+            else:
+                ip = '<a class="not_thing" href="/w/' + url_pas('사용자:' + user_list[j]['id']) + '">' + user_list[j]['id'] + '</a> <a href="/record/' + url_pas(user_list[j]['id']) + '/n/1">(기록)</a>'
+                
+            list = list + '<li>' + str(j + 1) + '. ' + ip + ban_button + '</li>'
+            
+            if(j == i):
+                if(number == 1):
+                    list = list + '<br><a href="/userlog/n/' + str(number + 1) + '">(다음)'
+                else:
+                    list = list + '<br><a href="/userlog/n/' + str(number - 1) + '">(이전) <a href="/userlog/n/' + str(number + 1) + '">(다음)'
+                break
+            else:
+                j += 1
+                
+        return web_render('index.html', login = login_check(), logo = set_data['name'], data = list, title = '유저 가입 기록')
+    else:
+        return web_render('index.html', login = login_check(), logo = set_data['name'], data = '', title = '유저 가입 기록')
+        
+@app.route('/backlink/<path:name>/n/<int:num>')
+def backlink(name = None, num = None):
+    v = num * 50
+    i = v - 50
+    div = ''
+    restart = 0
+    
+    db_ex("select * from back where title = '" + db_pas(name) + "' order by link asc")
+    rows = db_get()
+    if(rows):        
+        while(True):
+            try:
+                a = rows[i]
+            except:
+                if(num != 1):
+                    div = div + '<br><a href="/backlink/n/' + str(num - 1) + '">(이전)'
+                break
+                
+            if(rows[i]['type'] == 'include'):
+                db_ex("select * from back where title = '" + db_pas(name) + "' and link = '" + db_pas(rows[i]['link']) + "' and type = ''")
+                test = db_get()
+                if(test):
+                    restart = 1
+                    
+                    db_ex("delete from back where title = '" + db_pas(name) + "' and link = '" + db_pas(rows[i]['link']) + "' and type = ''")
+                    db_com()
+                
+            if(not re.search('^사용자:', rows[i]['link'])):
+                db_ex("select * from data where title = '" + db_pas(rows[i]['link']) + "'")
+                row = db_get()
+                if(row):
+                    data = row[0]['data']
+                    data = re.sub("(?P<in>\[include\((?P<out>(?:(?!\)\]|,).)*)((?:,\s?(?:[^)]*))+)?\)\])", "\g<in>\n\n[[\g<out>]]\n\n", data)
+                    data = re.sub('^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)', '[[\g<in>]]', data)
+                    data = namumark('', data)
+                    
+                    if(re.search("<a(?:(?:(?!href=).)*)?href=\"\/w\/" + url_pas(name) + "(?:\#[^\"]*)?\">([^<]*)<\/a>", data)):
+                        div = div + '<li><a href="/w/' + url_pas(rows[i]['link']) + '">' + rows[i]['link'] + '</a>'
+                        
+                        if(rows[i]['type']):
+                            div = div + ' (' + rows[i]['type'] + ')</li>'
+                        else:
+                            div = div + '</li>'
+                            
+                        if(i == v):
+                            if(num == 1):
+                                div = div + '<br><a href="/backlink/' + url_pas(name) + '/n/' + str(num + 1) + '">(다음)'
+                            else:
+                                div = div + '<br><a href="/backlink/' + url_pas(name) + '/n/' + str(num - 1) + '">(이전) <a href="/backlink/' + url_pas(name) + '/n/' + str(num + 1) + '">(다음)'
+                                
+                            break
+                        else:
+                            i += 1
+                    else:
+                        db_ex("delete from back where title = '" + db_pas(name) + "' and link = '" + db_pas(rows[i]['link']) + "'")
+                        db_com()
+                        
+                    i += 1
+                    v += 1
+                else:
+                    db_ex("delete from back where title = '" + db_pas(name) + "' and link = '" + db_pas(rows[i]['link']) + "'")
+                    db_com()
+                    
+                    i += 1
+                    v += 1
+            else:
+                db_ex("delete from back where title = '" + db_pas(name) + "' and link = '" + db_pas(rows[i]['link']) + "'")
+                db_com()
+                
+                i += 1
+                v += 1
+                
+        if(restart == 1):
+            return '<meta http-equiv="refresh" content="0;url=/backlink/' + url_pas(name) + '/n/' + str(num) + '" />'
+        else:    
+            return web_render('index.html', login = login_check(), logo = set_data['name'], data = div, title = name, page = url_pas(name), sub = '역링크')
+    else:
+        return web_render('index.html', login = login_check(), logo = set_data['name'], data = '', title = name, page = url_pas(name), sub = '역링크')
+        
+@app.route('/recentdiscuss')
+def recent_discuss():
+    i = 0
+    div = '<div>'
+    
+    db_ex("select * from rd order by date desc limit 50")
+    rows = db_get()
+    if(rows):
+        while(True):
+            try:
+                a = rows[i]
+            except:
+                div = div + '</div>'
+                break
+                
+            title = rows[i]['title']
+            title = re.sub('<', '&lt;', title)
+            title = re.sub('>', '&gt;', title)
+            
+            sub = rows[i]['sub']
+            sub = re.sub('<', '&lt;', sub)
+            sub = re.sub('>', '&gt;', sub)
+            
+            div = div + '<table style="width: 100%;"><tbody><tr><td style="text-align: center;width:50%;"><a href="/topic/' + url_pas(rows[i]['title']) + '/sub/' + url_pas(rows[i]['sub']) + '">' + title + '</a> (' + sub + ')</td><td style="text-align: center;width:50%;">' + rows[i]['date'] + '</td></tr></tbody></table>'
+            
+            i += 1
+            
+        return web_render('index.html', login = login_check(), logo = set_data['name'], rows = div, tn = 12, title = '최근 토론내역')
+    else:
+        return web_render('index.html', login = login_check(), logo = set_data['name'], rows = '', tn = 12, title = '최근 토론내역')
+        
+@app.route('/history/<path:name>/n/<int:num>', methods=['POST', 'GET'])
+def history_view(name = None, num = None):
+    if(request.method == 'POST'):
+        return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '/r/' + request.form["b"] + '/diff/' + request.form["a"] + '" />'
+    else:
+        select = ''
+        v = num * 50
+        i = v - 50
+        div = '<div>'
+        
+        db_ex("select * from history where title = '" + db_pas(name) + "' order by id+0 desc")
+        rows = db_get()
+        if(rows):
+            while(True):
+                style = ''
+            
+                try:
+                    a = rows[i]
+                except:
+                    div = div + '</div>'
+                    
+                    if(num != 1):
+                        div = div + '<br><a href="/history/' + url_pas(name) + '/n/' + str(num - 1) + '">(이전)'
+                    break
+                    
+                select = '<option value="' + str(i + 1) + '">' + str(i + 1) + '</option>' + select
+                
+                if(rows[i]['send']):
+                    send = rows[i]['send']
+                    send = re.sub('<a href="\/w\/(?P<in>[^"]*)">(?P<out>[^&]*)<\/a>', '<a href="/w/\g<in>">\g<out></a>', send)
+                else:
+                    send = '<br>'
+                    
+                m = re.search("\+", rows[i]['leng'])
+                n = re.search("\-", rows[i]['leng'])
+                if(m):
+                    leng = '<span style="color:green;">' + rows[i]['leng'] + '</span>'
+                elif(n):
+                    leng = '<span style="color:red;">' + rows[i]['leng'] + '</span>'
+                else:
+                    leng = '<span style="color:gray;">' + rows[i]['leng'] + '</span>'                    
+                    
+                if(re.search("\.", rows[i]["ip"])):
+                    ip = rows[i]["ip"] + ' <a href="/record/' + url_pas(rows[i]["ip"]) + '/n/1">(기록)</a>'
+                else:
+                    db_ex("select * from data where title = '사용자:" + db_pas(rows[i]['ip']) + "'")
+                    row = db_get()
+                    if(row):
+                        ip = '<a href="/w/' + url_pas('사용자:' + rows[i]['ip']) + '">' + rows[i]['ip'] + '</a> <a href="/record/' + url_pas(rows[i]["ip"]) + '/n/1">(기록)</a>'
+                    else:
+                        ip = '<a class="not_thing" href="/w/' + url_pas('사용자:' + rows[i]['ip']) + '">' + rows[i]['ip'] + '</a> <a href="/record/' + url_pas(rows[i]["ip"]) + '/n/1">(기록)</a>'
+                        
+                if(admin_check() == 1):
+                    db_ex("select * from user where id = '" + db_pas(rows[i]['ip']) + "'")
+                    row = db_get()
+                    if(row):
+                        if(row[0]['acl'] == 'owner' or row[0]['acl'] == 'admin'):
+                            ban = ''
+                        else:
+                            db_ex("select * from ban where block = '" + db_pas(rows[i]['ip']) + "'")
+                            row = db_get()
+                            if(row):
+                                ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(해제)</a>'
+                            else:
+                                ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(차단)</a>'
+                    else:
+                        db_ex("select * from ban where block = '" + db_pas(rows[i]['ip']) + "'")
+                        row = db_get()
+                        if(row):
+                            ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(해제)</a>'
+                        else:
+                            ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(차단)</a>'
+                            
+                    if(owner_check() == 1):
+                        db_ex("select * from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(rows[i]['id']) + "'")
+                        row = db_get()
+                        if(row):                            
+                            ip = ip + ' (숨김)'                            
+                            hidden = ' <a href="/history/' + url_pas(name) + '/r/' + rows[i]['id'] + '/hidden">(공개)'
+                        else:
+                            hidden = ' <a href="/history/' + url_pas(name) + '/r/' + rows[i]['id'] + '/hidden">(숨김)'
+                    else:
+                        db_ex("select * from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(rows[i]['id']) + "'")
+                        row = db_get()
+                        if(row):
+                            ip = '숨김'
+                            hidden = ''
+                            send = '숨김'
+                            ban = ''
+                            style = 'display:none;'
+                            v += 1
+                        else:
+                            hidden = ''
+                else:
+                    ban = ''
+                    
+                    db_ex("select * from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(rows[i]['id']) + "'")
+                    row = db_get()
+                    if(row):
+                        ip = '숨김'
+                        hidden = ''
+                        send = '숨김'
+                        ban = ''
+                        style = 'display:none;'
+                        v += 1
+                    else:
+                        hidden = ''                
+                        
+                div = div + '<table style="width: 100%;' + style + '"><tbody><tr><td style="text-align: center;width:33.33%;">r' + rows[i]['id'] + '</a> <a href="/w/' + url_pas(rows[i]['title']) + '/r/' + rows[i]['id'] + '">(w)</a> <a href="/w/' + url_pas(rows[i]['title']) + '/raw/' + rows[i]['id'] + '">(Raw)</a> <a href="/revert/' + url_pas(rows[i]['title']) + '/r/' + rows[i]['id'] + '">(되돌리기)</a> (' + leng + ')</td><td style="text-align: center;width:33.33%;">' + ip + ban + hidden + '</td><td style="text-align: center;width:33.33%;">' + rows[i]['date'] + '</td></tr><tr><td colspan="3" style="text-align: center;width:100%;">' + send + '</td></tr></tbody></table>'
+                
+                if(i == v):
+                    div = div + '</div>'
+                    
+                    if(num == 1):
+                        div = div + '<br><a href="/history/' + url_pas(name) + '/n/' + str(num + 1) + '">(다음)'
+                    else:
+                        div = div + '<br><a href="/history/' + url_pas(name) + '/n/' + str(num - 1) + '">(이전) <a href="/history/' + url_pas(name) + '/n/' + str(num + 1) + '">(다음)'
+                        
+                    break
+                else:
+                    i += 1
+                    
+            return web_render('index.html', login = login_check(), logo = set_data['name'], rows = div, tn = 5, title = name, page = url_pas(name), select = select, sub = '역사')
+        else:
+            return web_render('index.html', login = login_check(), logo = set_data['name'], rows = '', tn = 5, title = name, page = url_pas(name), select = select, sub = '역사')
+            
+@app.route('/search', methods=['POST'])
+def search():
+    db_ex("select * from data where title = '" + db_pas(request.form["search"]) + "'")
+    rows = db_get()
+    if(rows):
+        return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(request.form["search"]) + '" />'
+    else:
+        db_ex("select * from data where title like '%" + db_pas(request.form["search"]) + "%'")
+        rows = db_get()
+        if(rows):
+            i = 0
+            
+            div = '<li>문서가 없습니다. <a href="/w/' + url_pas(request.form["search"]) + '">바로가기</a></li><br>'
+            
+            while(True):
+                try:
+                    div = div + '<li><a href="/w/' + url_pas(rows[i]['title']) + '">' + rows[i]['title'] + '</a></li>'
+                except:
+                    break
+                    
+                i += 1
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(request.form["search"]) + '" />'
+            
+        return web_render('index.html', login = login_check(), logo = set_data['name'], data = div, title = '검색')
+        
+@app.route('/w/<path:name>')
+@app.route('/w/<path:name>/from/<path:redirect>')
+def read_view(name = None, redirect = None):
+    i = 0
+    
+    db_ex("select * from rd where title = '" + db_pas(name) + "' order by date asc")
+    rows = db_get()
+    while(True):
+        try:
+            a = rows[i]
+        except:
+            topic = ""
+            break
+            
+        db_ex("select * from stop where title = '" + db_pas(rows[i]['title']) + "' and sub = '" + db_pas(rows[i]['sub']) + "' and close = 'O'")
+        row = db_get()
+        if(not row):
+            topic = "open"
+            
+            break
+        else:
+            i += 1
+            
+    acl = ''
+    
+    m = re.search("^(.*)\/(.*)$", name)
+    if(m):
+        g = m.groups()
+        uppage = g[0]
+        style = ""
+    else:
+        uppage = ""
+        style = "display:none;"
+        
+    if(admin_check() == 1):
+        admin_memu = 'ACL'
+    else:
+        admin_memu = ''
+    
+    if(re.search("^분류:", name)):
+        db_ex("select * from cat where title = '" + db_pas(name) + "' order by cat asc")
+        rows = db_get()
+        if(rows):
+            div = ''
+            i = 0
+            
+            while(True):
+                try:
+                    a = rows[i]
+                except:
+                    break
+                    
+                db_ex("select * from data where title = '" + db_pas(rows[i]['cat']) + "'")
+                row = db_get()
+                if(row):
+                    aa = row[0]['data']                  
+                    aa = namumark('', aa)
+                    bb = re.search('<div style="width:100%;border: 1px solid #777;padding: 5px;margin-top: 1em;">분류:((?:(?!<\/div>).)*)<\/div>', aa)
+                    if(bb):
+                        cc = bb.groups()
+                        
+                        mm = re.search("^분류:(.*)", name)
+                        if(mm):
+                            ee = mm.groups()
+                            
+                            if(re.search("<a (class=\"not_thing\")? href=\"\/w\/" + url_pas(name) + "\">" + ee[0] + "<\/a>", cc[0])):
+                                div = div + '<li><a href="/w/' + url_pas(rows[i]['cat']) + '">' + rows[i]['cat'] + '</a></li>'
+                                
+                                i += 1
+                            else:
+                                db_ex("delete from cat where title = '" + db_pas(name) + "' and cat = '" + db_pas(rows[i]['cat']) + "'")
+                                db_com()
+                                
+                                i += 1
+                        else:
+                            db_ex("delete from cat where title = '" + db_pas(name) + "' and cat = '" + db_pas(rows[i]['cat']) + "'")
+                            db_com()
+                            
+                            i += 1
+                    else:
+                        db_ex("delete from cat where title = '" + db_pas(name) + "' and cat = '" + db_pas(rows[i]['cat']) + "'")
+                        db_com()
+                        
+                        i += 1
+                else:
+                    db_ex("delete from cat where title = '" + db_pas(name) + "' and cat = '" + db_pas(rows[i]['cat']) + "'")
+                    db_com()
+                    
+                    i += 1
+                    
+            div = '<h2>분류</h2>' + div
+        else:
+            div = ''
+    else:
+        div = ''
+    
+    db_ex("select * from data where title = '" + db_pas(name) + "'")
+    rows = db_get()
+    if(rows):
+        if(rows[0]['acl'] == 'admin'):
+            acl = '(관리자)'
+        elif(rows[0]['acl'] == 'user'):
+            acl = '(유저)'
+        else:
+            if(not acl):
+                acl = ''
+
+        m = re.search("^사용자:(.*)", name)
+        if(m):
+            g = m.groups()
+            
+            db_ex("select * from user where id = '" + db_pas(g[0]) + "'")
+            test = db_get()
+            if(test):
+                if(test[0]['acl'] == 'owner'):
+                    acl = '(소유자)'
+                elif(test[0]['acl'] == 'admin'):
+                    acl = '(관리자)'
+
+            db_ex("select * from ban where block = '" + db_pas(g[0]) + "'")
+            user = db_get()
+            if(user):
+                elsedata = '{{{#!wiki style="border:2px solid red;padding:10px;"\r\n{{{+2 {{{#red 이 사용자는 차단 당했습니다.}}}}}}\r\n\r\n차단 해제 일 : ' + user[0]['end'] + '[br]사유 : ' + user[0]['why'] + '}}}[br]' + rows[0]['data']
+            else:
+                elsedata = rows[0]['data']
+        else:
+            elsedata = rows[0]['data']
+                
+        if(redirect):
+            elsedata = re.sub("^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)", " * [[\g<in>]] 문서로 넘겨주기", elsedata)
+                
+        enddata = namumark(name, elsedata)
+        
+        m = re.search('<div id="toc">((?:(?!\/div>).)*)<\/div>', enddata)
+        if(m):
+            result = m.groups()
+            left = result[0]
+        else:
+            left = ''
+            
+        return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = enddata + div, license = set_data['license'], tn = 1, acl = acl, left = left, uppage = uppage, style = style, topic = topic, redirect = redirect, admin = admin_memu)
+    else:
+        m = re.search("^사용자:(.*)", name)
+        if(m):
+            g = m.groups()
+            
+            db_ex("select * from ban where block = '" + db_pas(g[0]) + "'")
+            user = db_get()
+            if(user):
+                elsedata = '{{{#!wiki style="border:2px solid red;padding:10px;"\r\n{{{+2 {{{#red 이 사용자는 차단 당했습니다.}}}}}}\r\n\r\n차단 해제 일 : ' + user[0]['end'] + '[br]사유 : ' + user[0]['why'] + '}}}[br]' + '문서 없음'
+            else:
+                elsedata = '문서 없음'
+        else:
+            elsedata = '문서 없음'
+            
+        if(redirect):
+            elsedata = re.sub("^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)", " * [[\g<in>]] 문서로 넘겨주기", elsedata)
+        
+        return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = namumark(name, elsedata) + div, license = set_data['license'], tn = 1, uppage = uppage, style = style, acl = acl, topic = topic, redirect = redirect, admin = admin_memu), 404
+        
+@app.route('/w/<path:name>/r/<int:number>')
+def old_view(name = None, num = None):
+    db_ex("select * from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(str(num)) + "'")
+    row = db_get()
+    if(row):
+        if(owner_check() == 1):
+            db_ex("select * from history where title = '" + db_pas(name) + "' and id = '" + str(num) + "'")
+            rows = db_get()
+            if(rows):
+                enddata = namumark(name, rows[0]['data'])
+                
+                m = re.search('<div id="toc">((?:(?!\/div>).)*)<\/div>', enddata)
+                if(m):
+                    result = m.groups()
+                    left = result[0]
+                else:
+                    left = ''
+                    
+                return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = enddata, tn = 6, left = left, sub = '옛 문서')
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/history/' + url_pas(name) + '" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+    else:
+        db_ex("select * from history where title = '" + db_pas(name) + "' and id = '" + str(num) + "'")
+        rows = db_get()
+        if(rows):
+            enddata = namumark(name, rows[0]['data'])
+            
+            m = re.search('<div id="toc">((?:(?!\/div>).)*)<\/div>', enddata)
+            if(m):
+                result = m.groups()
+                left = result[0]
+            else:
+                left = ''
+                
+            return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = enddata, tn = 6, left = left, sub = '옛 문서')
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/history/' + url_pas(name) + '" />'
+            
+@app.route('/w/<path:name>/raw/<int:num>')
+def old_raw(name = None, num = None):
+    db_ex("select * from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(str(num)) + "'")
+    row = db_get()
+    if(row):
+        if(owner_check() == 1):
+            db_ex("select * from history where title = '" + db_pas(name) + "' and id = '" + str(num) + "'")
+            rows = db_get()
+            if(rows):
+                enddata = re.sub('<', '&lt;', rows[0]['data'])
+                enddata = re.sub('>', '&gt;', enddata)
+                enddata = re.sub('"', '&quot;', enddata)
+                
+                enddata = '<pre>' + enddata + '</pre>'
+                
+                return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = enddata)
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/history/' + url_pas(name) + '" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+    else:
+        db_ex("select * from history where title = '" + db_pas(name) + "' and id = '" + str(num) + "'")
+        rows = db_get()
+        if(rows):
+            enddata = re.sub('<', '&lt;', rows[0]['data'])
+            enddata = re.sub('>', '&gt;', enddata)
+            enddata = re.sub('"', '&quot;', enddata)
+            
+            enddata = '<pre>' + enddata + '</pre>'
+            
+            return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = enddata)
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/history/' + url_pas(name) + '" />'
+            
+@app.route('/raw/<path:name>')
+def raw_view(name = None):
+    db_ex("select * from data where title = '" + db_pas(name) + "'")
+    rows = db_get()
+    if(rows):
+        enddata = re.sub('<', '&lt;', rows[0]['data'])
+        enddata = re.sub('>', '&gt;', enddata)
+        enddata = re.sub('"', '&quot;', enddata)
+        
+        enddata = '<pre>' + enddata + '</pre>'
+        
+        return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = enddata, tn = 7, sub = 'Raw')
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+        
+@app.route('/revert/<path:name>/r/<int:num>', methods=['POST', 'GET'])
+def revert(name = None, num = None):
+    ip = ip_check()
+    can = acl_check(ip, name)
+    today = get_time()
+    
+    if(request.method == 'POST'):
+        db_ex("select * from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(str(num)) + "'")
+        row = db_get()
+        if(row):
+            if(owner_check() == 1):        
+                db_ex("select * from history where title = '" + db_pas(name) + "' and id = '" + str(num) + "'")
+                rows = db_get()
+                if(rows):
+                    if(can == 1):
+                        return '<meta http-equiv="refresh" content="0;url=/ban" />'
+                    else:
+                        db_ex("select * from data where title = '" + db_pas(name) + "'")
+                        row = db_get()
+                        if(row):
+                            leng = leng_check(len(row[0]['data']), len(rows[0]['data']))
+                            
+                            db_ex("update data set data = '" + db_pas(rows[0]['data']) + "' where title = '" + db_pas(name) + "'")
+                            db_com()
+                        else:
+                            leng = '+' + str(len(rows[0]['data']))
+                            
+                            db_ex("insert into data (title, data, acl) value ('" + db_pas(name) + "', '" + db_pas(rows[0]['data']) + "', '')")
+                            db_com()
+                            
+                        history_plus(name, rows[0]['data'], today, ip, '문서를 ' + str(num) + '판으로 되돌렸습니다.', leng)
+                        
+                        return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+                else:
+                    return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+        else:
+            db_ex("select * from history where title = '" + db_pas(name) + "' and id = '" + str(num) + "'")
+            rows = db_get()
+            if(rows):                
+                if(can == 1):
+                    return '<meta http-equiv="refresh" content="0;url=/ban" />'
+                else:                    
+                    db_ex("select * from data where title = '" + db_pas(name) + "'")
+                    row = db_get()
+                    if(row):
+                        leng = leng_check(len(row[0]['data']), len(rows[0]['data']))
+                        
+                        db_ex("update data set data = '" + db_pas(rows[0]['data']) + "' where title = '" + db_pas(name) + "'")
+                        db_com()
+                    else:
+                        leng = '+' + str(len(rows[0]['data']))
+                        
+                        db_ex("insert into data (title, data, acl) value ('" + db_pas(name) + "', '" + db_pas(rows[0]['data']) + "', '')")
+                        db_com()
+                        
+                    history_plus(name, rows[0]['data'], today, ip, '문서를 ' + str(num) + '판으로 되돌렸습니다.', leng)
+                    
+                    return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'            
+    else:
+        db_ex("select * from hidhi where title = '" + db_pas(name) + "' and re = '" + db_pas(str(num)) + "'")
+        row = db_get()
+        if(row):
+            if(owner_check() == 1):                
+                if(can == 1):
+                    return '<meta http-equiv="refresh" content="0;url=/ban" />'
+                else:
+                    db_ex("select * from history where title = '" + db_pas(name) + "' and id = '" + str(num) + "'")
+                    rows = db_get()
+                    if(rows):
+                        return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), r = url_pas(str(num)), tn = 13, plus = '정말 되돌리시겠습니까?', sub = '되돌리기')
+                    else:
+                        return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+        else:            
+            if(can == 1):
+                return '<meta http-equiv="refresh" content="0;url=/ban" />'
+            else:
+                db_ex("select * from history where title = '" + db_pas(name) + "' and id = '" + str(num) + "'")
+                rows = db_get()
+                if(rows):
+                    return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), r = url_pas(str(num)), tn = 13, plus = '정말 되돌리시겠습니까?', sub = '되돌리기')
+                else:
+                    return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+                    
+@app.route('/edit/<path:name>', methods=['POST', 'GET'])
+def edit(name = None):
+    ip = ip_check()
+    can = acl_check(ip, name)
+    
+    if(request.method == 'POST'):
+        m = re.search('(?:[^A-Za-zㄱ-힣0-9 ])', request.form["send"])
+        
+        if(m):
+            return '<meta http-equiv="refresh" content="0;url=/error/17" />'
+        else:
+            today = get_time()
+            
+            content = savemark(request.form["content"])
+            
+            db_ex("select * from data where title = '" + db_pas(name) + "'")
+            rows = db_get()
+            if(rows):
+                if(rows[0]['data'] == content):
+                    return '<meta http-equiv="refresh" content="0;url=/error/18" />'
+                else:                    
+                    if(can == 1):
+                        return '<meta http-equiv="refresh" content="0;url=/ban" />'
+                    else:                        
+                        leng = leng_check(len(rows[0]['data']), len(content))
+                        history_plus(name, content, today, ip, request.form["send"], leng)
+                        
+                        db_ex("update data set data = '" + db_pas(content) + "' where title = '" + db_pas(name) + "'")
+                        db_com()
+            else:                
+                if(can == 1):
+                    return '<meta http-equiv="refresh" content="0;url=/ban" />'
+                else:
+                    leng = '+' + str(len(content))
+                    history_plus(name, content, today, ip, request.form["send"], leng)
+                    
+                    db_ex("insert into data (title, data, acl) value ('" + db_pas(name) + "', '" + db_pas(content) + "', '')")
+                    db_com()
+                    
+            include_check(name, content)
+            
+            return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+    else:        
+        if(can == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            db_ex("select * from data where title = '" + db_pas(set_data["help"]) + "'")
+            rows = db_get()
+            if(rows):
+                newdata = re.sub('^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)', ' * [[\g<in>]] 문서로 넘겨주기', rows[0]["data"])
+                left = namumark(name, newdata)
+            else:
+                left = ''
+                
+            db_ex("select * from data where title = '" + db_pas(name) + "'")
+            rows = db_get()
+            if(rows):
+                return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = rows[0]['data'], tn = 2, left = left, sub = '편집')
+            else:
+                return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = '', tn = 2, left = left, sub = '편집')
+                
+@app.route('/edit/<path:name>/section/<int:num>', methods=['POST', 'GET'])
+def section_edit(name = None, num = None):
+    ip = ip_check()
+    can = acl_check(ip, name)
+    
+    if(request.method == 'POST'):
+        m = re.search('(?:[^A-Za-zㄱ-힣0-9 ])', request.form["send"])
+        if(m):
+            return '<meta http-equiv="refresh" content="0;url=/error/17" />'
+        else:
+            today = get_time()
+            
+            content = savemark(request.form["content"])
+            
+            db_ex("select * from data where title = '" + db_pas(name) + "'")
+            rows = db_get()
+            if(rows):
+                if(request.form["otent"] == content):
+                    return '<meta http-equiv="refresh" content="0;url=/error/18" />'
+                else:                    
+                    if(can == 1):
+                        return '<meta http-equiv="refresh" content="0;url=/ban" />'
+                    else:                        
+                        leng = leng_check(len(request.form['otent']), len(content))
+                        content = rows[0]['data'].replace(request.form['otent'], content)
+                        
+                        history_plus(name, content, today, ip, request.form["send"], leng)
+                        
+                        db_ex("update data set data = '" + db_pas(content) + "' where title = '" + db_pas(name) + "'")
+                        db_com()
+                        
+                    include_check(name, content)
+                    
+                    return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+    else:        
+        if(can == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            db_ex("select * from data where title = '" + db_pas(data["help"]) + "'")
+            rows = db_get()
+            if(rows):
+                newdata = re.sub('^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)', ' * [[\g<in>]] 문서로 넘겨주기', rows[0]["data"])
+                
+                left = namumark(name, newdata)
+            else:
+                left = ''
+                
+            db_ex("select * from data where title = '" + db_pas(name) + "'")
+            rows = db_get()
+            if(rows):
+                i = 0
+                j = 0
+                
+                gdata = rows[0]['data'] + '\r\n'
+                
+                while(True):
+                    m = re.search("((?:={1,6})\s?(?:[^=]*)\s?(?:={1,6})(?:\s+)?\n(?:(?:(?:(?!(?:={1,6})\s?(?:[^=]*)\s?(?:={1,6})(?:\s+)?\n).)*)(?:\n)?)+)", gdata)
+                    if(m):
+                        if(i == num - 1):
+                            g = m.groups()
+                            
+                            gdata = re.sub("\r\n$", "", g[0])
+                            
+                            break
+                        else:
+                            gdata = re.sub("((?:={1,6})\s?(?:[^=]*)\s?(?:={1,6})(?:\s+)?\n(?:(?:(?:(?!(?:={1,6})\s?(?:[^=]*)\s?(?:={1,6})(?:\s+)?\n).)*)(?:\n)?)+)", "", gdata, 1)
+                            
+                            i += 1
+                    else:
+                        j = 1
+                        
+                        break
+                        
+                if(j == 0):
+                    return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = gdata, tn = 2, left = left, section = 1, number = num, sub = '편집')
+                else:
+                    return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+                
+@app.route('/preview/<path:name>', methods=['POST'])
+def preview(name = None):
+    ip = ip_check()
+    can = acl_check(ip, name)
+    
+    if(can == 1):
+        return '<meta http-equiv="refresh" content="0;url=/ban" />'
+    else:            
+        newdata = request.form["content"]
+        newdata = re.sub('^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)', ' * [[\g<in>]] 문서로 넘겨주기', newdata)
+        enddata = namumark(name, newdata)
+        
+        db_ex("select * from data where title = '" + db_pas(data["help"]) + "'")
+        rows = db_get()
+        if(rows):
+            newdata = re.sub('^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)', ' * [[\g<in>]] 문서로 넘겨주기', rows[0]["data"])
+            
+            left = namumark(name, newdata)
+        else:
+            left = ''
+            
+        return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = request.form["content"], tn = 2, preview = 1, enddata = enddata, left = left, sub = '미리보기')
+        
+@app.route('/preview/<path:name>/section/<int:num>', methods=['POST'])
+def section_preview(name = None, num = None):
+    ip = ip_check()
+    can = acl_check(ip, name)
+    
+    if(can == 1):
+        return '<meta http-equiv="refresh" content="0;url=/ban" />'
+    else:            
+        newdata = request.form["content"]
+        newdata = re.sub('^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)', ' * [[\g<in>]] 문서로 넘겨주기', newdata)
+        enddata = namumark(name, newdata)
+        
+        db_ex("select * from data where title = '" + db_pas(data["help"]) + "'")
+        rows = db_get()
+        if(rows):
+            newdata = re.sub('^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s(?P<in>[^\n]*)', ' * [[\g<in>]] 문서로 넘겨주기', rows[0]["data"])
+            left = namumark(name, newdata)
+        else:
+            left = ''
+            
+        return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), data = request.form["content"], tn = 2, preview = 1, enddata = enddata, left = left, section = 1, number = num, odata = request.form["otent"], sub = '미리보기')
+        
+@app.route('/delete/<path:name>', methods=['POST', 'GET'])
+def delete(name = None):
+    ip = ip_check()
+    can = acl_check(ip, name)
+    
+    if(request.method == 'POST'):
+        db_ex("select * from data where title = '" + db_pas(name) + "'")
+        rows = db_get()
+        if(rows):
+            if(can == 1):
+                return '<meta http-equiv="refresh" content="0;url=/ban" />'
+            else:
+                today = get_time()
+                
+                leng = '-' + str(len(rows[0]['data']))
+                
+                history_plus(name, '', today, ip, '문서를 삭제 했습니다.', leng)
+                
+                db_ex("delete from data where title = '" + db_pas(name) + "'")
+                db_com()
+                
+                return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+    else:
+        db_ex("select * from data where title = '" + db_pas(name) + "'")
+        rows = db_get()
+        if(rows):
+            if(can == 1):
+                return '<meta http-equiv="refresh" content="0;url=/ban" />'
+            else:
+                return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), tn = 8, plus = '정말 삭제 하시겠습니까?', sub = '삭제')
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />'
+            
+@app.route('/move/<path:name>', methods=['POST', 'GET'])
+def move(name = None):
+    ip = ip_check()
+    can = acl_check(ip, name)
+    today = get_time()
+    
+    if(request.method == 'POST'):
+        db_ex("select * from data where title = '" + db_pas(name) + "'")
+        rows = db_get()
+
+        if(can == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            leng = '0'
+            db_ex("select * from history where title = '" + db_pas(request.form["title"]) + "'")
+            row = db_get()
+            if(row):
+                return '<meta http-equiv="refresh" content="0;url=/error/19" />'
+            else:
+                history_plus(name, rows[0]['data'], today, ip, '<a href="/w/' + url_pas(name) + '">' + name + '</a> 문서를 <a href="/w/' + url_pas(request.form["title"]) + '">' + request.form["title"] + '</a> 문서로 이동 했습니다.', leng)
+                
+                if(rows):
+                    db_ex("update data set title = '" + db_pas(request.form["title"]) + "' where title = '" + db_pas(name) + "'")
+
+                db_ex("update history set title = '" + db_pas(request.form["title"]) + "' where title = '" + db_pas(name) + "'")
+                db_com()
+                return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(request.form["title"]) + '" />'
+    else:
+        if(can == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], page = url_pas(name), tn = 9, plus = '정말 이동 하시겠습니까?', sub = '이동')
+            
+@app.route('/other')
+def other():
+    return web_render('index.html', login = login_check(), title = '기타 메뉴', logo = set_data['name'], data = '<h2 style="margin-top: 0px;">기록</h2><li><a href="/blocklog/n/1">유저 차단 기록</a></li><li><a href="/userlog/n/1">유저 가입 기록</a></li><li><a href="/manager/6">유저 기록</a></li><h2>기타</h2><li><a href="/titleindex">모든 문서</a></li><li><a href="/upload">업로드</a></li><li><a href="/adminlist">관리자 목록</a></li><li><a href="/manager/1">관리자 메뉴</a></li><br>이 오픈나무의 버전은 <a href="https://github.com/2DU/openNAMU/blob/master/version.md">1.9.1</a> 입니다.')
+    
+@app.route('/manager/<int:num>', methods=['POST', 'GET'])
+def manager(num = None):
+    if(num == 1):
+        return web_render('index.html', login = login_check(), title = '관리자 메뉴', logo = set_data['name'], data = '<h2 style="margin-top: 0px;">관리자 및 소유자</h2><li><a href="/manager/2">문서 ACL</a></li><li><a href="/manager/3">유저 체크</a></li><li><a href="/manager/4">유저 차단</a></li><h2>소유자</h2><li><a href="/manager/5">관리자 권한 주기</a></li><h2>기타</h2><li>이 메뉴에 없는 기능은 해당 문서의 역사나 토론에서 바로 사용 가능함</li>')
+    elif(num == 2):
+        if(request.method == 'POST'):
+            return '<meta http-equiv="refresh" content="0;url=/acl/' + url_pas(request.form["name"]) + '" />'
+        else:
+            return web_render('index.html', login = login_check(), title = 'ACL 이동', logo = set_data['name'], data = '<form id="usrform" method="POST" action="/manager/2"><input name="name" type="text"><br><br><button class="btn btn-primary" type="submit">이동</button></form>')
+    elif(num == 3):
+        if(request.method == 'POST'):
+            return '<meta http-equiv="refresh" content="0;url=/check/' + url_pas(request.form["name"]) + '" />'
+        else:
+            return web_render('index.html', login = login_check(), title = '체크 이동', logo = set_data['name'], data = '<form id="usrform" method="POST" action="/manager/3"><input name="name" type="text"><br><br><button class="btn btn-primary" type="submit">이동</button></form>')
+    elif(num == 4):
+        if(request.method == 'POST'):
+            return '<meta http-equiv="refresh" content="0;url=/ban/' + url_pas(request.form["name"]) + '" />'
+        else:
+            return web_render('index.html', login = login_check(), title = '차단 이동', logo = set_data['name'], data = '<form id="usrform" method="POST" action="/manager/4"><input name="name" type="text"><br><br><button class="btn btn-primary" type="submit">이동</button><br><br><span>아이피 앞 두자리 (XXX.XXX) 입력하면 대역 차단</span></form>')
+    elif(num == 5):
+        if(request.method == 'POST'):
+            return '<meta http-equiv="refresh" content="0;url=/admin/' + url_pas(request.form["name"]) + '" />'
+        else:
+            return web_render('index.html', login = login_check(), title = '권한 이동', logo = set_data['name'], data = '<form id="usrform" method="POST" action="/manager/5"><input name="name" type="text"><br><br><button class="btn btn-primary" type="submit">이동</button></form>')   
+    elif(num == 6):
+        if(request.method == 'POST'):
+            return '<meta http-equiv="refresh" content="0;url=/record/' + url_pas(request.form["name"]) + '/n/1" />'
+        else:
+            return web_render('index.html', login = login_check(), title = '기록 이동', logo = set_data['name'], data = '<form id="usrform" method="POST" action="/manager/6"><input name="name" type="text"><br><br><button class="btn btn-primary" type="submit">이동</button></form>')    
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/" />'
+        
+@app.route('/titleindex')
+def title_index():
+    i = 0
+    data = '<div>'
+    db_ex("select title from data order by title asc")
+    title_list = db_get()
+    if(title_list):
+        while(True):
+            try:
+                a = title_list[i]
+            except:
+                break
+
+            data = data + '<li>' + str(i + 1) + '. <a href="/w/' + url_pas(title_list[i]['title']) + '">' + title_list[i]['title'] + '</a></li>'
+            
+            i += 1
+
+        data = data + '</div>'
+
+        return web_render('index.html', login = login_check(), logo = set_data['name'], rows = data + '<br><span>이 위키에는 총 ' + str(i) + '개의 문서가 있습니다.</span>', tn = 4, title = '모든 문서')
+    else:
+        return web_render('index.html', login = login_check(), logo = set_data['name'], rows = '', tn = 4, title = '모든 문서')
+        
+@app.route('/topic/<path:name>', methods=['POST', 'GET'])
+def topic_list(name = None):
+    if(request.method == 'POST'):
+        return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(request.form["topic"]) + '" />'
+    else:
+        div = '<div>'
+        i = 0
+        j = 1
+        db_ex("select * from rd where title = '" + db_pas(name) + "' order by date asc")
+        rows = db_get()
+        while(True):
+            try:
+                a = rows[i]
+            except:
+                div = div + '</div>'
+                break
+                
+            db_ex("select * from topic where title = '" + db_pas(rows[i]['title']) + "' and sub = '" + db_pas(rows[i]['sub']) + "' and id = '1' order by sub asc")
+            aa = db_get()
+            
+            indata = namumark(name, aa[0]['data'])
+            
+            if(aa[0]['block'] == 'O'):
+                indata = '블라인드 되었습니다.'
+                block = 'style="background: gainsboro;"'
+            else:
+                block = ''
+
+            ip = ip_pas(aa[0]['ip'])
+                
+            db_ex("select * from stop where title = '" + db_pas(rows[i]['title']) + "' and sub = '" + db_pas(rows[i]['sub']) + "' and close = 'O'")
+            row = db_get()
+            if(not row):
+                div = div + '<h2><a href="/topic/' + url_pas(rows[i]['title']) + '/sub/' + url_pas(rows[i]['sub']) + '">' + str(j) + '. ' + rows[i]['sub'] + '</a></h2><table id="toron"><tbody><tr><td id="toroncolorgreen"><a href="javascript:void(0);" id="1">#1</a> ' + ip + ' <span style="float:right;">' + aa[0]['date'] + '</span></td></tr><tr><td ' + block + '>' + indata + '</td></tr></tbody></table><br>'
+                j += 1
+                
+            i += 1
+            
+        return web_render('index.html', login = login_check(), title = name, page = url_pas(name), logo = set_data['name'], plus = div, tn = 10, list = 1, sub = '토론 목록')
+        
+@app.route('/topic/<path:name>/close')
+def close_topic_list(name = None):
+    div = '<div>'
+    i = 0
+    
+    db_ex("select * from stop where title = '" + db_pas(name) + "' and close = 'O' order by sub asc")
+    rows = db_get()
+    while(True):
+        try:
+            a = rows[i]
+        except:
+            div = div + '</div>'
+            break
+            
+        db_ex("select * from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(rows[i]['sub']) + "' and id = '1'")
+        row = db_get()
+        if(row):
+            indata = namumark(name, row[0]['data'])
+            
+            if(row[0]['block'] == 'O'):
+                indata = '블라인드 되었습니다.'
+                block = 'style="background: gainsboro;"'
+            else:
+                block = ''
+
+            ip = ip_pas(row[0]['ip'])
+                
+            div = div + '<h2><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(rows[i]['sub']) + '">' + str((i + 1)) + '. ' + rows[i]['sub'] + '</a></h2><table id="toron"><tbody><tr><td id="toroncolorgreen"><a href="javascript:void(0);" id="1">#1</a> ' + ip + ' <span style="float:right;">' + row[0]['date'] + '</span></td></tr><tr><td ' + block + '>' + indata + '</td></tr></tbody></table><br>'
+            
+        i += 1
+        
+    return web_render('index.html', login = login_check(), title = name, page = url_pas(name), logo = set_data['name'], plus = div, tn = 10, sub = '닫힌 토론')
+    
+@app.route('/topic/<path:name>/agree')
+def agree_topic_list(name = None):
+    div = '<div>'
+    i = 0
+    
+    db_ex("select * from agreedis where title = '" + db_pas(name) + "' order by sub asc")
+    agree_list = db_get()
+    while(True):
+        try:
+            a = agree_list[i]
+        except:
+            div = div + '</div>'
+            break
+            
+        db_ex("select * from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(agree_list[i]['sub']) + "' and id = '1'")
+        data = db_get()
+        if(data):
+            indata = namumark(name, data[0]['data'])
+            
+            if(data[0]['block'] == 'O'):
+                indata = '블라인드 되었습니다.'
+                block = 'style="background: gainsboro;"'
+            else:
+                block = ''
+
+            ip = ip_pas(data[0]['ip'])
+                
+            div = div + '<h2><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(data[i]['sub']) + '">' + str((i + 1)) + '. ' + data[i]['sub'] + '</a></h2><table id="toron"><tbody><tr><td id="toroncolorgreen"><a href="javascript:void(0);" id="1">#1</a> ' + 아이디 + ' <span style="float:right;">' + data[0]['date'] + '</span></td></tr><tr><td ' + block + '>' + indata + '</td></tr></tbody></table><br>'
+            
+        i += 1
+        
+    return web_render('index.html', login = login_check(), title = name, page = url_pas(name), logo = set_data['name'], plus = div, tn = 10, sub = '합의된 토론')
+    
+@app.route('/topic/<path:name>/sub/<path:sub>', methods=['POST', 'GET'])
+def topic(name = None, sub = None):
+    ip = ip_check()
+    ban = topic_check(ip, name, sub)
+    admin = admin_check()
+    
+    if(request.method == 'POST'):
+        db_ex("select * from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' order by id+0 desc limit 1")
+        rows = db_get()
+        if(rows):
+            number = int(rows[0]['id']) + 1
+        else:
+            number = 1
+        
+        if(ban == 1 and not admin == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            db_ex("select * from user where id = '" + db_pas(ip) + "'")
+            rows = db_get()
+            if(rows):
+                if(rows[0]['acl'] == 'owner' or rows[0]['acl'] == 'admin'):
+                    ip = ip + ' - Admin'
+                    
+            today = get_time()
+            rd_plus(name, sub, today)
+            
+            aa = request.form["content"]
+            aa = re.sub("\[\[(분류:(?:(?:(?!\]\]).)*))\]\]", "[br]", aa)
+            aa = savemark(aa)
+            
+            db_ex("insert into topic (id, title, sub, data, date, ip, block) value ('" + str(number) + "', '" + db_pas(name) + "', '" + db_pas(sub) + "', '" + db_pas(aa) + "', '" + today + "', '" + ip + "', '')")
+            db_com()
+            
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+    else:
+        style = ''
+
+        db_ex("select * from stop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and close = 'O'")
+        close = db_get()
+
+        db_ex("select * from stop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and close = ''")
+        stop = db_get()
+        
+        if(admin == 1):
+            div = '<div>'
+            
+            if(close):
+                div = div + '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/close">(토론 열기)</a> '
+            else:
+                div = div + '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/close">(토론 닫기)</a> '
+            
+            if(stop):
+                div = div + '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/stop">(토론 재개)</a> '
+            else:
+                div = div + '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/stop">(토론 정지)</a> '
+
+            db_ex("select * from agreedis where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "'")
+            agree = db_get()
+            if(agree):
+                div = div + '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/agree">(합의 취소)</a>'
+            else:
+                div = div + '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/agree">(합의 완료)</a>'
+            
+            div = div + '<br><br>'
+        else:
+            div = '<div>'
+        
+        if(닫음 or 정지):
+            if(not admin == 1):
+                style = 'display:none;'
+        
+        db_ex("select * from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' order by id+0 asc")
+        rows = db_get()
+
+        db_ex("select * from distop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' order by id+0 asc")
+        top = db_get()
+
+        i = 0
+
 
 
+        if(top):
+            while(True):
+                try:
+                    a = top[i]
+                except:
+                    break
+
+                num = int(top[i]['id']) - 1
+
+                if(i == 0):
+                    start = rows[num]['ip']
+                    
+                top_data = namumark('', rows[num]['data'])
+                top_data = re.sub("(?P<in>#(?:[0-9]*))", '<a href="\g<in>">\g<in></a>', top_data)
+                        
+                ip = ip_pas(rows[num]['ip'])
+                                   
+                div = div + '<table id="toron"><tbody><tr><td id="toroncolorred"><a href="#' + top[i]['id'] + '" id="' + top[i]['id'] + '-nt">#' + top[i]['id'] + '</a> ' + ip + ' <span style="float:right;">' + rows[num]['date'] + '</span></td></tr><tr><td>' + top_data + '</td></tr></tbody></table><br>'
+                    
+                i = i + 1
+
+        i = 0
+        
+        while(True):
+            try:
+                a = rows[i]
+            except:
+                div = div + '</div>'
+                break
+                
+            if(i == 0):
+                start = rows[i]['ip']
+                
+            indata = namumark('', rows[i]['data'])
+            indata = re.sub("(?P<in>#(?:[0-9]*))", '<a href="\g<in>">\g<in></a>', indata)
+            
+            if(rows[i]['block'] == 'O'):
+                indata = '블라인드 되었습니다.'
+                block = 'style="background: gainsboro;"'
+            else:
+                block = ''
+
+            m = re.search("^([^-]*)\s\-\s(Close|Reopen|Stop|Restart|Agreement|Settlement)$", rows[i]['ip'])
+            if(m):
+                ban = ""
+            else:
+                if(admin == 1):
+                    if(rows[i]['block'] == 'O'):
+                        isblock = ' <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/b/' + str(i + 1) + '">(해제)</a>'
+                    else:
+                        isblock = ' <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/b/' + str(i + 1) + '">(블라인드)</a>'
+
+                    db_ex("select * from distop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and id = '" + db_pas(str(i + 1)) + "'")
+                    row = db_get()
+                    if(row):
+                        isblock = isblock + ' <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/notice/' + str(i + 1) + '">(해제)</a>'
+                    else:
+                        isblock = isblock + ' <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/notice/' + str(i + 1) + '">(공지)</a>'
+                        
+                    n = re.search("\- (?:Admin)$", rows[i]['ip'])
+                    if(n):
+                        ban = isblock
+                    else:
+                        db_ex("select * from ban where block = '" + db_pas(rows[i]['ip']) + "'")
+                        row = db_get()
+                        if(row):
+                            ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(해제)</a>' + isblock
+                        else:
+                            ban = ' <a href="/ban/' + url_pas(rows[i]['ip']) + '">(차단)</a>' + isblock
+                else:
+                    ban = ""
+
+            ip = ip_pas(rows[i]['ip'])
+                    
+            if(rows[i]['ip'] == start):
+                j = i + 1
+                
+                div = div + '<table id="toron"><tbody><tr><td id="toroncolorgreen"><a href="javascript:void(0);" id="' + str(j) + '">#' + str(j) + '</a> ' + ip + ban + ' <span style="float:right;">' + rows[i]['date'] + '</span></td></tr><tr><td ' + block + '>' + indata + '</td></tr></tbody></table><br>'
+            else:
+                j = i + 1
+                
+                div = div + '<table id="toron"><tbody><tr><td id="toroncolor"><a href="javascript:void(0);" id="' + str(j) + '">#' + str(j) + '</a> ' + ip + ban + ' <span style="float:right;">' + rows[i]['date'] + '</span></td></tr><tr><td ' + block + '>' + indata + '</td></tr></tbody></table><br>'
+                
+            i += 1
+            
+        return web_render('index.html', login = login_check(), title = name, page = url_pas(name), suburl = url_pas(sub), toron = sub, logo = set_data['name'], rows = div, tn = 11, ban = ban, style = style, sub = '토론')
+        
+@app.route('/topic/<path:name>/sub/<path:sub>/b/<int:num>')
+def topic_block(name = None, sub = None, num = None):
+    if(admin_check() == 1):
+        db_ex("select * from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and id = '" + str(num) + "'")
+        block = db_get()
+        if(block):
+            if(block[0]['block'] == 'O'):
+                db_ex("update topic set block = '' where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and id = '" + str(num) + "'")
+            else:
+                db_ex("update topic set block = 'O' where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and id = '" + str(num) + "'")
+            db_com()
+            
+            rd_plus(name, sub, get_time())
+            
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+        
+@app.route('/topic/<path:name>/sub/<path:sub>/notice/<int:num>')
+def topic_top(name = None, sub = None, num = None):
+    if(admin_check() == 1):
+        db_ex("select * from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and id = '" + str(num) + "'")
+        topic_data = db_get()
+        if(topic_data):
+            db_ex("select * from distop where id = '" + str(num) + "' and title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "'")
+            top_data = db_get()
+            if(top_data):
+                db_ex("delete from distop where id = '" + str(num) + "' and title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "'")
+            else:
+                db_ex("insert into distop (id, title, sub) value ('" + db_pas(str(num)) + "', '" + db_pas(name) + "', '" + db_pas(sub) + "')")
+            db_com()
+            
+            rd_plus(name, sub, get_time())
+
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+        
+@app.route('/topic/<path:name>/sub/<path:sub>/stop')
+def topic_stop(name = None, sub = None):
+    if(admin_check() == 1):
+        ip = ip_check()
+        
+        db_ex("select * from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' limit 1")
+        topic_check = db_get()
+        if(topic_check):
+            time = get_time()
+            
+            db_ex("select * from stop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and close = ''")
+            stop = db_get()
+            if(stop):
+                db_ex("insert into topic (id, title, sub, data, date, ip, block) value ('" + db_pas(str(int(topic_check[0]['id']) + 1)) + "', '" + db_pas(name) + "', '" + db_pas(sub) + "', 'Restart', '" + db_pas(time) + "', '" + db_pas(ip) + " - Restart', '')")
+                db_ex("delete from stop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and close = ''")
+            else:
+                db_ex("insert into topic (id, title, sub, data, date, ip, block) value ('" + db_pas(str(int(topic_check[0]['id']) + 1)) + "', '" + db_pas(name) + "', '" + db_pas(sub) + "', 'Stop', '" + db_pas(time) + "', '" + db_pas(ip) + " - Stop', '')")
+                db_ex("insert into stop (title, sub, close) value ('" + db_pas(name) + "', '" + db_pas(sub) + "', '')")
+            db_com()
+            
+            rd_plus(name, sub, time)
+            
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+        
+@app.route('/topic/<path:name>/sub/<path:sub>/close')
+def topic_close(name = None, sub = None):
+    if(admin_check() == 1):
+        ip = ip_check()
+        
+        db_ex("select * from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' order by id+0 desc limit 1")
+        topic_check = db_get()
+        if(topic_check):
+            time = get_time()
+            
+            db_ex("select * from stop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and close = 'O'")
+            close = db_get()
+            if(close):
+                db_ex("insert into topic (id, title, sub, data, date, ip, block) value ('" + db_pas(str(int(topic_check[0]['id']) + 1)) + "', '" + db_pas(name) + "', '" + db_pas(sub) + "', 'Reopen', '" + db_pas(time) + "', '" + db_pas(ip) + " - Reopen', '')")
+                db_ex("delete from stop where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' and close = 'O'")
+            else:
+                db_ex("insert into topic (id, title, sub, data, date, ip, block) value ('" + db_pas(str(int(topic_check[0]['id']) + 1)) + "', '" + db_pas(name) + "', '" + db_pas(sub) + "', 'Close', '" + db_pas(time) + "', '" + db_pas(ip) + " - Close', '')")
+                db_ex("insert into stop (title, sub, close) value ('" + db_pas(name) + "', '" + db_pas(sub) + "', 'O')")
+            db_com()
+            
+            rd_plus(name, sub, time)
+            
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+        
+@app.route('/topic/<path:name>/sub/<path:sub>/agree')
+def topic_agree(name = None, sub = None):
+    if(admin_check() == 1):
+        ip = ip_check()
+        
+        db_ex("select id from topic where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "' order by id+0 desc limit 1")
+        topic_check = db_get()
+        if(topic_check):
+            time = get_time()
+            
+            db_ex("select * from agreedis where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "'")
+            agree = db_get()
+            if(agree):
+                db_ex("insert into topic (id, title, sub, data, date, ip, block) value ('" + db_pas(str(int(topic_check[0]['id']) + 1)) + "', '" + db_pas(name) + "', '" + db_pas(sub) + "', 'Settlement', '" + db_pas(time) + "', '" + db_pas(ip) + " - Settlement', '')")
+                db_ex("delete from agreedis where title = '" + db_pas(name) + "' and sub = '" + db_pas(sub) + "'")
+            else:
+                db_ex("insert into topic (id, title, sub, data, date, ip, block) value ('" + db_pas(str(int(topic_check[0]['id']) + 1)) + "', '" + db_pas(name) + "', '" + db_pas(sub) + "', 'Agreement', '" + db_pas(time) + "', '" + db_pas(ip) + " - Agreement', '')")
+                db_ex("insert into agreedis (title, sub) value ('" + db_pas(name) + "', '" + db_pas(sub) + "')")
+            db_com()
+            
+            rd_plus(name, sub, time)
+            
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '" />'
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+        
+@app.route('/login', methods=['POST', 'GET'])
+def login():
+    ip = ip_check()
+    ban = ban_check(ip)
+        
+    if(request.method == 'POST'):        
+        if(ban == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            db_ex("select * from user where id = '" + db_pas(request.form["id"]) + "'")
+            user = db_get()
+            if(user):
+                if(session.get('Now') == True):
+                    return '<meta http-equiv="refresh" content="0;url=/error/11" />'
+                elif(bcrypt.checkpw(bytes(request.form["pw"], 'utf-8'), bytes(user[0]['pw'], 'utf-8'))):
+                    session['Now'] = True
+                    session['DREAMER'] = request.form["id"]
+                    
+                    db_ex("insert into login (user, ip, today) value ('" + db_pas(request.form["id"]) + "', '" + db_pas(ip) + "', '" + db_pas(get_time()) + "')")
+                    db_com()
+                    
+                    return '<meta http-equiv="refresh" content="0;url=/user" />'
+                else:
+                    return '<meta http-equiv="refresh" content="0;url=/error/13" />'
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/error/12" />'
+    else:        
+        if(ban == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            if(session.get('Now') == True):
+                return '<meta http-equiv="refresh" content="0;url=/error/11" />'
+            else:
+                return web_render('index.html', login = login_check(), title = '로그인', enter = '로그인', logo = set_data['name'], tn = 15)
+                
+@app.route('/change', methods=['POST', 'GET'])
+def change_password():
+    ip = ip_check()
+    ban = ban_check(ip)
+    
+    if(request.method == 'POST'):      
+        if(request.form["pw2"] == request.form["pw3"]):
+            if(ban == 1):
+                return '<meta http-equiv="refresh" content="0;url=/ban" />'
+            else:
+                db_ex("select * from user where id = '" + db_pas(request.form["id"]) + "'")
+                user = db_get()
+                if(user):
+                    if(session.get('Now') == True):
+                        session['Now'] = False
+                        session.pop('DREAMER', None)
+                        return '<meta http-equiv="refresh" content="0;url=/change" />'
+                    elif(bcrypt.checkpw(bytes(request.form["pw"], 'utf-8'), bytes(user[0]['pw'], 'utf-8'))):
+                        hashed = bcrypt.hashpw(bytes(request.form["pw2"], 'utf-8'), bcrypt.gensalt())
+                        
+                        db_ex("update user set pw = '" + db_pas(hashed.decode()) + "' where id = '" + db_pas(request.form["id"]) + "'")
+                        db_com()
+                        
+                        return '<meta http-equiv="refresh" content="0;url=/login" />'
+                    else:
+                        return '<meta http-equiv="refresh" content="0;url=/error/10" />'
+                else:
+                    return '<meta http-equiv="refresh" content="0;url=/error/9" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/20" />'
+    else:        
+        if(ban == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            if(session.get('Now') == True):
+                session['Now'] = False
+                session.pop('DREAMER', None)
+                return '<meta http-equiv="refresh" content="0;url=/change" />'
+            else:
+                return web_render('index.html', login = login_check(), title = '비밀번호 변경', enter = '변경', logo = set_data['name'], tn = 15)
+                
+@app.route('/check/<name>')
+def user_check(name = None, sub = None):
+    db_ex("select * from user where id = '" + db_pas(name) + "'")
+    user = db_get()
+    if(user and user[0]['acl'] == 'owner' or user and user[0]['acl'] == 'admin'):
+        return '<meta http-equiv="refresh" content="0;url=/error/4" />'
+    else:
+        if(admin_check() == 1):
+            m = re.search('(?:[0-9](?:[0-9][0-9])?\.[0-9](?:[0-9][0-9])?\.[0-9](?:[0-9][0-9])?\.[0-9](?:[0-9][0-9])?)', name)
+            if(m):
+                db_ex("select * from login where ip = '" + db_pas(name) + "' order by today desc")
+                row = db_get()
+                if(row):
+                    i = 0
+                    c = ''
+                    while(True):
+                        try:
+                            c = c + '<table style="width: 100%;"><tbody><tr><td style="text-align: center;width:33.33%;">' + row[i]['user'] + '</td><td style="text-align: center;width:33.33%;">' + row[i]['ip'] + '</td><td style="text-align: center;width:33.33%;">' + row[i]['today'] + '</td></tr></tbody></table>'
+                        except:
+                            break
+                            
+                        i += 1
+                        
+                    return web_render('index.html', login = login_check(), title = '다중 검사', logo = set_data['name'], tn = 22, rows = c)
+                else:
+                    return web_render('index.html', login = login_check(), title = '다중 검사', logo = set_data['name'], tn = 22, rows = '')
+            else:
+                db_ex("select * from login where user = '" + db_pas(name) + "' order by today desc")
+                row = db_get()
+                if(row):
+                    i = 0
+                    c = ''
+                    while(True):
+                        try:
+                            c = c + '<table style="width: 100%;"><tbody><tr><td style="text-align: center;width:33.33%;">' + row[i]['user'] + '</td><td style="text-align: center;width:33.33%;">' + row[i]['ip'] + '</td><td style="text-align: center;width:33.33%;">' + row[i]['today'] + '</td></tr></tbody></table>'
+                        except:
+                            break
+                            
+                        i += 1
+                        
+                    return web_render('index.html', login = login_check(), title = '다중 검사', logo = set_data['name'], tn = 22, rows = c)
+                else:
+                    return web_render('index.html', login = login_check(), title = '다중 검사', logo = set_data['name'], tn = 22, rows = '')
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+                
+@app.route('/register', methods=['POST', 'GET'])
+def register():
+    ip = ip_check()
+    ban = ban_check(ip)
+    
+    if(request.method == 'POST'):        
+        if(request.form["pw"] == request.form["pw2"]):
+            if(ban == 1):
+                return '<meta http-equiv="refresh" content="0;url=/ban" />'
+            else:
+                m = re.search('(?:[^A-Za-zㄱ-힣0-9 ])', request.form["id"])
+                if(m):
+                    return '<meta http-equiv="refresh" content="0;url=/error/8" />'
+                else:
+                    if(len(request.form["id"]) > 20):
+                        return '<meta http-equiv="refresh" content="0;url=/error/7" />'
+                    else:
+                        db_ex("select * from user where id = '" + db_pas(request.form["id"]) + "'")
+                        rows = db_get()
+                        if(rows):
+                            return '<meta http-equiv="refresh" content="0;url=/error/6" />'
+                        else:
+                            hashed = bcrypt.hashpw(bytes(request.form["pw"], 'utf-8'), bcrypt.gensalt())
+                            
+                            if(request.form["id"] == data['owner']):
+                                db_ex("insert into user (id, pw, acl) value ('" + db_pas(request.form["id"]) + "', '" + db_pas(hashed.decode()) + "', 'owner')")
+                            else:
+                                db_ex("insert into user (id, pw, acl) value ('" + db_pas(request.form["id"]) + "', '" + db_pas(hashed.decode()) + "', 'user')")
+                            db_com()
+                            
+                            return '<meta http-equiv="refresh" content="0;url=/login" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/20" />'
+    else:        
+        if(ban == 1):
+            return '<meta http-equiv="refresh" content="0;url=/ban" />'
+        else:
+            return web_render('index.html', login = login_check(), title = '회원가입', enter = '회원가입', logo = set_data['name'], tn = 15)
+            
+@app.route('/logout')
+def logout():
+    session['Now'] = False
+    session.pop('DREAMER', None)
+    return '<meta http-equiv="refresh" content="0;url=/user" />'
+    
+@app.route('/ban/<name>', methods=['POST', 'GET'])
+def user_ban(name = None):
+    db_ex("select * from user where id = '" + db_pas(name) + "'")
+    user = db_get()
+    if(user and user[0]['acl'] == 'owner' or user and user[0]['acl'] == 'admin'):
+        return '<meta http-equiv="refresh" content="0;url=/error/4" />'
+    else:
+        if(request.method == 'POST'):
+            if(admin_check() == 1):
+                ip = ip_check()
+                
+                if(not re.search("[0-9]{4}-[0-9]{2}-[0-9]{2}", request.form["end"])):
+                    end = ''
+                else:
+                    end = request.form["end"]
+
+                db_ex("select * from ban where block = '" + db_pas(name) + "'")
+                row = db_get()
+                if(row):
+                    rb_plus(name, '해제', 시간(), ip, '')
+                    
+                    db_ex("delete from ban where block = '" + db_pas(name) + "'")
+                else:
+                    b = re.search("^([0-9](?:[0-9]?[0-9]?)\.[0-9](?:[0-9]?[0-9]?))$", name)
+                    if(b):
+                        rb_plus(name, end, 시간(), ip, request.form["why"])
+                        
+                        db_ex("insert into ban (block, end, why, band) value ('" + db_pas(name) + "', '" + db_pas(end) + "', '" + db_pas(request.form["why"]) + "', 'O')")
+                    else:
+                        rb_plus(name, end, 시간(), ip, request.form["why"])
+                        
+                        db_ex("insert into ban (block, end, why, band) value ('" + db_pas(name) + "', '" + db_pas(end) + "', '" + db_pas(request.form["why"]) + "', '')")
+                db_com()
+                
+                return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(data['frontpage']) + '" />'
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+        else:
+            if(admin_check() == 1):
+                db_ex("select * from ban where block = '" + db_pas(name) + "'")
+                row = db_get()
+                if(row):
+                    now = '차단 해제'
+                else:
+                    b = re.search("^([0-9](?:[0-9]?[0-9]?)\.[0-9](?:[0-9]?[0-9]?))$", name)
+                    if(b):
+                        now = '대역 차단'
+                    else:
+                        now = '차단'
+                        
+                return web_render('index.html', login = login_check(), title = name, page = url_pas(name), logo = set_data['name'], tn = 16, now = now, today = get_time(), sub = '차단')
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+                
+@app.route('/acl/<path:name>', methods=['POST', 'GET'])
+def acl(name = None):
+    if(request.method == 'POST'):
+        if(admin_check() == 1):
+            db_ex("select * from data where title = '" + db_pas(name) + "'")
+            row = db_get()
+            if(row):
+                if(request.form["select"] == 'admin'):
+                   db_ex("update data set acl = 'admin' where title = '" + db_pas(name) + "'")
+                elif(request.form["select"] == 'user'):
+                    db_ex("update data set acl = 'user' where title = '" + db_pas(name) + "'")
+                else:
+                    db_ex("update data set acl = '' where title = '" + db_pas(name) + "'")
+                    
+                db_com()
+                
+            return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />' 
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+    else:
+        if(admin_check() == 1):
+            db_ex("select * from data where title = '" + db_pas(name) + "'")
+            row = db_get()
+            if(row):
+                if(row[0]['acl'] == 'admin'):
+                    now = '관리자만'
+                elif(row[0]['acl'] == 'user'):
+                    now = '유저 이상'
+                else:
+                    now = '일반'
+                    
+                return web_render('index.html', login = login_check(), title = name, page = url_pas(name), logo = set_data['name'], tn = 19, now = '현재 ACL 상태는 ' + now, sub = 'ACL')
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(name) + '" />' 
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+            
+@app.route('/admin/<name>', methods=['POST', 'GET'])
+def user_admin(name = None):
+    if(request.method == 'POST'):
+        if(owner_check() == 1):
+            db_ex("select * from user where id = '" + db_pas(name) + "'")
+            user = db_get()
+            if(user):
+                if(user[0]['acl'] == 'admin' or user[0]['acl'] == 'owner'):
+                    db_ex("update user set acl = 'user' where id = '" + db_pas(name) + "'")
+                else:
+                    db_ex("update user set acl = '" + db_pas(request.form["select"]) + "' where id = '" + db_pas(name) + "'")
+                db_com()
+                
+                return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(data['frontpage']) + '" />'
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/error/5" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+    else:
+        if(owner_check() == 1):
+            db_ex("select * from user where id = '" + db_pas(name) + "'")
+            user = db_get()
+            if(user):
+                if(user[0]['acl'] == 'admin' or user[0]['acl'] == 'owner'):
+                    now = '권한 해제'
+                else:
+                    now = '권한 부여'
+                    
+                return web_render('index.html', login = login_check(), title = name, page = url_pas(name), logo = data['name'], tn = 18, now = now, sub = '권한 부여')
+            else:
+                return '<meta http-equiv="refresh" content="0;url=/error/5" />'
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/error/3" />'
+            
+@app.route('/ban')
+def are_you_ban():
+    ip = ip_check()
+    
+    if(ban_check(ip) == 1):
+        db_ex("select * from ban where block = '" + db_pas(ip) + "'")
+        rows = db_get()
+        if(rows):
+            if(rows[0]['end']):
+                end = rows[0]['end'] + ' 까지 차단 상태 입니다. / 사유 : ' + rows[0]['why']                
+                now = get_time()
+                
+                now = re.sub(':', '', now)
+                now = re.sub('\-', '', now)
+                now = re.sub(' ', '', now)
+                now = int(now)
+                
+                day = rows[0]['end']
+                day = re.sub('\-', '', day)    
+                
+                if(now >= int(day + '000000')):
+                    db_ex("delete from ban where block = '" + db_pas(ip) + "'")
+                    db_com()
+                    
+                    end = '차단이 풀렸습니다. 다시 시도 해 보세요.'
+            else:
+                end = '영구 차단 상태 입니다. / 사유 : ' + rows[0]['why']
+        else:
+            b = re.search("^([0-9](?:[0-9]?[0-9]?)\.[0-9](?:[0-9]?[0-9]?))", ip)
+            if(b):
+                results = b.groups()
+                
+                db_ex("select * from ban where block = '" + db_pas(results[0]) + "' and band = 'O'")
+                row = db_get()
+                if(row):
+                    if(row[0]['end']):
+                        end = row[0]['end'] + ' 까지 차단 상태 입니다. / 사유 : ' + rows[0]['why']             
+                        
+                        now = get_time()
+                        now = re.sub(':', '', now)
+                        now = re.sub('\-', '', now)
+                        now = re.sub(' ', '', now)
+                        now = int(now)    
+                        
+                        day = row[0]['end']
+                        day = re.sub('\-', '', day)
+                        
+                        if(now >= int(day + '000000')):
+                            db_ex("delete from ban where block = '" + db_pas(results[0]) + "' and band = 'O'")
+                            db_com()
+                            
+                            end = '차단이 풀렸습니다. 다시 시도 해 보세요.'
+                    else:
+                        end = '영구 차단 상태 입니다. / 사유 : ' + row[0]['why']                
+    else:
+        end = '권한이 맞지 않는 상태 입니다.'
+        
+    return web_render('index.html', login = login_check(), title = '권한 오류', logo = set_data['name'], data = end), 401
+    
+@app.route('/w/<path:name>/r/<int:a>/diff/<int:b>')
+def diff_data(name = None, a = None, b = None):
+    db_ex("select * from history where id = '" + db_pas(str(a)) + "' and title = '" + db_pas(name) + "'")
+    a_raw_data = db_get()
+    if(a_raw_data):
+        db_ex("select * from history where id = '" + db_pas(str(b)) + "' and title = '" + db_pas(name) + "'")
+        b_raw_data = db_get()
+        if(b_raw_data):
+            a_data = re.sub('<', '&lt;', a_raw_data[0]['data'])
+            a_data = re.sub('>', '&gt;', a_data)
+            a_data = re.sub('"', '&quot;', a_data)
+            
+            b_data = re.sub('<', '&lt;', b_raw_data[0]['data'])
+            b_data = re.sub('>', '&gt;', b_data)
+            b_data = re.sub('"', '&quot;', b_data)
+            
+            diff_data = difflib.SequenceMatcher(None, a_data, b_data)
+            result = diff(diff_data)
+            
+            result = '<pre>' + result + '</pre>'
+            
+            return web_render('index.html', login = login_check(), title = name, logo = set_data['name'], data = result, sub = '비교')
+        else:
+            return '<meta http-equiv="refresh" content="0;url=/history/' + url_pas(name) + '" />'
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/history/' + url_pas(name) + '" />'
+        
+@app.route('/user')
+def user_info():
+    ip = ip_check()
+    raw_ip = ip
+    
+    db_ex("select * from user where id = '" + db_pas(ip) + "'")
+    rows = db_get()
+    if(ban_check(ip) == 0):
+        if(rows):
+            if(rows[0]['acl'] == 'admin' or rows[0]['acl'] == 'owner'):
+                if(rows[0]['acl'] == 'admin'):
+                    acl = '관리자'
+                else:
+                    acl = '소유자'
+            else:
+                acl = '유저'
+        else:
+            acl = '일반'
+    else:
+        acl = '차단'
+        
+    ip = ip_pas(ip)
+        
+    return web_render('index.html', login = login_check(), title = '유저 메뉴', logo = set_data['name'], data = ip + '<br><br><span>권한 상태 : ' + acl + '<h2>로그인 관련</h2><li><a href="/login">로그인</a></li><li><a href="/logout">로그아웃</a></li><li><a href="/register">회원가입</a></li><h2>기타</h2><li><a href="/change">비밀번호 변경</a></li><li><a href="/count">기여 횟수</a></li><li><a href="/record/' + raw_ip + '/n/1">기여 목록</a></li>')
+    
+@app.route('/count')
+def count_edit():
+    db_ex("select count(title) from history where ip = '" + ip_check() + "'")
+    i = db_get()
+    
+    if(i):
+        return web_render('index.html', login = login_check(), title = '기여 횟수', logo = set_data['name'], data = "기여 횟수 : " + str(i[0]["count(title)"]))
+    else:
+        return web_render('index.html', login = login_check(), title = '기여 횟수', logo = set_data['name'], data = "기여 횟수 : 0")
+        
+@app.route('/random')
+def random():
+    db_ex("select * from data order by rand() limit 1")
+    rows = db_get()
+    if(rows):
+        return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(rows[0]['title']) + '" />'
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/" />'
+        
+@app.route('/error/<int:num>')
+def 오류(num = None):
+    if(num == 1):
+        return web_render('index.html', login = login_check(), title = '권한 오류', logo = set_data['name'], data = '비 로그인 상태 입니다.'), 401
+    elif(num == 2):
+        return web_render('index.html', login = login_check(), title = '권한 오류', logo = set_data['name'], data = '이 계정이 없습니다.'), 401
+    elif(num == 3):
+        return web_render('index.html', login = login_check(), title = '권한 오류', logo = set_data['name'], data = '권한이 모자랍니다.'), 401
+    elif(num == 4):
+        return web_render('index.html', login = login_check(), title = '권한 오류', logo = set_data['name'], data = '관리자는 차단, 검사 할 수 없습니다.'), 401
+    elif(num == 5):
+        return web_render('index.html', login = login_check(), title = '유저 오류', logo = set_data['name'], data = '그런 계정이 없습니다.'), 401
+    elif(num == 6):
+        return web_render('index.html', login = login_check(), title = '가입 오류', logo = set_data['name'], data = '동일한 아이디의 유저가 있습니다.'), 401
+    elif(num == 7):
+        return web_render('index.html', login = login_check(), title = '가입 오류', logo = set_data['name'], data = '아이디는 20글자보다 짧아야 합니다.'), 401
+    elif(num == 8):
+        return web_render('index.html', login = login_check(), title = '가입 오류', logo = set_data['name'], data = '아이디에는 한글과 알파벳과 공백만 허용 됩니다.'), 401
+    elif(num == 9):
+        return web_render('index.html', login = login_check(), title = '변경 오류', logo = set_data['name'], data = '그런 계정이 없습니다.'), 401
+    elif(num == 10):
+        return web_render('index.html', login = login_check(), title = '변경 오류', logo = set_data['name'], data = '비밀번호가 다릅니다.'), 401
+    elif(num == 11):
+        return web_render('index.html', login = login_check(), title = '로그인 오류', logo = set_data['name'], data = '이미 로그인 되어 있습니다.'), 401
+    elif(num == 12):
+        return web_render('index.html', login = login_check(), title = '로그인 오류', logo = set_data['name'], data = '그런 계정이 없습니다.'), 401
+    elif(num == 13):
+        return web_render('index.html', login = login_check(), title = '로그인 오류', logo = set_data['name'], data = '비밀번호가 다릅니다.'), 401
+    elif(num == 14):
+        return web_render('index.html', login = login_check(), title = '업로드 오류', logo = set_data['name'], data = 'jpg, gif, jpeg, png만 가능 합니다.'), 401
+    elif(num == 15):
+        return web_render('index.html', login = login_check(), title = '업로드 오류', logo = set_data['name'], data = '파일 명에 . / \ * < > | : ? 가 들어 갈 수 없습니다.'), 401
+    elif(num == 16):
+        return web_render('index.html', login = login_check(), title = '업로드 오류', logo = set_data['name'], data = '동일한 이름의 파일이 있습니다.'), 401
+    elif(num == 17):
+        return web_render('index.html', login = login_check(), title = '편집 오류', logo = set_data['name'], data = '편집 내용 기록에는 한글과 영어와 숫자, 공백만 허용 됩니다.'), 401
+    elif(num == 18):
+        return web_render('index.html', login = login_check(), title = '편집 오류', logo = set_data['name'], data = '내용이 원래 문서와 동일 합니다.'), 401
+    elif(num == 19):
+        return web_render('index.html', login = login_check(), title = '이동 오류', logo = set_data['name'], data = '이동 하려는 곳에 문서가 이미 있습니다.'), 401
+    elif(num == 20):
+        return web_render('index.html', login = login_check(), title = '비밀번호 오류', logo = set_data['name'], data = '재 확인이랑 비밀번호가 다릅니다.'), 401
+    else:
+        return '<meta http-equiv="refresh" content="0;url=/" />'
+
+@app.errorhandler(404)
+def uncaughtError(error):
+    return '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(set_data['frontpage']) + '" />'
+
+@app.errorhandler(413)
+def uncaughtError(error):
+    app.config['MAX_CONTENT_LENGTH'] = (1024**3)
+    return error, 401
+    
+if(__name__ == '__main__'):
+    app.run(host = '0.0.0.0', port = int(set_data['port']))

+ 1013 - 0
mark.py

@@ -0,0 +1,1013 @@
+from func import *
+
+json_data = open('set.json').read()
+set_data = json.loads(json_data)
+
+conn = pymysql.connect(host = set_data['host'], user = set_data['user'], password = set_data['pw'], charset = 'utf8mb4')
+curs = conn.cursor(pymysql.cursors.DictCursor)
+
+def db_com():
+    conn.commit()
+
+def url_pas(data):
+    return parse.quote(data).replace('/','%2F')
+    
+def db_get():
+    return curs.fetchall()
+    
+db_ex = curs.execute
+db_pas = pymysql.escape_string
+
+db_ex("use " + set_data['db'])
+
+def savemark(data):
+    data = re.sub("\[date\(now\)\]", get_time(), data)
+    
+    if(not re.search("\.", ip_check())):
+        name = '[[사용자:' + ip_check() + '|' + ip_check() + ']]'
+    else:
+        name = ip_check()
+        
+    data = re.sub("\[name\]", name, data)
+
+    return data
+
+def html_pas(data):
+    while(True):
+        y = re.search("<((div|span|embed|iframe)(?:[^>]*))>", data)
+        
+        if(y):
+            b = y.groups()
+
+            if(re.search("<(\/" + b[1] + ")>", data)):
+                XSS = re.search('src=(?:"|\')http(?:s)?:\/\/([^\/]*)\/(?:[^"\']*)(?:"|\')', b[0])
+                
+                if(XSS):
+                    check = XSS.groups()
+                    
+                    if(check[0] == "www.youtube.com" or check[0] == "serviceapi.nmv.naver.com" or check[0] == "tv.kakao.com" or check[0] == "tvple.com"):
+                        a = b[0]
+                    else:
+                        a = re.sub('src=(?:"|\')([^"\']*)(?:"|\')', '', b[0])
+                else:
+                    a = b[0]
+                
+                a = re.sub('(?:"|\')', '#.#', a)
+                data = re.sub("<((?:\/)?" + b[1] + "(?:[^>]*))>", "[" + a + "]", data, 1)
+                data = re.sub("<\/" + b[1] + ">", "[/" + b[1] + "]", data, 1)
+            else:
+                data = re.sub("<((?:\/)?" + b[1] + "(?:[^>]*))>", '&lt;' + b[0] + '&gt;', data, 1)
+                
+                break
+        else:
+            break
+
+    data = re.sub('<', '&lt;', data)
+    data = re.sub('>', '&gt;', data)
+    data = re.sub('"', '&quot;', data)
+    
+    data = re.sub("\[(?P<in>(?:\/)?(?:div|span|embed|iframe)(?:[^\]]*))\]", "<\g<in>>", data)
+    data = re.sub('#.#', '"', data)
+    
+    return data
+    
+def mid_pas(data, fol_num, include):
+    while(True):
+        com = re.compile("{{{((?:(?!{{{)(?!}}}).)*)}}}", re.DOTALL)
+        y = com.search(data)
+        
+        if(y):
+            a = y.groups()
+            
+            big_a = re.compile("^\+([1-5])\s(.*)$", re.DOTALL)
+            big = big_a.search(a[0])
+            
+            small_a = re.compile("^\-([1-5])\s(.*)$", re.DOTALL)
+            small = small_a.search(a[0])
+            
+            color_a = re.compile("^(#[0-9a-f-A-F]{6})\s(.*)$", re.DOTALL)
+            color = color_a.search(a[0])
+            
+            color_b = re.compile("^(#[0-9a-f-A-F]{3})\s(.*)$", re.DOTALL)
+            color_2 = color_b.search(a[0])
+            
+            color_c = re.compile("^#(\w+)\s(.*)$", re.DOTALL)
+            color_3 = color_c.search(a[0])
+            
+            back_a = re.compile("^@([0-9a-f-A-F]{6})\s(.*)$", re.DOTALL)
+            back = back_a.search(a[0])
+            
+            back_b = re.compile("^@([0-9a-f-A-F]{3})\s(.*)$", re.DOTALL)
+            back_2 = back_b.search(a[0])
+            
+            back_c = re.compile("^@(\w+)\s(.*)$", re.DOTALL)
+            back_3 = back_c.search(a[0])
+            
+            include_out_a = re.compile("^#!noin\s(.*)$", re.DOTALL)
+            include_out = include_out_a.search(a[0])
+            
+            div_a = re.compile("^#!wiki\sstyle=&quot;((?:(?!&quot;|\n).)*)&quot;\n?\s\n(.*)$", re.DOTALL)
+            div = div_a.search(a[0])
+            
+            html_a = re.compile("^#!html\s(.*)$", re.DOTALL)
+            html = html_a.search(a[0])
+            
+            fol_a = re.compile("^#!folding\s((?:(?!\n).)*)\n?\s\n(.*)$", re.DOTALL)
+            flo = fol_a.search(a[0])
+            
+            if(big):
+                result = big.groups()
+                data = com.sub('<span class="font-size-' + result[0] + '">' + result[1] + '</span>', data, 1)
+            elif(small):
+                result = small.groups()
+                data = com.sub('<span class="font-size-small-' + result[0] + '">' + result[1] + '</span>', data, 1)
+            elif(color):
+                result = color.groups()
+                data = com.sub('<span style="color:' + result[0] + '">' + result[1] + '</span>', data, 1)
+            elif(color_2):
+                result = color_2.groups()
+                data = com.sub('<span style="color:' + result[0] + '">' + result[1] + '</span>', data, 1)
+            elif(color_3):
+                result = color_3.groups()
+                data = com.sub('<span style="color:' + result[0] + '">' + result[1] + '</span>', data, 1)
+            elif(back):
+                result = back.groups()
+                data = com.sub('<span style="background:#' + result[0] + '">' + result[1] + '</span>', data, 1)
+            elif(back_2):
+                result = back_2.groups()
+                data = com.sub('<span style="background:#' + result[0] + '">' + result[1] + '</span>', data, 1)
+            elif(back_3):
+                result = back_3.groups()
+                data = com.sub('<span style="background:' + result[0] + '">' + result[1] + '</span>', data, 1)
+            elif(div):
+                result = div.groups()
+                data = com.sub('<div style="' + result[0] + '">' + result[1] + '</div>', data, 1)
+            elif(html):
+                result = html.groups()
+                data = com.sub(result[0], data, 1)
+            elif(fol):
+                result = fol.groups()
+                data = com.sub("<div>" + result[0] + "<span style='float:right;'><div id='folding_" + str(fol_num + 1) + "' style='display:block;'>[<a href='javascript:void(0);' onclick='var f=document.getElementById(\"folding_" + str(fol_num) + "\");var s=f.style.display==\"block\";f.style.display=s?\"none\":\"block\";this.className=s?\"\":\"opened\";var f=document.getElementById(\"folding_" + str(fol_num + 1) + "\");var s=f.style.display==\"none\";f.style.display=s?\"block\":\"none\";var f=document.getElementById(\"folding_" + str(fol_num + 2) + "\");var s=f.style.display==\"block\";f.style.display=s?\"none\":\"block\";'>펼치기</a>]</div><div id='folding_" + str(fol_num + 2) + "' style='display:none;'>[<a href='javascript:void(0);' onclick='var f=document.getElementById(\"folding_" + str(fol_num) + "\");var s=f.style.display==\"block\";f.style.display=s?\"none\":\"block\";this.className=s?\"\":\"opened\";var f=document.getElementById(\"folding_" + str(fol_num + 1) + "\");var s=f.style.display==\"none\";f.style.display=s?\"block\":\"none\";var f=document.getElementById(\"folding_" + str(fol_num + 2) + "\");var s=f.style.display==\"block\";f.style.display=s?\"none\":\"block\";'>접기</a>]</div></a></span><div id='folding_" + str(fol_num) + "' style='display:none;'><br>" + result[1] + "</div></div>", data, 1)
+                
+                fol_num += 3
+            elif(html):
+                result = html.groups()
+                data = com.sub(result[0], data, 1)
+            elif(include_out):
+                if(include == True):
+                    data = com.sub("", data, 1)
+                else:
+                    result = include_out.groups()
+                    data = com.sub(result[0], data, 1)
+            else:
+                data = com.sub('<code>' + a[0] + '</code>', data, 1)
+        else:
+            break
+            
+    while(True):
+        com = re.compile("<code>(((?!<\/code>).)*)<\/code>", re.DOTALL)
+        y = com.search(data)
+        if(y):
+            a = y.groups()
+            
+            mid_data = re.sub("<\/span>", "}}}", a[0])
+            mid_data = re.sub("<\/div>", "}}}", mid_data)
+            mid_data = re.sub('<span class="font\-size\-(?P<in>[1-6])">', "{{{+\g<in> ", mid_data)
+            mid_data = re.sub('<span class="font\-size\-small\-(?P<in>[1-6])">', "{{{-\g<in> ", mid_data)
+            mid_data = re.sub('<span style="color:(?:#)?(?P<in>[^"]*)">', "{{{#\g<in> ", mid_data)
+            mid_data = re.sub('<span style="background:(?:#)?(?P<in>[^"]*)">', "{{{@\g<in> ", mid_data)
+            mid_data = re.sub('<div style="(?P<in>[^"]*)">', "{{{#!wiki style=&quot;\g<in>&quot;\n", mid_data)
+            mid_data = re.sub("(?P<in>.)", "<span>\g<in></span>", mid_data)
+            
+            data = com.sub(mid_data, data, 1)
+        else:
+            break
+            
+    data = re.sub("<span>&</span><span>l</span><span>t</span><span>;</span>", "<span>&lt;</span>", data)
+    data = re.sub("<span>&</span><span>g</span><span>t</span><span>;</span>", "<span>&gt;</span>", data)
+            
+    return (data, fol_num)
+
+def backlink_plust(name, link, type):
+    db_ex("select title from back where title = '" + db_pas(link) + "' and link = '" + db_pas(name) + "' and type = '" + type + "'")
+    y = db_get()
+    if(not y):
+        db_ex("insert into back (title, link, type) value ('" + db_pas(link) + "', '" + db_pas(name) + "',  'include')")
+        db_com()
+
+def cat_plus(name, link):
+    db_ex("select title from cat where title = '" + db_pas(link) + "' and cat = '" + db_pas(name) + "'")
+    y = db_get()
+    if(not y):
+        db_ex("insert into cat (title, cat) value ('" + db_pas(link) + "', '" + db_pas(name) + "')")
+        db_com()
+
+def namumark(title, data):
+    data = html_pas(data)
+
+    b = 0
+    a = mid_pas(data, b, False)
+    
+    data = a[0]
+    b = a[1]
+    
+    data = re.sub("\[anchor\((?P<in>[^\[\]]*)\)\]", '<span id="\g<in>"></span>', data)
+    data = savemark(data)
+    
+    while(True):
+        m = re.search("\[include\(((?:(?!\)\]|,).)*)((?:,\s?(?:[^)]*))+)?\)\]", data)
+        if(m):
+            results = m.groups()
+            if(results[0] == title):
+                data = re.sub("\[include\(((?:(?!\)\]|,).)*)((?:,\s?(?:[^)]*))+)?\)\]", "<b>" + results[0] + "</b>", data, 1)
+            else:
+                db_ex("select * from data where title = '" + db_pas(results[0]) + "'")
+                in_con = db_get()
+                
+                backlink_plus(title, results[0], 'include')
+                if(in_con):                        
+                    in_data = in_con[0]['data']
+                    in_data = re.sub("\[include\(((?:(?!\)\]|,).)*)((?:,\s?(?:[^)]*))+)?\)\]", "", in_data)
+                    
+                    in_data = html_pas(in_data)
+                    in_data = mid_pas(in_data, b, True)[0]
+                    
+                    if(results[1]):
+                        a = results[1]
+                        while(True):
+                            g = re.search("([^= ,]*)\=([^,]*)", a)
+                            if(g):
+                                result = g.groups()
+                                in_data = re.sub("@" + result[0] + "@", result[1], in_data)
+                                a = re.sub("([^= ,]*)\=([^,]*)", "", a, 1)
+                            else:
+                                break       
+
+                    data = re.sub("\[include\(((?:(?!\)\]|,).)*)((?:,\s?(?:[^)]*))+)?\)\]", '\n#nobr#<div>' + in_data + '</div>\n#nobr#', data, 1)
+                else:
+                    data = re.sub("\[include\(((?:(?!\)\]|,).)*)((?:,\s?(?:[^)]*))+)?\)\]", "<a class=\"not_thing\" href=\"" + url_pas(results[0]) + "\">" + results[0] + "</a>", data, 1)
+        else:
+            break
+    
+    while(True):
+        m = re.search('^#(?:[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|넘겨주기)\s([^\n]*)', data)
+        if(m):
+            results = m.groups()
+            aa = re.search("^(.*)(#(?:.*))$", results[0])
+            if(aa):
+                results = aa.groups()
+                data = re.sub('^#(?:redirect|넘겨주기)\s([^\n]*)', '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(results[0]) + '/from/' + url_pas(title) + results[1] + '" />', data, 1)
+            else:
+                data = re.sub('^#(?:redirect|넘겨주기)\s([^\n]*)', '<meta http-equiv="refresh" content="0;url=/w/' + url_pas(results[0]) + '/from/' + url_pas(title) + '" />', data, 1)
+            
+            backlink_plus(title, results[0], 'redirect')
+        else:
+            break
+
+    data = '\n' + data + '\n'
+    
+    while(True):
+        m = re.search("\n&gt;\s?((?:[^\n]*)(?:(?:(?:(?:\n&gt;\s?)(?:[^\n]*))+)?))", data)
+        if(m):
+            result = m.groups()
+            blockquote = result[0]
+            blockquote = re.sub("\n&gt;\s?", "\n", blockquote)
+            data = re.sub("\n&gt;\s?((?:[^\n]*)(?:(?:(?:(?:\n&gt;\s?)(?:[^\n]*))+)?))", "\n<blockquote>" + blockquote + "</blockquote>", data, 1)
+        else:
+            break
+    
+    m = re.search('\[목차\]', data)
+    if(not m):
+        data = re.sub("(?P<in>(={1,6})\s?([^=]*)\s?(?:={1,6})(?:\s+)?\n)", "[목차]\n\g<in>", data, 1)
+        
+    data = re.sub("(\n)(?P<in>\r\n(={1,6})\s?([^=]*)\s?(?:={1,6})(?:\s+)?\n)", "\g<in>", data)
+    
+    i = 0
+    h0c = 0
+    h1c = 0
+    h2c = 0
+    h3c = 0
+    h4c = 0
+    h5c = 0
+    last = 0
+    rtoc = '<div id="toc"><span id="toc-name">목차</span><br><br>'
+    while(True):
+        i = i + 1
+        m = re.search('(={1,6})\s?([^=]*)\s?(?:={1,6})(?:\s+)?\n', data)
+        if(m):
+            result = m.groups()
+            wiki = len(result[0])
+            if(last < wiki):
+                last = wiki
+            else:
+                last = wiki
+                if(wiki == 1):
+                    h1c = 0
+                    h2c = 0
+                    h3c = 0
+                    h4c = 0
+                    h5c = 0
+                elif(wiki == 2):
+                    h2c = 0
+                    h3c = 0
+                    h4c = 0
+                    h5c = 0
+                elif(wiki == 3):
+                    h3c = 0
+                    h4c = 0
+                    h5c = 0
+                elif(wiki == 4):
+                    h4c = 0
+                    h5c = 0
+                elif(wiki == 5):
+                    h5c = 0
+            if(wiki == 1):
+                h0c = h0c + 1
+            elif(wiki == 2):
+                h1c = h1c + 1
+            elif(wiki == 3):
+                h2c = h2c + 1
+            elif(wiki == 4):
+                h3c = h3c + 1
+            elif(wiki == 5):
+                h4c = h4c + 1
+            else:
+                h5c = h5c + 1
+
+            toc = str(h0c) + '.' + str(h1c) + '.' + str(h2c) + '.' + str(h3c) + '.' + str(h4c) + '.' + str(h5c) + '.'
+            toc = re.sub("(?P<in>[0-9]0(?:[0]*)?)\.", '\g<in>#.', toc)
+
+            toc = re.sub("0\.", '', toc)
+            toc = re.sub("#\.", '.', toc)
+            toc = re.sub("\.$", '', toc)
+
+            rtoc = rtoc + '<a href="#s-' + toc + '">' + toc + '</a>. ' + result[1] + '<br>'
+
+            c = re.sub(" $", "", result[1])
+            d = c
+            c = re.sub("\[\[(([^|]*)\|)?(?P<in>[^\]]*)\]\]", "\g<in>", c)
+
+            data = re.sub('(={1,6})\s?([^=]*)\s?(?:={1,6})(?:\s+)?\n', '<h' + str(wiki) + ' id="' + c + '"><a href="#toc" id="s-' + toc + '">' + toc + '.</a> ' + d + ' <span style="font-size:11px;">[<a href="/edit/' + url_pas(title) + '/section/' + str(i) + '">편집</a>]</span></h' + str(wiki) + '>', data, 1);
+        else:
+            rtoc = rtoc + '</div>'
+            break
+    
+    data = re.sub("\[목차\]", rtoc, data)
+    
+    category = ''
+    while(True):
+        m = re.search("\[\[(분류:(?:(?:(?!\]\]).)*))\]\]", data)
+        if(m):
+            g = m.groups()
+            
+            if(not title == g[0]):
+                cat_plus(title, g[0])
+                    
+                if(category == ''):
+                    db_ex("select * from data where title = '" + db_pas(g[0]) + "'")
+                    exists = db_get()
+                    if(exists):
+                        red = ""
+                    else:
+                        red = 'class="not_thing"'
+                        
+                    category = category + '<a ' + red + ' href="/w/' + url_pas(g[0]) + '">' + re.sub("분류:", "", g[0]) + '</a>'
+                else:
+                    db_ex("select * from data where title = '" + db_pas(g[0]) + "'")
+                    exists = db_get()
+                    if(exists):
+                        red = ""
+                    else:
+                        red = 'class="not_thing"'
+                        
+                    category = category + ' / ' + '<a ' + red + ' href="/w/' + url_pas(g[0]) + '">' + re.sub("분류:", "", g[0]) + '</a>'
+            
+            data = re.sub("\[\[(분류:(?:(?:(?!\]\]).)*))\]\]", '', data, 1)
+        else:
+            break
+
+    data = re.sub("'''(?P<in>.+?)'''(?!')", '<b>\g<in></b>', data)
+    data = re.sub("''(?P<in>.+?)''(?!')", '<i>\g<in></i>', data)
+    data = re.sub('~~(?P<in>.+?)~~(?!~)', '<s>\g<in></s>', data)
+    data = re.sub('--(?P<in>.+?)--(?!-)', '<s>\g<in></s>', data)
+    data = re.sub('__(?P<in>.+?)__(?!_)', '<u>\g<in></u>', data)
+    data = re.sub('\^\^(?P<in>.+?)\^\^(?!\^)', '<sup>\g<in></sup>', data)
+    data = re.sub(',,(?P<in>.+?),,(?!,)', '<sub>\g<in></sub>', data)
+    
+    data = re.sub('&lt;math&gt;(?P<in>((?!&lt;math&gt;).)*)&lt;\/math&gt;', '$\g<in>$', data)
+    
+    data = re.sub('{{\|(?P<in>(?:(?:(?:(?!\|}}).)*)(?:\n?))+)\|}}', '<table><tbody><tr><td>\g<in></td></tr></tbody></table>', data)
+    
+    data = re.sub('\[ruby\((?P<in>[^\|]*)\|(?P<out>[^\)]*)\)\]', '<ruby>\g<in><rp>(</rp><rt>\g<out></rt><rp>)</rp></ruby>', data)
+    
+    data = re.sub("##\s?(?P<in>[^\n]*)\n", "<div style='display:none;'>\g<in></div>", data);
+    
+    while(True):
+        m = re.search("\[\[파일:((?:(?!\]\]|\|).)*)(?:\|((?:(?!\]\]).)*))?\]\]", data)
+        if(m):
+            c = m.groups()
+
+            if(c):
+                if(c[1]):
+                    n = re.search("width=([^ \n&]*)", c[1])
+                    e = re.search("height=([^ \n&]*)", c[1])
+
+                    if(n):
+                        a = n.groups()
+                        width = a[0]
+                    else:
+                        width = ''
+                    if(e):
+                        b = e.groups()
+                        height = b[0]
+                    else:
+                        height = ''
+
+                    img = re.sub("\.(?P<in>[Jj][Pp][Gg]|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Ee][Gg])", "#\g<in>#", c[0])
+                    data = re.sub("\[\[파일:((?:(?!\]\]|\?).)*)(?:\?((?:(?!\]\]).)*))?\]\]", '<a href="/w/파일:' + img + '"><img src="/image/' + img + '" width="' + width + '" height="' + height + '"></a>', data, 1)
+                else:
+                    img = re.sub("\.(?P<in>[Jj][Pp][Gg]|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Ee][Gg])", "#\g<in>#", c[0])
+                    data = re.sub("\[\[파일:((?:(?!\]\]|\?).)*)(?:\?((?:(?!\]\]).)*))?\]\]", "<a href='/w/파일:" + img + "'><img src='/image/" + img + "'></a>", data, 1)
+            else:
+                img = re.sub("\.(?P<in>[Jj][Pp][Gg]|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Ee][Gg])", "#\g<in>#", c[0])
+                data = re.sub("\[\[파일:((?:(?!\]\]|\?).)*)(?:\?((?:(?!\]\]).)*))?\]\]", "<a href='/w/파일:" + img + "'><img src='/image/" + img + "'></a>", data, 1)
+
+            if(not re.search("^파일:([^\n]*)", title)):
+                backlink_plus(title, '파일' + c[0], 'file')            
+        else:
+            break
+    
+    data = re.sub("\[br\]",'<br>', data)
+    
+    while(True):
+        com = re.compile("\[youtube\(((?:(?!,|\)\]).)*)(?:,(?:\s)?)?(?:width=((?:(?!,|\)\]).)*))?(?:,(?:\s)?)?(?:height=((?:(?!,|\)\]).)*))?\)\]")
+        m = com.search(data)
+        if(m):
+            result = m.groups()
+            if(result[1]):
+                if(result[2]):
+                    width = result[1]
+                    height = result[2]
+                else:
+                    width = result[1]
+                    height = '315'
+            elif(result[2]):
+                height = result[2]
+                width = '560'
+            else:
+                width = '560'
+                height = '315'
+
+            data = com.sub('<iframe width="' + width + '" height="' + height + '" src="https://www.youtube.com/embed/' + result[0] + '" frameborder="0" allowfullscreen></iframe>', data, 1)
+        else:
+            break
+     
+    data = re.sub("\[\[(?::(?P<in>(?:분류|파일):(?:(?:(?!\]\]).)*)))\]\]", "[[\g<in>]]", data)
+            
+    while(True):
+        m = re.search("\[\[(((?!\]\]).)*)\]\]", data)
+        if(m):
+            result = m.groups()
+            a = re.search("((?:(?!\|).)*)\|(.*)", result[0])
+            if(a):
+                results = a.groups()
+                aa = re.search("^(.*)(#(?:.*))$", results[0])
+                if(aa):
+                    g = results[1]
+                    results = aa.groups()
+                    b = re.search("^http(?:s)?:\/\/", results[0])
+                    if(b):
+                        data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a class="out_link" href="' + results[0] + results[1] + '">' + g + '</a>', data, 1)
+                    else:
+                        if(results[0] == title):
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<b>' + g + '</b>', data, 1)
+                        else:
+                            db_ex("select title from data where title = '" + db_pas(results[0]) + "'")
+                            y = db_get()
+                            if(y):
+                                clas = ''
+                            else:
+                                clas = 'not_thing'
+                                
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a title="' + results[0] + results[1] + '" class="' + clas + '" href="/w/' + url_pas(results[0]) + results[1] + '">' + g + '</a>', data, 1)
+                            
+                            backlink_plus(title, results[0], '')
+                else:
+                    b = re.search("^http(?:s)?:\/\/", results[0])
+                    if(b):
+                        c = re.search("(?:\.[Jj][Pp][Gg]|\.[Pp][Nn][Gg]|\.[Gg][Ii][Ff]|\.[Jj][Pp][Ee][Gg])", results[0])
+                        if(c):
+                            img = results[0]
+                            img = re.sub("\.(?P<in>[Jj][Pp][Gg]|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Ee][Gg])", "#\g<in>#", img)
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a class="out_link" href="' + img + '">' + results[1] + '</a>', data, 1)
+                        else:
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a class="out_link" href="' + results[0] + '">' + results[1] + '</a>', data, 1)
+                    else:
+                        if(results[0] == title):
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<b>' + results[1] + '</b>', data, 1)
+                        else:
+                            db_ex("select title from data where title = '" + db_pas(results[0]) + "'")
+                            y = db_get()
+                            if(y):
+                                clas = ''
+                            else:
+                                clas = 'not_thing'
+
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a title="' + results[0] + '" class="' + clas + '" href="/w/' + url_pas(results[0]) + '">' + results[1] + '</a>', data, 1)
+
+                            backlink_plus(title, results[0], '')
+            else:
+                aa = re.search("^(.*)(#(?:.*))$", result[0])
+                if(aa):
+                    result = aa.groups()
+                    b = re.search("^http(?:s)?:\/\/", result[0])
+                    if(b):
+                        data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a class="out_link" href="' + result[0] + result[1] + '">' + result[0] + result[1] + '</a>', data, 1)
+                    else:
+                        if(result[0] == title):
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<b>' + result[0] + result[1] + '</b>', data, 1)
+                        else:
+                            db_ex("select title from data where title = '" + db_pas(result[0]) + "'")
+                            y = db_get()
+                            if(y):
+                                clas = ''
+                            else:
+                                clas = 'not_thing'
+
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a href="/w/' + url_pas(result[0]) + result[1] + '" class="' + clas + '">' + result[0] + result[1] + '</a>', data, 1)
+                            
+                            backlink_plus(title, result[0], '')
+                else:
+                    b = re.search("^http(?:s)?:\/\/", result[0])
+                    if(b):
+                        c = re.search("(?:\.[Jj][Pp][Gg]|\.[Pp][Nn][Gg]|\.[Gg][Ii][Ff]|\.[Jj][Pp][Ee][Gg])", result[0])
+                        if(c):
+                            img = result[0]
+                            img = re.sub("\.(?P<in>[Jj][Pp][Gg]|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Ee][Gg])", "#\g<in>#", img)
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a class="out_link" href="' + img + '">' + img + '</a>', data, 1)
+                        else:
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a class="out_link" href="' + result[0] + '">' + result[0] + '</a>', data, 1)
+                    else:
+                        if(result[0] == title):
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<b>' + result[0] + '</b>', data, 1)
+                        else:
+                            db_ex("select title from data where title = '" + db_pas(result[0]) + "'")
+                            y = db_get()
+                            if(y):
+                                clas = ''
+                            else:
+                                clas = 'not_thing'
+
+                            data = re.sub('\[\[(((?!\]\]).)*)\]\]', '<a href="/w/' + url_pas(result[0]) + '" class="' + clas + '">' + result[0] + '</a>', data, 1)
+                            
+                            backlink_plus(title, result[0], '')
+        else:
+            break
+            
+    while(True):
+        com = re.compile("(http(?:s)?:\/\/(?:(?:(?:(?!\.[Jj][Pp][Gg]|\.[Pp][Nn][Gg]|\.[Gg][Ii][Ff]|\.[Jj][Pp][Ee][Gg]|#[Jj][Pp][Gg]#|#[Pp][Nn][Gg]#|#[Gg][Ii][Ff]#|#[Jj][Pp][Ee][Gg]#|<\/(?:[^>]*)>).)*)(?:\.[Jj][Pp][Gg]|\.[Pp][Nn][Gg]|\.[Gg][Ii][Ff]|\.[Jj][Pp][Ee][Gg])))(?:(?:(?:\?)width=((?:[0-9]*)(?:px|%)?))?(?:(?:\?|&)height=((?:[0-9]*)(?:px|%)?))?)")
+        m = com.search(data)
+        if(m):
+            result = m.groups()
+            if(result[1]):
+                if(result[2]):
+                    width = result[1]
+                    height = result[2]
+                else:
+                    width = result[1]
+                    height = ''
+            elif(result[2]):
+                height = result[2]
+                width = ''
+            else:
+                width = ''
+                height = ''
+
+            c = result[0]
+            c = re.sub("\.(?P<in>[Jj][Pp][Gg]|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Ee][Gg])", "#\g<in>#", c)
+
+            data = com.sub("<img width='" + width + "' height='" + height + "' src='" + c + "'>", data, 1)
+        else:
+            break
+            
+    while(True):
+        m = re.search("((?:(?:( +)\*\s(?:[^\n]*))\n?)+)", data)
+        if(m):
+            result = m.groups()
+            end = str(result[0])
+
+            while(True):
+                isspace = re.search("( +)\*\s([^\n]*)", end)
+                if(isspace):
+                    spacebar = isspace.groups()
+                    up = len(spacebar[0]) * 20
+                    end = re.sub("( +)\*\s([^\n]*)", "<li style='margin-left:" + str(up) + "px'>" + spacebar[1] + "</li>", end, 1)
+                else:
+                    break
+
+            end = re.sub("\n", '', end)
+            data = re.sub("(?:(?:(?:( +)\*\s([^\n]*))\n?)+)", '<ul id="list">' + end + '</ul>', data, 1)
+        else:
+            break
+    
+    data = re.sub('\[date\]', get_time(), data)
+    data = re.sub("#(?P<in>[Jj][Pp][Gg]|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Ee][Gg])#", ".\g<in>", data)
+    data = re.sub("-{4,11}", "<hr>", data)
+    
+    while(True):
+        b = re.search("\n( +)", data)
+        if(b):
+            result = b.groups()
+            up = re.sub(' ', '<span id="in"></span>', result[0])
+            data = re.sub("\n( +)", '<br>' + up, data, 1)
+        else:
+            break
+    
+    a = 1
+    tou = "<hr id='footnote'><div class='wiki-macro-footnote'><br>"
+    while(True):
+        b = re.search("\[\*([^\s]*)\s(((?!\]).)*)\]", data)
+        if(b):
+            results = b.groups()
+            if(results[0]):
+                c = results[1]
+                c = re.sub("<(?:[^>]*)>", '', c)
+
+                tou = tou + "<span class='footnote-list'><a href=\"#rfn-" + str(a) + "\" id=\"fn-" + str(a) + "\">[" + results[0] + "]</a> " + results[1] + "</span><br>"
+                data = re.sub("\[\*([^\s]*)\s(((?!\]).)*)\]", "<sup><a class=\"footnotes\" title=\"" + c + "\" id=\"rfn-" + str(a) + "\" href=\"#fn-" + str(a) + "\">[" + results[0] + "]</a></sup>", data, 1)
+            else:
+                c = results[1]
+                c = re.sub("<(?:[^>]*)>", '', c)
+
+                tou = tou + "<span class='footnote-list'><a href=\"#rfn-" + str(a) + "\" id=\"fn-" + str(a) + "\">[" + str(a) + "]</a> " + results[1] + "</span><br>"
+                data = re.sub("\[\*([^\s]*)\s(((?!\]).)*)\]", '<sup><a class="footnotes" title="' + c + '" id="rfn-' + str(a) + '" href="#fn-' + str(a) + '">[' + str(a) + ']</a></sup>', data, 1)
+
+            a = a + 1
+        else:
+            tou = tou + '</div>'
+
+            if(tou == "<hr id='footnote'><div class='wiki-macro-footnote'><br></div>"):
+                tou = ""
+
+            break
+    
+    data = re.sub("\[각주\](?:(?:<br>| |\r|\n)+)?$", "", data)
+    data = re.sub("(?:(?:<br>| |\r|\n)+)$", "", data)
+    data = re.sub("\[각주\]", "<br>" + tou, data)
+    data = data + tou
+    
+    if(category):
+        data = data + '<div style="width:100%;border: 1px solid #777;padding: 5px;margin-top: 1em;">분류: ' + category + '</div>'
+        
+    data = re.sub("(?:\|\|\r\n)", "#table#<nobr>", data)
+        
+    while(True):
+        y = re.search("(\|\|(?:(?:(?:(?:(?!\|\|).)*)(?:\n?))+))", data)
+        if(y):
+            a = y.groups()
+            
+            mid_data = re.sub("\|\|", "#table#", a[0])
+            mid_data = re.sub("\r\n", "<br>", mid_data)
+            
+            data = re.sub("(\|\|((?:(?:(?:(?!\|\|).)*)(?:\n?))+))", mid_data, data, 1)
+        else:
+            break
+            
+    data = re.sub("#table#", "||", data)
+    data = re.sub("<nobr>", "\r\n", data)
+    
+    while(True):
+        m = re.search("(\|\|(?:(?:(?:.*)\n?)\|\|)+)", data)
+        if(m):
+            results = m.groups()
+            table = results[0]
+            while(True):
+                a = re.search("^(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", table)
+                if(a):
+                    row = ''
+                    cel = ''
+                    celstyle = ''
+                    rowstyle = ''
+                    alltable = ''
+                    result = a.groups()
+                    if(result[1]):
+                        alltable = 'style="'
+                        celstyle = 'style="'
+                        rowstyle = 'style="'
+
+                        q = re.search("&lt;table\s?width=((?:(?!&gt;).)*)&gt;", result[1])
+                        w = re.search("&lt;table\s?height=((?:(?!&gt;).)*)&gt;", result[1])
+                        e = re.search("&lt;table\s?align=((?:(?!&gt;).)*)&gt;", result[1])
+                        if(q):
+                            resultss = q.groups()
+                            alltable = alltable + 'width:' + resultss[0] + ';'
+                        if(w):
+                            resultss = w.groups()
+                            alltable = alltable + 'height:' + resultss[0] + ';'
+                        if(e):
+                            resultss = e.groups()
+                            if(resultss[0] == 'right'):
+                                alltable = alltable + 'margin-left:auto;'
+                            elif(resultss[0] == 'center'):
+                                alltable = alltable + 'margin:auto;'
+                            else:
+                                alltable = alltable + 'margin-right:auto;'
+                                
+                        ee = re.search("&lt;table\s?textalign=((?:(?!&gt;).)*)&gt;", result[1])
+                        if(ee):
+                            resultss = ee.groups()
+                            if(resultss[0] == 'right'):
+                                alltable = alltable + 'text-align:right;'
+                            elif(resultss[0] == 'center'):
+                                alltable = alltable + 'text-align:center;'
+                            else:
+                                alltable = alltable + 'text-align:left;'
+                        
+                        r = re.search("&lt;-((?:(?!&gt;).)*)&gt;", result[1])
+                        if(r):
+                            resultss = r.groups()
+                            cel = 'colspan="' + resultss[0] + '"'
+                        else:
+                            cel = 'colspan="' + str(round(len(result[0]) / 2)) + '"'   
+
+                        t = re.search("&lt;\|((?:(?!&gt;).)*)&gt;", result[1])
+                        if(t):
+                            resultss = t.groups()
+                            row = 'rowspan="' + resultss[0] + '"'
+
+                        ba = re.search("&lt;rowbgcolor=(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        bb = re.search("&lt;rowbgcolor=(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        bc = re.search("&lt;rowbgcolor=(\w+)&gt;", result[1])
+                        if(ba):
+                            resultss = ba.groups()
+                            rowstyle = rowstyle + 'background:' + resultss[0] + ';'
+                        elif(bb):
+                            resultss = bb.groups()
+                            rowstyle = rowstyle + 'background:' + resultss[0] + ';'
+                        elif(bc):
+                            resultss = bc.groups()
+                            rowstyle = rowstyle + 'background:' + resultss[0] + ';'
+                            
+                        z = re.search("&lt;table\s?bordercolor=(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        x = re.search("&lt;table\s?bordercolor=(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        c = re.search("&lt;table\s?bordercolor=(\w+)&gt;", result[1])
+                        if(z):
+                            resultss = z.groups()
+                            alltable = alltable + 'border:' + resultss[0] + ' 2px solid;'
+                        elif(x):
+                            resultss = x.groups()
+                            alltable = alltable + 'border:' + resultss[0] + ' 2px solid;'
+                        elif(c):
+                            resultss = c.groups()
+                            alltable = alltable + 'border:' + resultss[0] + ' 2px solid;'
+                            
+                        aq = re.search("&lt;table\s?bgcolor=(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        aw = re.search("&lt;table\s?bgcolor=(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        ae = re.search("&lt;table\s?bgcolor=(\w+)&gt;", result[1])
+                        if(aq):
+                            resultss = aq.groups()
+                            alltable = alltable + 'background:' + resultss[0] + ';'
+                        elif(aw):
+                            resultss = aw.groups()
+                            alltable = alltable + 'background:' + resultss[0] + ';'
+                        elif(ae):
+                            resultss = ae.groups()
+                            alltable = alltable + 'background:' + resultss[0] + ';'
+                            
+                        j = re.search("&lt;bgcolor=(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        k = re.search("&lt;bgcolor=(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        l = re.search("&lt;bgcolor=(\w+)&gt;", result[1])
+                        if(j):
+                            resultss = j.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(k):
+                            resultss = k.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(l):
+                            resultss = l.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                            
+                        aa = re.search("&lt;(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        ab = re.search("&lt;(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        ac = re.search("&lt;(\w+)&gt;", result[1])
+                        if(aa):
+                            resultss = aa.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(ab):
+                            resultss = ab.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(ac):
+                            resultss = ac.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                            
+                        qa = re.search("&lt;width=((?:(?!&gt;).)*)&gt;", result[1])
+                        qb = re.search("&lt;height=((?:(?!&gt;).)*)&gt;", result[1])
+                        if(qa):
+                            resultss = qa.groups()
+                            celstyle = celstyle + 'width:' + resultss[0] + ';'
+                        if(qb):
+                            resultss = qb.groups()
+                            celstyle = celstyle + 'height:' + resultss[0] + ';'
+                            
+                        i = re.search("&lt;\)&gt;", result[1])
+                        o = re.search("&lt;:&gt;", result[1])
+                        p = re.search("&lt;\(&gt;", result[1])
+                        if(i):
+                            celstyle = celstyle + 'text-align:right;'
+                        elif(o):
+                            celstyle = celstyle + 'text-align:center;'
+                        elif(p):
+                            celstyle = celstyle + 'text-align:left;'
+                            
+                        alltable = alltable + '"'
+                        celstyle = celstyle + '"'
+                        rowstyle = rowstyle + '"'
+                            
+                        table = re.sub("^(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", "<table " + alltable + "><tbody><tr " + rowstyle + "><td " + cel + " " + row + " " + celstyle + ">", table, 1)
+                    else:
+                        cel = 'colspan="' + str(round(len(result[0]) / 2)) + '"'
+                        table = re.sub("^(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", "<table><tbody><tr><td " + cel + ">", table, 1)
+                else:
+                    break
+                    
+            table = re.sub("\|\|$", "</td></tr></tbody></table>", table)
+            
+            while(True):
+                b = re.search("\|\|\r\n(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", table)
+                if(b):
+                    row = ''
+                    cel = ''
+                    celstyle = ''
+                    rowstyle = ''
+
+                    result = b.groups()
+                    if(result[1]):
+                        celstyle = 'style="'
+                        rowstyle = 'style="'
+                        
+                        r = re.search("&lt;-((?:(?!&gt;).)*)&gt;", result[1])
+                        if(r):
+                            resultss = r.groups()
+                            cel = 'colspan="' + resultss[0] + '"'
+                        else:
+                            cel = 'colspan="' + str(round(len(result[0]) / 2)) + '"'
+
+                        t = re.search("&lt;\|((?:(?!&gt;).)*)&gt;", result[1])
+                        if(t):
+                            resultss = t.groups()
+                            row = 'rowspan="' + resultss[0] + '"'
+                            
+                        ba = re.search("&lt;rowbgcolor=(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        bb = re.search("&lt;rowbgcolor=(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        bc = re.search("&lt;rowbgcolor=(\w+)&gt;", result[1])
+                        if(ba):
+                            resultss = ba.groups()
+                            rowstyle = rowstyle + 'background:' + resultss[0] + ';'
+                        elif(bb):
+                            resultss = bb.groups()
+                            rowstyle = rowstyle + 'background:' + resultss[0] + ';'
+                        elif(bc):
+                            resultss = bc.groups()
+                            rowstyle = rowstyle + 'background:' + resultss[0] + ';'
+                            
+                        j = re.search("&lt;bgcolor=(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        k = re.search("&lt;bgcolor=(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        l = re.search("&lt;bgcolor=(\w+)&gt;", result[1])
+                        if(j):
+                            resultss = j.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(k):
+                            resultss = k.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(l):
+                            resultss = l.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+
+                        aa = re.search("&lt;(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        ab = re.search("&lt;(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        ac = re.search("&lt;(\w+)&gt;", result[1])
+                        if(aa):
+                            resultss = aa.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(ab):
+                            resultss = ab.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(ac):
+                            resultss = ac.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'    
+
+                        qa = re.search("&lt;width=((?:(?!&gt;).)*)&gt;", result[1])
+                        qb = re.search("&lt;height=((?:(?!&gt;).)*)&gt;", result[1])
+                        if(qa):
+                            resultss = qa.groups()
+                            celstyle = celstyle + 'width:' + resultss[0] + ';'
+                        if(qb):
+                            resultss = qb.groups()
+                            celstyle = celstyle + 'height:' + resultss[0] + ';'
+                            
+                        i = re.search("&lt;\)&gt;", result[1])
+                        o = re.search("&lt;:&gt;", result[1])
+                        p = re.search("&lt;\(&gt;", result[1])
+                        if(i):
+                            celstyle = celstyle + 'text-align:right;'
+                        elif(o):
+                            celstyle = celstyle + 'text-align:center;'
+                        elif(p):
+                            celstyle = celstyle + 'text-align:left;'
+
+                        celstyle = celstyle + '"'
+                        rowstyle = rowstyle + '"'
+                        
+                        table = re.sub("\|\|\r\n(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", "</td></tr><tr " + rowstyle + "><td " + cel + " " + row + " " + celstyle + ">", table, 1)
+                    else:
+                        cel = 'colspan="' + str(round(len(result[0]) / 2)) + '"'
+                        table = re.sub("\|\|\r\n(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", "</td></tr><tr><td " + cel + ">", table, 1)
+                else:
+                    break
+
+            while(True):
+                c = re.search("(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", table)
+                if(c):
+                    row = ''
+                    cel = ''
+                    celstyle = ''
+
+                    result = c.groups()
+                    if(result[1]):
+                        celstyle = 'style="'
+                        
+                        r = re.search("&lt;-((?:(?!&gt;).)*)&gt;", result[1])
+                        if(r):
+                            resultss = r.groups()
+                            cel = 'colspan="' + resultss[0] + '"';
+                        else:
+                            cel = 'colspan="' + str(round(len(result[0]) / 2)) + '"'
+                        t = re.search("&lt;\|((?:(?!&gt;).)*)&gt;", result[1])
+                        if(t):
+                            resultss = t.groups()
+                            row = 'rowspan="' + resultss[0] + '"';
+                            
+                        j = re.search("&lt;bgcolor=(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        k = re.search("&lt;bgcolor=(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        l = re.search("&lt;bgcolor=(\w+)&gt;", result[1])
+                        if(j):
+                            resultss = j.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(k):
+                            resultss = k.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(l):
+                            resultss = l.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                            
+                        aa = re.search("&lt;(#[0-9a-f-A-F]{6})&gt;", result[1])
+                        ab = re.search("&lt;(#[0-9a-f-A-F]{3})&gt;", result[1])
+                        ac = re.search("&lt;(\w+)&gt;", result[1])
+                        if(aa):
+                            resultss = aa.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(ab):
+                            resultss = ab.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                        elif(ac):
+                            resultss = ac.groups()
+                            celstyle = celstyle + 'background:' + resultss[0] + ';'
+                            
+                        qa = re.search("&lt;width=((?:(?!&gt;).)*)&gt;", result[1])
+                        qb = re.search("&lt;height=((?:(?!&gt;).)*)&gt;", result[1])
+                        if(qa):
+                            resultss = qa.groups()
+                            celstyle = celstyle + 'width:' + resultss[0] + ';'
+                        if(qb):
+                            resultss = qb.groups()
+                            celstyle = celstyle + 'height:' + resultss[0] + ';'
+                            
+                        i = re.search("&lt;\)&gt;", result[1])
+                        o = re.search("&lt;:&gt;", result[1])
+                        p = re.search("&lt;\(&gt;", result[1])
+                        if(i):
+                            celstyle = celstyle + 'text-align:right;'
+                        elif(o):
+                            celstyle = celstyle + 'text-align:center;'
+                        elif(p):
+                            celstyle = celstyle + 'text-align:left;'
+
+                        celstyle = celstyle + '"'
+                            
+                        table = re.sub("(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", "</td><td " + cel + " " + row + " " + celstyle + ">", table, 1)
+                    else:
+                        cel = 'colspan="' + str(round(len(result[0]) / 2)) + '"'
+                        table = re.sub("(\|\|(?:(?:\|\|)+)?)((?:&lt;(?:(?:(?!&gt;).)*)&gt;)+)?", "</td><td " + cel + ">", table, 1)
+                else:
+                    break
+            
+            data = re.sub("(\|\|(?:(?:(?:.*)\n?)\|\|)+)", table, data, 1)
+        else:
+            break
+    
+    data = re.sub("(\n#nobr#|#nobr#\n|#nobr#)", "", data)
+    data = re.sub('<\/blockquote>((\r)?\n){2}<blockquote>', '</blockquote><br><blockquote>', data)
+    data = re.sub('\n', '<br>', data)
+    data = re.sub('^<br>', '', data)
+    
+    return data

+ 0 - 0
parser.py