diff -urN saku-1.6.1.orig/file/message-en.txt saku-1.6.1/file/message-en.txt
--- saku-1.6.1.orig/file/message-en.txt 2006-07-24 22:20:04.000000000 +0900
+++ saku-1.6.1/file/message-en.txt 2006-08-29 17:26:50.000000000 +0900
@@ -14,6 +14,7 @@
recent<>RECENT
search<>SEARCH
rss<>RSS
+kako<>KAKOLOG
# description
desc_index<>Index of ached BBS (sorted by character code).
diff -urN saku-1.6.1.orig/file/message-ja.txt saku-1.6.1/file/message-ja.txt
--- saku-1.6.1.orig/file/message-ja.txt 2006-07-24 22:20:04.000000000 +0900
+++ saku-1.6.1/file/message-ja.txt 2006-08-29 17:26:33.000000000 +0900
@@ -14,6 +14,7 @@
recent<>新着情報
search<>検索
rss<>RSS
+kako<>過去ログ
# top page
logo<>新月
diff -urN saku-1.6.1.orig/file/sample.ini saku-1.6.1/file/sample.ini
--- saku-1.6.1.orig/file/sample.ini 2006-07-28 21:26:53.000000000 +0900
+++ saku-1.6.1/file/sample.ini 2006-08-29 22:17:12.000000000 +0900
@@ -21,6 +21,7 @@
log_dir: %(var)s/log/saku
run_dir: %(var)s/run/saku
cache_dir: %(var)s/spool/saku
+kako_dir: %(var)s/spool/sakukako
spam_list: %(sysconfig)s/saku/spam.txt
diff -urN saku-1.6.1.orig/shingetsu/LightCGIHTTPServer.py saku-1.6.1/shingetsu/LightCGIHTTPServer.py
--- saku-1.6.1.orig/shingetsu/LightCGIHTTPServer.py 2006-07-24 22:53:29.000000000 +0900
+++ saku-1.6.1/shingetsu/LightCGIHTTPServer.py 2006-08-29 17:20:43.000000000 +0900
@@ -36,13 +36,14 @@
import CGIHTTPServer
import SocketServer
-import admin_cgi, client_cgi, server_cgi, gateway_cgi, thread_cgi
+import admin_cgi, client_cgi, server_cgi, gateway_cgi, thread_cgi, kako_cgi
cgimodule = {"admin.cgi": admin_cgi,
"client.cgi": client_cgi,
"server.cgi": server_cgi,
"gateway.cgi": gateway_cgi,
- "thread.cgi": thread_cgi}
+ "thread.cgi": thread_cgi,
+ "kako.cgi": kako_cgi}
__version__ = "$Revision: 1213 $"
diff -urN saku-1.6.1.orig/shingetsu/admin_cgi.py saku-1.6.1/shingetsu/admin_cgi.py
--- saku-1.6.1.orig/shingetsu/admin_cgi.py 2006-06-10 14:16:55.000000000 +0900
+++ saku-1.6.1/shingetsu/admin_cgi.py 2006-08-29 21:19:37.000000000 +0900
@@ -39,6 +39,8 @@
from cache import *
from node import *
+from kako import KakoList
+
__version__ = "$Revision: 1207 $"
@@ -81,6 +83,8 @@
self.print_status()
elif path.startswith("search"):
self.print_search(path, form)
+ elif path == "kako":
+ self.print_kako()
else:
self.print404()
@@ -343,4 +347,21 @@
self.footer()
+ def print_kako(self):
+ self.header(self.message['kako'])
+ self.stdout.write('
')
+ kakolist = KakoList()
+ for kako in kakolist:
+ x = self.file_decode(kako.datfile)
+ y = self.str_encode(x)
+ self.stdout.write(
+ ' - %s\n' %
+ (self.kako_cgi, self.sep, y, x)
+ )
+ self.stdout.write(
+ '(%d)\n
\n' % len(kako)
+ )
+ self.stdout.write('
')
+ self.footer()
+
# End of CGI
diff -urN saku-1.6.1.orig/shingetsu/cache.py saku-1.6.1/shingetsu/cache.py
--- saku-1.6.1.orig/shingetsu/cache.py 2006-07-24 22:20:04.000000000 +0900
+++ saku-1.6.1/shingetsu/cache.py 2006-08-29 22:42:34.000000000 +0900
@@ -308,6 +308,31 @@
sys.stderr.write("%s: IOError/OSError: %s\n"%(self.path, strerror))
return False
+ def move_to_kako(self, kako_path):
+ if not self.load():
+ sys.stderr.write("move_to_kako: Cannot load Record %s" % self.path)
+ return False
+
+ kako_body_path = '/'.join((kako_path, 'body'))
+ if (not os.path.exists(kako_path)) or (not os.path.exists(kako_body_path)):
+ try:
+ os.makedirs(kako_body_path)
+ except (IOError, OSError), (errorno, strerror):
+ sys.stderr.write("%s: IOError/OSError: %s\n"%(kako_path, strerror))
+ return False
+
+ apath = self.attach_path()
+ if (apath is not None) and os.path.isfile(apath):
+ kako_attach_path = '/'.join((kako_path, 'attach'))
+ if not os.path.exists(kako_attach_path):
+ try:
+ os.makedirs(kako_attach_path)
+ except (IOError, OSError), (errorno, strerror):
+ sys.stderr.write("%s: IOError/OSError: %s\n"%(kako_attach_path, strerror))
+ return False
+ shutil.move(apath, kako_attach_path)
+ self._write_file('/'.join((kako_path, 'body', self.idstr)), self.body_string())
+
# End of Record
@@ -663,10 +688,14 @@
elif len(self) <= 0:
break
once = {}
+ kako_path = '/'.join((config.kako_dir, self.datfile))
for r in ids:
rec = self[r]
- if ((limit > 0) and (rec.stamp + limit < now)) or \
- (rec.id in once):
+ if ((limit > 0) and (rec.stamp + limit < now)):
+ if not rec.removed():
+ rec.move_to_kako(kako_path)
+ rec.remove()
+ elif rec.id in once:
rec.remove()
else:
once[rec.id] = True
diff -urN saku-1.6.1.orig/shingetsu/config.py saku-1.6.1/shingetsu/config.py
--- saku-1.6.1.orig/shingetsu/config.py 2006-08-08 22:01:02.000000000 +0900
+++ saku-1.6.1/shingetsu/config.py 2006-08-29 17:14:17.000000000 +0900
@@ -66,6 +66,7 @@
run_dir = _get_value(_extconf, 'Path', 'run_dir', '../run', 'path')
file_dir = _get_value(_extconf, 'Path', 'file_dir', '../file', 'path')
cache_dir = _get_value(_extconf, 'Path', 'cache_dir', '../cache', 'path')
+kako_dir = _get_value(_extconf, 'Path', 'kako_dir', '../kako', 'path')
spam_list = _get_value(_extconf, 'Path', 'spam_list',
'../file/spam.txt', 'path')
@@ -147,6 +148,7 @@
gateway = root_path + "gateway.cgi"
thread_cgi = root_path + "thread.cgi"
admin_cgi = root_path + "admin.cgi"
+kako_cgi = root_path + "kako.cgi"
xsl = root_path + "rss1.xsl"
application = {"thread": thread_cgi}
diff -urN saku-1.6.1.orig/shingetsu/gateway.py saku-1.6.1/shingetsu/gateway.py
--- saku-1.6.1.orig/shingetsu/gateway.py 2006-08-04 21:47:45.000000000 +0900
+++ saku-1.6.1/shingetsu/gateway.py 2006-08-29 18:01:26.000000000 +0900
@@ -113,6 +113,7 @@
gateway_cgi = config.gateway
thread_cgi = config.thread_cgi
admin_cgi = config.admin_cgi
+ kako_cgi = config.kako_cgi
message = None
filter = None
str_filter = ''
diff -urN saku-1.6.1.orig/shingetsu/gateway_cgi.py saku-1.6.1/shingetsu/gateway_cgi.py
--- saku-1.6.1.orig/shingetsu/gateway_cgi.py 2006-07-25 00:55:08.000000000 +0900
+++ saku-1.6.1/shingetsu/gateway_cgi.py 2006-08-29 22:52:42.000000000 +0900
@@ -121,7 +121,7 @@
self.stdout.write(' %s\n' %
self.gateway_link(self.gateway_cgi, i))
if self.isadmin:
- for i in ("search", "status"):
+ for i in ("kako", "search", "status"):
self.stdout.write(' %s\n' %
self.gateway_link(self.admin_cgi, i))
self.stdout.write(
diff -urN saku-1.6.1.orig/shingetsu/kako.py saku-1.6.1/shingetsu/kako.py
--- saku-1.6.1.orig/shingetsu/kako.py 1970-01-01 09:00:00.000000000 +0900
+++ saku-1.6.1/shingetsu/kako.py 2006-08-29 21:30:02.000000000 +0900
@@ -0,0 +1,93 @@
+"""Kako Log of Saku BBS
+"""
+
+from cache import Record
+import config
+import os, re, sys
+
+if hasattr(sys, "winver"):
+ from os import listdir
+else:
+ from dircache import listdir
+
+
+class Kako(list):
+ datfile = ""
+ datpath = config.kako_dir
+ bpath = ''
+ apath = ''
+ stamp = 0 # when the cache is modified
+ size = 0 # size of cache file
+ type = "" # "thread"
+
+ def __init__(self, datfile):
+ list.__init__(self)
+ self.datfile = datfile
+ self.datpath += "/" + datfile
+ self.bpath = '/'.join((self.datpath, 'body'))
+ self.apath = '/'.join((self.datpath, 'attach'))
+
+ #self.stamp = self._load_status("stamp")
+ #self.size = self._load_status("size")
+
+ for type in config.types:
+ if self.datfile.startswith(type):
+ self.type = type
+ break
+
+ if self.exists():
+ try:
+ for k in listdir(self.datpath + "/body"):
+ #self[k] = Record(datfile=self.datfile, idstr=k)
+ self.append(k)
+ except OSError:
+ sys.stderr.write("%s/record: OSError\n" % self.datpath)
+
+ #def __str__(self):
+ # return self.datfile
+
+ #def keys(self):
+ # k = dict.keys(self)
+ # k.sort()
+ # return k
+
+ #def __iter__(self):
+ # return iter(self.keys())
+
+ def exists(self):
+ return bool(os.listdir(self.bpath))
+
+ def remove(self):
+ """Remove cache (a.k.a DATFILE).
+
+ It is removed from disk.
+ """
+ try:
+ shutil.rmtree(self.datpath)
+ return True
+ except IOError, strerror:
+ sys.stderr.write("IOError: " + strerror + "\n")
+ return False
+
+ def load_body(self, start=0, num=100):
+ """Load records from body."""
+ tmp = []
+ try:
+ for k in self[start:start + num]:
+ body = file('/'.join((self.datpath, 'body', k)), 'r')
+ r = Record(datfile=self.datfile)
+ if r.parse(body.read()):
+ tmp.append(r)
+ body.close()
+ except IOError:
+ sys.stderr.write("%s/body.cache: IOError\n" % self.datpath)
+ return tmp
+
+class KakoList(list):
+ def __init__(self):
+ list.__init__(self)
+ for i in os.listdir(config.kako_dir):
+ k = Kako(i)
+ if k.exists():
+ self.append(k)
+ self.sort()
diff -urN saku-1.6.1.orig/shingetsu/kako_cgi.py saku-1.6.1/shingetsu/kako_cgi.py
--- saku-1.6.1.orig/shingetsu/kako_cgi.py 1970-01-01 09:00:00.000000000 +0900
+++ saku-1.6.1/shingetsu/kako_cgi.py 2006-08-29 22:28:58.000000000 +0900
@@ -0,0 +1,244 @@
+'''Saku Kako Log CGI methods.
+'''
+#
+# Copyright (c) 2005,2006 shinGETsu Project.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: thread_cgi.py 1234 2006-08-04 12:47:36Z fuktommy $
+#
+
+import cgi
+import mimetypes
+import re
+import time
+from Cookie import SimpleCookie
+
+import config
+import gateway
+from kako import *
+
+__version__ = "$Revision: 1234 $"
+
+
+class CGI(gateway.CGI):
+
+ """Class for /kako.cgi."""
+
+ appli_type = "thread"
+
+ def run(self):
+ path = self.path_info()
+
+ if not self.isadmin:
+ self.print403()
+ return
+ elif (path != ""):
+ if (path.find("/") < 0):
+ self.print_thread(path)
+ return
+ else:
+ tmp = path.split('/')
+ if len(tmp) == 2:
+ path, page = tmp
+ page = int(page)
+ self.print_thread(path, page)
+ return
+
+ found = re.search(r"^(thread_[0-9A-F]+)/([0-9a-f]{32})/(\d+)\.(.*)",
+ path)
+ if found:
+ (datfile, stamp, id, suffix) = found.groups()
+ self.print_attach(datfile, stamp, id, suffix)
+ return
+
+ self.print404()
+
+ def print_thread(self, path, page=1, num=100):
+ kako = Kako(self.file_encode("thread", path))
+ if not kako.exists():
+ self.print404()
+ return
+ start = (page - 1) * num
+ record = kako.load_body(start, num)
+ if not record:
+ self.print404()
+ return
+ self.header(path + ' (' + self.message["kako"] + ')', cookie='')
+ self.stdout.write('\npage \n')
+ self.pageindex(kako, path, page, num)
+ self.stdout.write('
\n')
+ if self.isadmin:
+ self.stdout.write(
+ '\n')
+ else:
+ self.stdout.write('\n')
+
+ def pageindex(self, kako, path, page, num):
+ s = '%%d \n' % (self.kako_cgi, self.sep, path, self.sep)
+ for i in range(0, (len(kako) + num -1) / num):
+ i += 1
+ if i == page:
+ self.stdout.write('%d \n' % i )
+ else:
+ self.stdout.write(s % (i, i))
+
+ def print_attach(self, datfile, id, stamp, suffix):
+ """Print attachment."""
+ kako = Kako(datfile)
+ (type, null) = mimetypes.guess_type("." + suffix)
+ if type is None:
+ type = "text/plain"
+ if kako.exists():
+ pass
+ else:
+ self.print404(kako)
+ return
+ aname = stamp + '_' + id + '.' + suffix
+ attach_file = '/'.join((kako.datpath, 'attach', aname))
+ if not os.path.isfile(attach_file):
+ self.print404(kako)
+ return
+ attach_size = os.path.getsize(attach_file)
+
+ if attach_file is not None:
+ self.stdout.write(
+ "Content-Type: " + type + "\n" +
+ "Last-Modified: " + self.rfc822_time(stamp) + "\n" +
+ "Content-Length: " + str(attach_size) + "\n" +
+ "\n")
+ try:
+ f = file(attach_file, "rb")
+ buf = f.read(1024)
+ while (buf != ""):
+ self.stdout.write(buf)
+ buf = f.read(1024)
+ f.close()
+ except IOError:
+ self.print404(kako)
diff -urN saku-1.6.1.orig/www/kako.cgi saku-1.6.1/www/kako.cgi
--- saku-1.6.1.orig/www/kako.cgi 1970-01-01 09:00:00.000000000 +0900
+++ saku-1.6.1/www/kako.cgi 2006-08-29 17:10:33.000000000 +0900
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+# Copyright (C) 2005 shinGETsu Project.
+#
+# $Id: thread.cgi 991 2005-05-15 14:10:40Z fuktommy $
+#
+
+import shingetsu.kako_cgi
+
+if __name__ == "__main__":
+ shingetsu.kako_cgi.CGI().start()