Exemple #1
0
/***************************************************************************
Desc:
****************************************************************************/
void FilenameIterator::produceFilename(
	char *			pszBuffer)
{
	char 		pszTemp[ FILENAME_ITERATOR_MAX_EXTENSION_LENGTH + 1];
	
	f_strcpy( pszBuffer, m_pszFullPrefix);
	f_strcat( pszBuffer, ".");
	f_sprintf( pszTemp, "%03x", (unsigned)m_uiExtension);
	f_strcat( pszBuffer, pszTemp);
}
Exemple #2
0
/***************************************************************************
Desc:
****************************************************************************/
FilenameIterator::FilenameIterator(
	const char * 		pszPath, 
	const char * 		pszPrefix)
{

	f_strcpy( m_pszFullPrefix, pszPath);

#if defined( FLM_UNIX)
	f_strcat( m_pszFullPrefix, "/");
#elif defined( FLM_WIN) || defined( FLM_NLM)
	f_strcat( m_pszFullPrefix, "\\");
#else
	#error Platform not supported.
#endif

	f_strcat( m_pszFullPrefix, pszPrefix);
	this->reset();
}
Exemple #3
0
/****************************************************************************
Desc:
****************************************************************************/
FlagSet FlagSet::crossProduct( 
	FlagSet&		fs2)
{
	FlagSet		fsCross;
	FLMUINT		uiLoop1;
	FLMUINT		uiCrossProductElems = this->getNumElements() * fs2.getNumElements();
	FLMBYTE **	ppszCross = NULL;
	
	if( RC_BAD( f_alloc( sizeof( FLMBYTE *) * uiCrossProductElems,
		&ppszCross)))
	{
		flmAssert( 0);
		goto Exit;
	}

	for( uiLoop1 = 0; uiLoop1 < this->getNumElements(); uiLoop1++)
	{
		for( FLMUINT uiLoop2 = 0; uiLoop2 < fs2.getNumElements(); uiLoop2++)
		{
			FLMUINT	uiIndex = uiLoop1 * fs2.getNumElements() + uiLoop2;
			
			if( RC_BAD( f_alloc( f_strlen((char *)this->m_ppucElemArray[ uiLoop1]) + 
						f_strlen((char *)fs2.m_ppucElemArray[ uiLoop2]) + 1,
					&ppszCross[ uiIndex])))
			{
				flmAssert( 0);
			}
			
			f_strcpy( (char *)ppszCross[ uiIndex], 
				(char *)this->m_ppucElemArray[ uiLoop1]);
				
			f_strcat( (char *)ppszCross[ uiIndex], 
				(char *)fs2.m_ppucElemArray[ uiLoop2]);
		}
	}
	
	fsCross.init( ppszCross, uiCrossProductElems);

	for( uiLoop1 = 0; uiLoop1 < uiCrossProductElems; uiLoop1++)
	{
		f_free( &ppszCross[ uiLoop1]);
	}
	
	f_free( &ppszCross);
	
Exit:

	return( fsCross);
}
/****************************************************************************
Desc:	Prints the web page showing the binary data in an SCache block
****************************************************************************/
RCODE F_SCacheDataPage::display( 
	FLMUINT			uiNumParams,
	const char ** 	ppszParams)
{
	RCODE			rc = FERR_OK;

	FLMUINT		uiBlkAddress = 0;
	FLMUINT		uiLowTransID = 0;
	FLMUINT		uiHighTransID = 0;
	FFILE *		pFile = NULL;
	FLMBOOL		bFlaimLocked = FALSE;
	SCACHE		LocalSCacheBlock;
	char *		pucData = NULL;
	char *		pucDataLine;
	char			szData[97];
	char			szOneChar[7];
	FLMUINT		uiCurrentOffset = 0;
	FLMUINT		uiLoop = 0;
	
	f_mutexLock( gv_FlmSysData.hShareMutex);
	bFlaimLocked = TRUE;
	rc = locateSCacheBlock( uiNumParams, ppszParams, &LocalSCacheBlock,
									&uiBlkAddress, &uiLowTransID,	&uiHighTransID,
									&pFile);
	if (RC_BAD( rc))
	{
		if(rc == FERR_NOT_FOUND)
		{
			notFoundErr();
			rc = FERR_OK;
		}
		goto Exit;
	}
	else
	{
		// Store the data in a local variable...
		if( RC_BAD( rc = f_alloc( 
			LocalSCacheBlock.ui16BlkSize, &pucData)))
		{
			goto Exit;
		}

		f_memcpy( pucData, LocalSCacheBlock.pucBlk, LocalSCacheBlock.ui16BlkSize);
	}

	f_mutexUnlock( gv_FlmSysData.hShareMutex);
	bFlaimLocked = FALSE;

	// Start the HTML...
	
	stdHdr();
	fnPrintf( m_pHRequest, HTML_DOCTYPE 
				"<HTML> <BODY>\n<font face=arial><PRE>\n");

	while (uiCurrentOffset < LocalSCacheBlock.ui16BlkSize)
	{
		szData[0] = '\0';
		pucDataLine =  pucData + uiCurrentOffset;
		fnPrintf( m_pHRequest, "<font color=blue>0x%04X</font>    "
						"%02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X    ",
						uiCurrentOffset,
						pucDataLine[ 0], pucDataLine[ 1], pucDataLine[ 2], pucDataLine[ 3],
						pucDataLine[ 4], pucDataLine[ 5], pucDataLine[ 6], pucDataLine[ 7],
						pucDataLine[ 8], pucDataLine[ 9], pucDataLine[10], pucDataLine[11],
						pucDataLine[12], pucDataLine[13], pucDataLine[14], pucDataLine[15]);
	
		for (uiLoop = 0; uiLoop < 16; uiLoop++)
		{
			if (	(pucDataLine[uiLoop] >= 32) &&  // 32 is a space
					(pucDataLine[uiLoop] <= 126)  ) // 126 is a ~
			{
				f_sprintf( szOneChar, "&#%d;", pucDataLine[uiLoop]);
			}
			else
			{
				f_strcpy( szOneChar, "&#46;"); // 46 is a .
			}
			f_strcat(szData, szOneChar);

			// The reason for all the &#xxx; nonsence is because if we just put
			// the characters into a string, when the brower comes across a <
			// character, it will try to interpret what follows as an HTML
			// tag...
		}

		fnPrintf( m_pHRequest, "<font color=green>%s</font>\n", szData);
		
		uiCurrentOffset += 16;
	}

	fnPrintf( m_pHRequest, "</PRE></font>\n</BODY> </HTML>\n");
	fnEmit();

Exit:
	if (bFlaimLocked)
	{
		f_mutexUnlock( gv_FlmSysData.hShareMutex);
	}

	if (pucData)
	{
		f_free( &pucData);
	}

	return( rc);
}
/****************************************************************************
Desc:	Prints the web page for an SCACHE struct
****************************************************************************/
RCODE F_SCacheBlockPage::display(
	FLMUINT			uiNumParams,
	const char ** 	ppszParams)
{
	RCODE				rc = FERR_OK;
	FLMUINT			uiBlkAddress = 0;
	FLMUINT			uiLowTransID = 0;
	FLMUINT			uiHighTransID = 0;
	FFILE *			pFile;
	FLMBOOL			bHighlight = FALSE;
	char *			pszTemp = NULL;
	char *			pszTemp1 = NULL;
	FLMUINT			uiLoop = 0;
	char				szOffsetTable[10][6];
	char				szAddressTable[4][20];
	SCACHE			LocalSCacheBlock;
	FLMUINT			uiPFileBucket = 0;
	char *			pszSCacheRequestString[8] = {0, 0, 0, 0, 0, 0, 0, 0};
	char *			pszSCacheDataRequest = NULL;
	char *			pszSCacheAutoRequest = NULL; 
	char *			pszSCacheUseListRequest = NULL;
	char *			pszSCacheNotifyListRequest = NULL;
	char *			pszFFileRequest = NULL;
	char *			pszFlagNames = NULL;

	if( RC_BAD( rc = f_alloc( 200, &pszTemp)))
	{
		printErrorPage( rc, TRUE, (char *)"Failed to allocate temporary buffer");
		goto Exit;
	}

	if( RC_BAD( rc = f_alloc( 200, &pszTemp1)))
	{
		printErrorPage( rc, TRUE, (char *)"Failed to allocate temporary buffer");
		goto Exit;
	}

	// Allocate memory for all those string pointers we declared above...
	for (uiLoop = 0; uiLoop < 8; uiLoop++)
	{
		if( RC_BAD( rc = f_alloc( 150, &pszSCacheRequestString[ uiLoop])))
		{
			goto Exit;
		}
	}
		
	if( RC_BAD( rc = f_alloc( 150, &pszSCacheDataRequest)))
	{
		goto Exit;
	}

	if( RC_BAD( rc = f_alloc( 150, &pszSCacheAutoRequest)))
	{
		goto Exit;
	}

	if( RC_BAD( rc = f_alloc( 150, &pszSCacheUseListRequest)))
	{
		goto Exit;
	}

	if( RC_BAD( rc = f_alloc( 150, &pszSCacheNotifyListRequest)))
	{
		goto Exit;
	}

	if( RC_BAD( rc = f_alloc( 100, &pszFFileRequest)))
	{
		goto Exit;
	}

	if( RC_BAD( rc = f_alloc( 100, &pszFlagNames)))
	{
		goto Exit;
	}

	f_mutexLock( gv_FlmSysData.hShareMutex);

	rc = locateSCacheBlock( uiNumParams, ppszParams, &LocalSCacheBlock,
									&uiBlkAddress, &uiLowTransID,	&uiHighTransID,
									&pFile);

	if (RC_OK(rc) && LocalSCacheBlock.pFile)
	{
		uiPFileBucket = LocalSCacheBlock.pFile->uiBucket;
	}

	
	if (RC_OK( rc))
	{
		// Build the proper strings to request various other SCache blocks
		flmBuildSCacheBlockString( pszSCacheRequestString[0], LocalSCacheBlock.pPrevInFile);
		flmBuildSCacheBlockString( pszSCacheRequestString[1], LocalSCacheBlock.pNextInFile);
		flmBuildSCacheBlockString( pszSCacheRequestString[2], LocalSCacheBlock.pPrevInGlobalList);
		flmBuildSCacheBlockString( pszSCacheRequestString[3], LocalSCacheBlock.pNextInGlobalList);
		flmBuildSCacheBlockString( pszSCacheRequestString[4], LocalSCacheBlock.pPrevInHashBucket);
		flmBuildSCacheBlockString( pszSCacheRequestString[5], LocalSCacheBlock.pNextInHashBucket);
		flmBuildSCacheBlockString( pszSCacheRequestString[6], LocalSCacheBlock.pPrevInVersionList);
		flmBuildSCacheBlockString( pszSCacheRequestString[7], LocalSCacheBlock.pNextInVersionList);

		// Build the proper string to request the current Page
		flmBuildSCacheBlockString( pszSCacheAutoRequest, &LocalSCacheBlock);
	}

	f_mutexUnlock( gv_FlmSysData.hShareMutex);

	if (RC_BAD( rc))
	{
		if (rc == FERR_NOT_FOUND)
		{
			
			// The block wasn't there, print an error message and exit
			notFoundErr();
			rc = FERR_OK;
		}
		else if (rc == FERR_MEM)
		{
			// Parameters were too long to store in the space provided.
			// Probably means that the URL was malformed...
			malformedUrlErr();
			rc = FERR_OK;
		}
		goto Exit;
	}
	
	//Build the proper string to request this block's data...
	printAddress( pFile, szAddressTable[0]);
	f_sprintf( (char *)pszSCacheDataRequest,
		"%s/SCacheData?BlockAddress=%lu&File=%s&LowTransID=%lu&HighTransID=%lu",
		m_pszURLString, LocalSCacheBlock.uiBlkAddress, szAddressTable[0],
		uiLowTransID, uiHighTransID);
	
#ifdef FLM_DEBUG
	//Build the proper string to request this block's use list
	if( LocalSCacheBlock.pUseList)
	{
		f_sprintf( (char *)pszSCacheUseListRequest,
			"%s/SCacheUseList?BlockAddress=%lu&File=%s&LowTransID=%lu&HighTransID=%lu",
			m_pszURLString, LocalSCacheBlock.uiBlkAddress, szAddressTable[0],
			uiLowTransID, uiHighTransID);
	}
	else
	{
		pszSCacheUseListRequest[0] = '\0';
	}
#endif

	//Build the proper string to request the notify list data...
	if (LocalSCacheBlock.pNotifyList)
	{
		f_sprintf( (char *)pszSCacheNotifyListRequest,
			"%s/SCacheNotifyList?BlockAddress=%lu&File=%s&LowTransID=%lu&HighTransID=%lu",
			m_pszURLString, LocalSCacheBlock.uiBlkAddress, szAddressTable[0],
			uiLowTransID, uiHighTransID);
	}
	else
	{
		pszSCacheNotifyListRequest[0] = '\0';
	}

	//Build the proper string to request the FFile
	printAddress( LocalSCacheBlock.pFile, szAddressTable[0]);
	f_sprintf( (char *)pszFFileRequest, "%s/FFile?From=SCacheBlock&Bucket=%lu&Address=%s",
				 m_pszURLString, uiPFileBucket, szAddressTable[0]);
					

	// Build a string with the names of all the flags that have been set...
	pszFlagNames[0]='\0';
	if (LocalSCacheBlock.ui16Flags & CA_DIRTY)
	{
		f_strcat( pszFlagNames, "<BR> CA_DIRTY");
	}
	if (LocalSCacheBlock.ui16Flags & CA_READ_PENDING)
	{
		f_strcat( pszFlagNames, "<BR> CA_READ_PENDING");
	}
	if (LocalSCacheBlock.ui16Flags & CA_WRITE_TO_LOG)
	{
		f_strcat( pszFlagNames, "<BR> CA_WRITE_TO_LOG");
	}
	if (LocalSCacheBlock.ui16Flags & CA_LOG_FOR_CP)
	{
		f_strcat( pszFlagNames, "<BR> CA_LOG_FOR_CP");
	}
	if (LocalSCacheBlock.ui16Flags & CA_WAS_DIRTY)
	{
		f_strcat( pszFlagNames, "<BR> CA_WAS_DIRTY");
	}
	if (LocalSCacheBlock.ui16Flags & CA_WRITE_PENDING)
	{
		f_strcat( pszFlagNames, "<BR> CA_WRITE_PENDING");
	}
	if (LocalSCacheBlock.ui16Flags & CA_IN_WRITE_PENDING_LIST)
	{
		f_strcat( pszFlagNames, "<BR> CA_IN_WRITE_PENDING_LIST");
	}


	// OK - Start outputting HTML...
	stdHdr();

	fnPrintf( m_pHRequest, HTML_DOCTYPE "<html>\n");
		
	// Determine if we are being requested to refresh this page or  not.
	if (DetectParameter( uiNumParams, ppszParams, "Refresh"))
	{
		// Send back the page with a refresh command in the header
		fnPrintf( m_pHRequest, 
			"<HEAD>\n"
			"<META http-equiv=\"refresh\" content=\"5; url=\"%s\">"
			"<TITLE>SCache Block</TITLE>\n", pszSCacheAutoRequest);
		printStyle();
		popupFrame();  //Spits out a Javascript function that will open a new window..
		fnPrintf( m_pHRequest, "</HEAD>\n<body>\n");
		
		f_sprintf( (char*)pszTemp,
					"<A HREF=\"%s\">Stop Auto-refresh</A>", pszSCacheAutoRequest);
	}
	else
	{
		// Send back a page without the refresh command
		
		fnPrintf( m_pHRequest, "<HEAD>\n");
		printStyle();
		popupFrame();  //Spits out a Javascript function that will open a new window..
		fnPrintf( m_pHRequest, "</HEAD>\n<body>\n");
		
		f_sprintf( (char *)pszTemp,
					"<A HREF=\"%s?Refresh\">Start Auto-refresh (5 sec.)</A>", pszSCacheAutoRequest);
	}

	// Write out the table headings
	printTableStart( "SCache Block Structure", 4, 100);

	printTableRowStart();
	printColumnHeading( "", JUSTIFY_LEFT, FLM_IMON_COLOR_PUTTY_1, 4, 1, FALSE);
	fnPrintf( m_pHRequest, "<A HREF=\"%s\">Refresh</A>, %s\n",
				 pszSCacheAutoRequest, pszTemp);
	printColumnHeadingClose();
	printTableRowEnd();

	// Write out the table headings.
	printTableRowStart();
	printColumnHeading( "Byte Offset (hex)");
	printColumnHeading( "Field Name");
	printColumnHeading( "Field Type");
	printColumnHeading( "Value");
	printTableRowEnd();

	// Print the two rows for pPrevInFile and pNextInFile
	printTableRowStart( bHighlight = ~bHighlight);
	flmPrintCacheLine(m_pHRequest, pszSCacheRequestString[0], "pPrevInFile", &LocalSCacheBlock, &LocalSCacheBlock.pPrevInFile);
	printTableRowStart( bHighlight = ~bHighlight);
	flmPrintCacheLine(m_pHRequest, pszSCacheRequestString[1], "pNextInFile", &LocalSCacheBlock, &LocalSCacheBlock.pNextInFile);


	// Format the strings that are displayed in the Offset and Address
	// columns of the table
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.pucBlk, szOffsetTable[0]);
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.pFile, szOffsetTable[1]);
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.uiBlkAddress, szOffsetTable[2]);
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.pNotifyList, szOffsetTable[3]);
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.uiHighTransID, szOffsetTable[4]);
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.uiUseCount, szOffsetTable[5]);
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.ui16Flags, szOffsetTable[6]);
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.ui16BlkSize, szOffsetTable[7]);
#ifdef FLM_DEBUG
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.uiChecksum, szOffsetTable[8]);
	printOffset( &LocalSCacheBlock, &LocalSCacheBlock.pUseList, szOffsetTable[9]);
