OSDN Git Service

search in raw
[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         self.render('title.htm',coll=self.name(),full=self.full,
85                     count=self.count,title=self.title,update=self.update)            
86
87     def count(self,dbname):
88         if dbname in self.application.db.tables():
89             return len(self.application.db.table(dbname))
90         else:
91             return ''
92
93     def title(self,dbname):
94         if dbname in self.application.db.tables():
95             table = self.application.db.table(dbname)
96             if table.contains(where('number') == 1) == True:
97                 dic = table.get(where('number') == 1)
98                 return dic['title']
99             else:
100                 return ''
101             
102     def update(self,dbname):
103         if dbname in self.application.db.tables():
104             table = self.application.db.table(dbname)
105             i = len(table)
106             if i == 0:
107                 return ''
108             else:
109                 rec = sorted(table.all(),key=lambda x: x['number'])
110                 return rec[i-1]['date']
111         
112 class RegistHandler(tornado.web.RequestHandler):
113     def post(self,dbname):
114         if self.application.collection(dbname) == False:
115             raise tornado.web.HTTPError(404)
116             return
117         rec = self.application.db.get(where('kinds') == 'conf')
118         words = rec['bad_words']
119         out = rec['out_words']
120         na = self.get_argument('name')
121         sub = self.get_argument('title')
122         com = self.get_argument('comment')
123         text = ''
124         i = 0
125         error = ''
126         for word in out:
127             if word in com:
128                 error = error + u'禁止ワード.'
129                 break
130         for line in com.splitlines(True):
131             for word in words:
132                 if word in line:
133                     error = error + u'タグ違反.('+word+')'       
134             i += len(line)
135             text = text+'<p>'+self.link(line)+'<br></p>'
136         pw = self.get_argument('password')
137         if sub == '':
138             sub = u'タイトルなし.'
139         if i == 0:
140             error = error + u'本文がありません.'
141         elif i > 1000:
142             error = error +u'文字数が1,000をこえました.'
143         article = self.application.db.table(dbname)
144         if len(article) == 0:
145             no = 1
146         else:
147             item = sorted(article.all(),key=lambda x: x['number'])[len(article)-1]
148             no = item['number']+1
149         if error == '':
150             reg = {'number':no,'name':na,'title':sub,'comment':text,'raw':com,'password':pw,'date':datetime.now().strftime('%Y/%m/%d %H:%M')}
151             article.insert(reg)
152             restart()
153             self.set_cookie('username',tornado.escape.url_escape(na))
154             self.redirect('/'+dbname+'#article')
155         else:
156             self.render('regist.htm',content=error)
157     
158     def link(self,command):
159         y = ''
160         i = 0
161         text = ''
162         for x in command.split():
163             if (y == '>>')and(x.isdecimal() == True):
164                 s = '<a href=#'+x+'>'+x+'</a>'
165                 while -1 < command.find(x,i):
166                     j = command.find(x,i)
167                     tmp = command[i:j]
168                     i = j+len(x)
169                     k = tmp.rsplit(None,1)
170                     if ((len(k) > 1)and(k[1] == y))or(k[0] == y):
171                         text = text+tmp+s                                                                       
172                         break
173                     else:
174                         text = text+tmp+x                        
175             y = x    
176         if text == '':
177             return command
178         else:
179             if len(command) > i:
180                 return text+command[i:]
181             else:
182                 return text
183     
184 class AdminHandler(BaseHandler):
185     @tornado.web.authenticated               
186     def get(self,dbname,page='0'):
187         if dbname == '':
188             dbname = self.get_argument('record','')
189         if self.application.collection(dbname) == False:
190             raise tornado.web.HTTPError(404)
191             return
192         table = self.application.db.table(dbname) 
193         rec = sorted(table.all(),key=lambda x: x['number'])                   
194         mente = self.application.db.get(where('kinds') == 'conf')
195         if mente['mentenance'] == True:
196             check = 'checked=checked'
197         else:
198             check = ''
199         pos = self.application.gpos(dbname,page)
200         i = mente['count']
201         start = (pos-1)*i
202         if start < 0:
203             start = len(table)-i
204             if start < 0:
205                 start = 0
206         restart()
207         self.application.db = TinyDB(st.json)
208         self.render('modules/admin.htm',position=pos,records=rec[start:start+i],mente=check,password=mente['password'],db=dbname)
209
210 class AdminConfHandler(BaseHandler):
211     @tornado.web.authenticated
212     def post(self,dbname,func):
213         if func == 'set':
214             param = self.application.db.get(where('kinds') == 'conf')['mentenance']
215             if self.get_argument('mente','') == 'on':
216                 mente = True
217                 if param != mente:
218                     self.store()
219             else:
220                 mente = False  
221                 if param != mente:
222                     self.restore()
223             word = self.get_argument('pass','')
224             if word == '':
225                 self.render('regist.htm',content='パスワードを設定してください')
226                 return
227             else:
228                 self.application.db.update({'mentenance':mente,'password':word},where('kinds') == 'conf')  
229         elif func == 'del':
230             table = self.application.db.table(dbname)
231             for x in self.get_arguments('item'):
232                 table.remove(where('number') == int(x))
233         restart()
234         self.redirect('/'+dbname+'/admin/0/')
235         
236     def store(self):
237         self.application.db.close()
238         shutil.copy(st.json,st.bak)
239         self.application.db = TinyDB(st.json)
240         
241     def restore(self):
242         database = self.application.db
243         bak = TinyDB(st.bak)
244         for x in database.tables():
245             if self.application.collection(x) == True:
246                 database.purge_table(x)
247                 if x in bak.tables():
248                     table = database.table(x)
249                     table.insert_multiple(bak.table(x).all())
250         restart()
251           
252 class UserHandler(tornado.web.RequestHandler):
253     def post(self,dbname):
254         num = int(self.get_argument('number'))
255         pas = self.get_argument('password')
256         table = self.application.db.table(dbname)
257         qwr = Query()
258         obj = table.get(qwr.number == num)
259         if obj and(obj['password'] == pas):
260             table.remove(qwr.number == num)
261         self.redirect('/'+dbname)
262       
263 class SearchHandler(tornado.web.RequestHandler):       
264     def post(self,dbname):
265         self.word = tornado.escape.url_unescape(self.get_argument('word1'))
266         self.radiobox = self.get_argument('filter')
267         self.set_cookie('search',tornado.escape.url_escape(self.word))         
268         rec = self.search(dbname)
269         self.render('modules/search.htm',records=rec,word1=self.word,db=dbname)
270     
271     def get(self,dbname):
272         if self.application.collection(dbname) == False:
273             raise tornado.web.HTTPError(404)
274             return
275         word = tornado.escape.url_unescape(self.get_cookie('search'))
276         self.render('modules/search.htm',records=[],word1=word,db=dbname)
277         
278     def search(self,name):
279         table = self.application.db.table(name)    
280         element = self.word.split()
281         if len(element) == 0:
282             element = ['']
283         while len(element) < 3:
284             element.append(element[0])
285         if self.radiobox == 'comment':
286             query = (Query().raw.search(element[0])) | (Query().raw.search(element[1])) | (Query().raw.search(element[2]))
287         else:
288             query = (Query().name == element[0]) | (Query().name == element[1]) | (Query().name == element[2])
289         if self.radiobox == 'comment':
290             rec = []
291             mem = TinyDB(storage=MemoryStorage)            
292             for x in table.search(query):
293                 result = ''
294                 for text in x['raw'].splitlines(True):                  
295                     for word in self.word.split():                        
296                         if text.find(word) > -1:
297                             result = result+'<p style=background-color:yellow>'+text+'<br></p>'  
298                             break                          
299                     else:
300                         result = result+'<p>'+text+'<br></p>'
301                 i = mem.insert(x)
302                 mem.update({'comment':result},eids=[i])   
303                 rec = sorted(mem.all(),key=lambda x: x['number'])
304             mem.close()
305             return rec        
306         else:
307             rec = table.search(query)
308             return sorted(rec,key=lambda x: x['number'])   
309                                         
310 class FooterModule(tornado.web.UIModule):
311     def render(self,number,url,link):
312         return self.render_string('modules/footer.htm',index=number,url=url,link=link)
313     
314 class Application(tornado.web.Application):    
315     def __init__(self):
316         self.db = TinyDB(st.json)
317         handlers = [(r'/',NaviHandler),(r'/login',LoginHandler),(r'/logout',LogoutHandler),(r'/title',TitleHandler),
318                     (r'/([a-zA-Z0-9_]+)',IndexHandler),(r'/([a-zA-Z0-9_]+)/([0-9]+)/',IndexHandler),
319                     (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),
320                     (r'/([a-zA-Z0-9_]+)/search',SearchHandler),(r'/([a-zA-Z0-9_]+)/regist',RegistHandler)]
321         settings = {'template_path':os.path.join(os.path.dirname(__file__),'pybbs'),
322                         'static_path':os.path.join(os.path.dirname(__file__),'static'),
323                         'ui_modules':{'Footer':FooterModule},
324                         'cookie_secret':'bZJc2sWbQLKos6GkHn/VB9oXwQt8SOROkRvJ5/xJ89E=',
325                         'xsrf_cookies':True,
326                         #'debug':True,
327                         'login_url':'/login'
328                         }
329         tornado.web.Application.__init__(self,handlers,**settings)
330  
331     def gpos(self,dbname,page):
332         params = self.db.get(where('kinds') == 'conf')
333         pos = int(page)
334         if pos <= 0:
335             pos = 0
336         elif (pos-1)*params['count'] >= len(self.db.table(dbname)):
337             pos = 0
338         return pos
339     
340     def collection(self,name):
341         for x in self.db.tables():
342             if x == name:
343                 return True
344         else:
345             return False
346
347 class static():
348     json = 'static/db/db.json'
349     bak = 'static/db/bak.json'
350
351 st = static()
352 app = Application()
353
354 def restart():
355     pass
356     #app.db.close()
357     #app.db = TinyDB(st.json)