OSDN Git Service

重要なコミット:env flexの使用が課金対象になっているのでpytnon27に変更
[pybbs/pybbs.git] / index.py
index a47ff91..fabcc7c 100755 (executable)
--- a/index.py
+++ b/index.py
@@ -1,20 +1,15 @@
 
-import tornado.wsgi
-import wsgiref.simple_server
 import os.path
+import shutil,copy
 import tornado.auth
 import tornado.escape
-import tornado.httpserver
-import tornado.ioloop
-import tornado.options
 import tornado.web
-from tornado.options import define,options
+import tornado.wsgi
+import wsgiref.simple_server
 from tinydb import TinyDB,Query,where
 from tinydb.operations import delete
 from datetime import datetime
 
-define('port',default=8000,help='run on the given port.',type=int)
-
 class BaseHandler(tornado.web.RequestHandler):
     def get_current_user(self):
         user = self.get_secure_cookie('admin_user')
@@ -35,9 +30,10 @@ class IndexHandler(BaseHandler):
             if self.current_user == b'admin':
                 self.application.db.table(dbname)
             else:
-                self.render('regist.htm',content='urlが見つかりません')
+                raise tornado.web.HTTPError(404)
+                return
         i = params['count']      
-        na = self.get_cookie('username')
+        na = tornado.escape.url_unescape(self.get_cookie("username",u"誰かさん"))
         pos = self.application.gpos(dbname,page)
         table = self.application.db.table(dbname)
         start = (pos-1)*i
@@ -45,9 +41,10 @@ class IndexHandler(BaseHandler):
             start = len(table)-i
             if start < 0:
                 start = 0
-        rec = table.all()[start:start+i]
+        rec = sorted(table.all(),key=lambda x: x['number'])[start:start+i]
         if len(table) >= 10*i:
-            self.render('modules/full.htm',position=pos,records=rec,data=params,db=dbname)  
+            self.render('modules/full.htm',position=pos,records=rec,data=params,db=dbname)
+            return
         self.render('modules/index.htm',position=pos,records=rec,data=params,username=na,db=dbname)
         
 class LoginHandler(BaseHandler):
@@ -68,136 +65,259 @@ class LogoutHandler(BaseHandler):
         
 class NaviHandler(tornado.web.RequestHandler):
     def get(self):
-        self.render('top.htm',coll=self.name())
+        self.render('top.htm',coll=sorted(self.name()),full=self.full)
         
     def name(self):
-        y = []
         for x in self.application.db.tables():
             if x != '_default':
-                y.append(x)
-        return sorted(y)
+                yield x
+                
+    def full(self,dbname):
+        if dbname in self.application.db.tables():
+            i = 10*self.application.db.get(where('kinds') == 'conf')['count']
+            table = self.application.db.table(dbname)
+            if len(table) >= i:
+                return True
+        return False
 
+class TitleHandler(NaviHandler):
+    def get(self):
+        rec = sorted(self.title(),key=lambda x: x['date2'])
+        self.render('title.htm',coll=rec,full=self.full)  
+        
+    def title(self):
+        for x in self.name():
+            item = {}
+            item['name'] = x
+            table = self.application.db.table(x)
+            i = len(table)
+            item['count'] = i            
+            if table.contains(where('number') == 1) == True:
+                s = table.get(where('number') == 1)['title']
+            else:
+                s = ''
+            item['title'] = s   
+            if i == 0:
+                item['date'] = ''
+                item['date2'] = 0
+            else:
+                rec = sorted(table.all(),key=lambda k: k['number'])
+                s = rec[i-1]['date']
+                item['date'] = s
+                i = datetime.strptime(s,'%Y/%m/%d %H:%M')
+                year = datetime.now().year-i.year
+                if year == 0:
+                    j = 800
+                elif year == 1:
+                    j = 400
+                else:
+                    j = 0
+                item['date2'] = j+31*(i.month-1)+i.day
+            yield item
+        
 class RegistHandler(tornado.web.RequestHandler):
     def post(self,dbname):
         if self.application.collection(dbname) == False:
-            self.render('regist.htm',content='urlが存在しません')
-        words = ['<link','<script','<style','<img']
-        out = ['ばか','死ね','あほ']
+            raise tornado.web.HTTPError(404)
+            return
+        rec = self.application.db.get(where('kinds') == 'conf')
+        words = rec['bad_words']
+        out = rec['out_words']
         na = self.get_argument('name')
         sub = self.get_argument('title')
         com = self.get_argument('comment')
         text = ''
         i = 0
         error = ''
+        for word in out:
+            if word in com:
+                error = error + u'禁止ワード.'
+                break
         for line in com.splitlines(True):
             for word in words:
-                if word in line:
+                if word in line.lower():
                     error = error + u'タグ違反.('+word+')'       
-            text = text+'<p>'+line
             i += len(line)
-        for word in out:
-            if word in text:
-                error = error + u'禁止ワード.'
-                break
+            text = text+'<p>'+self.link(line)+'<br></p>'
         pw = self.get_argument('password')
