PDA

View Full Version : Back again


darkone
03-29-2005, 10:19 PM
I apologize for being away for such a long perioid without notifying anyone. I'm not sure, if I should explain why I was gone, but for your pleasure I will write a brief explanation.

As some of you know I was enrolled in university from January 2003 to January 2004 (I still am, but duh). During that time (2003 - 2004) I was paid study grants total of ~4700euros. But because of reasons that I'm not willing to disclose on public, I didn't advance in my studies. Instead, I was working on ioFTPD fulltime. Long story short: ~few months ago, I was informed that I have to pay that ~4700e + intrest back...

...

Next version of daemon was quite near completion before I disappeared without a trace. However during that time, I came up with some ideas that simply have/had to be implemented. (not yet another core rewrite though)

I'm not sure, if I'm supposed to reveal much of information what I had in mind (& have been doing). But since these changes will effect compatability with existing scripts & I've left you misinformed for so long time, I'm going to leak them:
- Optimizations (right)
+ new timers (less overhead when inserting/deleting)
+ smarter (faster, more efficient) configuration value store (ripped idea from database API)
+ faster memory allocation (per thread memory caches)
+ new string tokenizer (it's more important than it sounds :p)
+ list API with threadsafe list iterators (used for storing client list etc. - less overhead than scanning a vector)
- Database API changes
+ row level locks (as opposed to 'item' (user/group) level locking)
+ column names
- 'Client environment'
+ Custom environment with editable values (allows changing host, path, user, ident, ip etc. through script/module.. you'll love this; oh. say bye bye to internal IDNT support :p You never saw this one coming, did you?)
- Something will happend to cookie system. (programming language? .. not a high priority item, but current cookie system isn't well suited for the new environment, and it's likely that it's not worth the effort to make it work with it)
- Certificate based authentication (not a high priority item either, but it's still something that will be implemented eventually to replace internal ident + ip based authentication)

Don't ask, when it will be done. Most of the code left is trivial, but there's still a lot to do.

mr_F_2
03-29-2005, 10:30 PM
mmmm

glad you're back.
can't wait for the new version.
hope everything went peachy with paying back the grant

jron
03-29-2005, 11:17 PM
sounds good... saw you in #winprog the other day; got my hopes up. =)

also, I hope io will turn into a distributed ftpd in the future as this seems to be where things are headed.

Harm
03-30-2005, 12:52 AM
It's nice to see you again :) I hope everything is going ok for you now.
Keep up the good work.

tuff
03-30-2005, 01:03 AM
wb, nice to see you are still around

fobban
03-30-2005, 02:31 AM
Nice to see darkone post in the forum. Maybe there still is hope for this great project :)

Mave_2
03-30-2005, 03:14 AM
Well thats great to see you back :)

Hope everything is going well again for you

Thought you were vanished from earth kidnapped by some aliens
which did need a great programmer :p

:)

JoC
03-30-2005, 03:20 AM
Welcome back... :)

Didnt IniCom say they also coded on a new version of io based on some older code? Do your return mean that they will stop and you will continue this great project?

neoxed
03-30-2005, 05:02 AM
No JoC, IniCom said they would hire another programmer to finish the project. Whether darkone's return will change their mind(s) or not, I don't know.

http://www.ioftpd.com/board/showthread.php?s=&threadid=4858

JoC
03-30-2005, 05:07 AM
Thanks for the clear up. :)

IniCom
03-30-2005, 04:39 PM
S'pose I should quell the rumors before they get too rampant. DarkOne *is* back and we're all on the same page. I didn't want to post anything until we'd had a chance to figure out whether things were going to truly be back on schedule and it looks as if they are. D1 is continuing as he described above and we've got things back on track for everyone working on ioFTPD. No, we weren't going to hire a new programmer. We already have other programmers within the company that would take on project lead. IniCom is more than D1, CED, and the individual coders that are recognized. D1, CED, and some others just happen to be leads on their respective projects, and for good reason. It's nice to work with talented developers. D1 is going to remain project lead now that we know he's alive. As for the other post, I'm going to close it and it'll fade into obscurity. We're still going to take care of the scripters and keep moving forward. A lot of new stuff is going to come together both technically and logistically in the next couple months. I look forward to what people have to say about the next rev. of ioFTPD.

