ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | |
51f590 | 2000-09-27 | Per Hedbor | | * $Id: Roxen.pmod,v 1.42 2000/09/26 23:12:10 per Exp $
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | *
* Various helper functions.
*
* Henrik Grubbström 1999-05-03
*/
|
69e4cd | 2000-03-09 | Martin Stjernholm | | #include <config.h>
|
88bff1 | 2000-09-12 | Per Hedbor | | #include <version.h>
|
69e4cd | 2000-03-09 | Martin Stjernholm | | inherit "roxenlib";
|
796fb6 | 2000-08-12 | Per Hedbor | |
#if constant( _Roxen )
inherit _Roxen;
#endif
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
#ifdef QUOTA_DEBUG
#define QD_WRITE(X) werror(X)
#else /* !QUOTA_DEBUG */
#define QD_WRITE(X)
#endif /* QUOTA_DEBUG */
|
7e9a0b | 2000-09-16 | Per Hedbor | | #undef CACHE
#undef NOCACHE
#define CACHE(id,X) ([mapping(string:mixed)]id->misc)->cacheable=min(([mapping(string:mixed)]id->misc)->cacheable,X)
#define NOCACHE(id) ([mapping(string:mixed)]id->misc)->cacheable=0
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | class QuotaDB
{
#if constant(create_thread)
object(Thread.Mutex) lock = Thread.Mutex();
|
2543b7 | 2000-07-02 | Henrik Grubbström (Grubba) | | #define LOCK() mixed key__; catch { key__ = lock->lock(); }
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | #define UNLOCK() do { if (key__) destruct(key__); } while(0)
#else /* !constant(create_thread) */
#define LOCK()
#define UNLOCK()
#endif /* constant(create_thread) */
constant READ_BUF_SIZE = 256;
constant CACHE_SIZE_LIMIT = 512;
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | string base;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | object catalog_file;
object data_file;
mapping(string:int) new_entries_cache = ([]);
mapping(string:object) active_objects = ([]);
array(int) index;
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | array(string) index_acc;
int acc_scale;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
int next_offset;
static class QuotaEntry
{
string name;
int data_offset;
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | static int usage;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | static int quota;
static void store()
{
LOCK();
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaEntry::store(): Usage for %O is now %O(%O)\n",
name, usage, quota));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
data_file->seek(data_offset);
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | data_file->write(sprintf("%4c", usage));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
UNLOCK();
}
static void read()
{
LOCK();
data_file->seek(data_offset);
string s = data_file->read(4);
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | usage = 0;
sscanf(s, "%4c", usage);
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
|
01f680 | 1999-06-20 | Henrik Grubbström (Grubba) | | if (usage < 0) {
usage = 0;
}
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaEntry::read(): Usage for %O is %O(%O)\n",
name, usage, quota));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
UNLOCK();
}
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | void create(string n, int d_o, int q)
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | {
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaEntry(%O, %O, %O)\n", n, d_o, q));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
name = n;
data_offset = d_o;
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | quota = q;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
read();
}
int check_quota(string uri, int amount)
{
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaEntry::check_quota(%O, %O): usage:%d(%d)\n",
uri, amount, usage, quota));
if (!quota) {
return 0;
}
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
if (amount == 0x7fffffff) {
return 1;
}
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | return(usage + amount <= quota);
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
int allocate(string uri, int amount)
{
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaEntry::allocate(%O, %O): usage:%d => %d(%d)\n",
uri, amount, usage, usage + amount, quota));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | usage += amount;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
|
01f680 | 1999-06-20 | Henrik Grubbström (Grubba) | | if (usage < 0) {
usage = 0;
}
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | store();
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | return(usage <= quota);
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
int deallocate(string uri, int amount)
{
return(allocate(uri, -amount));
}
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | int get_usage(string uri)
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | {
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | return usage;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | void set_usage(string uri, int amount)
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | {
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | usage = amount;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
store();
}
#if !constant(set_weak_flag)
static int refs;
void add_ref()
{
refs++;
}
void free_ref()
{
if (!(--refs)) {
destruct();
}
}
}
static class QuotaProxy
{
static object(QuotaEntry) master;
function(string, int:int) check_quota;
function(string, int:int) allocate;
function(string, int:int) deallocate;
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | function(string, int:void) set_usage;
function(string:int) get_usage;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
void create(object(QuotaEntry) m)
{
master = m;
master->add_ref();
check_quota = master->check_quota;
allocate = master->allocate;
deallocate = master->deallocate;
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | set_usage = master->set_usage;
get_usage = master->get_usage;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
void destroy()
{
master->free_ref();
}
#endif /* !constant(set_weak_flag) */
}
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | static object read_entry(int offset, int|void quota)
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | {
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaDB::read_entry(%O, %O)\n", offset, quota));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
catalog_file->seek(offset);
string data = catalog_file->read(READ_BUF_SIZE);
if (data == "") {
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaDB::read_entry(%O, %O): At EOF\n",
offset, quota));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
return 0;
}
int len;
int data_offset;
string key;
sscanf(data[..7], "%4c%4c", len, data_offset);
if (len > sizeof(data)) {
key = data[8..] + catalog_file->read(len - sizeof(data));
len -= 8;
if (sizeof(key) != len) {
error(sprintf("Failed to read catalog entry at offset %d.\n"
"len: %d, sizeof(key):%d\n",
offset, len, sizeof(key)));
}
} else {
key = data[8..len-1];
|
6fa7e8 | 1999-05-14 | Henrik Grubbström (Grubba) | | catalog_file->seek(offset + 8 + sizeof(key));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | return QuotaEntry(key, data_offset, quota);
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
static object open(string fname, int|void create_new)
{
object f = Stdio.File();
string mode = create_new?"rwc":"rw";
if (!f->open(fname, mode)) {
error(sprintf("Failed to open quota file %O.\n", fname));
}
if (f->try_lock && !f->try_lock()) {
error(sprintf("Failed to lock quota file %O.\n", fname));
}
return(f);
}
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | static void init_index_acc()
{
acc_scale = 1;
if (sizeof(index)) {
int i = sizeof(index)/2;
while (i) {
i /= 4;
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | | acc_scale *= 2;
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | }
}
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | | index_acc = allocate((sizeof(index) + acc_scale -1)/acc_scale);
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | |
QD_WRITE(sprintf("QuotaDB()::init_index_acc(): "
"sizeof(index):%d, sizeof(index_acc):%d acc_scale:%d\n",
sizeof(index), sizeof(index_acc), acc_scale));
}
|
1a7b00 | 1999-05-14 | Henrik Grubbström (Grubba) | | void rebuild_index()
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | {
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | array(string) new_keys = sort(indices(new_entries_cache));
int prev;
array(int) new_index = ({});
foreach(new_keys, string key) {
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaDB::rebuild_index(): key:%O lo:0 hi:%d\n",
key, sizeof(index_acc)));
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | int lo;
int hi = sizeof(index_acc);
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | if (hi) {
do {
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | |
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | int probe = (lo + hi)/2;
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaDB::rebuild_index(): acc: "
"key:%O lo:%d probe:%d hi:%d\n",
key, lo, probe, hi));
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | if (!index_acc[probe]) {
object e = read_entry(index[probe * acc_scale]);
index_acc[probe] = e->name;
}
if (index_acc[probe] < key) {
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | lo = probe + 1;
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | } else if (index_acc[probe] > key) {
hi = probe;
} else {
break;
}
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | } while(lo < hi);
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | |
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | if (lo < hi) {
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | |
continue;
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | }
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | | if (hi) {
hi *= acc_scale;
lo = hi - acc_scale;
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | |
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | | if (hi > sizeof(index)) {
hi = sizeof(index);
}
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | |
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | | do {
int probe = (lo + hi)/2;
QD_WRITE(sprintf("QuotaDB::rebuild_index(): "
"key:%O lo:%d probe:%d hi:%d\n",
key, lo, probe, hi));
object e = read_entry(index[probe]);
if (e->name < key) {
lo = probe + 1;
} else if (e->name > key) {
hi = probe;
} else {
break;
}
} while (lo < hi);
if (lo < hi) {
continue;
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | }
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | }
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | new_index += index[prev..hi-1] + ({ new_entries_cache[key] });
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | prev = hi;
} else {
new_index += ({ new_entries_cache[key] });
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | }
}
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | |
new_index += index[prev..];
QD_WRITE("Index rebuilt.\n");
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | LOCK();
object index_file = open(base + ".index.new", 1);
string to_write = sprintf("%@4c", new_index);
if (index_file->write(to_write) != sizeof(to_write)) {
index_file->close();
rm(base + ".index.new");
} else {
mv(base + ".index.new", base + ".index");
}
index = new_index;
init_index_acc();
UNLOCK();
foreach(new_keys, string key) {
m_delete(new_entries_cache, key);
}
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | static object low_lookup(string key, int quota)
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | {
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaDB::low_lookup(%O, %O)\n", key, quota));
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | int cat_offset;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | if (!zero_type(cat_offset = new_entries_cache[key])) {
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaDB::low_lookup(%O, %O): "
"Found in new entries cache.\n", key, quota));
return read_entry(cat_offset, quota);
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | }
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | |
int lo;
int hi = sizeof(index_acc);
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | if (hi) {
do {
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | |
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | int probe = (lo + hi)/2;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaDB:low_lookup(%O): "
"In acc: lo:%d, probe:%d, hi:%d\n",
key, lo, probe, hi));
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | if (!index_acc[probe]) {
object e = read_entry(index[probe * acc_scale], quota);
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | |
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | index_acc[probe] = e->name;
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | |
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | if (key == e->name) {
QD_WRITE(sprintf("QuotaDB:low_lookup(%O): In acc: Found at %d\n",
key, probe * acc_scale));
return e;
}
}
if (index_acc[probe] < key) {
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | lo = probe + 1;
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | } else if (index_acc[probe] > key) {
hi = probe;
} else {
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | QD_WRITE(sprintf("QuotaDB:low_lookup(%O): In acc: Found at %d\n",
key, probe * acc_scale));
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | return read_entry(index[probe * acc_scale], quota);
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | }
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | } while(lo < hi);
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | if (hi) {
hi *= acc_scale;
lo = hi - acc_scale;
|
8b5f0c | 1999-05-16 | Henrik Grubbström (Grubba) | |
if (hi > sizeof(index)) {
hi = sizeof(index);
}
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | do {
int probe = (lo + hi)/2;
QD_WRITE(sprintf("QuotaDB:low_lookup(%O): lo:%d, probe:%d, hi:%d\n",
key, lo, probe, hi));
object e = read_entry(index[probe], quota);
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | |
|
366b79 | 1999-05-16 | Henrik Grubbström (Grubba) | | if (e->name < key) {
lo = probe + 1;
} else if (e->name > key) {
hi = probe;
} else {
QD_WRITE(sprintf("QuotaDB:low_lookup(%O): Found at %d\n",
key, probe));
return e;
}
} while (lo < hi);
}
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | }
QD_WRITE(sprintf("QuotaDB::low_lookup(%O): Not found\n", key));
return 0;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
object lookup(string key, int quota)
{
QD_WRITE(sprintf("QuotaDB::lookup(%O, %O)\n", key, quota));
LOCK();
object res;
if (res = active_objects[key]) {
QD_WRITE(sprintf("QuotaDB::lookup(%O, %O): User in active objects.\n",
key, quota));
#if constant(set_weak_flag)
return res;
#else /* !constant(set_weak_flag) */
return QuotaProxy(res);
#endif /* constant(set_weak_flag) */
}
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | if (res = low_lookup(key, quota)) {
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | active_objects[key] = res;
#if constant(set_weak_flag)
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | return res;
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | #else /* !constant(set_weak_flag) */
return QuotaProxy(res);
#endif /* constant(set_weak_flag) */
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
QD_WRITE(sprintf("QuotaDB::lookup(%O, %O): New user.\n", key, quota));
data_file->seek(-1);
data_file->read(1);
catalog_file->seek(next_offset);
int data_offset = data_file->tell();
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | if (data_file->write(sprintf("%4c", 0)) != 4) {
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | error(sprintf("write() failed for quota data file!\n"));
}
string entry = sprintf("%4c%4c%s", sizeof(key)+8, data_offset, key);
if (catalog_file->write(entry) != sizeof(entry)) {
error(sprintf("write() failed for quota catalog file!\n"));
}
new_entries_cache[key] = next_offset;
next_offset = catalog_file->tell();
if (sizeof(new_entries_cache) > CACHE_SIZE_LIMIT) {
rebuild_index();
}
|
eed714 | 1999-05-12 | Henrik Grubbström (Grubba) | | return low_lookup(key, quota);
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | }
void create(string base_name, int|void create_new)
{
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | base = base_name;
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | catalog_file = open(base_name + ".cat", create_new);
data_file = open(base_name + ".data", create_new);
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | object index_file = open(base_name + ".index", 1);
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | |
#if constant(set_weak_flag)
set_weak_flag(active_objects, 1);
#endif /* constant(set_weak_flag) */
array index_st = index_file->stat();
if (!index_st || !sizeof(index_st)) {
error(sprintf("stat() failed for quota index file!\n"));
}
array data_st = data_file->stat();
if (!data_st || !sizeof(data_st)) {
error(sprintf("stat() failed for quota data file!\n"));
}
if (index_st[1] < 0) {
error("quota index file isn't a regular file!\n");
}
if (data_st[1] < 0) {
error("quota data file isn't a regular file!\n");
}
if (data_st[1] < index_st[1]) {
error("quota data file is shorter than the index file!\n");
}
if (index_st[1] & 3) {
error("quota index file has odd length!\n");
}
if (data_st[1] & 3) {
error("quota data file has odd length!\n");
}
int i;
array(string) index_str = index_file->read()/4;
index = allocate(sizeof(index_str));
|
a3e427 | 1999-05-11 | Henrik Grubbström (Grubba) | | if (sizeof(index_str) && (sizeof(index_str[-1]) != 4)) {
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | error("Truncated read of the index file!\n");
}
foreach(index_str, string offset_str) {
int offset;
sscanf(offset_str, "%4c", offset);
index[i++] = offset;
if (offset > next_offset) {
next_offset = offset;
}
}
|
e9857a | 1999-05-08 | Henrik Grubbström (Grubba) | | init_index_acc();
|
ebc988 | 1999-05-06 | Henrik Grubbström (Grubba) | | if (sizeof(index)) {
mixed entry = read_entry(next_offset);
next_offset = catalog_file->tell();
}
if (index_st[1] < data_st[1]) {
while (mixed entry = read_entry(next_offset)) {
new_entries_cache[entry->name] = next_offset;
next_offset = catalog_file->tell();
}
rebuild_index();
}
}
}
|
69e4cd | 2000-03-09 | Martin Stjernholm | |
|
df6c03 | 2000-08-09 | Per Hedbor | | #define CTX()
class EScope
{
string scope;
void delete( string var )
{
RXML.Context ctx = RXML.get_context( );
ctx->delete_var( var, scope );
}
string name()
{
RXML.Context ctx = RXML.get_context( );
return scope == "_" ? ctx->current_scope() : scope;
}
|
c16622 | 2000-08-09 | Per Hedbor | | mixed `[]( string what )
|
df6c03 | 2000-08-09 | Per Hedbor | | {
RXML.Context ctx = RXML.get_context( );
return ctx->get_var( what, scope );
}
|
c16622 | 2000-08-09 | Per Hedbor | | mixed `->( string what )
|
df6c03 | 2000-08-09 | Per Hedbor | | {
return `[]( what );
}
|
c16622 | 2000-08-09 | Per Hedbor | | mixed `[]=( string what, mixed nval )
|
df6c03 | 2000-08-09 | Per Hedbor | | {
RXML.Context ctx = RXML.get_context( );
ctx->set_var( what, nval, scope );
return nval;
}
|
c16622 | 2000-08-09 | Per Hedbor | | mixed `->=( string what, mixed nval )
|
df6c03 | 2000-08-09 | Per Hedbor | | {
return `[]=( what, nval );
}
|
c16622 | 2000-08-09 | Per Hedbor | | array(string) _indices( )
|
df6c03 | 2000-08-09 | Per Hedbor | | {
RXML.Context ctx = RXML.get_context( );
return ctx->list_var( scope );
}
|
c16622 | 2000-08-09 | Per Hedbor | | array(string) _values( )
|
df6c03 | 2000-08-09 | Per Hedbor | | {
RXML.Context ctx = RXML.get_context( );
return map( ctx->list_var( scope ), `[] );
}
|
c16622 | 2000-08-09 | Per Hedbor | | void create( string _scope )
|
df6c03 | 2000-08-09 | Per Hedbor | | {
scope = _scope;
}
}
class SRestore
{
mapping osc = ([]);
void destroy()
{
foreach( indices( osc ), string o )
add_constant( o, osc[o] );
add_constant( "roxen", roxenp() );
}
}
SRestore add_scope_constants( string|void name )
{
SRestore res = SRestore();
mapping ac = all_constants();
if(!name) name = "";
|
85a1bb | 2000-08-10 | Per Hedbor | | if( RXML.get_context() )
|
df6c03 | 2000-08-09 | Per Hedbor | | {
|
85a1bb | 2000-08-10 | Per Hedbor | | foreach( RXML.get_context()->list_scopes()|({"_"}), string scope )
{
res->osc[ name+scope ] = ac[ name+scope ];
add_constant( name+scope, EScope( scope ) );
}
|
df6c03 | 2000-08-09 | Per Hedbor | | }
return res;
}
|
703503 | 2000-08-23 | Martin Nilsson | |
mapping(string:string) parser_charref_table =
lambda () {
mapping(string:string) table = ([]);
for (int i = 0; i < sizeof (replace_entities); i++) {
string chref = replace_entities[i];
table[chref[1..sizeof (chref) - 2]] = replace_values[i];
}
return table;
}();
|
f4c4d5 | 2000-08-27 | Martin Stjernholm | |
mapping(string:string) inverse_charref_table =
lambda () {
mapping(string:string) table = ([]);
for (int i = 0; i < sizeof (replace_entities); i++) {
string chref = replace_entities[i];
table[replace_values[i]] = chref[1..sizeof (chref) - 2];
}
return table;
}();
string decode_charref (string chref)
{
if (sizeof (chref) <= 2 || chref[0] != '&' || chref[-1] != ';') return 0;
if (chref[1] != '#') return parser_charref_table[chref[1..sizeof (chref) - 2]];
if ((<'x', 'X'>)[chref[2]]) {
if (sscanf (chref, "&%*2s%x;%*c", int c) == 2) return sprintf ("%c", c);
}
else
if (sscanf (chref, "&%*c%d;%*c", int c) == 2) return sprintf ("%c", c);
return 0;
}
|
425fc6 | 2000-09-21 | Per Hedbor | | string|program safe_compile( string code )
{
program ret;
|
51f590 | 2000-09-27 | Per Hedbor | | roxenloader.LowErrorContainer ec = roxenloader.LowErrorContainer();
|
425fc6 | 2000-09-21 | Per Hedbor | | roxenloader.push_compile_error_handler( ec );
catch(ret = compile_string( code ));
|
51f590 | 2000-09-27 | Per Hedbor | | roxenloader.pop_compile_error_handler( );
|
425fc6 | 2000-09-21 | Per Hedbor | | if( !ret ) return ec->get();
return ret;
}
|
f4c4d5 | 2000-08-27 | Martin Stjernholm | | string encode_charref (string char)
|
d3beb0 | 2000-08-27 | Martin Stjernholm | |
|
f4c4d5 | 2000-08-27 | Martin Stjernholm | | {
if (string chref = inverse_charref_table[char]) return "&" + chref + ";";
|
d3beb0 | 2000-08-27 | Martin Stjernholm | | return sprintf ("&#%d;", char[0]);
|
f4c4d5 | 2000-08-27 | Martin Stjernholm | | }
|
703503 | 2000-08-23 | Martin Nilsson | |
|
df6c03 | 2000-08-09 | Per Hedbor | |
|
69e4cd | 2000-03-09 | Martin Stjernholm | |
class ScopeRoxen {
inherit RXML.Scope;
string pike_version=predef::version();
int ssl_strength=0;
#if constant(SSL)
void create() {
ssl_strength=40;
|
c4ee17 | 2000-04-06 | Henrik Grubbström (Grubba) | | #if constant(SSL.constants.CIPHER_des)
|
69e4cd | 2000-03-09 | Martin Stjernholm | | if(SSL.constants.CIPHER_algorithms[SSL.constants.CIPHER_des])
ssl_strength=128;
if(SSL.constants.CIPHER_algorithms[SSL.constants.CIPHER_3des])
ssl_strength=168;
|
c4ee17 | 2000-04-06 | Henrik Grubbström (Grubba) | | #endif /* !constant(SSL.constants.CIPHER_des) */
|
69e4cd | 2000-03-09 | Martin Stjernholm | | }
#endif
|
703503 | 2000-08-23 | Martin Nilsson | | mixed `[] (string var, void|RXML.Context c, void|string scope) {
|
69e4cd | 2000-03-09 | Martin Stjernholm | | switch(var)
{
case "uptime":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,1);
|
dbf991 | 2000-03-19 | Martin Nilsson | | return (time(1)-roxenp()->start_time);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | case "uptime-days":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,3600*2);
|
dbf991 | 2000-03-19 | Martin Nilsson | | return (time(1)-roxenp()->start_time)/3600/24;
|
69e4cd | 2000-03-09 | Martin Stjernholm | | case "uptime-hours":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,1800);
|
dbf991 | 2000-03-19 | Martin Nilsson | | return (time(1)-roxenp()->start_time)/3600;
|
69e4cd | 2000-03-09 | Martin Stjernholm | | case "uptime-minutes":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,60);
|
dbf991 | 2000-03-19 | Martin Nilsson | | return (time(1)-roxenp()->start_time)/60;
|
69e4cd | 2000-03-09 | Martin Stjernholm | | case "hits-per-minute":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,2);
|
dbf991 | 2000-03-19 | Martin Nilsson | | return c->id->conf->requests / ((time(1)-roxenp()->start_time)/60 + 1);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | case "hits":
|
7e9a0b | 2000-09-16 | Per Hedbor | | NOCACHE(c->id);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | return c->id->conf->requests;
case "sent-mb":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,10);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | return sprintf("%1.2f",c->id->conf->sent / (1024.0*1024.0));
case "sent":
|
7e9a0b | 2000-09-16 | Per Hedbor | | NOCACHE(c->id);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | return c->id->conf->sent;
case "sent-per-minute":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,2);
|
dbf991 | 2000-03-19 | Martin Nilsson | | return c->id->conf->sent / ((time(1)-roxenp()->start_time)/60 || 1);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | case "sent-kbit-per-second":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,2);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | return sprintf("%1.2f",((c->id->conf->sent*8)/1024.0/
|
dbf991 | 2000-03-19 | Martin Nilsson | | (time(1)-roxenp()->start_time || 1)));
|
69e4cd | 2000-03-09 | Martin Stjernholm | | case "ssl-strength":
return ssl_strength;
case "pike-version":
return pike_version;
case "version":
|
dbf991 | 2000-03-19 | Martin Nilsson | | return roxenp()->version();
|
88bff1 | 2000-09-12 | Per Hedbor | | case "base-version":
return __roxen_version__;
case "build":
return __roxen_build__;
|
69e4cd | 2000-03-09 | Martin Stjernholm | | case "time":
|
7e9a0b | 2000-09-16 | Per Hedbor | | CACHE(c->id,1);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | return time(1);
case "server":
return c->id->conf->query("MyWorldLocation");
|
9705b9 | 2000-07-02 | Martin Nilsson | | case "domain":
string tmp=c->id->conf->query("MyWorldLocation");
sscanf(tmp, "%*s//%s", tmp);
sscanf(tmp, "%s:", tmp);
sscanf(tmp, "%s/", tmp);
return tmp;
|
703503 | 2000-08-23 | Martin Nilsson | | case "locale":
|
7e9a0b | 2000-09-16 | Per Hedbor | | NOCACHE(c->id);
|
703503 | 2000-08-23 | Martin Nilsson | | return roxenp()->locale->get();
default:
return RXML.nil;
|
69e4cd | 2000-03-09 | Martin Stjernholm | | }
:: `[] (var, c, scope);
}
array(string) _indices() {
return ({"uptime", "uptime-days", "uptime-hours", "uptime-minutes",
"hits-per-minute", "hits", "sent-mb", "sent",
"sent-per-minute", "sent-kbit-per-second", "ssl-strength",
|
703503 | 2000-08-23 | Martin Nilsson | | "pike-version", "version", "time", "server", "domain",
"locale"});
|
69e4cd | 2000-03-09 | Martin Stjernholm | | }
string _sprintf() { return "RXML.Scope(roxen)"; }
}
class ScopePage {
inherit RXML.Scope;
constant converter=(["fgcolor":"fgcolor", "bgcolor":"bgcolor",
"theme-bgcolor":"theme_bgcolor", "theme-fgcolor":"theme_fgcolor",
"theme-language":"theme_language"]);
constant in_defines=aggregate_multiset(@indices(converter));
mixed `[] (string var, void|RXML.Context c, void|string scope) {
|
7e9a0b | 2000-09-16 | Per Hedbor | | NOCACHE(c->id);
|
971ed3 | 2000-03-20 | Martin Stjernholm | | switch (var) {
case "pathinfo": return c->id->misc->path_info;
}
|
69e4cd | 2000-03-09 | Martin Stjernholm | | if(in_defines[var])
return c->id->misc->defines[converter[var]];
if(objectp(c->id->misc->scope_page[var])) return c->id->misc->scope_page[var]->rxml_var_eval(c, var, "page");
return c->id->misc->scope_page[var];
}
mixed `[]= (string var, mixed val, void|RXML.Context c, void|string scope_name) {
|
971ed3 | 2000-03-20 | Martin Stjernholm | | switch (var) {
case "pathinfo": return c->id->misc->path_info = val;
}
|
69e4cd | 2000-03-09 | Martin Stjernholm | | if(in_defines[var])
return c->id->misc->defines[converter[var]]=val;
return c->id->misc->scope_page[var]=val;
}
array(string) _indices(void|RXML.Context c) {
if(!c) return ({});
|
7e9a0b | 2000-09-16 | Per Hedbor | | NOCACHE(c->id);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | array ind=indices(c->id->misc->scope_page);
foreach(indices(in_defines), string def)
if(c->id->misc->defines[converter[def]]) ind+=({def});
|
a458af | 2000-03-20 | Martin Stjernholm | | return ind + ({"pathinfo"});
|
69e4cd | 2000-03-09 | Martin Stjernholm | | }
void m_delete (string var, void|RXML.Context c, void|string scope_name) {
if(!c) return;
|
971ed3 | 2000-03-20 | Martin Stjernholm | | switch (var) {
case "pathinfo":
predef::m_delete (c->id->misc, "pathinfo");
return;
}
|
69e4cd | 2000-03-09 | Martin Stjernholm | | if(in_defines[var]) {
if(var[0..4]=="theme")
predef::m_delete(c->id->misc->defines, converter[var]);
else
::m_delete(var, c, scope_name);
|
971ed3 | 2000-03-20 | Martin Stjernholm | | return;
|
69e4cd | 2000-03-09 | Martin Stjernholm | | }
predef::m_delete(c->id->misc->scope_page, var);
}
string _sprintf() { return "RXML.Scope(page)"; }
}
|
703503 | 2000-08-23 | Martin Nilsson | | class ScopeCookie {
inherit RXML.Scope;
|
69e4cd | 2000-03-09 | Martin Stjernholm | |
|
703503 | 2000-08-23 | Martin Nilsson | | mixed `[] (string var, void|RXML.Context c, void|string scope) {
if(!c) return RXML.nil;
|
7e9a0b | 2000-09-16 | Per Hedbor | | NOCACHE(c->id);
|
703503 | 2000-08-23 | Martin Nilsson | | return c->id->cookies[var];
}
mixed `[]= (string var, mixed val, void|RXML.Context c, void|string scope_name) {
if(c && c->id->cookies[var]!=val) {
c->id->cookies[var]=val;
add_http_header(c->id->misc->defines[" _extra_heads"], "Set-Cookie", http_encode_cookie(var)+
"="+http_encode_cookie( (string)(val||"") )+
"; expires="+http_date(time(1)+(3600*24*365*2))+"; path=/");
|
9bf118 | 2000-08-12 | Martin Stjernholm | | }
|
703503 | 2000-08-23 | Martin Nilsson | | return RXML.nil;
}
array(string) _indices(void|RXML.Context c) {
if(!c) return ({});
|
7e9a0b | 2000-09-16 | Per Hedbor | | NOCACHE(c->id);
|
703503 | 2000-08-23 | Martin Nilsson | | return indices(c->id->cookies);
}
void m_delete (string var, void|RXML.Context c, void|string scope_name) {
if(!c || !c->id->cookies[var]) return;
predef::m_delete(c->id->cookies, var);
add_http_header(c->id->misc->defines[" _extra_heads"], "Set-Cookie",
http_encode_cookie(var)+"=; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/");
}
string _sprintf() { return "RXML.Scope(Cookie)"; }
}
RXML.Scope scope_roxen=ScopeRoxen();
RXML.Scope scope_page=ScopePage();
RXML.Scope scope_cookie=ScopeCookie();
|
9bf118 | 2000-08-12 | Martin Stjernholm | |
|
69e4cd | 2000-03-09 | Martin Stjernholm | | RXML.TagSet entities_tag_set = class
{
inherit RXML.TagSet;
void prepare_context (RXML.Context c) {
c->add_scope("roxen",scope_roxen);
c->id->misc->scope_page=([]);
c->add_scope("page",scope_page);
|
703503 | 2000-08-23 | Martin Nilsson | | c->add_scope("cookie", scope_cookie);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | c->add_scope("form", c->id->variables);
|
703503 | 2000-08-23 | Martin Nilsson | | c->add_scope("client", c->id->client_var);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | c->add_scope("var", ([]) );
}
void create (string name)
{
::create (name);
|
7eeec7 | 2000-07-06 | Martin Stjernholm | |
|
9bf118 | 2000-08-12 | Martin Stjernholm | | add_string_entities (parser_charref_table);
|
69e4cd | 2000-03-09 | Martin Stjernholm | | }
} ("entities_tag_set");
|
dbf991 | 2000-03-19 | Martin Nilsson | |
|
b92a1c | 2000-08-14 | Martin Stjernholm | |
|
dbf991 | 2000-03-19 | Martin Nilsson | | constant monthnum=(["Jan":0, "Feb":1, "Mar":2, "Apr":3, "May":4, "Jun":5,
"Jul":6, "Aug":7, "Sep":8, "Oct":9, "Nov":10, "Dec":11,
"jan":0, "feb":1, "mar":2, "apr":3, "may":4, "jun":5,
"jul":6, "aug":7, "sep":8, "oct":9, "nov":10, "dec":11,]);
#define MAX_SINCE_CACHE 16384
static mapping(string:int) since_cache=([ ]);
array(int) parse_since(string date)
{
if(!date || sizeof(date)<14) return({0,-1});
int t=0, length = -1;
#if constant(mktime)
|
f6deda | 2000-07-11 | Martin Nilsson | | string dat=lower_case(date);
sscanf(dat+"; length=", "%*s, %s; length=%d", dat, length);
|
dbf991 | 2000-03-19 | Martin Nilsson | |
if(!(t=since_cache[dat])) {
int day, year = -1, month, hour, minute, second;
string m;
if(sscanf(dat, "%d-%s-%d %d:%d:%d", day, m, year, hour, minute, second)>2)
{
month=monthnum[m];
} else if(dat[2]==',') {
sscanf(dat, "%*s, %d %s %d %d:%d:%d", day, m, year, hour, minute, second);
month=monthnum[m];
} else if(!(int)dat) {
sscanf(dat, "%*[^ ] %s %d %d:%d:%d %d", m, day, hour, minute, second, year);
month=monthnum[m];
} else {
sscanf(dat, "%d %s %d %d:%d:%d", day, m, year, hour, minute, second);
month=monthnum[m];
}
if(year >= 0) {
if (year < 60) {
year += 100;
} else if (year >= 1900) {
year -= 1900;
}
catch {
|
df6c03 | 2000-08-09 | Per Hedbor | | t = mktime(second, minute, hour, day, month, year, 0, 0);
|
dbf991 | 2000-03-19 | Martin Nilsson | | };
} else {
report_debug("Could not parse \""+date+"\" to a time int.");
}
if (sizeof(since_cache) > MAX_SINCE_CACHE)
since_cache = ([]);
since_cache[dat]=t;
}
#endif /* constant(mktime) */
return ({ t, length });
}
int is_modified(string a, int t, void|int len)
{
array vals=parse_since(a);
if(len && len!=vals[1]) return 0;
if(vals[0]<t) return 0;
return 1;
}
int httpdate_to_time(string date)
{
return parse_since(date)[0]||-1;
}
|
31d164 | 2000-03-26 | Martin Nilsson | |
|
3580f5 | 2000-09-03 | Per Hedbor | | void set_cookie( RequestID id,
string name,
string value,
int|void expire_time_delta,
string|void domain,
string|void path )
{
if( expire_time_delta = -1 )
expire_time_delta = (3600*(24*365*5));
string cookie = (http_encode_cookie( name )+"="+
http_encode_cookie( value ));
if( expire_time_delta )
cookie += "; expires="+http_date( expire_time_delta+time(1) );
if( domain ) cookie += "; domain="+http_encode_cookie( domain );
if( path ) cookie += "; path="+http_encode_cookie( path );
if(!id->misc->moreheads)
id->misc->moreheads = ([]);
add_http_header( id->misc->moreheads, "Set-Cookie",cookie );
}
void remove_cookie( RequestID id,
string name,
string value,
string|void domain,
string|void path )
{
set_cookie( id, name, value, -time(1), domain, path );
}
|
c3c632 | 2000-09-20 | Per Hedbor | | void add_cache_callback( RequestID id,function(RequestID,object:int) callback )
|
a45647 | 2000-08-31 | Per Hedbor | |
|
c3c632 | 2000-09-20 | Per Hedbor | |
|
a45647 | 2000-08-31 | Per Hedbor | | {
while( id->misc->orig )
id = id->misc->orig;
|
862f38 | 2000-09-25 | Per Hedbor | | if( !id->misc->_cachecallbacks ) return;
|
a45647 | 2000-08-31 | Per Hedbor | | id->misc->_cachecallbacks |= ({ callback });
}
|
862f38 | 2000-09-25 | Per Hedbor | | string get_server_url(object c)
{
|
31d164 | 2000-03-26 | Martin Nilsson | | string url=c->query("MyWorldLocation");
if(stringp(url) && sizeof(url)) return url;
array(string) urls=c->query("URLs");
return get_world(urls);
}
|
862f38 | 2000-09-25 | Per Hedbor | | string get_world(array(string) urls)
{
|
31d164 | 2000-03-26 | Martin Nilsson | | if(!sizeof(urls)) return 0;
string url=urls[0];
foreach( ({"http:","fhttp:","https:","ftp:"}), string p)
foreach(urls, string u)
if(u[0..sizeof(p)-1]==p) {
url=u;
break;
}
|
f70aa7 | 2000-03-28 | Martin Nilsson | | string protocol, server, path="";
|
31d164 | 2000-03-26 | Martin Nilsson | | int port;
if(sscanf(url, "%s://%s:%d/%s", protocol, server, port, path)!=4 &&
|
f70aa7 | 2000-03-28 | Martin Nilsson | | sscanf(url, "%s://%s:%d", protocol, server, port)!=3 &&
sscanf(url, "%s://%s/%s", protocol, server, path)!=3 &&
sscanf(url, "%s://%s", protocol, server)!=2 )
|
31d164 | 2000-03-26 | Martin Nilsson | | return 0;
if(protocol=="fhttp") protocol="http";
array hosts=({ gethostname() }), dns;
catch(dns=Protocols.DNS.client()->gethostbyname(hosts[0]));
if(dns && sizeof(dns))
hosts+=dns[2]+dns[1];
foreach(hosts, string host)
if(glob(server, host)) {
server=host;
break;
}
if(port) return sprintf("%s://%s:%d/%s", protocol, server, port, path);
return sprintf("%s://%s/%s", protocol, server, path);
}
|
c16622 | 2000-08-09 | Per Hedbor | |
|
b92a1c | 2000-08-14 | Martin Stjernholm | | RoxenModule get_owning_module (object|function thing)
{
if (functionp (thing)) thing = function_object (thing);
if (objectp (thing)) {
if (thing->is_module) return thing;
if (object parent =
functionp (object_program (thing)) &&
function_object (object_program (thing))) {
if (parent->is_module) return parent;
}
}
return 0;
}
Configuration get_owning_config (object|function thing)
{
if (RoxenModule mod = get_owning_module (thing))
return mod->my_configuration();
if (functionp (thing)) thing = function_object (thing);
if (objectp (thing)) {
if (thing->is_configuration) return thing;
if (object parent =
functionp (object_program (thing)) &&
function_object (object_program (thing))) {
if (parent->is_configuration) return parent;
}
}
return 0;
}
#ifdef REQUEST_TRACE
|
acc6dd | 2000-08-15 | Martin Stjernholm | | static string trace_msg (RequestID id, string msg, string name)
|
b92a1c | 2000-08-14 | Martin Stjernholm | | {
|
acc6dd | 2000-08-15 | Martin Stjernholm | | msg = html_decode_string (
|
b92a1c | 2000-08-14 | Martin Stjernholm | | Parser.HTML()->_set_tag_callback (lambda (object p, string s) {return "";})->
finish (msg)->read());
|
acc6dd | 2000-08-15 | Martin Stjernholm | | array(string) lines = msg / "\n";
if (lines[-1] == "") lines = lines[..sizeof (lines) - 2];
if (sizeof (lines))
report_debug ("%s%s%-40s %s\n",
map (lines[..sizeof (lines) - 2],
lambda (string s) {
return sprintf ("%s%*s%s\n", id->misc->trace_id_prefix,
id->misc->trace_level + 1, "", s);
}) * "",
id->misc->trace_id_prefix,
sprintf ("%*s%s", id->misc->trace_level + 1, "", lines[-1]),
name);
}
void trace_enter (RequestID id, string msg, object|function thing)
{
if (!id->misc->trace_level) {
|
f4c4d5 | 2000-08-27 | Martin Stjernholm | | id->misc->trace_id_prefix = ({"%%", "##", "§§", "**", "@@", "$$", "¤¤"})[
|
acc6dd | 2000-08-15 | Martin Stjernholm | | all_constants()->id_trace_level_rotate_counter++ % 7];
report_debug ("%s%s Request handled by: %O\n",
id->misc->trace_id_prefix, id->misc->trace_id_prefix[..0],
id->conf);
}
|
b92a1c | 2000-08-14 | Martin Stjernholm | | string name;
if (thing) {
name = get_modfullname (get_owning_module (thing));
if (name)
name = "mod: " + html_decode_string (
Parser.HTML()->_set_tag_callback (lambda (object p, string s) {return "";})->
finish (name)->read());
else if (Configuration conf = get_owning_config (thing))
name = "conf: " + conf->query_name();
|
c7fb94 | 2000-09-05 | Martin Stjernholm | | else
|
b92a1c | 2000-08-14 | Martin Stjernholm | | name = sprintf ("obj: %O", thing);
}
else name = "";
|
acc6dd | 2000-08-15 | Martin Stjernholm | | trace_msg (id, msg, name);
|
b92a1c | 2000-08-14 | Martin Stjernholm | | id->misc->trace_level++;
if(function(string,mixed ...:void) _trace_enter =
[function(string,mixed ...:void)]([mapping(string:mixed)]id->misc)->trace_enter)
_trace_enter (msg, thing);
}
void trace_leave (RequestID id, string desc)
{
if (id->misc->trace_level) id->misc->trace_level--;
|
acc6dd | 2000-08-15 | Martin Stjernholm | | if (sizeof (desc)) trace_msg (id, desc, "");
|
b92a1c | 2000-08-14 | Martin Stjernholm | |
if(function(string:void) _trace_leave =
[function(string:void)]([mapping(string:mixed)]id->misc)->trace_leave)
_trace_leave (desc);
}
#endif
|
c16622 | 2000-08-09 | Per Hedbor | |
#if !constant(Parser.C)
|
b92a1c | 2000-08-14 | Martin Stjernholm | | object _Parser =
|
c16622 | 2000-08-09 | Per Hedbor | | class
{
object C =
class
{
mapping(string:string) global_groupings=(["{":"}","(":")","[":"]"]);
array(string) split(string data)
{
int start;
int line=1;
array(string) ret=({});
int pos;
data += "\n\0";
while(1)
{
int start=pos;
switch(data[pos])
{
case '\0':
return ret;
case '#':
{
pos=search(data,"\n",pos);
if(pos==-1)
error("Failed to find end of preprocessor statement.\n");
while(data[pos-1]=='\\') pos=search(data,"\n",pos+1);
break;
case 'a'..'z':
case 'A'..'Z':
case 128..65536:
case '_':
while(1)
{
switch(data[pos])
{
case '$':
case 'a'..'z':
case 'A'..'Z':
case '0'..'9':
case 128..65536:
case '_':
pos++;
continue;
}
break;
}
break;
case '.':
if(data[start..start+2]=="...")
{
pos+=3;
break;
}
if(data[start..start+1]=="..")
{
pos+=3;
break;
}
case '0'..'9':
if(data[pos]=='0' && (data[pos+1]=='x' || data[pos+1]=='X'))
{
pos+=2;
while(1)
{
switch(data[pos])
{
case '0'..'9':
case 'a'..'f':
case 'A'..'F':
pos++;
continue;
}
break;
}
break;
}
while(data[pos]>='0' && data[pos]<='9') pos++;
if(data[pos]=='.')
{
pos++;
while(data[pos]>='0' && data[pos]<='9') pos++;
if(data[pos]=='e' || data[pos]=='E')
{
pos++;
while(data[pos]>='0' && data[pos]<='9') pos++;
}
}
break;
default:
werror("%O\n",ret);
werror("Unknown token %O\n",data[pos..pos+20]);
exit(1);
case '`':
while(data[pos]=='`') data[pos]++;
case '\\': pos++; continue;
case '/':
case '{': case '}':
case '[': case ']':
case '(': case ')':
case ';':
case ',':
case '*': case '%':
case '?': case ':':
case '&': case '|': case '^':
case '!': case '~':
case '=':
case '@':
case '+':
case '-':
case '<': case '>':
switch(data[pos..pos+1])
{
case "//":
pos=search(data,"\n",pos);
break;
case "/*":
pos=search(data,"*/",pos);
pos+=2;
break;
case "<<": case ">>":
if(data[pos+2]=='=') pos++;
case "==": case "<=": case ">=":
case "*=": case "/=": case "%=":
case "&=": case "|=": case "^=":
case "+=": case "-=":
case "++": case "--":
case "&&": case "||":
case "->":
pos++;
default:
pos++;
}
break;
case ' ':
case '\n':
case '\r':
case '\t':
case '\14':
while(1)
{
switch(data[pos])
{
case ' ':
case '\n':
case '\r':
case '\t':
case '\14':
pos++;
continue;
}
break;
}
break;
case '\'':
pos++;
if(data[pos]=='\\') pos++;
pos=search(data, "'", pos+1)+1;
break;
case '"':
{
int q,s;
while(1)
{
q=search(data,"\"",pos+1);
s=search(data,"\\",pos+1);
if(q==-1) q=strlen(data)-1;
if(s==-1) s=strlen(data)-1;
if(q<s)
{
pos=q+1;
break;
}else{
pos=s+1;
}
}
break;
}
}
}
ret+=({ data[start..pos-1] });
}
}
class Token
{
int line;
string text;
string file;
string trailing_whitespaces="";
void create(string t, int l, void|string f, void|string space)
{
text=t;
line=l;
file=f;
if(space) trailing_whitespaces=space;
}
string _sprintf(int how)
{
switch(how)
{
case 's':
return text;
case 'O':
return sprintf("Token(%O,%O,%d)",text,file,line);
}
}
int `==(mixed foo)
{
return (objectp(foo) ? foo->text : foo) == text;
}
string `+(string ... s)
{
return predef::`+(text,@s);
}
string ``+(string ... s)
{
return predef::`+(@s,text);
}
mixed cast(string to)
{
if(to=="string") return text;
}
}
array(Token) tokenize(array(string) s, void|string file)
{
array(Token) ret=allocate(sizeof(s));
int line=1;
for(int e=0;e<sizeof(s);e++)
{
ret[e]=Token(s[e],line,file);
if(s[e][0]=='#')
{
sscanf(s[e],"#%*[ \t\14]%d%*[ \t\14]\"%s\"", line,file);
sscanf(s[e],"#%*[ \t\14]line%*[ \t\14]%d%*[ \t\14]\"%s\"",
line,file);
line--;
}
line+=sizeof(s[e]/"\n")-1;
}
return ret;
}
array group(array(string|Token) tokens, void|mapping groupings)
{
Stack.stack stack=Stack.stack();
array(Token) ret=({});
mapping actions=([]);
if(!groupings) groupings=global_groupings;
foreach((array)groupings,[string x, string y])
{
actions[x]=1;
actions[y]=2;
}
foreach(tokens, Token token)
{
switch(actions[(string)token])
{
case 0: ret+=({token}); break;
case 1: stack->push(ret); ret=({token}); break;
case 2:
if (!sizeof(ret) || !stack->ptr ||
(groupings[(string)ret[0]] != (string)token)) {
werror(sprintf("**** Grouping mismatch token=%O\n"
"**** tokens: ({ %{%O, %}})\n"
"**** ret: ({ %{%O, %}})\n"
"**** stackdepth: %d\n",
token->text, tokens->text,
ret->text, stack->ptr));
return ret;
}
ret=stack->pop()+({ ret + ({token}) });
}
}
return ret;
}
array strip_line_statements(array tokens)
{
array(Token) ret=({});
foreach(tokens, array|object(Token) t)
{
if(arrayp(t))
{
ret+=({ strip_line_statements(t) });
}else{
if( ((string)t) [0] != '#')
ret+=({t});
}
}
return ret;
}
array hide_whitespaces(array tokens)
{
array(Token) ret=({tokens[0]});
foreach(tokens[1..], array|object(Token) t)
{
if(arrayp(t))
{
ret+=({ hide_whitespaces(t) });
}else{
switch( ((string)t) [0])
{
case ' ':
case '\t':
case '\14':
case '\n':
mixed tmp=ret[-1];
while(arrayp(tmp)) tmp=tmp[-1];
tmp->trailing_whitespaces+=(string)t;
break;
default:
ret+=({t});
}
}
}
return ret;
}
array flatten(array a)
{
array ret=({});
foreach(a, a) ret+=arrayp(a)?flatten(a):({a});
return ret;
}
string simple_reconstitute(array(string|object(Token)|array) tokens)
{
string ret="";
foreach(flatten(tokens), mixed tok)
{
if(objectp(tok))
tok=tok->text + tok->trailing_whitespaces;
ret+=tok;
}
return ret;
}
string reconstitute_with_line_numbers(array(string|object(Token)|array)
tokens)
{
int line=1;
string file;
string ret="";
foreach(flatten(tokens), mixed tok)
{
if(objectp(tok))
{
if((tok->line && tok->line != line) ||
(tok->file && tok->file != file))
{
if(strlen(ret) && ret[-1]!='\n') ret+="\n";
line=tok->line;
if(tok->file) file=tok->file;
ret+=sprintf("#line %d %O\n",line,file);
}
tok=tok->text + tok->trailing_whitespaces;
}
ret+=tok;
line+=sizeof(tok/"\n")-1;
}
return ret;
}
}();
}();
#endif
|