-        if na == '':
-            na = u'誰かさん'
-        if sub == '':
-            sub = u'タイトルなし.'
         if i == 0:
             error = error + u'本文がありません.'
         elif i > 1000:
             error = error +u'文字数が1,000をこえました.'
+        if na == '':
+            na = u'誰かさん'
+        if sub == '':
+            sub = u'タイトルなし.'
         article = self.application.db.table(dbname)
         if len(article) == 0:
             no = 1
         else:
-            item = article.get(where('number') == len(article))
+            item = sorted(article.all(),key=lambda x: x['number'])[len(article)-1]
             no = item['number']+1
         if error == '':
-            reg = {'number':no,'name':na,'title':sub,'comment':text,'password':pw,'date':1}#datetime.today()}
+            s = datetime.now()
+            reg = {'number':no,'name':na,'title':sub,'comment':text,'raw':com,'password':pw,'date':s.strftime('%Y/%m/%d %H:%M')}
             article.insert(reg)
-            self.set_cookie('username',na)
+            self.set_cookie('username',tornado.escape.url_escape(na))
             self.redirect('/'+dbname+'#article')
         else:
             self.render('regist.htm',content=error)
-
+    
+    def link(self,command):
+        y = ''
+        i = 0
+        text = ''
+        for x in command.split():
+            if (y == '>>')and(x.isdecimal() == True):
+                s = '<a href=#'+x+'>'+x+'</a>'
+                while -1 < command.find(x,i):
+                    j = command.find(x,i)
+                    tmp = command[i:j]
+                    i = j+len(x)
+                    k = tmp.rsplit(None,1)
+                    if ((len(k) > 1)and(k[1] == y))or(k[0] == y):
+                        text = text+tmp+s                                                                       
+                        break
+                    else:
+                        text = text+tmp+x                        
+            y = x    
+        if text == '':
+            return command
+        else:
+            if len(command) > i:
+                return text+command[i:]
+            else:
+                return text
+    
 class AdminHandler(BaseHandler):
     @tornado.web.authenticated               
     def get(self,dbname,page='0'):
         if dbname == '':
             dbname = self.get_argument('record','')
         if self.application.collection(dbname) == False:
-            self.render('regist.htm',content='urlが見つかりません')
+            raise tornado.web.HTTPError(404)
+            return
         table = self.application.db.table(dbname) 
-        rec = table.all()                   
+        rec = sorted(table.all(),key=lambda x: x['number'])                   
         mente = self.application.db.get(where('kinds') == 'conf')
         if mente['mentenance'] == True:
             check = 'checked=checked'
         else:
             check = ''
         pos = self.application.gpos(dbname,page)
-        self.render('modules/admin.htm',position=pos,records=rec,mente=check,password=mente['password'],db=dbname)
+        i = mente['count']
+        start = (pos-1)*i
+        if start < 0:
+            start = len(table)-i
+            if start < 0:
+                start = 0
+        self.render('modules/admin.htm',position=pos,records=rec[start:start+i],mente=check,password=mente['password'],db=dbname)
 
 class AdminConfHandler(BaseHandler):
     @tornado.web.authenticated
     def post(self,dbname,func):
         if func == 'set':
+            param = self.application.db.get(where('kinds') == 'conf')['mentenance']
             if self.get_argument('mente','') == 'on':
                 mente = True
+                if param != mente:
+                    self.store()
             else:
                 mente = False  
+                if param != mente:
+                    self.restore()
             word = self.get_argument('pass','')
             if word == '':
                 self.render('regist.htm',content='パスワードを設定してください')
+                return
             else:
-                self.application.db.update({'mentenance':mente,'password':word},where('kinds') == 'conf')     
+                self.application.db.update({'mentenance':mente,'password':word},where('kinds') == 'conf')  
         elif func == 'del':
             table = self.application.db.table(dbname)
             for x in self.get_arguments('item'):
                 table.remove(where('number') == int(x))
         self.redirect('/'+dbname+'/admin/0/')
+        
+    def store(self):
+        self.application.db.close()
+        shutil.copy(st.json,st.bak)
+        self.application.db = TinyDB(st.json)
+        
+    def restore(self):
+        database = self.application.db
+        bak = TinyDB(st.bak)
+        for x in database.tables():
+            if self.application.collection(x) == True:
+                database.purge_table(x)
+                if x in bak.tables():
+                    table = database.table(x)
+                    table.insert_multiple(bak.table(x).all())
           
 class UserHandler(tornado.web.RequestHandler):
     def post(self,dbname):
-        num = int(self.get_argument('number'))
-        pas = self.get_argument('password')
-        table = self.application.db.table(dbname)
-        qwr = Query()
-        obj = table.get(qwr.number == num)
-        if obj and(obj['password'] == pas):
-            table.remove(qwr.number == num)
+        num = self.get_argument('number')
+        if num.isdigit() == True:
+            num = int(num)
+            pas = self.get_argument('password')
+            table = self.application.db.table(dbname)
+            qwr = Query()
+            obj = table.get(qwr.number == num)
+            if obj and(obj['password'] == pas):
+                table.remove(qwr.number == num)
         self.redirect('/'+dbname)
       
 class SearchHandler(tornado.web.RequestHandler):       
     def post(self,dbname):
