Initial revision
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
License notice for u-srif-py
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
+-----------+----------------------+----------------------+
|
||||
| | Statistic | Limits |
|
||||
| Period +-------------+--------+-------------+--------+
|
||||
| | Size | Number | Size | Number |
|
||||
+-----------+-------------+--------+-------------+--------+
|
||||
| Day | @%-11d,sent_day_size@ | @%-6d,sent_day_num@ | @%-11s,limit_size_day@ | @%-6s,limit_num_day@ |
|
||||
+-----------+-------------+--------+-------------+--------+
|
||||
| Week | @%-11d,sent_week_size@ | @%-6d,sent_week_num@ | @%-11s,limit_size_week@ | @%-6s,limit_num_week@ |
|
||||
+-----------+-------------+--------+-------------+--------+
|
||||
| Month | @%-11d,sent_month_size@ | @%-6d,sent_month_num@ | @%-11s,limit_size_month@ | @%-6s,limit_num_month@ |
|
||||
+-----------+-------------+--------+-------------+--------+
|
||||
| Total | @%-11d,sent_total_size@ | @%-6d,sent_total_num@ |
|
||||
+-----------+-------------+--------+
|
||||
|
||||
******************************************************************************
|
||||
File requests policy
|
||||
******************************************************************************
|
||||
|
||||
File requests supported at 00:00-05:30 and at least 9600 speed
|
||||
|
||||
There are aliases for file requests:
|
||||
|
||||
FILES - Happy Station files list
|
||||
BFORCE - The latest version of the binkleyforce mailer
|
||||
|
||||
Bye, call again!
|
||||
@@ -0,0 +1,2 @@
|
||||
Hello, @%s,remote_sysop@!
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
files /home/ftp/pub/info/happy.zip
|
||||
filelist /home/ftp/pub/info/happy.lst
|
||||
test /home/ftp/pub/fileecho/PNT5020/pnt5020.zip
|
||||
bforce /home/ftp/pub/bforce/bforce-last.tar.gz
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
##############################################################################
|
||||
### u-srif FREQ processor configuration file #################################
|
||||
##############################################################################
|
||||
|
||||
# Spool directory for files index, links statistic, etc.
|
||||
spool-dir /var/spool/u-srif
|
||||
|
||||
# Log file name
|
||||
log-file /var/log/ftn/u-srif.log
|
||||
|
||||
# File with list of freqable directories
|
||||
dir-list-file /usr/local/etc/u-srif/u-srif.dirs
|
||||
|
||||
# File with list of freqable directories
|
||||
alias-list-file /usr/local/etc/u-srif/u-srif.aliases
|
||||
|
||||
freq-policy /usr/local/etc/u-srif/policy.text
|
||||
|
||||
freq-magic bforce-cvs /usr/local/etc/u-srif/magic/bforce-cvs
|
||||
freq-alias = files /home/ftp/pub password
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/home/ftp/pub/bforce/
|
||||
/home/ftp/pub/fileecho/ADV_FTNSOFT/
|
||||
/home/ftp/pub/fileecho/AFTNMISC/
|
||||
/home/ftp/pub/fileecho/AVP/
|
||||
/home/ftp/pub/fileecho/BOOK/
|
||||
/home/ftp/pub/fileecho/CRACKER/
|
||||
/home/ftp/pub/fileecho/CRACKS/
|
||||
/home/ftp/pub/fileecho/FAR/
|
||||
/home/ftp/pub/fileecho/FR_CO.FILES/
|
||||
/home/ftp/pub/fileecho/FWUTILS/
|
||||
/home/ftp/pub/fileecho/GSS_BETA/
|
||||
/home/ftp/pub/fileecho/GSS_SOFT/
|
||||
/home/ftp/pub/fileecho/G_CHEAT/
|
||||
/home/ftp/pub/fileecho/IT.FILES/
|
||||
/home/ftp/pub/fileecho/IT.MP3/
|
||||
/home/ftp/pub/fileecho/IT.MUSIC/
|
||||
/home/ftp/pub/fileecho/IT.NDL/
|
||||
/home/ftp/pub/fileecho/LARRY.FILES/
|
||||
/home/ftp/pub/fileecho/HAPPY.XCK/
|
||||
/home/ftp/pub/fileecho/MOBIL/
|
||||
/home/ftp/pub/fileecho/NET5020/
|
||||
/home/ftp/pub/fileecho/PNT5020/
|
||||
/home/ftp/pub/fileecho/RUFO/
|
||||
/home/ftp/pub/fileecho/STICK.FILES/
|
||||
/home/ftp/pub/fileecho/T-MAIL/
|
||||
/home/ftp/pub/fileecho/UNKNOWN/
|
||||
/home/ftp/pub/fileecho/XDOCREF/
|
||||
/home/ftp/pub/fileecho/XGAMSOL/
|
||||
/home/ftp/pub/fileecho/XHAMRADIO/
|
||||
/home/ftp/pub/fileecho/XHRDASUS/
|
||||
/home/ftp/pub/fileecho/XHRDDOCS/
|
||||
/home/ftp/pub/fileecho/XHRDIDC/
|
||||
/home/ftp/pub/fileecho/XHRDUSR/
|
||||
/home/ftp/pub/fileecho/XPICART/
|
||||
/home/ftp/pub/fileecho/XPICHUMOR/
|
||||
/home/ftp/pub/fileecho/XPICMUSIC/
|
||||
/home/ftp/pub/fileecho/XPICSHIP/
|
||||
/home/ftp/pub/fileecho/XPICSYSOP/
|
||||
/home/ftp/pub/fileecho/XPICWEAPON/
|
||||
/home/ftp/pub/files/uue_files/
|
||||
/home/ftp/pub/redhat-5.2/RedHat/RPMS/
|
||||
/home/ftp/pub/redhat-6.1/RedHat/RPMS/
|
||||
@@ -0,0 +1,163 @@
|
||||
|
||||
import gdbm
|
||||
import string
|
||||
import os
|
||||
import ufido
|
||||
|
||||
ALIAS_TYPE_NORMAL = 1 # Traditional aliase
|
||||
ALIAS_TYPE_MAGIC = 2 # "Magic" alias
|
||||
|
||||
# TODO: These functions must generate an exception in case of errors
|
||||
def get_bool(str):
|
||||
str = string.lower(str)
|
||||
if str == 'yes' or str == 'true':
|
||||
return 1
|
||||
elif str == 'no' or str == 'false':
|
||||
return 0
|
||||
return None
|
||||
|
||||
def get_size(str):
|
||||
# TODO: support nice size formats like 64M, 10G
|
||||
return str
|
||||
|
||||
def get_alias(str, type):
|
||||
args = string.split(str)
|
||||
if len(args) < 2 or len(args) > 3:
|
||||
return None
|
||||
if len(args) == 3:
|
||||
passwd = args[2]
|
||||
else:
|
||||
passwd = None
|
||||
return Alias(args[0], args[1], passwd, type)
|
||||
|
||||
class Alias:
|
||||
""" Aliases implementation
|
||||
"""
|
||||
def __init__(self, name, filename, passwd, type):
|
||||
""" Alias initialisation
|
||||
"""
|
||||
self.name = name
|
||||
self.filename = filename
|
||||
self.type = type
|
||||
|
||||
def get(self, passwd):
|
||||
""" Get the list of files to send for this alias
|
||||
"""
|
||||
yield = []
|
||||
if self.type == ALIAS_TYPE_NORMAL:
|
||||
yield.append(self.filename)
|
||||
return yield
|
||||
elif self.type == ALIAS_TYPE_MAGIC:
|
||||
# Prepare the environment (TODO)
|
||||
putenv('PASSWORD', passwd)
|
||||
putenv('ADDRESS', None)
|
||||
putenv('PROTECTED', 'FALSE')
|
||||
putenv('LISTED', 'FALSE')
|
||||
# Execute magic program and process its output
|
||||
try:
|
||||
magic = popen(self.filename)
|
||||
line = magic.readline()
|
||||
while line:
|
||||
line = magic.readline()
|
||||
yield.append(string.strip(line))
|
||||
if magic.close():
|
||||
print "Magic return code is non-zero: ", self.filename
|
||||
return None
|
||||
return yield
|
||||
except IOError:
|
||||
print "Failed to run magic: ", self.filename
|
||||
return None
|
||||
|
||||
class Config:
|
||||
def read_dir_list(self):
|
||||
yield = []
|
||||
fp = open(self.dir_list_file, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
if line != '':
|
||||
yield.append(line)
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return yield
|
||||
|
||||
def read_alias_list(self):
|
||||
yield = []
|
||||
fp = open(self.alias_list_file, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
if line != '':
|
||||
[name, filename] = string.split(line, None, 1)
|
||||
yield.append(alias(name, filename))
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return yield
|
||||
|
||||
def read(self, name):
|
||||
fp = open(name, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
args = string.split(line, None, 1)
|
||||
if line[0:1] == '#' or len(line) == 0:
|
||||
pass
|
||||
elif len(args) != 2:
|
||||
print "Invalid string in config: ", line
|
||||
else:
|
||||
key = string.lower(args[0])
|
||||
val = args[1]
|
||||
if key == 'dir-list-file':
|
||||
self.dir_list_file = val
|
||||
elif key == 'send-report':
|
||||
self.send_report = get_bool(val)
|
||||
elif key == 'limit-size-day':
|
||||
self.limit_size_day = get_size(val)
|
||||
elif key == 'limit-size-week':
|
||||
self.limit_size_week = get_size(val)
|
||||
elif key == 'limit-size-month':
|
||||
self.limit_size_month = get_size(val)
|
||||
elif key == 'spool-dir':
|
||||
self.spool_dir = val
|
||||
elif key == 'freq-alias':
|
||||
self.freq_alias.append(get_alias(val, ALIAS_TYPE_NORMAL))
|
||||
elif key == 'freq-magic':
|
||||
self.freq_magic.append(get_alias(val, ALIAS_TYPE_MAGIC))
|
||||
elif key == 'log-file':
|
||||
self.log_file = val
|
||||
elif key == 'local-address':
|
||||
self.local_address.parse(var)
|
||||
elif key == 'report-header':
|
||||
self.report_header = val
|
||||
elif key == 'report-footer':
|
||||
self.report_footer = val
|
||||
elif key == 'report-from':
|
||||
self.report_from = val
|
||||
elif key == 'report-subj':
|
||||
self.report_subj = val
|
||||
elif key == 'stat-dbase':
|
||||
self.stat_dbase = val
|
||||
else:
|
||||
print "unknown config keyword:", key
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
|
||||
def __init__(self, name):
|
||||
self.dir_list_file = ''
|
||||
self.send_report = 0
|
||||
self.limit_size_day = 0
|
||||
self.limit_size_week = 0
|
||||
self.limit_size_month = 0
|
||||
self.spool_dir = ''
|
||||
self.freq_policy = ''
|
||||
self.freq_alias = []
|
||||
self.freq_magic = []
|
||||
self.log_file = ''
|
||||
self.local_address = ufido.address()
|
||||
self.report_header = ''
|
||||
self.report_footer = ''
|
||||
self.report_from = 'FREQ manager'
|
||||
self.report_subj = 'FREQ report'
|
||||
self.stat_dbase = None
|
||||
self.read(name)
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
|
||||
import os
|
||||
import gdbm
|
||||
import string
|
||||
|
||||
def get_file_desc(filename):
|
||||
path, name = os.path.split(filename)
|
||||
descname = os.path.join(path, '.desc', name + '.desc')
|
||||
if not os.path.isfile(descname):
|
||||
return None
|
||||
try:
|
||||
fp = open(descname, 'r')
|
||||
except IOError:
|
||||
print 'Cannot open', descname
|
||||
return None
|
||||
line = fp.readline()
|
||||
yield = ''
|
||||
while line:
|
||||
yield = yield + line
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return string.strip(yield)
|
||||
|
||||
def get_area_desc(areapath):
|
||||
descname = os.path.join(areapath, '.desc', '.desc')
|
||||
if not os.path.isfile(descname):
|
||||
return None
|
||||
try:
|
||||
fp = open(descname, 'r')
|
||||
except IOError:
|
||||
print 'Cannot open', descname
|
||||
return None
|
||||
line = fp.readline()
|
||||
yield = ''
|
||||
while line:
|
||||
yield = yield + line
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return string.strip(yield)
|
||||
|
||||
class file:
|
||||
def stat(self):
|
||||
if self.fake:
|
||||
return
|
||||
try:
|
||||
statinfo = os.stat(self.fullname)
|
||||
self.size = statinfo[6]
|
||||
self.time = statinfo[8]
|
||||
except OSError:
|
||||
self.size = -1
|
||||
self.time = -1
|
||||
self.desc = 'File is not accessable'
|
||||
|
||||
def set(self, fullname, name = None, area = '', dlcnt = 0,\
|
||||
mode = '', desc = '', fake = 0):
|
||||
if name == None:
|
||||
self.name = os.path.split(fullname)[1]
|
||||
else:
|
||||
self.name = name
|
||||
self.fullname = fullname
|
||||
self.dlcnt = dlcnt
|
||||
self.size = -1
|
||||
self.time = -1
|
||||
self.area = area
|
||||
self.mode = mode
|
||||
self.desc = desc
|
||||
self.fake = fake
|
||||
|
||||
def reset(self):
|
||||
self.name = ''
|
||||
self.fullname = ''
|
||||
self.area = ''
|
||||
self.dlcnt = 0
|
||||
self.mode = ''
|
||||
self.desc = ''
|
||||
self.size = -1
|
||||
self.time = -1
|
||||
self.fake = 0
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
class filebase:
|
||||
""" Index entry format: [fullname, area, dlcnt, accessmode, desc]
|
||||
"""
|
||||
def open(self, mode):
|
||||
self.db = gdbm.open(self.dbfile, mode)
|
||||
|
||||
def close(self):
|
||||
self.db.close()
|
||||
|
||||
def sync(self):
|
||||
self.db.sync()
|
||||
|
||||
def clean(self):
|
||||
for filename in self.db.keys():
|
||||
file = self.get(filename)
|
||||
if not os.path.isfile(file.fullname):
|
||||
print 'Remove file "%s" from index' % file.fullname
|
||||
del self.db[filename]
|
||||
|
||||
def get_all(self, filenames):
|
||||
""" Lookup files in the database and return list
|
||||
of file objects
|
||||
"""
|
||||
yield = []
|
||||
for name in filenames:
|
||||
files = self.get(name)
|
||||
if files and len(files) > 0:
|
||||
yield.extend(files)
|
||||
return yield
|
||||
|
||||
def get(self, filename):
|
||||
""" Lookup file by its name in the database and
|
||||
return list of file objects for this name
|
||||
"""
|
||||
yield = []
|
||||
if not self.db.has_key(filename):
|
||||
return None
|
||||
files_info = eval(self.db[filename])
|
||||
if files_info == None:
|
||||
newfile = file()
|
||||
newfile.set(filename, desc='File not found', fake=1)
|
||||
yield.append(newfile)
|
||||
else:
|
||||
for finfo in files_info:
|
||||
newfile = file()
|
||||
finfo = eval(finfo)
|
||||
newfile.set(finfo[0], area = finfo[1],\
|
||||
dlcnt = finfo[2], mode = finfo[3],\
|
||||
desc = finfo[4])
|
||||
yield.append(newfile)
|
||||
return yield
|
||||
|
||||
def put(self, file):
|
||||
finfo = []
|
||||
finfo.append(file.fullname)
|
||||
finfo.append(file.area)
|
||||
finfo.append(file.dlcnt)
|
||||
finfo.append(file.mode)
|
||||
finfo.append(file.desc)
|
||||
if self.db.has_key(file.name):
|
||||
files_info = eval(self.db[file.name])
|
||||
else:
|
||||
files_info = []
|
||||
files_info.append(repr(finfo))
|
||||
self.db[file.name] = repr(files_info)
|
||||
|
||||
def __init__(self, spooldir):
|
||||
self.dbfile = os.path.join(spooldir, 'filebase.db')
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
|
||||
import string
|
||||
import re
|
||||
import struct
|
||||
import time
|
||||
|
||||
#address_1 = re.compile('^\([0-9]+\):\([0-9]+\)/\([0-9]+\)\.?\([0-9]+\)?$')
|
||||
address_1 = re.compile('^(\d+):(\d+)/(\d+)\.?(\d+)?$')
|
||||
|
||||
months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\
|
||||
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Jan')
|
||||
|
||||
class address:
|
||||
def is_set(self):
|
||||
if self.zone > 0 and self.net > 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def string(self):
|
||||
if self.invalid:
|
||||
yield = 'Invalid address'
|
||||
elif self.point > 0:
|
||||
yield = '%d:%d/%d.%d' % (self.zone, self.net, self.node, self.point)
|
||||
else:
|
||||
yield = '%d:%d/%d' % (self.zone, self.net, self.node)
|
||||
return yield
|
||||
|
||||
def parse(self, str):
|
||||
match = address_1.match(str)
|
||||
if match:
|
||||
try:
|
||||
self.zone = string.atoi(match.group(1))
|
||||
self.net = string.atoi(match.group(2))
|
||||
self.node = string.atoi(match.group(3))
|
||||
tmp = match.group(4)
|
||||
if tmp and tmp != '-1':
|
||||
self.point = string.atoi(tmp)
|
||||
else:
|
||||
self.point = 0
|
||||
self.invalid = 0
|
||||
except IndexError:
|
||||
self.__init__()
|
||||
return -1
|
||||
else:
|
||||
print "Regexp doesnt match!"
|
||||
return -1
|
||||
return 0
|
||||
|
||||
def __init__(self):
|
||||
self.zone = 0
|
||||
self.net = 0
|
||||
self.node = 0
|
||||
self.point = 0
|
||||
self.invalid = 1
|
||||
|
||||
class message:
|
||||
def newmsg(self, addr_from, user_from, addr_to, user_to, subject):
|
||||
self.unix_time = time.time()
|
||||
self.addr_orig = addr_from
|
||||
self.addr_dest = addr_to
|
||||
self.user_orig = user_from
|
||||
self.user_dest = user_to
|
||||
self.subject = subject
|
||||
self.msgbody = ''
|
||||
self.append_line('\001FMPT %d' % self.addr_orig.point)
|
||||
self.append_line('\001TOPT %d' % self.addr_dest.point)
|
||||
|
||||
def append_line(self, string):
|
||||
self.msgbody = self.msgbody + string + '\r'
|
||||
|
||||
def append_text(self, text):
|
||||
for line in string.split(text, '\n'):
|
||||
self.append_line(line)
|
||||
|
||||
def append_file(self, filename):
|
||||
try:
|
||||
fp = open(filename, 'r')
|
||||
except IOError:
|
||||
print 'Cannot append file', filename
|
||||
return
|
||||
line = fp.readline()
|
||||
while line:
|
||||
self.append_line(string.rstrip(line))
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
|
||||
def __init__(self):
|
||||
self.unix_time = 0
|
||||
self.addr_orig = address()
|
||||
self.addr_dest = address()
|
||||
self.user_orig = ''
|
||||
self.user_dest = ''
|
||||
self.subject = ''
|
||||
self.msgbody = ''
|
||||
self.origin = ''
|
||||
|
||||
class packet:
|
||||
def reset(self):
|
||||
self.addr_orig = address()
|
||||
self.addr_dest = address()
|
||||
self.password = ''
|
||||
self.messages = []
|
||||
|
||||
# TODO
|
||||
def read(self, filename):
|
||||
self.reset()
|
||||
fp = open(filename, "w")
|
||||
fp.close()
|
||||
|
||||
def get_time_string(self, unix_time):
|
||||
msgtime = time.localtime(unix_time)
|
||||
return '%02d %s %02d %02d:%02d:%02d' % \
|
||||
(msgtime[2], months[msgtime[1]], msgtime[0] % 100, \
|
||||
msgtime[3], msgtime[4], msgtime[5])
|
||||
|
||||
def get_message_header(self, message):
|
||||
return struct.pack('7H20s',\
|
||||
2,\
|
||||
message.addr_orig.node,\
|
||||
message.addr_dest.node,\
|
||||
message.addr_orig.net,\
|
||||
message.addr_dest.net,\
|
||||
0,\
|
||||
0,\
|
||||
self.get_time_string(message.unix_time)) + \
|
||||
message.user_dest[0:36] + '\0' + \
|
||||
message.user_orig[0:36] + '\0' + \
|
||||
message.subject[0:72] + '\0'
|
||||
|
||||
def get_packet_header(self):
|
||||
now = time.localtime(time.time())
|
||||
return struct.pack('13H8s12H',\
|
||||
self.addr_orig.node,\
|
||||
self.addr_dest.node,\
|
||||
now[0], # Year\
|
||||
now[1], # Month\
|
||||
now[2], # Day\
|
||||
now[3], # Hour\
|
||||
now[4], # Minute\
|
||||
now[5], # Second\
|
||||
9600, # Baud\
|
||||
2, # PKT type\
|
||||
self.addr_orig.net,\
|
||||
self.addr_dest.net,\
|
||||
254, # Prod. code + Rev. number\
|
||||
self.password,\
|
||||
self.addr_orig.zone,\
|
||||
self.addr_dest.zone,\
|
||||
0, # AuxNet\
|
||||
0, # CWvalidationCopy\
|
||||
0, # ProductCode + Revision \
|
||||
0, # CapabilWord\
|
||||
self.addr_orig.zone,\
|
||||
self.addr_dest.zone,\
|
||||
self.addr_orig.point,\
|
||||
self.addr_dest.point,\
|
||||
0,
|
||||
0)
|
||||
|
||||
def write(self, filename):
|
||||
fp = open(filename, "w")
|
||||
fp.write(self.get_packet_header())
|
||||
|
||||
for msg in self.messages:
|
||||
fp.write(self.get_message_header(msg))
|
||||
fp.write(msg.msgbody)
|
||||
fp.write('\0')
|
||||
|
||||
fp.write('\0\0')
|
||||
fp.close()
|
||||
|
||||
def add_message(self, message):
|
||||
self.messages.append(message)
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
if __name__ == "__main__":
|
||||
tmp = address()
|
||||
tmp.parse('2:5020/2120')
|
||||
print tmp.string()
|
||||
@@ -0,0 +1,102 @@
|
||||
import time
|
||||
import gdbm
|
||||
import ufido
|
||||
|
||||
class nodestat:
|
||||
""" [[month_id, month_size, month_num, month_time],
|
||||
[week_id, seek_size, week_num, week_time],
|
||||
[day_id, day_size, day_num, day_time],
|
||||
[total_size, total_num, total_time]]
|
||||
"""
|
||||
def __init__(self, dbpath, address):
|
||||
self.addr = address
|
||||
self.key = address.string()
|
||||
self.stat_session_size = 0
|
||||
self.stat_session_num = 0
|
||||
self.stat_session_time = 0
|
||||
self.stat_day_size = 0
|
||||
self.stat_day_num = 0
|
||||
self.stat_day_time = 0
|
||||
self.stat_week_size = 0
|
||||
self.stat_week_num = 0
|
||||
self.stat_week_time = 0
|
||||
self.stat_month_size = 0
|
||||
self.stat_month_num = 0
|
||||
self.stat_month_time = 0
|
||||
self.stat_total_size = 0
|
||||
self.stat_total_num = 0
|
||||
self.stat_total_time = 0
|
||||
self.dbpath = dbpath
|
||||
tt = time.localtime()
|
||||
self.month_id = time.strftime('%Y%m', tt)
|
||||
self.week_id = time.strftime('%Y%W', tt)
|
||||
self.day_id = time.strftime('%Y%j', tt)
|
||||
self.notexist = 0 # Entry for this node doesn't exist yet?
|
||||
|
||||
def upd_stat(self, num, size):
|
||||
self.stat_session_size = self.stat_session_size + size
|
||||
self.stat_session_num = self.stat_session_num + num
|
||||
self.stat_month_size = self.stat_month_size + size
|
||||
self.stat_month_num = self.stat_month_num + num
|
||||
self.stat_week_size = self.stat_week_size + size
|
||||
self.stat_week_num = self.stat_week_num + num
|
||||
self.stat_day_size = self.stat_day_size + size
|
||||
self.stat_day_num = self.stat_day_num + num
|
||||
self.stat_total_size = self.stat_total_size + size
|
||||
self.stat_total_num = self.stat_total_num + num
|
||||
|
||||
def get_stat(self):
|
||||
try:
|
||||
db = gdbm.open(self.dbpath, 'r')
|
||||
except gdbm.error:
|
||||
return 0
|
||||
if not db.has_key(self.key):
|
||||
self.notexist = 1
|
||||
db.close()
|
||||
return 0
|
||||
entry = eval(db[self.key])
|
||||
# Check month statistic
|
||||
if entry[0][0] == self.month_id:
|
||||
self.stat_month_size = entry[0][1]
|
||||
self.stat_month_num = entry[0][2]
|
||||
self.stat_month_time = entry[0][3]
|
||||
# Check week statistic
|
||||
if entry[1][0] == self.week_id:
|
||||
self.stat_week_size = entry[1][1]
|
||||
self.stat_week_num = entry[1][2]
|
||||
self.stat_week_time = entry[1][3]
|
||||
# Check day statistic
|
||||
if entry[2][0] == self.day_id:
|
||||
self.stat_day_size = entry[2][1]
|
||||
self.stat_day_num = entry[2][2]
|
||||
self.stat_day_time = entry[2][3]
|
||||
# Get total statistic
|
||||
self.stat_total_size = entry[3][0]
|
||||
self.stat_total_num = entry[3][1]
|
||||
self.stat_total_time = entry[3][2]
|
||||
db.close()
|
||||
return 0
|
||||
|
||||
def put_stat(self):
|
||||
db = gdbm.open(self.dbpath, 'cf')
|
||||
# Don't handle exceptions
|
||||
entry = [[self.month_id, self.stat_month_size, self.stat_month_num, self.stat_month_time],
|
||||
[self.week_id, self.stat_week_size, self.stat_week_num, self.stat_week_time],
|
||||
[self.day_id, self.stat_day_size, self.stat_day_num, self.stat_day_time],
|
||||
[self.stat_total_size, self.stat_total_num, self.stat_total_time]]
|
||||
db[self.key] = repr(entry)
|
||||
db.close()
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
addr = ufido.address()
|
||||
addr.parse('2:5020/2120')
|
||||
ns = nodestat('./tmp.db', addr)
|
||||
ns.upd_stat(2, 32768)
|
||||
ns.put_stat()
|
||||
addr2 = ufido.address()
|
||||
addr2.parse('2:5020/2120')
|
||||
ns2 = nodestat('./tmp.db', addr2)
|
||||
ns2.get_stat()
|
||||
print ns2.stat_total_num, ns2.stat_total_size
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import string
|
||||
|
||||
class template:
|
||||
def __init__(self):
|
||||
self.local_address = ''
|
||||
self.local_sysop = ''
|
||||
self.local_location = ''
|
||||
self.local_phone = ''
|
||||
self.remote_address = ''
|
||||
self.remote_sysop = ''
|
||||
self.remote_location = ''
|
||||
self.remote_phone = ''
|
||||
self.remote_cid = ''
|
||||
self.limit_size_day = -1
|
||||
self.limit_size_week = -1
|
||||
self.limit_size_month = -1
|
||||
self.sent_size_day = -1
|
||||
self.sent_size_week = -1
|
||||
self.sent_size_month = -1
|
||||
self.sent_size = -1
|
||||
self.conn_speed = -1
|
||||
self.text = None
|
||||
|
||||
def set(self, srif=None, conf=None, nodestat=None):
|
||||
if srif:
|
||||
self.remote_address = srif.aka.string()
|
||||
self.remote_sysop = srif.sysop
|
||||
self.remote_location = srif.site
|
||||
self.remote_cid = srif.callerid
|
||||
self.conn_speed = srif.baud
|
||||
if conf:
|
||||
self.local_address = conf.local_address.string()
|
||||
self.limit_size_day = conf.limit_size_day
|
||||
self.limit_size_week = conf.limit_size_week
|
||||
self.limit_size_month = conf.limit_size_month
|
||||
if nodestat:
|
||||
self.sent_session_size = nodestat.stat_session_size
|
||||
self.sent_session_num = nodestat.stat_session_num
|
||||
self.sent_day_size = nodestat.stat_day_size
|
||||
self.sent_day_num = nodestat.stat_day_num
|
||||
self.sent_week_size = nodestat.stat_week_size
|
||||
self.sent_week_num = nodestat.stat_week_num
|
||||
self.sent_month_size = nodestat.stat_month_size
|
||||
self.sent_month_num = nodestat.stat_month_num
|
||||
self.sent_total_size = nodestat.stat_total_size
|
||||
self.sent_total_num = nodestat.stat_total_num
|
||||
|
||||
def __cmd__(self, str):
|
||||
try:
|
||||
[fmt, arg] = string.split(str, ',', 1)
|
||||
return eval('"' + fmt + '" % self.' + arg)
|
||||
except ValueError:
|
||||
return '@ValueError@'
|
||||
except AttributeError:
|
||||
return '@AttributeError@'
|
||||
|
||||
def process(self, text=None):
|
||||
if text == None:
|
||||
text = self.text
|
||||
if text == None:
|
||||
return None
|
||||
pos = 0
|
||||
while 1:
|
||||
pos = string.find(text, '@', pos)
|
||||
if pos < 0:
|
||||
break
|
||||
end_pos = string.find(text, '@', pos+1)
|
||||
if end_pos < 0:
|
||||
break
|
||||
if end_pos - pos > 1:
|
||||
# Process escaped command
|
||||
replace = self.__cmd__(text[pos+1:end_pos])
|
||||
if replace:
|
||||
text = text[:pos]+replace+text[end_pos+1:]
|
||||
# Fix the current position
|
||||
pos = end_pos + len(replace)-(end_pos-pos+1)
|
||||
else:
|
||||
# Leave text untouched
|
||||
pos = end_pos + 1
|
||||
else:
|
||||
# Replace '@@' by the single '@'
|
||||
text = text[:pos+1]+text[pos+2:]
|
||||
pos = end_pos
|
||||
return text
|
||||
|
||||
def readfile(self, path):
|
||||
try:
|
||||
fp = open(path, 'r')
|
||||
self.text = fp.read()
|
||||
fp.close()
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
test = template()
|
||||
print test.process("'@@'\n'@@'\n'@%d,conn_speed@'\n'@@@'")
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
import string
|
||||
|
||||
# Header for the files information
|
||||
file_info_header = 'File Size Description\n'\
|
||||
+ '-' * 78
|
||||
|
||||
class ULog:
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.fp = open(path, 'a')
|
||||
|
||||
def puts(self, string):
|
||||
fp.puts(strftime('%b %d %H:%M:%S ', gmtime())+string)
|
||||
|
||||
def close(self):
|
||||
fp.close()
|
||||
|
||||
def format_desc(desc, offset, width=78):
|
||||
""" Format file's description
|
||||
"""
|
||||
yield = ''
|
||||
desc = string.expandtabs(desc, 1)
|
||||
for line in string.split(desc, '\n'):
|
||||
line = string.rstrip(line)
|
||||
if line == '':
|
||||
continue
|
||||
pos = 0
|
||||
endpos = width
|
||||
while line[pos:endpos]:
|
||||
if yield:
|
||||
yield = yield + '\n'
|
||||
yield = yield + offset * ' '
|
||||
yield = yield + line[pos:endpos]
|
||||
pos = endpos
|
||||
endpos = endpos + width
|
||||
return yield
|
||||
|
||||
def format_file_info(name, size, desc, line_length=78):
|
||||
""" Format file information to meet human requirements
|
||||
"""
|
||||
if size < 0:
|
||||
yield = '%-20s ' % name + 11 * ' '
|
||||
else:
|
||||
yield = '%-20s %-11d' % (name, size)
|
||||
if desc:
|
||||
offset = len(yield) + 1
|
||||
width = line_length - offset
|
||||
desc = format_desc(desc, offset, width)
|
||||
yield = yield + ' ' + string.lstrip(desc)
|
||||
else:
|
||||
yield = yield + ' Description not available'
|
||||
return yield
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
import posix
|
||||
import os
|
||||
import libconf
|
||||
import libfbase
|
||||
|
||||
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
|
||||
|
||||
##############################
|
||||
# The main program starts here
|
||||
|
||||
# Read configuration
|
||||
Conf = libconf.config(USRIF_CONFIG)
|
||||
|
||||
# Open files index for writing
|
||||
FBase = libfbase.filebase(Conf.spool_dir)
|
||||
FBase.open('cwf')
|
||||
|
||||
file = libfbase.file()
|
||||
|
||||
# Process aliases from 'alias-list-file'
|
||||
for alias in Conf.read_alias_list():
|
||||
print 'Processing alias "%s": %s' % (alias.name, alias.filename)
|
||||
file_desc = libfbase.get_file_desc(alias.filename)
|
||||
file.set(alias.filename, name = alias.name, desc = file_desc)
|
||||
file.stat()
|
||||
FBase.put(file)
|
||||
|
||||
# Process dirs from 'dir-list-file'
|
||||
for dir in Conf.read_dir_list():
|
||||
area_desc = libfbase.get_area_desc(dir)
|
||||
print 'Processing: %s (%s)' % (dir, area_desc)
|
||||
files_list = posix.listdir(dir)
|
||||
for file_name in files_list:
|
||||
full_name = os.path.join(dir, file_name)
|
||||
if os.path.isfile(full_name):
|
||||
file_desc = libfbase.get_file_desc(full_name)
|
||||
file.set(full_name, area = area_desc, desc = file_desc)
|
||||
file.stat()
|
||||
FBase.put(file)
|
||||
|
||||
# Purge files index
|
||||
#print 'Purging removed files from files index'
|
||||
#FBase.clean()
|
||||
|
||||
FBase.close()
|
||||
sys.exit(0)
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/local/bin/python
|
||||
|
||||
import sys
|
||||
|
||||
# Our own libraries
|
||||
sys.path.append('./lib')
|
||||
import uconfig
|
||||
import udbase
|
||||
from uutil import *
|
||||
|
||||
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
|
||||
|
||||
##############################
|
||||
# The main program starts here
|
||||
if len(sys.argv) < 2:
|
||||
print 'usage:', sys.argv[0], '<[file] [file] ..>'
|
||||
sys.exit(1)
|
||||
|
||||
# Read configuration
|
||||
Conf = uconfig.Config(USRIF_CONFIG)
|
||||
|
||||
# Lookup files in the database
|
||||
FBase = udbase.filebase(Conf.spool_dir)
|
||||
FBase.open('r')
|
||||
yield = FBase.get_all(sys.argv[1:])
|
||||
FBase.close()
|
||||
|
||||
# Pretty printing
|
||||
print file_info_header
|
||||
for file in yield:
|
||||
file.stat()
|
||||
print format_file_info(file.name, file.size, file.desc)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
#!/usr/local/bin/python
|
||||
|
||||
import string
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Our own libraries
|
||||
sys.path.append('./lib')
|
||||
import uconfig
|
||||
import udbase
|
||||
import ufido
|
||||
import utmpl
|
||||
import unodestat
|
||||
from uutil import *
|
||||
|
||||
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
|
||||
|
||||
class freq_report(ufido.message):
|
||||
def write_packet(self, pktname):
|
||||
self.packet.addr_orig = self.addr_orig
|
||||
self.packet.addr_dest = self.addr_dest
|
||||
self.packet.write(pktname)
|
||||
|
||||
def add_file(self, name, size, desc):
|
||||
text = format_file_info(name, size, desc)
|
||||
self.append_text(text)
|
||||
|
||||
def __init__(self):
|
||||
ufido.message.__init__(self)
|
||||
self.packet = ufido.packet()
|
||||
self.packet.add_message(self)
|
||||
|
||||
class srif_file:
|
||||
def read_req_list(self):
|
||||
yield = []
|
||||
fp = open(self.requestlist, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
yield.append(line)
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return yield
|
||||
|
||||
def write_resp_list(self, list):
|
||||
fp = open(self.responselist, 'w')
|
||||
for file in list:
|
||||
fp.write('+' + file + '\n')
|
||||
fp.close()
|
||||
|
||||
def read(self, name):
|
||||
fp = open(name, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
args = string.split(line, None, 1)
|
||||
if len(args) == 2:
|
||||
if string.lower(args[0]) == 'sysop':
|
||||
self.sysop = args[1]
|
||||
if string.lower(args[0]) == 'aka':
|
||||
self.aka.parse(args[1])
|
||||
elif string.lower(args[0]) == 'baud':
|
||||
self.baud = args[1]
|
||||
elif string.lower(args[0]) == 'requestlist':
|
||||
self.requestlist = args[1]
|
||||
elif string.lower(args[0]) == 'responselist':
|
||||
self.responselist = args[1]
|
||||
elif string.lower(args[0]) == 'remotestatus':
|
||||
self.remotestatus = args[1]
|
||||
elif string.lower(args[0]) == 'systemstatus':
|
||||
self.systemstatus = args[1]
|
||||
elif string.lower(args[0]) == 'site':
|
||||
self.site = args[1]
|
||||
elif string.lower(args[0]) == 'callerid':
|
||||
self.callerid = args[1]
|
||||
elif string.lower(args[0]) == 'password':
|
||||
self.password = args[1]
|
||||
else:
|
||||
print "skipping keyword", args[0], "in SRIF"
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
|
||||
def __init__(self, name):
|
||||
self.sysop = ''
|
||||
self.aka = ufido.address()
|
||||
self.baud = 0
|
||||
self.requestlist = ''
|
||||
self.responselist = ''
|
||||
self.remotestatus = ''
|
||||
self.systemstatus = ''
|
||||
self.site = ''
|
||||
self.callerid = ''
|
||||
self.password = ''
|
||||
self.read(name)
|
||||
|
||||
def remote_addr(self):
|
||||
return self.aka
|
||||
|
||||
def isprotected(self):
|
||||
if string.lower(self.remotestatus) == 'protected':
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def islisted(self):
|
||||
if string.lower(self.systemstatus) == 'listed':
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def append_new_file(fileslist, file):
|
||||
TotalFiles = TotalFiles + 1
|
||||
TotalSize = TotalSize + file.size
|
||||
fileslist.append(file.fullname)
|
||||
|
||||
##############################
|
||||
# The main program starts here
|
||||
|
||||
# Global variables
|
||||
yield_list = []
|
||||
|
||||
if len(sys.argv) <> 2:
|
||||
print 'usage: u-srif <srif file name>'
|
||||
sys.exit(1)
|
||||
|
||||
# Read configuration
|
||||
conf = uconfig.Config(USRIF_CONFIG)
|
||||
# Read SRIF files
|
||||
srif = srif_file(sys.argv[1])
|
||||
# Read node's statistic
|
||||
nodestat = unodestat.nodestat(conf.stat_dbase, srif.aka)
|
||||
nodestat.get_stat()
|
||||
|
||||
# Lookup requested files in the our database
|
||||
FBase = udbase.filebase(conf.spool_dir)
|
||||
FBase.open('r')
|
||||
yield = FBase.get_all(srif.read_req_list())
|
||||
FBase.close()
|
||||
|
||||
# Prepare found files for sending
|
||||
for file in yield:
|
||||
if not file.fake:
|
||||
file.stat()
|
||||
nodestat.upd_stat(1, file.size)
|
||||
yield_list.append(file.fullname)
|
||||
|
||||
# Store node's statistic
|
||||
nodestat.put_stat()
|
||||
|
||||
# Send FREQ report?
|
||||
if conf.send_report:
|
||||
# Prepare templates object
|
||||
tmpl = utmpl.template()
|
||||
tmpl.set(srif=srif, conf=conf, nodestat=nodestat)
|
||||
# Setup report object
|
||||
report = freq_report()
|
||||
report.newmsg(conf.local_address, conf.report_from, \
|
||||
srif.aka, srif.sysop, conf.report_subj)
|
||||
report.append_line('')
|
||||
# Append header
|
||||
tmpl.readfile(conf.report_header)
|
||||
text = tmpl.process()
|
||||
if text:
|
||||
report.append_text(text)
|
||||
# Append per files statistic
|
||||
for file in yield:
|
||||
report.add_file(file.name, file.size, file.desc)
|
||||
# Append footer
|
||||
tmpl.readfile(conf.report_footer)
|
||||
text = tmpl.process()
|
||||
if text:
|
||||
report.append_text(text)
|
||||
# Add empty line to the report
|
||||
report.append_line('')
|
||||
# Create netmail packet with the FREQ report
|
||||
pktname = '/var/tmp/12345678.pkt' # XXX
|
||||
report.write_packet(pktname)
|
||||
# Add packet file to the response files list
|
||||
yield_list.append(pktname)
|
||||
|
||||
# Dump reponse list
|
||||
srif.write_resp_list(yield_list)
|
||||
sys.exit(0)
|
||||
|
||||
Reference in New Issue
Block a user