#endif

	printAddress( LocalSCacheBlock.pucBlk, szAddressTable[0]);
	printAddress( LocalSCacheBlock.pFile, szAddressTable[1]);
	printAddress( LocalSCacheBlock.pNotifyList, szAddressTable[2]);
#ifdef FLM_DEBUG
	printAddress( LocalSCacheBlock.pUseList, szAddressTable[3]);
#endif


	printTableRowStart( bHighlight = ~bHighlight);
	fnPrintf( m_pHRequest, TD_s "<td><A HREF=\"javascript:openPopup('%s')\">pucBlk</A></td>\n"
				"<td>FLMBYTE *</td>\n<td><A HREF=\"javascript:openPopup('%s')\">%s</A></td>\n",
				szOffsetTable[0],	pszSCacheDataRequest, pszSCacheDataRequest, szAddressTable[0] );
	printTableRowEnd();

	printTableRowStart( bHighlight = ~bHighlight);
	fnPrintf( m_pHRequest, TD_s "<td><A href=%s>pFile</A></td>\n"
				"<td>FFILE *</td>\n<td><A HREF=%s>%s</a></td>\n",
				szOffsetTable[1], pszFFileRequest, pszFFileRequest, szAddressTable[1]);
	printTableRowEnd();

	printTableRowStart( bHighlight = ~bHighlight);
	fnPrintf( m_pHRequest, TD_s "<td>uiBlkAddress</td>\n<td>FLMUINT</td>\n"
				"<td>0x%lX</td>\n", szOffsetTable[2], LocalSCacheBlock.uiBlkAddress);
	printTableRowEnd();

	//Print the rows for the remaining SCache * fields
	printTableRowStart( bHighlight = ~bHighlight);
	flmPrintCacheLine(m_pHRequest, pszSCacheRequestString[2], "pPrevInGlobalList", &LocalSCacheBlock, &LocalSCacheBlock.pPrevInGlobalList);		
	printTableRowStart( bHighlight = ~bHighlight);
	flmPrintCacheLine(m_pHRequest, pszSCacheRequestString[3], "pNextInGlobalList", &LocalSCacheBlock, &LocalSCacheBlock.pNextInGlobalList);
	printTableRowStart( bHighlight = ~bHighlight);
	flmPrintCacheLine(m_pHRequest, pszSCacheRequestString[4], "pPrevInHashBucket", &LocalSCacheBlock, &LocalSCacheBlock.pPrevInHashBucket);		
	printTableRowStart( bHighlight = ~bHighlight);
	flmPrintCacheLine(m_pHRequest, pszSCacheRequestString[5], "pNextInHashBucket", &LocalSCacheBlock, &LocalSCacheBlock.pNextInHashBucket);
	printTableRowStart( bHighlight = ~bHighlight);
	flmPrintCacheLine(m_pHRequest, pszSCacheRequestString[6], "pPrevInVersionList", &LocalSCacheBlock, &LocalSCacheBlock.pPrevInVersionList);		
	printTableRowStart( bHighlight = ~bHighlight);
	flmPrintCacheLine(m_pHRequest, pszSCacheRequestString[7], "pNextInVersionList", &LocalSCacheBlock, &LocalSCacheBlock.pNextInVersionList);

	//Notify list line
	printTableRowStart( bHighlight = ~bHighlight);
	if (LocalSCacheBlock.pNotifyList)
	{
		fnPrintf( m_pHRequest,
			TD_s
			" <td> <A HREF=\"javascript:openPopup('%s')\"> pNotifyList </A> </td>	<td>FNOTIFY *</td> "
			"<td> <A HREF=\"javascript:openPopup('%s')\"> %s </A> </td>",
			szOffsetTable[3], pszSCacheNotifyListRequest,
			pszSCacheNotifyListRequest, szAddressTable[2]);
	}
	else
	{
		fnPrintf( m_pHRequest,
			TD_s " <td> pNotifyList </td>	<td>FNOTIFY *</td> "
			"<td> 0x0 </td>", szOffsetTable[3]);
	}
	printTableRowEnd();


	printTableRowStart( bHighlight = ~bHighlight);
	fnPrintf( m_pHRequest, TD_s "<td>uiHighTransID</td>\n"
				"<td>FLMUINT</td>\n" TD_8x, szOffsetTable[4],
				LocalSCacheBlock.uiHighTransID);
	printTableRowEnd();

	printTableRowStart( bHighlight = ~bHighlight);
	fnPrintf( m_pHRequest, TD_s "<td>uiUseCount</td>\n<td>FLMUINT</td>\n"
				 TD_lu,  szOffsetTable[5], LocalSCacheBlock.uiUseCount);
	printTableRowEnd();

	printTableRowStart( bHighlight = ~bHighlight);
	fnPrintf( m_pHRequest, TD_s "<td>ui16Flags</td>\n<td>FLMUINT16</td>\n"
					"<td>0x%04X %s</td>\n", szOffsetTable[6],
					LocalSCacheBlock.ui16Flags, pszFlagNames);
	printTableRowEnd();

	printTableRowStart( bHighlight = ~bHighlight);
	fnPrintf( m_pHRequest, TD_s "<td>ui16BlkSize</td>\n<td>FLMUINT16</td>\n" TD_i,
					szOffsetTable[7], LocalSCacheBlock.ui16BlkSize);
	printTableRowEnd();