-Jon L. Hill
President / COO
IniCom Networks Inc.

deo
03-31-2005, 08:26 AM
So, is updated info of broken cookies, new implementations and whats not gonna work be regularly updated on forum?

peep
04-04-2005, 06:38 AM
Great to see you back on track d1. hope you got that moneyissue sorted. I know what a pain those minimum studyhours can be. been facing the same problem myself some time ago.

But it's great to see you back, wouldn't be the same project without you handling it!

jahknee
04-11-2005, 06:30 AM
wonderful to hear this! best news in ages! :) i'd hate to see such a great project just die ...

darkone
04-12-2005, 12:27 PM
Did I mention, that new code is designed so that server will die nicely when there's no references to virtual services => no more crashing & trashing on shutdown. Also, I'm thinking of adding ipv6 support (so far i've written everything to support arbitary length network address's)

router
04-12-2005, 02:30 PM
Ipv6 - good idea!
In my honest network i have 1200 computers ,and we using ipv6 about 1.5 year.
So, if you going to add ipv6 support , im not need ipv6-ipv4 switch anymore!
Thank you

FTPServerTools
04-12-2005, 06:32 PM
Great to see you back D1, we missed you.

peep
05-03-2005, 05:58 AM
Any possibility we might be getting an update on the progress anytime soon? Would be fun to be able to follow the progress of the upcomming release!
No intentions to rush things or anything, would just be fun to get some updates every now and then.

caladan
05-03-2005, 07:09 AM
nice to see ya back d1 and thx that u finally add ipv6 support. i remember a time nearly 2 years ago where i asked ya about that but u didnt want to do that... so nice to see that i finally reached ya *g*

greetz cal

Mave_2
05-04-2005, 08:56 AM
1 Month later and no news anymore from inicom or d1
Some info now and then about progress etc would be nice .......for sure after waiting over a year now.

darkone
05-06-2005, 02:30 AM
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:

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>'

SnypeTEST
05-06-2005, 02:08 PM
ah.. LUA is da bombzzzz...

darkone
05-07-2005, 12:19 PM
Just to show off, how trivial it's to write database modules for the new interface, I decided to publish source of current file database module (still work in progress = incomplete notepad draft) But it gives you idea, how much (or should I say little) work it's to write eg. SQL module.


LPWSTR *TokenizeCommaSeperatedString(LPWSTR wszInput, PULONG pStringCount)
{
PWCHAR pFrom, pTo, pBegin;
WCHAR wCurrent;
LPVOID lpMemory;
BOOL bBackSlash = FALSE;
ULONG lResultSize = 16;
ULONG lResultCount = 0;
LPWSTR *wszResult = 0;

/* tokenize comma seperated string */
wszResult = (LPWSTR *)Allocate("Tokenized string", sizeof(LPWSTR) * lResultSize);
if (! wszResult) {
/* out of memory */
return 0;
}

for (pFrom = pBegin = pTo = wszInput;;++pFrom) {
switch ((wCurrent = pFrom[0])) {
case L',':
if (bBackSlash) {
/* escaped comma */
break;
}
case L'\0':
if (bBackSlash) {
/* escaped nul.. decode failure */
Free(wszResult);
return 0;
}
if (lResultCount == lResultSize) {
lpMemory = ReAllocate(wszResult, 0, sizeof(LPWSTR) * (lResultSize + 16));
if (! lpMemory) {
/* out of memory */
Free(wszResult);
return 0;
}
lResultSize += 16;
wszResult = (LPWSTR *)lpMemory;
}
wszResult[lResultCount++] = pBegin;
if (wCurrent == L'\0') {
/* nul char */
pTo[0] = L'\0';
return wszResult;
}
pTo[0] = L'\0';
pTo = &pFrom[1];
pBegin = pTo;
continue;
case L'\\':
/* escape character */
if (bBackSlash) {
/* escaped escape character */
break;
}
bBackSlash = TRUE;
continue;
}
bBackSlash = FALSE;
if (pTo != pFrom) {
pTo++[0] = wCurrent;
continue;
}
pTo++;
}
}


