I guess it's time for status update.
I've been lately working on device/service/environment releated code, which is where the magic happends. I've discarded most of ordinary 'struct'ures for storing client related data and moved nearly everything to dynamic environment, which is far more flexible - and safer thanks to mandatory environment variable destructors.
I've also written new hostname caching algorithms - similar to old, but faster & neater.
The big thing that I can't yet fully describe, as it's still work in progress, is native database support. Instead of providing fixed tables, I decided to write somewhat more complex code that allows customizing database structures. (read; you can add and remove both columns & rows to any database - or even create your own cached databases) To minimize memory usage and amount of memory allocations, I decided to make it rely heavily on reference counting. (Reference counting adds to complexity of code, but removes much of the overhead caused by dynamic allocations) Obviously the programming interface is done so, that scripts and modules do not need any database specific code.
Only thing, that I haven't had time to study yet, is LUA. I'm planning to replace cookies with programming language (due to fact, that fixed cookies would not work too well with database), and LUA seems to be perfect choice for the purpose.
Sample code for changing password:
Code:
lpDatabase = GetUserDatabase();
lpUserCollection = GetDatabaseCollection(lpDatabase, L"darkone");
if (lpUserCollection != 0) {
lUserDataRowID = GetDatabaseRowID(lpDatabase, L"USER");
lPasswordColumnID = GetDatabaseColumnID(lpDatabase, lUserDataRowID, L"PASSWORD");
lpRow = GetDatabaseRow(lpUserCollection, lUserDataRowID);
if (lpRow != 0) {
/* get password */
lpValue = GetDatabaseValue(lpRow, lPasswordColumnID);
if (lpValue != 0) {
wsprintfW("Current password is: %s\n", lpValue->wszValue);
}
/* lock selected rows */
lRows[0] = lUserDataRowID;
if (LockDatabaseCollectionRows(&lpUserCollection, lRows, 1)) {
bResult = FALSE;
/* create new value */
lpValue = CreateDatabaseWStringValue(L"New password", INFINITE /* length of pass, infinite = wcslen() */);
if (lpValue != 0) {
/* set value to database (one can use same value on several columns/rows/collections by duplicating it using DuplicateDatabaseValue(), which only increments reference counter instead of allocation memory) */
if (SetDatabaseCollectionColumnValue(lpUserCollection, lUserDataRowID, 0 /* index of row, if more than one rows. eg. certificate hash list & stats */, lPasswordColumnID, lpValue)) {
/* flush... */
bResult = CommitDatabaseCollectionChanges(&lpUserCollection);
} else {
FreeDatabaseValue(lpValue);
}
}
if (! bResult ){
CancelDatabaseCollectionChanges(&lpUserCollection);
}
}
}
CloseUserCollection(lpUserCollection);
}
As some of you can see, it is very easy to write a generic routine for changing any value with single command. eg. 'SITE CHANGE <DATABASE NAME> <USERNAME> <ROW NAME> <COLUMN NAME> <NEW VALUE>'