#ifdef FLM_DEBUG
	printTableRowStart( bHighlight = ~bHighlight);
	fnPrintf( m_pHRequest, TD_s "<td>uiChecksum</td>\n"
					"<td>FLMUINT</td>\n" TD_8x,
					szOffsetTable[8], LocalSCacheBlock.uiChecksum);
	printTableRowEnd();
#endif


#ifdef FLM_DEBUG
		//Last line - the use list...
		printTableRowStart( bHighlight = ~bHighlight);
		if (LocalSCacheBlock.pUseList)
		{
			fnPrintf( m_pHRequest,
				TD_s " <td> <A href=\"javascript:openPopup('%s')> pUseList </A> </td>	<td> SCACHE_USE_p </td>		<td> <A href=\"javascript:openPopup('%s')> %s </A></td>",
				szOffsetTable[9], pszSCacheUseListRequest, pszSCacheUseListRequest, szAddressTable[3]);
		}
		else
		{
			fnPrintf( m_pHRequest,
				TD_s " <td> pUseList </td>	<td> SCACHE_USE_p </td>	<td> 0x0 </td>",
				szOffsetTable[9]);
		}
		printTableRowEnd();

#endif

	fnPrintf( m_pHRequest, TABLE_END "</BODY></HTML>\n");
	fnEmit();