LONG EscapeStringCommas(LPWSTR wszInput, LPWSTR wszOutput, ULONG lOutputSize)
{
WCHAR wCurrent;
PWCHAR pFrom, pTo;
LPWSTR wszResult;

/* escape string commas */
for (pFrom = wszInput, pTo = wszOutput;;pFrom++,pTo++) {
switch ((wCurrent = pFrom[0])) {
case L'\0':
return pTo - wszOutput;
case L'\\':
/* escape character */
if (lOutputSize < 2) {
/* out of buffer space */
break;
}
pTo++[0] = L'\\';
pTo++[0] = L'\\';
lOutputSize -= 2;
continue;
case L',':
/* comma */
if (lOutputSize < 2) {
/* out of buffer space */
break;
}
pTo++[0] = L'\\';
pTo++[0] = L',';
lOutputSize -= 2;
continue;
default:
if (! lOutputSize) {
/* out of buffer space */
break;
}
pTo++[0] = wCurrent;
lOutputSize--;
continue;
}
break;
}
return -1;
}


BOOL LockCollection(LPDATABASE lpDatabase, LPDATABASE_COLLECTION *lpCollection)
{
/* lock and synchronize collection - does nothing for now */
return TRUE;
}


BOOL CommitCollectionChanges(LPDATABASE lpDatabase, LPDATABASE_COLLECTION *lpCollection)
{
LPDATABASE_ROW lpRow;
LPDATABASE_VALUE lpValue;
WCHAR wColumnName[16384], wColumnValue[16384];
LONG lColumnNameLength = 0;
LONG lColumnValueLength = 0;
LONG lResult;
DWORD dwBytesWritten;
ULONG lRowID, lRowIndex, lColumnID;
BOOL bError = FALSE;
BOOL bReturn = FALSE;

/* commit collection changes and release locks - no locks for now */
wColumnName[0] = L' ';
wColumnName[1] = L'{';
wColumnValue[0] = L'{';

hFile = CreateFileW(GetDatabaseCollectionName(lpCollection[0]),
GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
/* iterate all row ids */
for (lRowID = 0;lRowID < GetDatabaseRowIDCount(lpDatabase) && ! bError;lRowID++) {
/* iterate all rows */
for (lRowIndex = 0;lRowIndex < GetCollectionRowCount(lpCollection[0], lRowID);lRowIndex++) {
/* iterate all columns */
lpRow = GetCollectionRow(lpCollection[0], lRowID, lRowIndex);
if (! lpRow) {
continue;
}

lColumnValueLength = 1;
lColumnNameLength = _snwprintf(wColumnName,
sizeof(wColumnName) / sizeof(WCHAR) - 1, L"%s {", GetRowName(lpRow));
if (lColumnNameLength > 0) {
for (lColumnID = 0;lColumnID < GetRowColumnCount(lpRow);lColumnID++) {
lpValue = GetRowColumnValue(lpRow, lColumnID);
if (! lpValue) {
continue;
}

lResult = EscapeStringCommas(GetRowColumnName(lpRow, lColumnID),
&wColumnName[lColumnNameLength], sizeof(wColumnName) / sizeof(WCHAR) - lColumnNameLength - 2);
if (lResult <= 0) {
/* failure */
lColumnNameLength = INFINITE;
break;
}
lColumnNameLength += lResult;
wColumnName[lColumnNameLength++] = L',';

lResult = EscapeStringCommas(GetValueWString(lpValue),
&wColumnValue[lColumnValueLength], sizeof(wColumnValue) / sizeof(WCHAR) - lColumnValueLength - 3);
if (lResult < 0) {
/* failure */
lColumnValueLength = INFINITE;
break;
}
lColumnValueLength += lResult;
wColumnName[lColumnValueLength++] = L',';
}

if (lColumnValueLength != INFINITE && lColumnNameLength != INFINITE) {
/* prepend buffers */
wColumnName[lColumnNameLength - 1] = L'}';
wColumnName[lColumnNameLength++] = L' ';
wColumnValue[lColumnValueLength - 1] = L'}';
wColumnValue[lColumnValueLength++] = L'\r';
wColumnValue[lColumnValueLength++] = L'\n';

/* write to file */
if (WriteFile(hFile, wColumnName, lColumnNameLength * sizeof(WCHAR), &dwBytesWritten, 0)
&& WriteFile(hFile, wColumnValue, lColumnValueLength * sizeof(WCHAR), &dwBytesWritten, 0)) {
/* success */
continue;
}
}
} else {
/* out of buffer space */
lColumnNameLength = INFINITE;
}
bError = TRUE;
break;
}
}
CloseHandle(hFile);

if (! bError) {
bReturn = TRUE;
}
}
return bReturn;
}


