Go Back   FlashFXP Forums > > > >

ioFTPD General New releases, comments, questions regarding the latest version of ioFTPD.

Reply
 
Thread Tools Rate Thread Display Modes
Old 04-12-2005, 02:30 PM   #16
router
Member
ioFTPD Registered User
 
Join Date: Mar 2005
Posts: 26
Default

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
router is offline   Reply With Quote
Old 04-12-2005, 06:32 PM   #17
FTPServerTools
Senior Member
FlashFXP Beta Tester
ioFTPD Scripter
 
Join Date: Sep 2002
Posts: 543
Default

Great to see you back D1, we missed you.
FTPServerTools is offline   Reply With Quote
Old 05-03-2005, 05:58 AM   #18
peep
Senior Member
FlashFXP Scripter
ioFTPD Foundation User
 
Join Date: Sep 2003
Posts: 132
Default

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.
peep is offline   Reply With Quote
Old 05-03-2005, 07:09 AM   #19
caladan
Senior Member
ioFTPD Scripter
 
Join Date: Jan 2003
Posts: 179
Default

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
caladan is offline   Reply With Quote
Old 05-04-2005, 08:56 AM   #20
Mave_2
Member
 
Join Date: May 2003
Posts: 33
Default lo

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.
Mave_2 is offline   Reply With Quote
Old 05-06-2005, 02:30 AM   #21
darkone
Disabled
FlashFXP Registered User
ioFTPD Administrator
 
darkone's Avatar
 
Join Date: Dec 2001
Posts: 2,230
Default Ok

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>'
darkone is offline   Reply With Quote
Old 05-06-2005, 02:08 PM   #22
SnypeTEST
Senior Member
ioFTPD Scripter
 
Join Date: Feb 2003
Posts: 458
Default

ah.. LUA is da bombzzzz...
SnypeTEST is offline   Reply With Quote
Old 05-07-2005, 12:19 PM   #23
darkone
Disabled
FlashFXP Registered User
ioFTPD Administrator
 
darkone's Avatar
 
Join Date: Dec 2001
Posts: 2,230
Default

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.

Code:
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 is offline   Reply With Quote
Old 05-08-2005, 08:33 PM   #24
darkone
Disabled
FlashFXP Registered User
ioFTPD Administrator
 
darkone's Avatar
 
Join Date: Dec 2001
Posts: 2,230
Default

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.


Code:
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!).
darkone is offline   Reply With Quote
Old 05-12-2005, 04:10 AM   #25
godlike
Senior Member
ioFTPD Foundation User
 
Join Date: Dec 2003
Posts: 94
Default

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.
godlike is offline   Reply With Quote
Old 05-12-2005, 05:51 AM   #26
peep
Senior Member
FlashFXP Scripter
ioFTPD Foundation User
 
Join Date: Sep 2003
Posts: 132
Default

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!
peep is offline   Reply With Quote
Old 05-13-2005, 06:19 AM   #27
darkone
Disabled
FlashFXP Registered User
ioFTPD Administrator
 
darkone's Avatar
 
Join Date: Dec 2001
Posts: 2,230
Default

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.
darkone is offline   Reply With Quote
Old 05-22-2005, 03:55 AM   #28
Somnus
Junior Member
 
Join Date: Jun 2004
Posts: 16
Default

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.
Somnus is offline   Reply With Quote
Old 05-22-2005, 08:13 AM   #29
darkone
Disabled
FlashFXP Registered User
ioFTPD Administrator
 
darkone's Avatar
 
Join Date: Dec 2001
Posts: 2,230
Default

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.
darkone is offline   Reply With Quote
Old 05-22-2005, 12:12 PM   #30
peep
Senior Member
FlashFXP Scripter
ioFTPD Foundation User
 
Join Date: Sep 2003
Posts: 132
Default

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?
peep is offline   Reply With Quote
Reply

Tags
api, item, list, long, time

Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
No UTF8 or Unicode Support! Tahattmeruh Software 1 12-02-2002 06:45 PM


All times are GMT -5. The time now is 09:17 AM.

Parts of this site powered by vBulletin Mods & Addons from DragonByte Technologies Ltd. (Details)