OSDN Git Service

error better
[pybbs/pybbs.git] / index.py
1
2 import os.path
3 import shutil,copy
4 import tornado.auth
5 import tornado.escape
6 import tornado.web
7 from tinydb import TinyDB,Query,where
8 from tinydb.operations import delete
9 from datetime import datetime
10
11 class BaseHandler(tornado.web.RequestHandler):
12     def get_current_user(self):
13         user = self.get_secure_cookie('admin_user')
14         return tornado.escape.utf8(user)
15     
16     def set_current_user(self,username):
17         self.set_secure_cookie('admin_user',username)
18         
19     def clear_current_user(self):
20         self.clear_cookie('admin_user')
21
22 class IndexHandler(BaseHandler):
23     def get(self,dbname,page='0'):
24         params = self.application.db.get(where('kinds') == 'conf')
25         if params['mentenance'] == True:
26             self.render('mentenance.htm',title=params['title'],db=dbname)
27         if self.application.collection(dbname) == False:
28             if self.current_user == b'admin':
29                 self.application.db.table(dbname)
30             else:
31                 raise tornado.web.HTTPError(404)
32                 return
33         i = params['count']      
34         na = tornado.escape.url_unescape(self.get_cookie("username",u"誰かさん"))
35         pos = self.application.gpos(dbname,page)
36         table = self.application.db.table(dbname)
37         start = (pos-1)*i
38         if start < 0:
39             start = len(table)-i
40             if start < 0:
41                 start = 0
42         rec = sorted(table.all(),key=lambda x: x['number'])[start:start+i]
43         if len(table) >= 10*i:
44             self.render('modules/full.htm',position=pos,records=rec,data=params,db=dbname)
45             return
46         self.render('modules/index.htm',position=pos,records=rec,data=params,username=na,db=dbname)
47         
48 class LoginHandler(BaseHandler):
49     def get(self):
50         self.render('login.htm')
51         
52     def post(self):
53         pw = self.application.db.get(where('kinds') == 'conf')
54         if self.get_argument('password') == pw['password']:
55             self.set_current_user('admin')
56         dbname = self.get_argument('record')
57         self.redirect('/'+dbname+'/admin/0/')
58         
59 class LogoutHandler(BaseHandler):
60     def get(self):
61         self.clear_current_user()
62         self.redirect('/login')
63         
64 class NaviHandler(tornado.web.RequestHandler):
65     def get(self):
66         self.render('top.htm',coll=sorted(self.name()),full=self.full)
67         
68     def name(self):
69         for x in self.application.db.tables():
70             if x != '_default':
71                 yield x
72                 
73     def full(self,dbname):
74         if dbname in self.application.db.tables():
75             i = 10*self.application.db.get(where('kinds') == 'conf')['count']
76             table = self.application.db.table(dbname)
77             if len(table) >= i:
78                 return True
79         return False
80
81 class TitleHandler(NaviHandler):
82     def get(self):
83         self.render('title.htm',coll=self.name(),full=self.full,
84                     count=self.count,title=self.title,update=self.update)            
85
86     def count(self,dbname):
87         if dbname in self.application.db.tables():
88             return len(self.application.db.table(dbname))
89         else:
90             return ''
91
92     def title(self,dbname):
93         if dbname in self.application.db.tables():
94             table = self.application.db.table(dbname)
95             if table.contains(where('number') == 1) == True:
96                 dic = table.get(where('number') == 1)
97                 return dic['title']
98             else:
99                 return ''
100             
101     def update(self,dbname):
102         if dbname in self.application.db.tables():
103             table = self.application.db.table(dbname)
104             i = len(table)
105             if i == 0:
106                 return ''
107             else:
108                 rec = sorted(table.all(),key=lambda x: x['number'])
109                 return rec[i-1]['date']
110         
111 class RegistHandler(tornado.web.RequestHandler):
112     def post(self,dbname):
113         if self.application.collection(dbname) == False:
114             raise tornado.web.HTTPError(404)
115             return
116         rec = self.application.db.get(where('kinds') == 'conf')
117         words = rec['bad_words']
118         out = rec['out_words']
119         na = self.get_argument('name')
120         sub = self.get_argument('title')
121         com = self.get_argument('comment')
122         text = ''
123         i = 0
124         error = ''
125         for word in out:
126             if word in com:
127                 error = error + u'禁止ワード.'
128                 break
129         for line in com.splitlines(True):
130             for word in words:
131                 if word in line:
132                     error = error + u'タグ違反.('+word+')'       
133             i += len(line)
134             text = text+'<p>'+self.link(line)+'<br></p>'
135         pw = self.get_argument('password')
136         if sub == '':
137             sub = u'タイトルなし.'
138         if i == 0:
139             error = error + u'本文がありません.'
140         elif i > 1000:
141             error = error +u'文字数が1,000をこえました.'
142         article = self.application.db.table(dbname)
143         if len(article) == 0:
144             no = 1
145         else:
146             item = article.all()[len(article)-1]
147             no = item['number']+1
148         if error == '':
149             reg = {'number':no,'name':na,'title':sub,'comment':text,'password':pw,'date':datetime.now().strftime('%Y/%m/%d %H:%M')}
150             article.insert(reg)
151             restart()
152             self.set_cookie('username',tornado.escape.url_escape(na))
153             self.redirect('/'+dbname+'#article')
154         else:
155             self.render('regist.htm',content=error)
156     
157     def link(self,command):
158         y = ''
159         i = 0
160         text = ''
161         for x in command.split():
162             if (y == '>>')and(x.isdecimal() == True):
163                 s = '<a href=#'+x+'>'+x+'</a>'
164                 while -1 < command.find(x,i):
165                     j = command.find(x,i)
166                     tmp = command[i:j]
167                     i = j+len(x)
168                     k = tmp.rsplit(None,1)
169                     if ((len(k) > 1)and(k[1] == y))or(k[0] == y):
170                         text = text+tmp+s                                                                       
171                         break
172                     else:
173                         text = text+tmp+x                        
174             y = x    
175         if text == '':
176             return command
177         else:
178             if len(command) > i:
179                 return text+command[i:]
180             else:
181                 return text
182     
183 class AdminHandler(BaseHandler):
184     @tornado.web.authenticated               
185     def get(self,dbname,page='0'):
186         if dbname == '':
187             dbname = self.get_argument('record','')
188         if self.application.collection(dbname) == False:
189             raise tornado.web.HTTPError(404)
190             return
191         table = self.application.db.table(dbname) 
192         rec = sorted(table.all(),key=lambda x: x['number'])                   
193         mente = self.application.db.get(where('kinds') == 'conf')
194         if mente['mentenance'] == True:
195             check = 'checked=checked'
196         else:
197             check = ''
198         pos = self.application.gpos(dbname,page)
199         restart()
200         self.application.db = TinyDB(json)
201         self.render('modules/admin.htm',position=pos,records=rec,mente=check,password=mente['password'],db=dbname)
202
203 class AdminConfHandler(BaseHandler):
204     @tornado.web.authenticated
205     def post(self,dbname,func):
206         if func == 'set':
207             param = self.application.db.get(where('kinds') == 'conf')['mentenance']
208             if self.get_argument('mente','') == 'on':
209                 mente = True
210                 if param != mente:
211                     self.store()
212             else:
213                 mente = False  
214                 if param != mente:
215                     self.restore()
216             word = self.get_argument('pass','')
217             if word == '':
218                 self.render('regist.htm',content='パスワードを設定してください')
219             else:
220                 self.application.db.update({'mentenance':mente,'password':word},where('kinds') == 'conf')     
221         elif func == 'del':
222             table = self.application.db.table(dbname)
223             for x in self.get_arguments('item'):
224                 table.remove(where('number') == int(x))
225         restart()
226         self.redirect('/'+dbname+'/admin/0/')
227         
228     def store(self):
229         self.application.db.close()
230         shutil.copy('static/db/db.json','static/db/bak.json')
231         self.application.db = TinyDB(json)
232         
233     def restore(self):
234         database = self.application.db
235         bak = TinyDB('static/db/bak.json')
236         for x in database.tables():
237             if self.application.collection(x) == True:
238                 database.purge_table(x)
239                 if x in bak.tables():
240                     table = database.table(x)
241                     table.insert_multiple(bak.table(x).all())
242           
243 class UserHandler(tornado.web.RequestHandler):
244     def post(self,dbname):
245         num = int(self.get_argument('number'))
246         pas = self.get_argument('password')
247         table = self.application.db.table(dbname)
248         qwr = Query()
249         obj = table.get(qwr.number == num)
250         if obj and(obj['password'] == pas):
251             table.remove(qwr.number == num)
252         self.redirect('/'+dbname)
253       
254 class SearchHandler(tornado.web.RequestHandler):       
255     def post(self,dbname):
256         word = self.get_argument('word1')
257         radiobox = self.get_argument('filter')
258         self.set_cookie('search',word)
259         table = self.application.db.table(dbname)            
260         self.render('modules/search.htm',records=table.search(where(radiobox).matches(word)),word1=word,db=dbname)
261     
262     def get(self,dbname):
263         word = self.get_cookie('search')
264         self.render('modules/search.htm',records={},word1=word,db=dbname)
265         
266 class FooterModule(tornado.web.UIModule):
267     def render(self,number,url,link):
268         return self.render_string('modules/footer.htm',index=number,url=url,link=link)
269     
270 class Application(tornado.web.Application):    
271     def __init__(self):
272         self.db = TinyDB(json)
273         handlers = [(r'/',NaviHandler),(r'/login',LoginHandler),(r'/logout',LogoutHandler),(r'/title',TitleHandler),
274                     (r'/([a-zA-Z0-9_]+)',IndexHandler),(r'/([a-zA-Z0-9_]+)/([0-9]+)/',IndexHandler),
275                     (r'/([a-zA-Z0-9_]+)/admin/([0-9]+)/',AdminHandler),(r'/([a-zA-Z0-9_]+)/admin/([a-z]+)/',AdminConfHandler),(r'/([a-zA-Z0-9_]+)/userdel',UserHandler),
276                     (r'/([a-zA-Z0-9_]+)/search',SearchHandler),(r'/([a-zA-Z0-9_]+)/regist',RegistHandler)]
277         settings = {'template_path':os.path.join(os.path.dirname(__file__),'pybbs'),
278                         'static_path':os.path.join(os.path.dirname(__file__),'static'),
279                         'ui_modules':{'Footer':FooterModule},
280                         'cookie_secret':'bZJc2sWbQLKos6GkHn/VB9oXwQt8SOROkRvJ5/xJ89E=',
281                         'xsrf_cookies':True,
282                         #'debug':True,
283                         'login_url':'/login'
284                         }
285         tornado.web.Application.__init__(self,handlers,**settings)
286  
287     def gpos(self,dbname,page):
288         params = self.db.get(where('kinds') == 'conf')
289         pos = int(page)
290         if pos <= 0:
291             pos = 0
292         elif (pos-1)*params['count'] >= len(self.db.table(dbname)):
293             pos = 0
294         return pos
295     
296     def collection(self,name):
297         for x in self.db.tables():
298             if x == name:
299                 return True
300         else:
301             return False
302
303 json = 'static/db/db.json'
304 app = Application()
305
306 def restart():
307     app.db.close()
308     app.db = TinyDB(json)