BOOL CancelCollectionChanges(LPDATABASE lpDatabase, LPDATABASE_COLLECTION *lpCollection)
{
/* cancel collection changes and release locks - does nothing for now */
return TRUE;
}


BOOL QueryCollection(LPDATABASE lpDatabase, LPDATABASE_COLLECTION lpCollection)
{
LPDATABASE_VALUE lpValue;
HANDLE hFile;
LPWSTR *wszColumnName, *wszColumnValue;
PWCHAR pLine, pBuffer, pEnd, pCurrent, pOpeningBrace[2], pClosingBrace, pWordEnd;
ULONG lBufferLength, lRowID, lRowIndex, lColumnID, lColumnNameCount, lColumnValueCount, lWord, lWordCount;
BOOL bReturn = FALSE;

/* query collection */
hFile = CreateFileW(GetDatabaseCollectionName(lpCollection[0]),
GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
lBufferLength = GetFileSize(hFile, 0);
if (lBufferLength != INVALID_FILE_SIZE || GetLastError() == NO_ERROR) {
pBuffer = (WCHAR *)Allocate("Collection read buffer", lBufferLength + sizeof(WCHAR));
if (pBuffer != 0) {
if (ReadFile(hFile, pBuffer, lBufferLength, &lBufferLength, 0)) {
lBufferLength = (lBufferLength / 2) + 1;
pBuffer[lBufferLength - 1] = L'\n';

/* seek entries */
for (pLine = pBuffer;(pCurrent = wmemchr(pLine, L'\n', pEnd - pCurrent)) != 0;pLine = &pCurrent[1]) {
pCurrent[(pLine > pCurrent && pCurrent[-1] == L'\r' ? -1 : 0] = L'\0';

pOpeningBrace[0] = wmemchr(pLine, L'{', pCurrent - pLine);
if (! pOpeningBrace[0]) {
/* no opening brace */
continue;
}
pClosingBrace[0] = wmemchr(&pOpeningBrace[0][1], L'}', pCurrent - &pOpeningBrace[0][1]);
if (! pClosingBrace[0]) {
/* no closing brace */
continue;
}
pOpeningBrace[1] = wmemchr(&pClosingBrace[0][1], L'{', pCurrent - &pClosingBrace[0][1]);
if (! pOpeningBrace[1]) {
/* no opening brace */
continue;
}
pClosingBrace[1] = wmemchr(&pOpeningBrace[1][1], L'}', pCurrent - &pOpeningBrace[1][1]);
if (! pClosingBrace) {
/* no closign brace */
continue;
}
pClosingBrace[0][0] = '\0';
pClosingBrace[1][0] = '\0';

/* remove heading and tailing spaces */
for (pWordEnd = pOpeningBrace[0];pWordEnd > pLine && iswspace(pWordEnd[-1]);--pWordEnd);
pWordEnd[0] = L'\0';
for (;pLine < pWordEnd && iswspace(pLine[0]);++pLine);

for (lRowID = 0;lRowID < GetDatabaseRowIDCount(lpDatabase);lRowID++) {
if (! wcsicmp(GetDatabaseRowName(lpDatabase, lRowID), pLine)) {
/* create row and get known columns */
lRowIndex = CreateCollectionRow(lpCollection[0], lRowID);
if (lRowIndex == INFINITE) {
/* error could not create row */
break;
}

/* tokenize strings */
wszColumnName = TokenizeCommaSeperatedString(&pOpeningBrace[0][1], &lColumnNameCount);
if (wszColumnName != 0) {
wszColumnValue = TokenizeCommaSeperatedString(&pOpeningBrace[1][1], &lColumnValueCount);
if (wszColumnValue != 0) {
/* get known columns */
lWordCount = min(lColumnNameCount, lColumnValueCount);
for (lColumnID = 0;lColumnID < GetDatabaseRowColumnCount(lpDatabase, lRowID);++lColumnID) {
for (lWord = 0;lWord < lWordCount;lWord++) {
if (! _wcsicmp(GetDatabaseRowColumnName(lpDatabase, lRowID, lColumnID), wszColumnName[n])) {
/* create value */
lpValue = CreateWStringValue(wszColumnValue[n]);
if (lpValue != 0) {
if (! SetCollectionRowColumnValue(lpCollection, lRowID, lRowIndex, lColumnID, lpValue)) {
FreeValue(lpValue);
}
}
break;
}
}
}
Free(wszColumnValue);
}
Free(wszColumnName);
}
break;
}
}
}
}
Free(pBuffer);
}
}
CloseHandle(hFile);
}
return bReturn;
}


BOOL DeleteCollection(LPDATABASE lpDatabase, LPDATABASE_COLLECTION lpCollection)
{
/* delete collection */
return DeleteFileW(GetDatabaseCollectionName(lpCollection ));
}

BOOL CreateCollection(LPDATABASE lpDatabase, LPWSTR wszCollectionName)
{
HANDLE hFile;
BOOL bReturn = FALSE;

/* create collection */
hFile = CreateFileW(wszCollectionName,
GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0;
if (hFile != INVALID_HANDLE_VALUE) {
bReturn = TRUE;
CloseHandle(hFile);
}
return bReturn;
}

BOOL Shutdown(LPDATABASE lpDatabase)
{
/* module shutdown */
return TRUE;
}

darkone
05-08-2005, 08:33 PM
File format for database files is following (if someone wants to write FILEDB to SQL converter)...

also we'd appreciate, if someone comes up with a script that converts existing files (v5) to new (v6) format.



USER_CERTIFICATE {HASH} {098323829328}
USER_CERTIFICATE {HASH} {098323829328}
USER_CERTIFICATE {HASH} {098323829328}
USER_GROUP {GROUP,IS_ADMIN} {500,1}
USER_GROUP {GROUP,IS_ADMIN} {200,1}
USER_GROUP {GROUP,IS_ADMIN} {400,1}
USER_RATIO {SECTION,RATIO} {PUB,3}
USER_RATIO {SECTION,RATIO} {PRIVATE,0}
USER_STATS {SECTION,WKDN,WKUP} {PUB,0,0}
USER_STATS {SECTION,WKDN,WKUP} {PRIVATE,100,500}


{},\ characters have been escaped with \ character. Files have are stored in unicode format (Just like with earlier versions, you still should not access them directly - you should not expect them to exist at all!).

godlike
05-12-2005, 04:10 AM
Everything seems promising, but it was promising 1 year ago too, so this kind of leaves me still by a simple question as this: any ETA or anything to tell me when this will be done. Im waiting long time and i would love to see the new ioFTPD, i know you people are working hard on the project, but could you give an estimate on when u should be done.

thank you, and don`t be mad at my question. :p

peep
05-12-2005, 05:51 AM
As many before me has answerd to this sort of question, it's done when it's done! Since this is a new core being built and not just any simple upgrade, it will take time. Believe you me, you're not the only one waiting for the new io (which will probably by the way revolutionize the windows ftpd scene remarkably).
The only thing we can do is sit back and relax and wait for The Day to come!

darkone
05-13-2005, 06:19 AM
I'm currently somewhat behind the alpha schedule (there is actually such) due to some last minute changes/additions. Note that early alpha versions will be limited to httpd.

And just like peep said, most of the codebase is completely rewritten. Writing ftpd from ground up to match & surpass earlier version in terms of features, is a whole lot of work. Even some of the code that could have been recycled, such as configuration data reader and hostname resolver, has been completely rewritten.

Somnus
05-22-2005, 03:55 AM
Personally I am still waiting for the other shoe to drop.

It has been a while since an update, a new company has taken over, D1 vanishes for months, and now everything and it's dog is being re-written.

When do we see the new license fees for the new and "improved" version?

Obviously IniCom is investing time and money in this venture and is looking to get paid on the backend. That isn't going to happen when the project is was deemed pretty much dead to the people that know/use it....

Like I said, when the other shoe drops we will totally know what is going on, or will be going on.

darkone
05-22-2005, 08:13 AM
I'm not fully aware of license changes that will follow release of next version. But there will be obviously some due to following reasons:

1) io is now what I do for living, while it used to be a mere hobby.
2) there are other people involved in the developement process & product support.
3) we have specific market segment that we target.
4) io should no longer be considered only as ftp daemon.

One you should all note is that I would have not continued working on io anymore, if there wasn't inicom. Even though they are paying me monthly salary on those months that I work on io, I've been forced to do other projects to cover my living expenses.

I do expect license prices of commerical licenses to go up. Also I expect to see some changes in license terms. (eg. 2 years of free product updates or 3 major updates - the one that lasts longer applies)

As usual these are my opinions, and they do not represent inicom's view in any way.

peep
05-22-2005, 12:12 PM
Well it's a conciderable amount of hours you've put out on io and therefor I fully support that you should get paid for it, even tho' you once had a goal to make this one for free and not to go commercial.
I wouldn't either mind putting out a few extra $'s to get my hands on this next version, but IniCom only has a one-time fee on FlashFXP aswell don't they?
And finally, will you take the amount one has already paid for io into concideration, or will this be a new payment that will go straight to IniCom and has nothing to do with the previous?

Linkster
05-23-2005, 10:46 AM
Let me make a few things clear before this gets out of control.

1. Our current ioFTPD registered users are most important to us, and please trust that you will be well taken care of with any changes that occur. I don't want to spoil any surprises, but good things will happen :).

2. ioFTPD will become much more modular, and thus more flexible in supporting everyone from a single home/pro user to an enterprise. Single/Pro users will not have to pay for the enterprise level product/modules while still getting everything they need.

3. The current IO community, both users and scripters, are the backbone of this product. We will continue to ask for input from both in the development of the new product so it meets everyone's needs and more.

4. IO development continues to go well. Please do not ask when it will be done, or what it will include. We will drop hints, and ask for input when need be. There will be an alpha test for the scripters, as well as a beta test for everyone. Be patient, and you will be rewarded with the best ioFTPD to date.

5. There are many changes occuring, but they will not change what ioftpd originally set out to do, and that is to be an extremely light, but powerful windows FTP daemon. There will NOT be bloated GUI's added, and every piece of code is painstakingly scrutinized for speed/optimization. You should know by now that dark0ne is a freak about clean, fast code, and often rewrites an entire routine to improve the speed/efficiency of a couple lines.

Thank you for your enthusiasm, and your continual support.

-IniCom Networks, Inc.

peep
05-24-2005, 02:20 AM
Great! That's the kind of answer many has wanted to hear :)

FTPServerTools
05-24-2005, 02:51 AM
I dont mind writing a v5 to v6 converter but do you mean a file converter?? I thought you were going to put it in a database (sqlite hint hint...)

darkone
05-24-2005, 01:20 PM
Io does run with out SQL/LDAP/??? database. Flat file db (module) still exists, just like in previous versions.

iXi
05-25-2005, 09:41 AM
nice to see that io still alive;)