func.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. from flask import session, render_template
  2. import json
  3. import sqlite3
  4. import hashlib
  5. from urllib import parse
  6. import requests
  7. import re
  8. import html
  9. from css_html_js_minify import html_minify, js_minify, css_minify
  10. import time
  11. import os
  12. from set_mark.tool import get_time
  13. from set_mark.tool import ip_check
  14. from set_mark.tool import url_pas
  15. from set_mark.tool import sha224
  16. from mark import *
  17. def captcha_get(conn):
  18. curs = conn.cursor()
  19. data = ''
  20. if custom(conn)[2] == 0:
  21. curs.execute('select data from other where name = "recaptcha"')
  22. recaptcha = curs.fetchall()
  23. if recaptcha and recaptcha[0][0] != '':
  24. curs.execute('select data from other where name = "sec_re"')
  25. sec_re = curs.fetchall()
  26. if sec_re and sec_re[0][0] != '':
  27. data += recaptcha[0][0] + '<hr>'
  28. return data
  29. def captcha_post(test, conn, num = 1):
  30. curs = conn.cursor()
  31. if num == 1:
  32. if custom(conn)[2] == 0 and captcha_get(conn) != '':
  33. curs.execute('select data from other where name = "sec_re"')
  34. sec_re = curs.fetchall()
  35. if sec_re and sec_re[0][0] != '':
  36. data = requests.get('https://www.google.com/recaptcha/api/siteverify', params = { 'secret' : sec_re, 'response' : test })
  37. if not data:
  38. return 0
  39. else:
  40. json_data = data.json()
  41. if data.status_code == 200 and json_data['success'] == True:
  42. return 0
  43. else:
  44. return 1
  45. else:
  46. return 0
  47. else:
  48. return 0
  49. else:
  50. pass
  51. def ip_warring(conn):
  52. curs = conn.cursor()
  53. if custom(conn)[2] == 0:
  54. curs.execute('select data from other where name = "no_login_warring"')
  55. data = curs.fetchall()
  56. if data and data[0][0] != '':
  57. text_data = '<span>' + data[0][0] + '</span><hr>'
  58. else:
  59. text_data = '<span>비 로그인 상태입니다. 비 로그인으로 진행 시 아이피가 기록됩니다.</span><hr>'
  60. else:
  61. text_data = ''
  62. return text_data
  63. def skin_check(conn):
  64. curs = conn.cursor()
  65. skin = './views/acme/'
  66. try:
  67. curs.execute('select data from other where name = "skin"')
  68. skin_exist = curs.fetchall()
  69. if skin_exist:
  70. if os.path.exists(os.path.abspath('./views/' + skin_exist[0][0] + '/index.tpl')) == 1:
  71. skin = './views/' + skin_exist[0][0] + '/'
  72. except:
  73. pass
  74. return skin
  75. def next_fix(link, num, page, end = 50):
  76. list_data = ''
  77. if num == 1:
  78. if len(page) == end:
  79. list_data += '<hr><a href="' + link + str(num + 1) + '">(이후)</a>'
  80. elif len(page) != end:
  81. list_data += '<hr><a href="' + link + str(num - 1) + '">(이전)</a>'
  82. else:
  83. list_data += '<hr><a href="' + link + str(num - 1) + '">(이전)</a> <a href="' + link + str(num + 1) + '">(이후)</a>'
  84. return list_data
  85. def other2(origin):
  86. return origin + ['제거 되었음. 스킨 업데이트 필요함.']
  87. def wiki_set(conn, num):
  88. curs = conn.cursor()
  89. if num == 1:
  90. data_list = []
  91. curs.execute('select data from other where name = ?', ['name'])
  92. db_data = curs.fetchall()
  93. if db_data and db_data[0][0] != '':
  94. data_list += [db_data[0][0]]
  95. else:
  96. data_list += ['무명위키']
  97. curs.execute('select data from other where name = "license"')
  98. db_data = curs.fetchall()
  99. if db_data and db_data[0][0] != '':
  100. data_list += [db_data[0][0]]
  101. else:
  102. data_list += ['CC 0']
  103. data_list += ['', '']
  104. curs.execute('select data from other where name = "logo"')
  105. db_data = curs.fetchall()
  106. if db_data and db_data[0][0] != '':
  107. data_list += [db_data[0][0]]
  108. else:
  109. data_list += [data_list[0]]
  110. curs.execute("select data from other where name = 'head'")
  111. db_data = curs.fetchall()
  112. if db_data and db_data[0][0] != '':
  113. data_list += [db_data[0][0]]
  114. else:
  115. data_list += ['']
  116. return data_list
  117. if num == 2:
  118. var_data = '위키:대문'
  119. curs.execute('select data from other where name = "frontpage"')
  120. elif num == 3:
  121. var_data = '2'
  122. curs.execute('select data from other where name = "upload"')
  123. db_data = curs.fetchall()
  124. if db_data and db_data[0][0] != '':
  125. return db_data[0][0]
  126. else:
  127. return var_data
  128. def diff(seqm):
  129. output = []
  130. for opcode, a0, a1, b0, b1 in seqm.get_opcodes():
  131. if opcode == 'equal':
  132. output += [seqm.a[a0:a1]]
  133. elif opcode == 'insert':
  134. output += ["<span style='background:#CFC;'>" + seqm.b[b0:b1] + "</span>"]
  135. elif opcode == 'delete':
  136. output += ["<span style='background:#FDD;'>" + seqm.a[a0:a1] + "</span>"]
  137. elif opcode == 'replace':
  138. output += ["<span style='background:#FDD;'>" + seqm.a[a0:a1] + "</span>"]
  139. output += ["<span style='background:#CFC;'>" + seqm.b[b0:b1] + "</span>"]
  140. return ''.join(output)
  141. def admin_check(conn, num, what):
  142. ip = ip_check()
  143. curs = conn.cursor()
  144. curs.execute("select acl from user where id = ?", [ip])
  145. user = curs.fetchall()
  146. if user:
  147. reset = 0
  148. while 1:
  149. if num == 1 and reset == 0:
  150. check = 'ban'
  151. elif num == 2 and reset == 0:
  152. check = 'mdel'
  153. elif num == 3 and reset == 0:
  154. check = 'toron'
  155. elif num == 4 and reset == 0:
  156. check = 'check'
  157. elif num == 5 and reset == 0:
  158. check = 'acl'
  159. elif num == 6 and reset == 0:
  160. check = 'hidel'
  161. elif num == 7 and reset == 0:
  162. check = 'give'
  163. else:
  164. check = 'owner'
  165. curs.execute('select name from alist where name = ? and acl = ?', [user[0][0], check])
  166. acl_data = curs.fetchall()
  167. if acl_data:
  168. if what:
  169. curs.execute("insert into re_admin (who, what, time) values (?, ?, ?)", [ip, what, get_time()])
  170. conn.commit()
  171. return 1
  172. else:
  173. if reset == 0:
  174. reset = 1
  175. else:
  176. break
  177. def ip_pas(conn, raw_ip):
  178. hide = 0
  179. curs = conn.cursor()
  180. if re.search("(\.|:)", raw_ip):
  181. if not re.search("^도구:", raw_ip):
  182. curs.execute("select data from other where name = 'ip_view'")
  183. d = curs.fetchall()
  184. if d and d[0][0] != '':
  185. ip = '<span style="font-size: 75%;">' + hashlib.md5(bytes(raw_ip, 'utf-8')).hexdigest() + '</span>'
  186. if not admin_check(conn, 'ban', None):
  187. hide = 1
  188. else:
  189. ip = raw_ip
  190. else:
  191. ip = raw_ip
  192. hide = 1
  193. else:
  194. curs.execute("select title from data where title = ?", ['사용자:' + raw_ip])
  195. if curs.fetchall():
  196. ip = '<a href="/w/' + url_pas('사용자:' + raw_ip) + '">' + raw_ip + '</a>'
  197. else:
  198. ip = '<a class="not_thing" href="/w/' + url_pas('사용자:' + raw_ip) + '">' + raw_ip + '</a>'
  199. if hide == 0:
  200. ip += ' <a href="/record/' + url_pas(raw_ip) + '">(기록)</a>'
  201. return ip
  202. def custom(conn):
  203. curs = conn.cursor()
  204. if 'MyMaiToNight' in session:
  205. user_head = session['MyMaiToNight']
  206. else:
  207. user_head = ''
  208. if 'Now' in session and session['Now'] == 1:
  209. curs.execute('select name from alarm where name = ? limit 1', [ip_check()])
  210. if curs.fetchall():
  211. user_icon = 2
  212. else:
  213. user_icon = 1
  214. else:
  215. user_icon = 0
  216. if user_icon == 1:
  217. curs.execute('select email from user where id = ?', [ip_check()])
  218. data = curs.fetchall()
  219. if data:
  220. email = data[0][0]
  221. else:
  222. email = ''
  223. else:
  224. email = ''
  225. return ['', '', user_icon, user_head, email]
  226. def acl_check(conn, name):
  227. ip = ip_check()
  228. curs = conn.cursor()
  229. if ban_check(conn) == 1:
  230. return 1
  231. acl_c = re.search("^사용자:([^/]*)", name)
  232. if acl_c:
  233. acl_n = acl_c.groups()
  234. if admin_check(conn, 5, None) == 1:
  235. return 0
  236. curs.execute("select dec from acl where title = ?", ['사용자:' + acl_n[0]])
  237. acl_d = curs.fetchall()
  238. if acl_d:
  239. if acl_d[0][0] == 'all':
  240. return 0
  241. if acl_d[0][0] == 'user' and not re.search("(\.|:)", ip):
  242. return 0
  243. if ip != acl_n[0] or re.search("(\.|:)", ip):
  244. return 1
  245. if ip == acl_n[0] and not re.search("(\.|:)", ip) and not re.search("(\.|:)", acl_n[0]):
  246. return 0
  247. else:
  248. return 1
  249. file_c = re.search("^파일:(.*)", name)
  250. if file_c and admin_check(conn, 5, 'edit (' + name + ')') != 1:
  251. return 1
  252. curs.execute("select acl from user where id = ?", [ip])
  253. user_d = curs.fetchall()
  254. curs.execute("select dec from acl where title = ?", [name])
  255. acl_d = curs.fetchall()
  256. if acl_d:
  257. if acl_d[0][0] == 'user':
  258. if not user_d:
  259. return 1
  260. if acl_d[0][0] == 'admin':
  261. if not user_d:
  262. return 1
  263. if not admin_check(conn, 5, 'edit (' + name + ')') == 1:
  264. return 1
  265. curs.execute('select data from other where name = "edit"')
  266. set_d = curs.fetchall()
  267. if set_d:
  268. if set_d[0][0] == 'user':
  269. if not user_d:
  270. return 1
  271. if set_d[0][0] == 'admin':
  272. if not user_d:
  273. return 1
  274. if not admin_check(conn, 5, None) == 1:
  275. return 1
  276. return 0
  277. def ban_check(conn):
  278. ip = ip_check()
  279. curs = conn.cursor()
  280. band = re.search("^([0-9]{1,3}\.[0-9]{1,3})", ip)
  281. if band:
  282. band_it = band.groups()
  283. else:
  284. band_it = ['Not']
  285. curs.execute("select block from ban where block = ? and band = 'O'", [band_it[0]])
  286. band_d = curs.fetchall()
  287. curs.execute("select block from ban where block = ?", [ip])
  288. ban_d = curs.fetchall()
  289. if band_d or ban_d:
  290. return 1
  291. return 0
  292. def topic_check(conn, name, sub):
  293. ip = ip_check()
  294. curs = conn.cursor()
  295. if ban_check(conn) == 1:
  296. return 1
  297. curs.execute("select title from stop where title = ? and sub = ?", [name, sub])
  298. topic_s = curs.fetchall()
  299. if topic_s:
  300. return 1
  301. return 0
  302. def ban_insert(conn, name, end, why, login, blocker = ip_check()):
  303. curs = conn.cursor()
  304. time = get_time()
  305. if re.search("^([0-9]{1,3}\.[0-9]{1,3})$", name):
  306. band = 'O'
  307. else:
  308. band = ''
  309. if end != '':
  310. year = int(int(end) / 525600)
  311. month = int(int(end) % 525600 / 40320)
  312. day = int(int(end) % 525600 % 40320 / 1440)
  313. hour = int(int(end) % 525600 % 40320 % 1440 / 60)
  314. minute = int(int(end) % 525600 % 40320 % 1440 % 60)
  315. end_data = [month, day, hour, minute]
  316. match = re.search("^([^-]+)-([^-]+)-([^ ]+) ([^:]+):([^:]+):(.+)$", time)
  317. time_data = match.groups()
  318. time_cut = [11, 27, 23, 59]
  319. test_list = [int(time_data[0]) + year, 0, 0, 0, 0]
  320. for number in range(0, 4):
  321. if month + int(time_data[number + 1]) > time_cut[number]:
  322. test_list[number] += 1
  323. test_list[number + 1] = end_data[number] + int(time_data[number + 1]) - (time_cut[number] + 1)
  324. else:
  325. test_list[number + 1] = end_data[number] + int(time_data[number + 1])
  326. time_list = [test_list[1], test_list[2], test_list[3], test_list[4]]
  327. number = 0
  328. for time_fix in time_list:
  329. if not re.search("[0-9]{2}", str(time_fix)):
  330. time_list[number] = '0' + str(time_fix)
  331. else:
  332. time_list[number] = str(time_fix)
  333. number += 1
  334. end = str(test_list[0]) + '-' + time_list[0] + '-' + time_list[1] + ' ' + time_list[2] + ':' + time_list[3] + ':' + time_data[5]
  335. else:
  336. end = ''
  337. curs.execute("select block from ban where block = ?", [name])
  338. if curs.fetchall():
  339. curs.execute("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)", [name, '해제', time, blocker, '', band])
  340. curs.execute("delete from ban where block = ?", [name])
  341. else:
  342. if login:
  343. login = 'O'
  344. else:
  345. login = ''
  346. curs.execute("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)", [name, end, time, blocker, why, band])
  347. curs.execute("insert into ban (block, end, why, band, login) values (?, ?, ?, ?, ?)", [name, end, why, band, login])
  348. conn.commit()
  349. def rd_plus(conn, title, sub, date):
  350. curs = conn.cursor()
  351. curs.execute("select title from rd where title = ? and sub = ?", [title, sub])
  352. if curs.fetchall():
  353. curs.execute("update rd set date = ? where title = ? and sub = ?", [date, title, sub])
  354. else:
  355. curs.execute("insert into rd (title, sub, date) values (?, ?, ?)", [title, sub, date])
  356. def history_plus(conn, title, data, date, ip, send, leng):
  357. curs = conn.cursor()
  358. curs.execute("select id from history where title = ? order by id + 0 desc limit 1", [title])
  359. d = curs.fetchall()
  360. if d:
  361. curs.execute("insert into history (id, title, data, date, ip, send, leng) values (?, ?, ?, ?, ?, ?, ?)", [str(int(d[0][0]) + 1), title, data, date, ip, send, leng])
  362. else:
  363. curs.execute("insert into history (id, title, data, date, ip, send, leng) values ('1', ?, ?, ?, ?, ?, ?)", [title, data, date, ip, send + ' (새 문서)', leng])
  364. def leng_check(a, b):
  365. if a < b:
  366. c = b - a
  367. c = '+' + str(c)
  368. elif b < a:
  369. c = a - b
  370. c = '-' + str(c)
  371. else:
  372. c = '0'
  373. return c
  374. def redirect(data):
  375. return '<meta http-equiv="refresh" content="0; url=' + data + '">'
  376. def re_error(conn, data):
  377. curs = conn.cursor()
  378. if data == '/ban':
  379. ip = ip_check()
  380. end = '<li>사유 : 권한이 맞지 않는 상태 입니다.</li>'
  381. if ban_check(conn) == 1:
  382. curs.execute("select end, why from ban where block = ?", [ip])
  383. d = curs.fetchall()
  384. if not d:
  385. m = re.search("^([0-9]{1,3}\.[0-9]{1,3})", ip)
  386. if m:
  387. curs.execute("select end, why from ban where block = ? and band = 'O'", [m.groups()[0]])
  388. d = curs.fetchall()
  389. if d:
  390. end = '<li>상태 : '
  391. if d[0][0]:
  392. now = int(re.sub('(:|-| )', '', get_time()))
  393. day = re.sub('\-', '', d[0][0])
  394. if re.search(':', day):
  395. day = re.sub('( |:)', '', day)
  396. else:
  397. day += '000000'
  398. if now >= int(day):
  399. curs.execute("delete from ban where block = ?", [ip])
  400. conn.commit()
  401. end += '차단이 풀렸습니다. 다시 시도 해 보세요.'
  402. else:
  403. end += d[0][0] + ' 까지 차단 상태 입니다.'
  404. else:
  405. end += '영구 차단 상태 입니다.'
  406. end += '</li>'
  407. if d[0][1] != '':
  408. end += '<li>사유 : ' + d[0][1] + '</li>'
  409. return html_minify(render_template('index.html',
  410. imp = ['권한 오류', wiki_set(conn, 1), custom(conn), other2([0, 0])],
  411. data = '<h2>권한 상태</h2><ul>' + end + '</ul>',
  412. menu = 0
  413. ))
  414. d = re.search('\/error\/([0-9]+)', data)
  415. if d:
  416. num = int(d.groups()[0])
  417. if num == 1:
  418. title = '권한 오류'
  419. data = '비 로그인 상태 입니다.'
  420. elif num == 2:
  421. title = '권한 오류'
  422. data = '이 계정이 없습니다.'
  423. elif num == 3:
  424. title = '권한 오류'
  425. data = '권한이 모자랍니다.'
  426. elif num == 4:
  427. title = '권한 오류'
  428. data = '관리자는 차단, 검사 할 수 없습니다.'
  429. elif num == 5:
  430. title = '사용자 오류'
  431. data = '그런 계정이 없습니다.'
  432. elif num == 6:
  433. title = '가입 오류'
  434. data = '동일한 아이디의 사용자가 있습니다.'
  435. elif num == 7:
  436. title = '가입 오류'
  437. data = '아이디는 20글자보다 짧아야 합니다.'
  438. elif num == 8:
  439. title = '가입 오류'
  440. data = '아이디에는 한글과 알파벳과 공백만 허용 됩니다.'
  441. elif num == 9:
  442. title = '파일 올리기 오류'
  443. data = '파일이 없습니다.'
  444. elif num == 10:
  445. title = '변경 오류'
  446. data = '비밀번호가 다릅니다.'
  447. elif num == 11:
  448. title = '로그인 오류'
  449. data = '이미 로그인 되어 있습니다.'
  450. elif num == 12:
  451. title = '편집 오류'
  452. data = '누군가 먼저 편집 했습니다.'
  453. elif num == 13:
  454. title = '리캡차 오류'
  455. data = '리캡차를 통과하세요.'
  456. elif num == 14:
  457. title = '파일 올리기 오류'
  458. data = 'jpg, gif, jpeg, png, webp만 가능 합니다.'
  459. elif num == 15:
  460. title = '편집 오류'
  461. data = '편집 기록은 500자를 넘을 수 없습니다.'
  462. elif num == 16:
  463. title = '파일 올리기 오류'
  464. data = '동일한 이름의 파일이 있습니다.'
  465. elif num == 17:
  466. title = '파일 올리기 오류'
  467. data = '파일 용량은 ' + wiki_set(conn, 3) + 'MB를 넘길 수 없습니다.'
  468. elif num == 18:
  469. title = '편집 오류'
  470. data = '내용이 원래 문서와 동일 합니다.'
  471. elif num == 19:
  472. title = '이동 오류'
  473. data = '이동 하려는 곳에 문서가 이미 있습니다.'
  474. elif num == 20:
  475. title = '비밀번호 오류'
  476. data = '재 확인이랑 비밀번호가 다릅니다.'
  477. elif num == 21:
  478. title = '편집 오류'
  479. data = '편집 필터에 의해 검열 되었습니다.'
  480. elif num == 22:
  481. title = '파일 올리기 오류'
  482. data = '파일 이름은 알파벳, 한글, 띄어쓰기, 언더바, 빼기표만 허용 됩니다.'
  483. else:
  484. title = '정체 불명의 오류'
  485. data = '???'
  486. if title:
  487. return html_minify(render_template('index.html',
  488. imp = [title, wiki_set(conn, 1), custom(conn), other2([0, 0])],
  489. data = '<h2>오류 발생</h2><ul><li>' + data + '</li></ul>',
  490. menu = 0
  491. ))
  492. else:
  493. return redirect('/')
  494. else:
  495. return redirect('/')