-        self.word = self.get_argument('word1')
+        self.word = tornado.escape.url_unescape(self.get_argument('word1'))
         self.radiobox = self.get_argument('filter')
-        self.set_cookie('search',self.word)
-        table = self.application.db.table(dbname)
-        self.render('modules/search.htm',records=self.mylist(table.all()),word1=self.word,db=dbname)
+        self.set_cookie('search',tornado.escape.url_escape(self.word))         
+        rec = sorted(self.search(dbname),key=lambda x: x['number'])
+        self.render('modules/search.htm',records=rec,word1=self.word,db=dbname)
     
     def get(self,dbname):
-        word = self.get_cookie('search')
-        self.render('modules/search.htm',records={},word1=word,db=dbname)
-        
-    def mylist(self,rec):
-        for searchrec in rec:       
-            if self.radiobox == 'name':
-                if searchrec['name'].find(self.word) == True:
-                    yield searchrec
-            else:
-                if searchrec['comment'].find(self.word) == True:
-                    yield searchrec
+        if self.application.collection(dbname) == False:
+            raise tornado.web.HTTPError(404)
+            return
+        word = self.get_cookie('search','')
+        word = tornado.escape.url_unescape(word)
+        self.render('modules/search.htm',records=[],word1=word,db=dbname)
         
+    def search(self,dbname):
+        table = self.application.db.table(dbname)    
+        element = self.word.split()
+        if len(element) == 0:
+            element = ['']
+        while len(element) < 3:
+            element.append(element[0])
+        if self.radiobox == 'comment':
+            query = (Query().raw.search(element[0])) | (Query().raw.search(element[1])) | (Query().raw.search(element[2]))
+        else:
+            query = (Query().name == element[0]) | (Query().name == element[1]) | (Query().name == element[2])
+        if self.radiobox == 'comment':    
+            for x in table.search(query):
+                com = ''
+                for text in x['raw'].splitlines(True):                  
+                    for word in self.word.split():                        
+                        if text.find(word) > -1:
+                            com = com +'<p style=background-color:yellow>'+text+'<br></p>'  
+                            break                          
+                    else:
+                        com = com+'<p>'+text+'<br></p>'
+                x['comment'] = com
+                yield x       
+        else:
+            for x in table.search(query):
+                yield x
+                                        
 class FooterModule(tornado.web.UIModule):
     def render(self,number,url,link):
         return self.render_string('modules/footer.htm',index=number,url=url,link=link)
     
 class Application(tornado.web.Application):    
     def __init__(self):
-        self.db = TinyDB('static/db/db.json')
-        handlers = [(r'/',NaviHandler),(r'/login',LoginHandler),(r'/logout',LogoutHandler),(r'/([a-zA-Z0-9_]+)',IndexHandler),(r'/([a-zA-Z0-9_]+)/([0-9]+)/',IndexHandler),
+        self.db = TinyDB(st.json)
+        handlers = [(r'/',NaviHandler),(r'/login',LoginHandler),(r'/logout',LogoutHandler),(r'/title',TitleHandler),
+                    (r'/([a-zA-Z0-9_]+)',IndexHandler),(r'/([a-zA-Z0-9_]+)/([0-9]+)/',IndexHandler),
                     (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),
                     (r'/([a-zA-Z0-9_]+)/search',SearchHandler),(r'/([a-zA-Z0-9_]+)/regist',RegistHandler)]
         settings = {'template_path':os.path.join(os.path.dirname(__file__),'pybbs'),
@@ -205,7 +325,7 @@ class Application(tornado.web.Application):
                         'ui_modules':{'Footer':FooterModule},
                         'cookie_secret':'bZJc2sWbQLKos6GkHn/VB9oXwQt8SOROkRvJ5/xJ89E=',
                         'xsrf_cookies':True,
-                        'debug':True,
+                        #'debug':True,
                         'login_url':'/login'
                         }
         tornado.web.Application.__init__(self,handlers,**settings)
@@ -220,17 +340,17 @@ class Application(tornado.web.Application):
         return pos
     
     def collection(self,name):
-        for x in self.db.tables():
-            if x == name:
-                return True
+        if name in self.db.tables():
+            return True
         else:
             return False
-        
+
+class static():
+    json = 'static/db/db.json'
+    bak = 'static/db/bak.json'
+
+st = static()
+app = tornado.wsgi.WSGIAdapter(Application())
 if __name__ == '__main__':
-    tornado.options.parse_command_line()
-    app = Application()
-    app.listen(options.port)
-    tornado.ioloop.IOLoop.instance().start()
-#    wsgi_app = tornado.wsgi.WSGIAdapter(Applications())
- #   server = wsgiref.simple_server.make_server('',8888,wsgi_app)
- #   server.serve_forever()
+    server = wsgiref.simple_server.make_server('',8888,app)
+    server.serve_forever()