Exit:

	// Even though uiLoop2 is not in the same scope as uiLoop, VC6 still
	// complains if this is called uiLoop....
	for (FLMUINT uiLoop2 = 0; uiLoop2 < 8; uiLoop2++)
	{
		if (pszSCacheRequestString[uiLoop2])
		{
			f_free( &pszSCacheRequestString[uiLoop2]);
		}
	}

	if (pszSCacheDataRequest)
	{
		f_free( &pszSCacheDataRequest);
	}

	if (pszSCacheAutoRequest)
	{
		f_free( &pszSCacheAutoRequest);
	}

	if (pszSCacheUseListRequest)
	{
		f_free( &pszSCacheUseListRequest);
	}

	if (pszSCacheNotifyListRequest)
	{
		f_free( &pszSCacheNotifyListRequest);
	}
	
	if( pszFFileRequest)
	{
		f_free( &pszFFileRequest);
	}

	if( pszFlagNames)
	{
		f_free( &pszFlagNames);
	}

	if (pszTemp)
	{
		f_free( &pszTemp);
	}

	if (pszTemp1)
	{
		f_free( &pszTemp1);
	}

	return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE SortKeyTestImpl::createOrModifyIndex( 
	FLMUINT			uiIndex,
	FLMBOOL			bComp1SortDescending,
	FLMBOOL			bComp1CaseSensitive,
	FLMBOOL			bComp1SortMissingHigh,
	FLMBOOL			bComp2SortDescending,
	FLMBOOL			bComp2SortMissingHigh)
{
	RCODE				rc = NE_XFLM_OK;
	char				szCompareRules1[100];
	char				szCompareRules2[100];
	char				szName[100];
	char *			pszIndex = NULL;
	IF_DOMNode *	pNode = NULL;
	const char *	pszIndexFormat = 		
		"<xflaim:Index "
			"xmlns:xflaim=\"http://www.novell.com/XMLDatabase/Schema\" "
			"xflaim:name=\"%s_IX\" "
			"xflaim:DictNumber=\"%u\">"
			"<xflaim:ElementComponent "
				"xflaim:CompareRules=\"%s\" "
				"xflaim:targetNameSpace=\"\" "
				"xflaim:DictNumber=\"%u\" "
				"xflaim:IndexOn=\"value\" "
				"xflaim:Required=\"1\" " // have to make this required so it will match the sort key ixd
				"xflaim:KeyComponent=\"1\" />"
			"<xflaim:ElementComponent "
				"xflaim:CompareRules=\"%s\" "
				"xflaim:targetNameSpace=\"\" "
				"xflaim:DictNumber=\"%u\" "
				"xflaim:IndexOn=\"value\" "
				"xflaim:Required=\"1\" " // have to make this required so it will match the sort key ixd
				"xflaim:KeyComponent=\"2\"/>"
		"</xflaim:Index>";

	szCompareRules1[0] = '\0';
	szCompareRules2[0] = '\0';

	if( bComp1SortDescending)
	{
		f_strcpy( szCompareRules1, XFLM_DESCENDING_OPTION_STR);
	}

	if ( !bComp1CaseSensitive)
	{
		f_strcat( szCompareRules1, " "XFLM_CASE_INSENSITIVE_OPTION_STR);
	}

	if ( bComp1SortMissingHigh)
	{
		f_strcat( szCompareRules1, " "XFLM_MISSING_HIGH_OPTION_STR);
	}

	if ( bComp2SortDescending)
	{
		f_strcpy( szCompareRules2, XFLM_DESCENDING_OPTION_STR);
	}

	if ( bComp2SortMissingHigh)
	{
		f_strcat( szCompareRules2, " "XFLM_MISSING_HIGH_OPTION_STR);
	}

	f_sprintf( szName, "(%s/%s)", szCompareRules1, szCompareRules2); 

	if ( RC_BAD( rc = f_alloc( f_strlen( pszIndexFormat) + 
		(f_strlen( szCompareRules1) + f_strlen(szCompareRules2)) * 2 +
		16, &pszIndex)))
	{
		MAKE_FLM_ERROR_STRING( "f_alloc failed", m_szDetails, rc);
		goto Exit;
	}

	f_sprintf( pszIndex, pszIndexFormat, szName, uiIndex, 
		szCompareRules1, FIRST_NAME_ID, szCompareRules2, LAST_NAME_ID); 

	// remove the index if it already exists

	if ( RC_OK( rc = m_pDb->getDictionaryDef( ELM_INDEX_TAG, uiIndex, &pNode)))
	{
		if ( RC_BAD( rc = pNode->deleteNode( m_pDb)))
		{
			MAKE_FLM_ERROR_STRING( "deleteNode failed.", m_szDetails, rc);
			goto Exit;
		}
	}

	if ( RC_BAD( rc = importBuffer( pszIndex, XFLM_DICT_COLLECTION)))
	{
		goto Exit;
	}

Exit:

	if ( pNode)
	{
		pNode->Release();
	}

	if ( pszIndex)
	{
		f_free( &pszIndex);
	}

	return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE IMetaphoneTestImpl::suite1( void)
{
	RCODE					rc = NE_XFLM_OK;
	IF_DOMNode *		pRoot = NULL;
	IF_DOMNode *		pChild = NULL;
	FLMBOOL				bTransStarted = FALSE;
	FLMBOOL				bDibCreated = FALSE;
	FLMUINT				uiLoop = 0;
	FLMUINT				uiWordDictNum = 0;
	IF_PosIStream	*	pMetaphoneIStream = NULL;
	IF_DataVector *	pSearchKey = NULL;
	IF_DataVector *	pFoundKey = NULL;
	FLMUINT				uiMetaphone1 = 0;
	FLMUINT				uiMetaphone2 = 0;
	FLMUINT				uiIxMetaVal;
	const char *		pszIndexDef =
		"<xflaim:Index "
		"	xmlns:xflaim=\"http://www.novell.com/XMLDatabase/Schema\""
		"	xflaim:name=\"Misspelled Words\" "
		"	xflaim:DictNumber=\"77\"> " // HARD-CODED Dict Num for easy retrieval
		"	<xflaim:ElementComponent "
		"		xflaim:name=\"Word\" "
		"		xflaim:KeyComponent=\"1\" "
		"		xflaim:IndexOn=\"metaphone\"/> "
		"</xflaim:Index> ";

	WordPair commonMisspellings[] =
	{
		//correct,incorrect
		
		{"night","nite"},
		{"anoint","annoint"},   
		{"coolly","cooly"}, 
		{"supercede","supersede"},   
		{"irresistible","irresistable"},   
		{"development","developement"},   
		{"separate","seperate"},   
		{"tyranny ","tyrrany"},
		{"harass", "harrass"}, 
		{"desiccate", "dessicate"},
		{"indispensable", "indispensible"}, 
		{"receive","recieve"}, 
		{"pursue", "persue"}, 
		{"recommend","reccomend"},
		{"desperate","desparate"}, 
		{"liquefy","liquify"}, 
		{"seize", "sieze"}, 
		{"cemetery","cemetary"},  
		{"subpoena", "subpena"}, 
		{"definitely", "definately"},
		{"occasion","ocassion"},
		{"consensus", "concensus"}, 
		{"inadvertent","inadvertant"},   
		{"miniscule","minuscule"},
		{"judgment","judgement"},
		{"inoculate","innoculate"}, 
		{"drunkenness","drunkeness"}, 
		{"occurrence","occurence"}, 
		{"dissipate","disippate"}, 
		{"weird","wierd"}, 
		{"accommodate","accomodate"},
		{"embarrassment","embarassment"},
		{"ecstasy","ecstacy"},
		{"repetition","repitition"},
		{"batallion","battalion"},
		{"despair","dispair"},
		{"irritable","irritible"},
		{"accidentally","accidently"},
		{"liaison","liason"},
		{"memento","momento "},
		{"broccoli","brocolli"},
		{"millennium","millenium"},
		{"yield","yeild"},
		{"existence","existance"},
		{"independent","independant"},
		{"sacrilegious","sacreligious"},
		{"insistent","insistant"},
		{"excee","excede"},
		{"privilege","priviledge"},
	};

	FLMUINT		uiNumWords = sizeof( commonMisspellings)/sizeof( commonMisspellings[0]);
 
	if ( RC_BAD( rc = initCleanTestState( DB_NAME_STR)))
	{
		MAKE_FLM_ERROR_STRING( "Failed to init test state.", m_szDetails, rc);
		goto Exit;
	}
	bDibCreated = TRUE;
	
	if ( RC_BAD( rc = m_pDb->transBegin( XFLM_UPDATE_TRANS)))
	{
		MAKE_FLM_ERROR_STRING( "transBegin failed", m_szDetails, rc);
		goto Exit;
	}
	bTransStarted = TRUE;

	if ( RC_BAD( rc = m_pDb->createElementDef(		
		NULL,
		"Word",
		XFLM_TEXT_TYPE,
		&uiWordDictNum)))
	{
		MAKE_FLM_ERROR_STRING( "createElementDef failed.", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = importBuffer( pszIndexDef, XFLM_DICT_COLLECTION)))
	{
		 goto Exit;
	}

	beginTest( 
		"Metaphone Index Key Creation Test",
		"Make sure mispelled words can be used to retrieve index keys "
		"created for correctly-spelled words.",
		"1) Create nodes with correctly-spelled words "
		"2) search for the index keys using mispelled versions of those words ",
		"");

	//Create a node with a word attribute with a value of a correctly-spelled word
	
	if( RC_BAD( rc = m_pDb->createRootElement(
		XFLM_DATA_COLLECTION, ELM_ELEMENT_TAG, &pRoot)))
	{
		MAKE_FLM_ERROR_STRING( "createRootElement failed.", m_szDetails, rc);
		goto Exit;
	}

	for( uiLoop = 0; uiLoop < uiNumWords; uiLoop++)
	{
		if( RC_BAD( rc = pRoot->createNode( 
			m_pDb, ELEMENT_NODE, uiWordDictNum, XFLM_FIRST_CHILD, &pChild)))
		{
			MAKE_FLM_ERROR_STRING( "createNode failed.", m_szDetails, rc);
			goto Exit;
		}

		if ( RC_BAD( rc = pChild->setUTF8( m_pDb, 
			(FLMBYTE *)commonMisspellings[uiLoop].pszWord1)))
		{
			MAKE_FLM_ERROR_STRING( "setUTF8 failed.", m_szDetails, rc);
			goto Exit;
		}
	}

	// Now, we should be able to locate every misspelled word in our list

	if ( RC_BAD( rc = m_pDbSystem->createIFDataVector( &pSearchKey)))
	{
		MAKE_FLM_ERROR_STRING( "createIFDataVector failed.", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = m_pDbSystem->createIFDataVector( &pFoundKey)))
	{
		MAKE_FLM_ERROR_STRING( "createIFDataVector failed.", m_szDetails, rc);
		goto Exit;
	}

	f_strcpy( m_szDetails, "Words: ");
	for ( uiLoop = 0; uiLoop < uiNumWords; uiLoop++)
	{
		if ( RC_BAD( rc = m_pDbSystem->openBufferIStream( 
			commonMisspellings[uiLoop].pszWord1,
			f_strlen( commonMisspellings[uiLoop].pszWord1),
			&pMetaphoneIStream)))
		{
			MAKE_FLM_ERROR_STRING( "openBufferIStream failed.", m_szDetails, rc);
			goto Exit;
		}

		if ( RC_BAD( rc = m_pDbSystem->getNextMetaphone( 
			pMetaphoneIStream, 
			&uiMetaphone1)))
		{
			MAKE_FLM_ERROR_STRING( "getNextMetaphone failed.", m_szDetails, rc);
			goto Exit;
		}
		
		pMetaphoneIStream->Release();
		pMetaphoneIStream = NULL;

		if ( RC_BAD( rc = m_pDbSystem->openBufferIStream( 
			commonMisspellings[uiLoop].pszWord2,
			f_strlen( commonMisspellings[uiLoop].pszWord2),
			&pMetaphoneIStream)))
		{
			MAKE_FLM_ERROR_STRING( "openBufferIStream failed.", m_szDetails, rc);
			goto Exit;
		}

		if ( RC_BAD( rc = m_pDbSystem->getNextMetaphone( 
			pMetaphoneIStream, 
			&uiMetaphone2)))
		{
			MAKE_FLM_ERROR_STRING( "getNextMetaphone failed.", m_szDetails, rc);
			goto Exit;
		}
		
		pMetaphoneIStream->Release();
		pMetaphoneIStream = NULL;

		// No sense in testing the index if the metaphone algorithm itself yields 
		// different codes for these two words.

		if ( uiMetaphone1 == uiMetaphone2)
		{

			if ( (sizeof( m_szDetails) - f_strlen( m_szDetails)) > 
			(f_strlen( commonMisspellings[uiLoop].pszWord1) + 
				f_strlen( " vs. ") + 
						f_strlen( commonMisspellings[uiLoop].pszWord2) + 
							f_strlen( " ")))
			{
				f_strcat( m_szDetails, commonMisspellings[uiLoop].pszWord1);
				f_strcat( m_szDetails, " vs. ");
				f_strcat( m_szDetails, commonMisspellings[uiLoop].pszWord2);
				f_strcat( m_szDetails, " ");
			}

			if ( RC_BAD( rc = pSearchKey->setUTF8( 0, 
				(FLMBYTE *)commonMisspellings[uiLoop].pszWord2)))
			{
				MAKE_FLM_ERROR_STRING( "setUTF8 failed.", m_szDetails, rc);
				goto Exit;
			}

			if ( RC_BAD( rc = m_pDb->keyRetrieve( 77, pSearchKey, XFLM_EXACT, pFoundKey)))
			{
				char szTemp[128];
				f_sprintf( szTemp, "\n\"%s\" indexed but cannot find \"%s\"!", 
					commonMisspellings[uiLoop].pszWord1, 
					commonMisspellings[uiLoop].pszWord2);

				MAKE_FLM_ERROR_STRING( "keyRetrieve failed. ", m_szDetails, rc);
				f_strcpy( m_szDetails, szTemp);

				goto Exit;
			}

			if ( RC_BAD( rc = pFoundKey->getUINT( 0, &uiIxMetaVal)))
			{
				MAKE_FLM_ERROR_STRING( "getUINT failed. ", m_szDetails, rc);
				goto Exit;
			}

			if ( uiIxMetaVal != uiMetaphone1)
			{
				rc = RC_SET( NE_XFLM_DATA_ERROR);
				MAKE_FLM_ERROR_STRING( "Unexpected metaphone code in index", m_szDetails, rc);
				goto Exit;
			}
		}
	}
	endTest("PASS");

Exit:

	if( RC_BAD( rc))
	{
		endTest("FAIL");
	}

	if( pMetaphoneIStream)
	{
		pMetaphoneIStream->Release();
	}

	if( pSearchKey)
	{
		pSearchKey->Release();
	}

	if( pFoundKey)
	{
		pFoundKey->Release();
	}

	if( pRoot)
	{
		pRoot->Release();
	}

	if( pChild)
	{
		pChild->Release();
	}

	if( bTransStarted)
	{
		m_pDb->transCommit();
	}

	shutdownTestState( DB_NAME_STR, bDibCreated);
	return( rc);
}
FSTATIC int Find1(
	char *				FindTemplate,
	F_IO_FIND_DATA *	DirInfo)
{
	char  	MaskNam[ F_PATH_MAX_SIZE];
	char  	*PathSeparator;
	FLMINT	uiFindLen;
	FLMINT	uiLen;
#ifdef FLM_LIBC_NLM
	char  	szPosixNam[ F_PATH_MAX_SIZE];
	FLMINT	uiCount;				
#endif

	// If supplied template is illegal, return immediately

	if( (FindTemplate == NULL) || (uiFindLen = f_strlen( FindTemplate)) == 0)
	{
		return( EINVAL);
	}

	// Now separate the template into a PATH and a template MASK
	// If no separating slash character found, use current directory
	// as path!

	f_strcpy( DirInfo->full_path, FindTemplate);
	
#ifdef FLM_LIBC_NLM
	if( (( PathSeparator = strrchr( DirInfo->full_path, '/')) == NULL) &&
		( PathSeparator = strrchr( DirInfo->full_path, '\\')) == NULL)
#else
	if( (PathSeparator = strrchr( DirInfo->full_path, '/')) == NULL)
#endif
	{
		(void) getcwd( DirInfo->full_path, F_PATH_MAX_SIZE);
		uiLen = f_strlen( DirInfo->full_path );
		DirInfo->full_path[uiLen] = '/';
		DirInfo->full_path[uiLen+1] = '\0';
		(void) f_strcat( DirInfo->full_path, FindTemplate );
		PathSeparator = strrchr( DirInfo->full_path, '/');
	}

	// Copy the template MASK, and null terminate the PATH
	
	f_strcpy( MaskNam, PathSeparator + 1);
	
	if( ! f_strlen(MaskNam))
	{
		(void) f_strcpy( MaskNam, "*");
	}

	*PathSeparator = '\0';

	// Use ROOT directory if PATH is empty
	
	if( ! f_strlen(DirInfo->full_path))
	{
		(void) f_strcpy( DirInfo->full_path, "/");
	}

	f_strcpy( DirInfo->dirpath, DirInfo->full_path );

	// Open the specified directory.  Return immediately
	// if error detected!

	errno = 0;
	DirInfo->globbuf.gl_pathv = 0;

#ifdef FLM_LIBC_NLM
	// glob does not seem to be able to handle a non-posix path
	// on NetWare.
	for( uiCount = 0; uiCount <= uiFindLen; uiCount++)
	{
		if( FindTemplate[ uiCount] == '\\')
		{
			szPosixNam[ uiCount] = '/';
		}
		else
		{
			szPosixNam[ uiCount] = FindTemplate[ uiCount];
		}
	}
	if( glob( szPosixNam, GLOB_NOSORT, 0, &DirInfo->globbuf) != 0 &&
		 !DirInfo->globbuf.gl_pathc)
#else
	if( glob( FindTemplate, GLOB_NOSORT, 0, &DirInfo->globbuf) != 0 &&
		 !DirInfo->globbuf.gl_pathc)
#endif
	{
		globfree(&DirInfo->globbuf);
		DirInfo->globbuf.gl_pathv = 0;
		return ENOENT;
	}
	
	// Call Find2 to get the 1st matching file

	return( Find2(DirInfo) );
}