OSDN Git Service

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