OSDN Git Service

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