//------------------------------------------------------------------------- // Desc: Base class for monitoring code. // Tabs: 3 // // Copyright (c) 2001-2006 Novell, Inc. All Rights Reserved. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public // License as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, contact Novell, Inc. // // To contact Novell about this file by physical or electronic mail, // you may find current contact information at www.novell.com // // $Id: imonbase.cpp 12334 2006-01-23 12:45:35 -0700 (Mon, 23 Jan 2006) dsanders $ //------------------------------------------------------------------------- #include "flaimsys.h" #define RESP_WRITE_BUF_SIZE 1024 #define FLM_SESSION_ID_NAME "flmsessionid" #define MAX_FIELD_SIZE(uiSize) \ (uiSize > 100 ? 100 : (uiSize < 20 ? 20 : uiSize)) /**************************************************************************** Desc: Outputs a javascript function that, when called, causes a new window to open and a page to be displayed in it. ****************************************************************************/ void F_WebPage::popupFrame( void) { fnPrintf( m_pHRequest, "\n"); } /****************************************************************************** Desc: This method will extract the value of the parameter in the form of PARAMETER=VALUE *******************************************************************************/ RCODE F_WebPage::ExtractParameter( FLMUINT uiNumParams, const char ** ppszParams, const char * pszParamName, FLMUINT uiParamLen, char* pszParamValue) { RCODE rc = FERR_OK; FLMUINT uiLoop; FLMUINT uiParamNameLen; const char* pszTemp; FLMBOOL bFound = FALSE; uiParamNameLen = f_strlen( pszParamName); for (uiLoop = 0; uiLoop < uiNumParams; uiLoop++) { if( f_strncmp( (char*) ppszParams[uiLoop], pszParamName, uiParamNameLen) == 0 && (ppszParams[uiLoop][uiParamNameLen] == '\0' || ppszParams[uiLoop][uiParamNameLen] == '=')) { pszTemp = &ppszParams[uiLoop][uiParamNameLen]; if (*pszTemp == '=') { // Skip past the equal sign pszTemp++; f_strncpy( pszParamValue, pszTemp, uiParamLen - 1); // See if the param was too long to store if (f_strlen( pszTemp) >= uiParamLen) { pszParamValue[uiParamLen] = '\0'; rc = RC_SET( FERR_MEM); } } else { *pszParamValue = 0; } bFound = TRUE; break; } } return (bFound ? rc : RC_SET( FERR_NOT_FOUND)); } /**************************************************************************** Desc: This method will detect the presence of a parameter in the form PARAMETER - no value will be checked. A TRUE or FALSE value will be returned. *****************************************************************************/ FLMBOOL F_WebPage::DetectParameter( FLMUINT uiNumParams, const char ** ppszParams, const char * pszParamName) { for (FLMUINT uiLoop = 0; uiLoop < uiNumParams; uiLoop++) { if (f_strncmp( (char*) ppszParams[uiLoop], pszParamName, f_strlen( (char*) pszParamName)) == 0) { return (TRUE); } } return (FALSE); } /**************************************************************************** Desc: *****************************************************************************/ RCODE F_WebPage::getDatabaseHandleParam( FLMUINT uiNumParams, const char ** ppszParams, F_Session * pFlmSession, HFDB* phDb, char* pszKey) { RCODE rc = FERR_OK; HFDB hDb; char szTmp[ 64]; char * pTmp; if (phDb) { *phDb = hDb = HFDB_NULL; } if (pszKey) { *pszKey = 0; } // Need to memset the first F_SESSION_DB_KEY_LEN bytes of szTmp // because the hash lookup algorithm expects the buffer to be padded // with zeros at the end of the key. f_memset( szTmp, 0, F_SESSION_DB_KEY_LEN); if (RC_BAD( ExtractParameter( uiNumParams, ppszParams, "dbhandle", sizeof(szTmp), szTmp))) { pTmp = &szTmp[0]; if (RC_BAD( getFormValueByName( "dbhandle", &pTmp, sizeof(szTmp), NULL))) { rc = RC_SET( FERR_NOT_FOUND); goto Exit; } } if (szTmp[0]) { if (RC_BAD( rc = pFlmSession->getDbHandle( szTmp, &hDb))) { goto Exit; } if (pszKey) { f_memcpy( pszKey, szTmp, F_SESSION_DB_KEY_LEN); } } if (phDb) { *phDb = hDb; } Exit: return (rc); } /**************************************************************************** Desc: Function to display the formatted time value in the form dd hh:mm:ss.ccc *****************************************************************************/ void F_WebPage::FormatTime( FLMUINT uiTimerUnits, char * pszFormattedTime) { FLMUINT uiMilli; FLMUINT uiSec; FLMUINT uiMin; FLMUINT uiHr; FLMUINT uiDays; FLMUINT uiTemp; // Initialize to NULL; pszFormattedTime[0] = '\0'; // Convert the timer units to milliseconds uiMilli = FLM_TIMER_UNITS_TO_MILLI( uiTimerUnits); // Determine the number of days uiDays = uiMilli / 86400000; uiTemp = uiMilli % 86400000; // Now the hours uiHr = uiTemp / 3600000; uiTemp = uiTemp % 3600000; // Determine the minutes uiMin = uiTemp / 60000; uiTemp = uiTemp % 60000; // Determine seconds uiSec = uiTemp / 1000; // Determine the milliseconds uiMilli = uiTemp % 1000; // Put it all together - hh:mm:ss f_sprintf( (char *) pszFormattedTime, "%ld %2.2ld:%2.2ld:%2.2ld.%3.3ld", uiDays, uiHr, uiMin, uiSec, uiMilli); } /**************************************************************************** Desc: Procedure to generate the HTML page that displays the usage statistics structure. ****************************************************************************/ RCODE F_WebPage::writeUsage( FLM_CACHE_USAGE* pUsage, FLMBOOL bRefresh, const char* pszURL, const char* pszTitle) { RCODE rc = FERR_OK; FLMBOOL bHighlight = FALSE; char szTemp[100]; stdHdr(); fnPrintf( m_pHRequest, HTML_DOCTYPE); fnPrintf( m_pHRequest, "\n"); // Setup the page header & refresh control... Assuming the the first // parameter ?Usage is already contained in the pszURL string. if (bRefresh) { fnPrintf( m_pHRequest, "" "" "%s\n", m_pszURLString, pszURL, pszTitle); printStyle(); fnPrintf( m_pHRequest, "\n\n"); f_sprintf( (char*) szTemp, "Stop Auto-refresh", m_pszURLString, pszURL); } else { fnPrintf( m_pHRequest, "%s\n", pszTitle); printStyle(); fnPrintf( m_pHRequest, "\n\n"); f_sprintf( (char*) szTemp, "Start Auto-refresh (5 sec.)", m_pszURLString, pszURL); } // Begin the table printTableStart( (char*) pszTitle, 4); printTableRowStart(); printColumnHeading( "", JUSTIFY_LEFT, FLM_IMON_COLOR_PUTTY_1, 4, 1, FALSE); fnPrintf( m_pHRequest, "Refresh, ", m_pszURLString, pszURL); fnPrintf( m_pHRequest, "%s\n", szTemp); printColumnHeadingClose(); printTableRowEnd(); // Write out the table headings. printTableRowStart(); printColumnHeading( "Byte Offset (hex)"); printColumnHeading( "Field Name"); printColumnHeading( "Byte Offset"); printColumnHeading( "Value"); printTableRowEnd(); // uiMaxBytes printHTMLUint( (char*) "uiMaxBytes", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiMaxBytes, pUsage->uiMaxBytes, (bHighlight = ~bHighlight)); // uiTotalBytesAllocated printHTMLUint( (char*) "uiTotalBytesAllocated", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiTotalBytesAllocated, pUsage->uiTotalBytesAllocated, (bHighlight = ~bHighlight)); // uiCount printHTMLUint( (char*) "uiCount", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiCount, pUsage->uiCount, (bHighlight = ~bHighlight)); // uiOldVerCount printHTMLUint( (char*) "uiOldVerCount", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiOldVerCount, pUsage->uiOldVerCount, (bHighlight = ~bHighlight)); // uiOldVerBytes printHTMLUint( (char*) "uiOldVerBytes", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiOldVerBytes, pUsage->uiOldVerBytes, (bHighlight = ~bHighlight)); // uiCacheHits printHTMLUint( (char*) "uiCacheHits", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiCacheHits, pUsage->uiCacheHits, (bHighlight = ~bHighlight)); // uiCacheHitLooks printHTMLUint( (char*) "uiCacheHitLooks", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiCacheHitLooks, pUsage->uiCacheHitLooks, (bHighlight = ~bHighlight)); // uiCacheFaults printHTMLUint( (char*) "uiCacheFaults", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiCacheFaults, pUsage->uiCacheFaults, (bHighlight = ~bHighlight)); // uiCacheFaultLooks printHTMLUint( (char*) "uiCacheFaultLooks", (char*) "FLMUINT", (void*) pUsage, (void*) &pUsage->uiCacheFaultLooks, pUsage->uiCacheFaultLooks, (bHighlight = ~bHighlight)); printTableEnd(); fnPrintf( m_pHRequest, "
\n"); fnPrintf( m_pHRequest, "
\n"); fnPrintf( m_pHRequest, "
\n"); fnPrintf( m_pHRequest, "\n"); fnEmit(); return (rc); } /********************************************************************* Desc: This function prints a linkable field in HTML *********************************************************************/ void F_WebPage::printHTMLLink( const char * pszName, const char * pszType, void * pvBase, void * pvAddress, void * pvValue, const char * pszLink, FLMBOOL bHighlight) { char szAddress[20]; char szOffset[8]; printOffset( pvBase, pvAddress, szOffset); printTableRowStart( bHighlight); fnPrintf( m_pHRequest, TD_s, szOffset); // Field offset if (pvValue) { printAddress( pvValue, szAddress); fnPrintf( m_pHRequest, TD_a_s_s, pszLink, pszName); // Link & Name fnPrintf( m_pHRequest, TD_s, pszType); // Type fnPrintf( m_pHRequest, TD_a_s_s, pszLink, szAddress); // Link & Value } else { fnPrintf( m_pHRequest, TD_s, pszName); fnPrintf( m_pHRequest, TD_s, pszType); fnPrintf( m_pHRequest, TD_s, "Null"); } printTableRowEnd(); } /********************************************************************* Desc: This function prints a text field in HTML *********************************************************************/ void F_WebPage::printHTMLString( const char * pszName, const char * pszType, void * pvBase, void * pvAddress, const char * pszValue, FLMBOOL bHighlight) { char szOffset[8]; printOffset( pvBase, pvAddress, szOffset); printTableRowStart( bHighlight); fnPrintf( m_pHRequest, TD_s, szOffset); // Field offset fnPrintf( m_pHRequest, TD_s, pszName); // Name fnPrintf( m_pHRequest, TD_s, pszType); // Type fnPrintf( m_pHRequest, TD_s, pszValue); // Value printTableRowEnd(); } /********************************************************************* Desc: This function prints a unsigned long (FLMUINT) field in HTML *********************************************************************/ void F_WebPage::printHTMLUint( const char * pszName, const char * pszType, void * pvBase, void * pvAddress, FLMUINT uiValue, FLMBOOL bHighlight) { char szOffset[8]; printOffset( pvBase, pvAddress, szOffset); printTableRowStart( bHighlight); fnPrintf( m_pHRequest, TD_s, szOffset); // Field offset fnPrintf( m_pHRequest, TD_s, pszName); // Name fnPrintf( m_pHRequest, TD_s, pszType); // Type fnPrintf( m_pHRequest, TD_ui, uiValue); // Value printTableRowEnd(); } /********************************************************************* Desc: This function prints a signed long (FLMINT) field in HTML *********************************************************************/ void F_WebPage::printHTMLInt( const char * pszName, const char * pszType, void * pvBase, void * pvAddress, FLMINT iValue, FLMBOOL bHighlight) { char szOffset[8]; printOffset( pvBase, pvAddress, szOffset); printTableRowStart( bHighlight); fnPrintf( m_pHRequest, TD_s, szOffset); // Field offset fnPrintf( m_pHRequest, TD_s, pszName); // Name fnPrintf( m_pHRequest, TD_s, pszType); // Type fnPrintf( m_pHRequest, TD_i, iValue); // Value printTableRowEnd(); } /********************************************************************* Desc: This function prints a unsigned long field in HTML *********************************************************************/ void F_WebPage::printHTMLUlong( const char * pszName, const char * pszType, void * pvBase, void * pvAddress, unsigned long luValue, FLMBOOL bHighlight) { char szOffset[8]; printOffset( pvBase, pvAddress, szOffset); printTableRowStart( bHighlight); fnPrintf( m_pHRequest, TD_s, szOffset); // Field offset fnPrintf( m_pHRequest, TD_s, pszName); // Name fnPrintf( m_pHRequest, TD_s, pszType); // Type fnPrintf( m_pHRequest, TD_lu, luValue); // Value printTableRowEnd(); } /********************************************************************* Desc: This function takes the name of a form field, and returns a pointer to it. This will allocate the buffer returned. The calling function is responsible for freeing that buffer. *********************************************************************/ RCODE F_WebPage::getFormValueByName( const char * pszValueTag, char ** ppszBuf, FLMUINT uiBufLen, FLMUINT * puiDataLen) { RCODE rc = FERR_OK; char szTag[128]; char * pszValue; FLMUINT uiLen; FLMBOOL bFreeFormData = FALSE; FLMBOOL bFreeUserData = FALSE; if (puiDataLen) { *puiDataLen = 0; } #ifdef FLM_DEBUG if (!uiBufLen) { flmAssert( ppszBuf && *ppszBuf == NULL); } #endif if (f_strlen( pszValueTag) + 1 >= sizeof(szTag)) { flmAssert( 0); rc = RC_SET( FERR_MEM); goto Exit; } f_sprintf( (char*) szTag, "%s=", pszValueTag); if (!m_pszFormData) { char * pszContentLength; FLMUINT uiContentLength; // First we need to determine how much form data there is. if ((pszContentLength = (char*) fnReqHdrValue( "Content-Length")) == NULL) { rc = RC_SET( FERR_NOT_FOUND); goto Exit; } if ((uiContentLength = f_atoi( pszContentLength)) == 0) { rc = RC_SET( FERR_NOT_FOUND); goto Exit; } // Now allocate a buffer to hold the form data if (RC_BAD( rc = f_alloc( uiContentLength + 1, &m_pszFormData))) { goto Exit; } bFreeFormData = TRUE; if (fnRecvBuffer( m_pszFormData, (FLMSIZET *) &uiContentLength) != 0) { rc = RC_SET( FERR_FAILURE); goto Exit; } m_pszFormData[uiContentLength] = 0; bFreeFormData = FALSE; } // Now, parse through the buffer until we find the field we are // looking for. The data is in the form name=value:name=value... if ((pszValue = f_strstr( m_pszFormData, szTag)) != NULL) { pszValue += f_strlen( szTag); for (uiLen = 0; pszValue[uiLen] && pszValue[uiLen] != ':' && pszValue[uiLen] != '&'; uiLen++); if (ppszBuf) { if (!uiBufLen) { uiBufLen = uiLen + 1; bFreeUserData = TRUE; *ppszBuf = NULL; if (RC_BAD( rc = f_alloc( uiBufLen, ppszBuf))) { goto Exit; } } if (uiLen >= uiBufLen) { rc = RC_SET( FERR_CONV_DEST_OVERFLOW); goto Exit; } f_memcpy( *ppszBuf, pszValue, uiLen); (*ppszBuf)[uiLen] = 0; bFreeUserData = FALSE; } if (puiDataLen) { *puiDataLen = uiLen + 1; } goto Exit; } else { rc = RC_SET( FERR_NOT_FOUND); goto Exit; } Exit: if (bFreeFormData) { f_free( &m_pszFormData); } if (bFreeUserData && *ppszBuf) { f_free( ppszBuf); } return (rc); } /**************************************************************************** Desc: Prints the standard style sheet ****************************************************************************/ void F_WebPage::printStyle(void) { fnPrintf( m_pHRequest, "\n", m_pszURLString); } /**************************************************************************** Desc: Outputs a column heading using elements from the standard style sheet ****************************************************************************/ void F_WebPage::printColumnHeading( const char * pszHeading, JustificationType eJustification, const char * pszBackground, FLMUINT uiColSpan, FLMUINT uiRowSpan, FLMBOOL bClose, FLMUINT uiWidth) { fnPrintf( m_pHRequest, "\n"); if (pszHeading) { printEncodedString( pszHeading); } if (bClose) { fnPrintf( m_pHRequest, "\n"); } } /**************************************************************************** Desc: Closes a column heading ****************************************************************************/ void F_WebPage::printColumnHeadingClose(void) { fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: Encodes a string for rendering in an HTML page or for inclusion in an URL ****************************************************************************/ void F_WebPage::printEncodedString( const char * pszString, FStringEncodeType eEncodeType, FLMBOOL bMapSlashes) { char ucChar; while ((ucChar = *pszString) != 0) { if ((ucChar >= '0' && ucChar <= '9') || (ucChar >= 'A' && ucChar <= 'Z') || (ucChar >= 'a' && ucChar <= 'z') || ucChar == '_' || ( eEncodeType == URL_PATH_ENCODING && (ucChar == '.' || (bMapSlashes && (ucChar == '/' || ucChar == '\\'))) )) { if (ucChar == '\\') { ucChar = '/'; } fnPrintf( m_pHRequest, "%c", ucChar); } else if (eEncodeType == URL_PATH_ENCODING) { fnPrintf( m_pHRequest, "%%%02X", (unsigned) ucChar); } else if (eEncodeType == URL_QUERY_ENCODING) { if (ucChar == ' ') { ucChar = '+'; } fnPrintf( m_pHRequest, "%%%02X", (unsigned) ucChar); } else // HTML encoding { fnPrintf( m_pHRequest, "&#%u;", (unsigned) ucChar); } pszString++; } } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printDocStart( const char * pszTitle, FLMBOOL bPrintTitle, FLMBOOL bStdHeader, const char * pszBackground) { if (bStdHeader) { stdHdr(); } fnPrintf( m_pHRequest, HTML_DOCTYPE); fnPrintf( m_pHRequest, "\n"); fnPrintf( m_pHRequest, "\n"); printRecordStyle(); printStyle(); fnPrintf( m_pHRequest, "Database iMonitor - "); printEncodedString( pszTitle); fnPrintf( m_pHRequest, "\n"); fnPrintf( m_pHRequest, "\n"); fnPrintf( m_pHRequest, "\n", pszBackground ? pszBackground : "white"); if (bPrintTitle) { printTableStart( pszTitle, 1); printTableEnd(); fnPrintf( m_pHRequest, "
\n"); } } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printDocEnd(void) { fnPrintf( m_pHRequest, "\n"); fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printMenuReload(void) { fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printTableStart( const char* pszTitle, FLMUINT uiColumns, FLMUINT uiWidthFactor) { fnPrintf( m_pHRequest, "\n"); if (pszTitle) { printTableRowStart(); fnPrintf( m_pHRequest, ""); printTableRowEnd(); } } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printTableEnd(void) { fnPrintf( m_pHRequest, "
\n"); printEncodedString( pszTitle); fnPrintf( m_pHRequest, "
\n"); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printTableRowStart( FLMBOOL bHighlight) { fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printTableRowEnd(void) { fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printTableDataStart( FLMBOOL bNoWrap, JustificationType eJustification, FLMUINT uiWidth) { fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printTableDataEnd(void) { fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printTableDataEmpty(void) { fnPrintf( m_pHRequest, " "); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printErrorPage( RCODE rc, FLMBOOL bStdHeader, const char * pszWhat) { printDocStart( "Error", TRUE, bStdHeader); fnPrintf( m_pHRequest, "

\n"); fnPrintf( m_pHRequest, "%s
%s (0x%04X).\n", pszWhat, FlmErrorString( rc), (unsigned) rc); fnPrintf( m_pHRequest, "

\n"); printDocEnd(); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printErrorPage( const char * pszErrStr, const char * pszErrStr2, FLMBOOL bStdHeader) { printDocStart( "Error", TRUE, bStdHeader); fnPrintf( m_pHRequest, "

\n"); fnPrintf( m_pHRequest, "%s\n", pszErrStr); if (pszErrStr2 && *pszErrStr2) { fnPrintf( m_pHRequest, "
%s\n", pszErrStr2); } fnPrintf( m_pHRequest, "

\n"); printDocEnd(); } /**************************************************************************** Desc: Start an input form ****************************************************************************/ void F_WebPage::printStartInputForm( const char * pszFormName, const char * pszPage, FLMUINT uiFormValue) { fnPrintf( m_pHRequest, "
\n" "\n", pszFormName, m_pszURLString, pszPage, (unsigned) uiFormValue); } /**************************************************************************** Desc: End an input form ****************************************************************************/ void F_WebPage::printEndInputForm(void) { fnPrintf( m_pHRequest, "
"); } /**************************************************************************** Desc: Generic function to output HTML that gererates a button ****************************************************************************/ void F_WebPage::printButton( const char * pszContents, ButtonTypes eBType, const char * pszName, const char * pszValue, const char * pszExtra, FLMBOOL bDisabled, FLMBYTE ucAccessKey, FLMUINT uiTabIndex) { fnPrintf( m_pHRequest, "\n", (char*) (pszContents ? pszContents : "")); } /**************************************************************************** Desc: Format and output date. ****************************************************************************/ void F_WebPage::printDate( FLMUINT uiGMTTime, char * pszBuffer) { F_TMSTAMP timeStamp; FLMUINT uiLocalTime; char * pszAmPm; const char * pszMonth; uiLocalTime = (FLMUINT) (uiGMTTime - f_timeGetLocalOffset()); f_timeSecondsToDate( uiLocalTime, &timeStamp); pszAmPm = (char*) ((timeStamp.hour >= 12) ? (char*) "pm" : (char*) "am"); if (timeStamp.hour > 12) { timeStamp.hour -= 12; } if (timeStamp.hour == 0) { timeStamp.hour = 12; } switch (timeStamp.month) { case 0: pszMonth = "Jan"; break; case 1: pszMonth = "Feb"; break; case 2: pszMonth = "Mar"; break; case 3: pszMonth = "Apr"; break; case 4: pszMonth = "May"; break; case 5: pszMonth = "Jun"; break; case 6: pszMonth = "Jul"; break; case 7: pszMonth = "Aug"; break; case 8: pszMonth = "Sep"; break; case 9: pszMonth = "Oct"; break; case 10: pszMonth = "Nov"; break; default: case 11: pszMonth = "Dec"; break; } if (pszBuffer != NULL) { f_sprintf( (char*) pszBuffer, "%s %u, %u %u:%02u:%02u %s", pszMonth, (unsigned) timeStamp.day, (unsigned) timeStamp.year, (unsigned) timeStamp.hour, (unsigned) timeStamp.minute, (unsigned) timeStamp.second, pszAmPm); } else { fnPrintf( m_pHRequest, "%s %u, %u %u:%02u:%02u %s", pszMonth, (unsigned) timeStamp.day, (unsigned) timeStamp.year, (unsigned) timeStamp.hour, (unsigned) timeStamp.minute, (unsigned) timeStamp.second, pszAmPm); } } /**************************************************************************** Desc: Outputs a Yes or No value based on the passed-in boolean ****************************************************************************/ void F_WebPage::printYesNo( FLMBOOL bYes) { fnPrintf( m_pHRequest, "%s", bYes ? "Yes" : "No"); } /**************************************************************************** Desc: Outputs a number with commas, for easier reading. ****************************************************************************/ void F_WebPage::printCommaNumText( FLMUINT64 ui64Num) { FLMUINT uiTerm; FLMUINT64 ui64Divisor = 1; FLMBOOL bFirstPass = TRUE; while ((FLMUINT64) (ui64Num / (ui64Divisor * (FLMUINT64) 1000))) { ui64Divisor *= 1000; } while (ui64Divisor) { uiTerm = (FLMUINT) (ui64Num / ui64Divisor); ui64Num -= ((FLMUINT64) uiTerm) * ui64Divisor; if (bFirstPass) { fnPrintf( m_pHRequest, "%u", (unsigned) uiTerm); bFirstPass = FALSE; } else { fnPrintf( m_pHRequest, "%03u", (unsigned) uiTerm); } if ((ui64Divisor /= (FLMUINT64) 1000) > (FLMUINT64) 0) { fnPrintf( m_pHRequest, ","); } } } /**************************************************************************** Desc: Outputs a number with commas, for easier reading. ****************************************************************************/ void F_WebPage::printCommaNum( FLMUINT64 ui64Num, JustificationType eJustify, FLMBOOL bChangedValue) { printTableDataStart( TRUE, eJustify); if (bChangedValue) { fnPrintf( m_pHRequest, ""); } printCommaNumText( ui64Num); if (bChangedValue) { fnPrintf( m_pHRequest, ""); } printTableDataEnd(); } /**************************************************************************** Desc: ****************************************************************************/ RCODE F_WebPage::acquireSession(void) { RCODE rc = FERR_OK; FLMBOOL bHttpSessionMutexLocked = FALSE; FLMUINT uiSize; void * pvHttpSession = NULL; char szSessionKey[F_SESSION_KEY_LEN]; m_pFlmSession = NULL; if (!gv_FlmSysData.HttpConfigParms.fnAcquireSession) { rc = RC_SET( FERR_NOT_IMPLEMENTED); goto Exit; } if ((pvHttpSession = fnAcquireSession()) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } f_mutexLock( gv_FlmSysData.hHttpSessionMutex); bHttpSessionMutexLocked = TRUE; uiSize = sizeof(szSessionKey); if (fnGetSessionValue( pvHttpSession, FLM_SESSION_ID_NAME, (void*) szSessionKey, (FLMSIZET *) &uiSize) != 0) { CreateSession: if (RC_BAD( rc = gv_FlmSysData.pSessionMgr->createSession( &m_pFlmSession))) { goto Exit; } fnSetSessionValue( pvHttpSession, FLM_SESSION_ID_NAME, m_pFlmSession->getKey(), sizeof(szSessionKey)); } else { if (RC_BAD( rc = gv_FlmSysData.pSessionMgr->getSession( szSessionKey, &m_pFlmSession))) { if (rc == FERR_NOT_FOUND) { goto CreateSession; } } } Exit: if (RC_BAD( rc)) { if (m_pFlmSession) { releaseSession(); } } if (pvHttpSession) { fnReleaseSession( pvHttpSession); } if (bHttpSessionMutexLocked) { f_mutexUnlock( gv_FlmSysData.hHttpSessionMutex); } return (rc); } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::releaseSession(void) { if (m_pFlmSession) { gv_FlmSysData.pSessionMgr->releaseSession( &m_pFlmSession); m_pFlmSession = NULL; } } /**************************************************************************** Desc: ****************************************************************************/ void F_WebPage::printSpaces( FLMUINT uiCount) { while (uiCount--) { fnPrintf( m_pHRequest, " "); } } /**************************************************************************** Desc: Outputs elapsed milliseconds as seconds.milli. The optional parameter pszBuffer will cause the time to be written to pszBuffer instead of the web page. That way it can be incorporated into more complex structures if desired. ****************************************************************************/ void F_WebPage::printElapTime( FLMUINT64 ui64ElapTime, char* pszBuffer, JustificationType eJustify, FLMBOOL bTimeIsMilli) { FLMUINT uiHours; FLMUINT uiMinutes; FLMUINT uiSeconds; FLMUINT uiMilli = 0; if (bTimeIsMilli) { uiHours = (FLMUINT) (ui64ElapTime / (FLMUINT64) (1000 * 3600)); uiMinutes = (FLMUINT) ((ui64ElapTime / (FLMUINT64) (1000 * 60)) % (FLMUINT64) 60); uiSeconds = (FLMUINT) ((ui64ElapTime / (FLMUINT64) 1000) % (FLMUINT64) 60); uiMilli = (FLMUINT) (ui64ElapTime % (FLMUINT64) 1000); } else { uiHours = (FLMUINT) (ui64ElapTime / (FLMUINT64) 3600); uiMinutes = (FLMUINT) ((ui64ElapTime / (FLMUINT64) 60) % (FLMUINT64) 60); uiSeconds = (FLMUINT) (ui64ElapTime % (FLMUINT64) 60); } if (!pszBuffer) { printTableDataStart( TRUE, eJustify); } if (pszBuffer) { f_sprintf( (char*) pszBuffer, "%02u:%02u:%02u", (unsigned) uiHours, (unsigned) uiMinutes, (unsigned) uiSeconds); } else { fnPrintf( m_pHRequest, "%02u:%02u:%02u", (unsigned) uiHours, (unsigned) uiMinutes, (unsigned) uiSeconds); } if (bTimeIsMilli) { if (pszBuffer) { char szTemp[5]; f_sprintf( szTemp, ".%03u", (unsigned) uiMilli); f_strncat( (char*) pszBuffer, szTemp, 4); } else { fnPrintf( m_pHRequest, ".%03u", (unsigned) uiMilli); } } if (!pszBuffer) { printTableDataEnd(); } } /**************************************************************************** Desc: This function will output a form in an already existing page that will present a formatted display of the record passed in. An optional parameter bReadOnly will determine if the form should allow editing of the record or not. The default value is TRUE (No editing capability). A null may be passed in for the FlmRecord pointer, in which case an empty display will be created. Normally, a bReadOnly value of false would accompany a null record so that a record can be created. The printRecordStyle() must be called in the header section of the page prior to calling this function. Multiple calls may be made to display multiple records per page. The puiContext parameter must be initialized to zero before the first (and possibly the only) call, otherwise the scripts need to run this page will not be loaded. ****************************************************************************/ void F_WebPage::printRecord( const char * pszDbKey, FlmRecord * pRec, F_NameTable * pNameTable, FLMUINT * puiContext, FLMBOOL bReadOnly, FLMUINT uiSelectedField, FLMUINT uiFlags) { #define SP " " FLMBOOL bEmpty = FALSE; FLMUINT uiContainer; FLMUINT uiDrn; void * pvField; FLMUINT uiFieldCounter; FLMUINT uiFldCnt; FLMUINT uiTagNum; FLMUINT uiLevel; FLMUINT uiType; FLMUINT uiContext = 0; char szNameBuf[128]; flmAssert( pNameTable); if (puiContext) { uiContext = *puiContext; (*puiContext)++; } // See if we need to write out the scripts if (uiContext == 0) { printRecordScripts(); } if (!pRec) { bEmpty = TRUE; uiDrn = 0; uiContainer = 0; } else { // Get the Drn & Container uiDrn = pRec->getID(); uiContainer = pRec->getContainerID(); } // Count the fields uiFldCnt = 0; if (pRec != NULL) { pvField = pRec->root(); while (pvField) { pvField = pRec->next( pvField); uiFldCnt++; } } // Begin the form that displays the record data (if any) fnPrintf( m_pHRequest, "
\n", uiContext, gv_FlmSysData.HttpConfigParms.pszURLString); printHiddenField( "ReadOnly", (char*) (bReadOnly ? "TRUE" : "FALSE")); if (pszDbKey) { printHiddenField( "dbhandle", (char*) (pszDbKey)); } printHiddenField( (char*) "Action", "none"); printHiddenField( (char*) "FieldLevel", (FLMUINT) 0); printHiddenField( (char*) "FieldNumber", (FLMUINT) 0); printHiddenField( (char*) "FieldCount", uiFldCnt); // Print out the block that displays the DRN and Container list fnPrintf( m_pHRequest, "
\n"); fnPrintf( m_pHRequest, "\n"); fnPrintf( m_pHRequest, "\n\n\n", uiDrn, pszDbKey == NULL ? "disabled" : ""); if (pszDbKey != NULL) { fnPrintf( m_pHRequest, "\n\n\n"); } fnPrintf( m_pHRequest, "\n\n\n", uiContainer); } fnPrintf( m_pHRequest, "\n\n"); if (pszDbKey != NULL) { // Print out the field list drop down box. fnPrintf( m_pHRequest, "\n\n\n"); // Print out the Add, Modify, Delete action buttons. fnPrintf( m_pHRequest, "\n"); } fnPrintf( m_pHRequest, "
DRN  
Flags \n"); printRetrievalFlagsPulldown( uiFlags); fnPrintf( m_pHRequest, "
Container \n"); if (pszDbKey != NULL) { printContainerPulldown( pNameTable, uiContainer); } else { fnPrintf( m_pHRequest, " 
Field list "); printFieldPulldown( pNameTable, uiSelectedField); fnPrintf( m_pHRequest, "
", uiContext); if (pRec != NULL) { if (!bReadOnly) { fnPrintf( m_pHRequest, "", uiContext); fnPrintf( m_pHRequest, "", uiContext); } fnPrintf( m_pHRequest, "", uiContext); } fnPrintf( m_pHRequest, "", uiContext); if (pRec != NULL && bReadOnly) { fnPrintf( m_pHRequest, "", uiContext); } fnPrintf( m_pHRequest, "
\n
\n"); // Print out the record fields (if there are any) if (pRec != NULL) { fnPrintf( m_pHRequest, "
\n"); if (!bReadOnly) { fnPrintf( m_pHRequest, "", uiContext); if (uiFldCnt > 1) { fnPrintf( m_pHRequest, "", uiContext); fnPrintf( m_pHRequest, "", uiContext); fnPrintf( m_pHRequest, "\n", uiContext); } } fnPrintf( m_pHRequest, "
\n");

		// Now for the actual data. Start with the root field.

		pvField = pRec->root();

		uiFieldCounter = 0;

		while (pvField)
		{
			uiTagNum = pRec->getFieldID( pvField);
			uiLevel = pRec->getLevel( pvField);
			uiType = pRec->getDataType( pvField);

			if (uiLevel != 0 && !bReadOnly)
			{
				fnPrintf( m_pHRequest,
							"",
						uiFieldCounter, uiContext, uiFieldCounter, uiLevel);
			}

			pNameTable->getFromTagNum( uiTagNum, NULL, szNameBuf, sizeof(szNameBuf));
			printSpaces( uiLevel + 5);

			fnPrintf( m_pHRequest, "%s%d%s%s%s", SP,
						uiLevel, SP, szNameBuf, SP);

			if (pRec->getDataLength( pvField))
			{
				switch (uiType)
				{
					case FLM_TEXT_TYPE:
						printTextField( pRec, pvField, uiFieldCounter, bReadOnly);
						break;
					case FLM_NUMBER_TYPE:
						printNumberField( pRec, pvField, uiFieldCounter, bReadOnly);
						break;
					case FLM_BINARY_TYPE:
						printBinaryField( pRec, pvField, uiFieldCounter, bReadOnly);
						break;
					case FLM_CONTEXT_TYPE:
						printContextField( pRec, pvField, uiFieldCounter, bReadOnly);
						break;
					case FLM_BLOB_TYPE:
						printBlobField( pRec, pvField, uiFieldCounter, bReadOnly);
						break;
					default:
						printDefaultField( pRec, pvField, uiFieldCounter, bReadOnly);
						break;
				}
			}
			else if (!bReadOnly)
			{
				fnPrintf( m_pHRequest,
							"",
						uiFieldCounter, MAX_FIELD_SIZE( 0));
			}

			// Print the hidden field Ids

			printFieldIds( uiFieldCounter, uiLevel, uiType, uiTagNum);
			fnPrintf( m_pHRequest, "\n");

			pvField = pRec->next( pvField);
			uiFieldCounter++;
		}

		fnPrintf( m_pHRequest, "
\n
\n
\n"); } fnPrintf( m_pHRequest, "
\n"); return; } /**************************************************************************** Desc: Prints out a style sheet specific to displaying records. ****************************************************************************/ void F_WebPage::printRecordStyle(void) { fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: Prints out the required scripts for displaying and updating records. ****************************************************************************/ void F_WebPage::printRecordScripts( void) { fnPrintf( m_pHRequest, "\n"); } /**************************************************************************** Desc: Prints out a hidden field with a character string value ****************************************************************************/ void F_WebPage::printHiddenField( const char * pszName, const char * pszValue) { fnPrintf( m_pHRequest, "", pszName, pszValue); } // /**************************************************************************** Desc: Prints out a hidden with an unsigned long value ****************************************************************************/ void F_WebPage::printHiddenField( const char * pszName, FLMUINT uiValue) { fnPrintf( m_pHRequest, "", pszName, (unsigned) uiValue); } // /**************************************************************************** Desc: Prints out the value for the field, assuming the field is a text field. ****************************************************************************/ void F_WebPage::printTextField( FlmRecord * pRec, void * pvField, FLMUINT uiFieldCounter, FLMBOOL bReadOnly) { RCODE rc = FERR_OK; FLMUNICODE * puzBuf = NULL; FLMUNICODE * puzTmp = NULL; F_DynamicBuffer * pBuffer = NULL; FLMUINT uiLen; if (RC_BAD( rc = pRec->getUnicodeLength( pvField, &uiLen))) { fnPrintf( m_pHRequest, "** Error retrieving Unicode field length (Return Code = 0x%04X, %s) **", (unsigned) rc, FlmErrorString( rc)); goto Exit; } // The length returned does not allow for 2 NULL terminators. We must // allow for them when allocating a buffer. uiLen += 2; if (RC_BAD( rc = f_alloc( uiLen, &puzBuf))) { fnPrintf( m_pHRequest, "** Error allocating memory buffer (Return Code = 0x%04X, %s) **", (unsigned) rc, FlmErrorString( rc)); goto Exit; } if (RC_BAD( rc = pRec->getUnicode( pvField, puzBuf, &uiLen))) { fnPrintf( m_pHRequest, "** Error retrieving Unicode field (Return Code = 0x%04X, %s) **", (unsigned) rc, FlmErrorString( rc)); goto Exit; } puzTmp = puzBuf; if ((pBuffer = f_new F_DynamicBuffer) == NULL) { fnPrintf( m_pHRequest, "** Error allocating memory **"); goto Exit; } // Start the text field if not read only mode. if (!bReadOnly) { fnPrintf( m_pHRequest, ""); } while (*puzTmp) { // Check for ASCII characters if ((*puzTmp >= 32) && (*puzTmp <= 126)) { if (RC_BAD( rc = pBuffer->addChar( (char) *puzTmp))) { fnPrintf( m_pHRequest, "** Error adding Unicode character to buffer (Return Code = 0x%04X, %s) **", (unsigned) rc, FlmErrorString( rc)); goto Exit; } } else { // Treat as though these are NON-ASCII. They will be printed in // the form ~[0x ] char szTempBuff[20]; f_sprintf( szTempBuff, "~[0x%04X]", (unsigned) (*puzTmp)); if (RC_BAD( rc = pBuffer->addString( szTempBuff))) { fnPrintf( m_pHRequest, "** Error formatting Unicode string (Return Code = 0x%04X, %s) **", (unsigned) rc, FlmErrorString( rc)); goto Exit; } } // We are attempting to not let our buffer get any larger than the // Http stack buffer size. We don't really know what the limit is, // but we are using what seems to reasonable to us... if ((pBuffer->getBufferSize() + 9) >= RESP_WRITE_BUF_SIZE) { fnPrintf( m_pHRequest, "%s", pBuffer->printBuffer()); pBuffer->reset(); } puzTmp++; } if (bReadOnly) { fnPrintf( m_pHRequest, "%s", pBuffer->printBuffer()); } else { fnPrintf( m_pHRequest, "%s\" size=\"%d\">", pBuffer->printBuffer(), MAX_FIELD_SIZE( uiLen)); } Exit: if (puzBuf) { f_free( &puzBuf); } if (pBuffer) { pBuffer->Release(); } } // /**************************************************************************** Desc: Prints out the value for the field, assuming the field is a number field. ****************************************************************************/ void F_WebPage::printNumberField( FlmRecord * pRec, void * pvField, FLMUINT uiFieldCounter, FLMBOOL bReadOnly) { RCODE rc = FERR_OK; FLMINT iVal; FLMUINT uiVal; if (RC_BAD( rc = pRec->getUINT( pvField, &uiVal))) { if (RC_OK( rc = pRec->getINT( pvField, &iVal))) { if (bReadOnly) { fnPrintf( m_pHRequest, "%d", (int) iVal); } else { fnPrintf( m_pHRequest, "", uiFieldCounter, (int) iVal, MAX_FIELD_SIZE( 0)); } } else { fnPrintf( m_pHRequest, "** Error retrieving number field (Return Code = 0x%04X, %s)**\n", (unsigned) rc, FlmErrorString( rc)); } } else { if (bReadOnly) { fnPrintf( m_pHRequest, "%lu", (unsigned long) uiVal); } else { fnPrintf( m_pHRequest, "", uiFieldCounter, (unsigned long) uiVal); } } } /**************************************************************************** Desc: Prints out the value for the field, assuming the field is a binary field. ****************************************************************************/ void F_WebPage::printBinaryField( FlmRecord * pRec, void * pvField, FLMUINT uiFieldCounter, FLMBOOL bReadOnly) { RCODE rc = FERR_OK; FLMBYTE * pucBuf = NULL; FLMBYTE * pszTmpBuf = NULL; FLMBYTE * pszTmp = NULL; FLMUINT uiLoop; FLMUINT uiLen; FLMUINT uiBufLen; uiLen = pRec->getDataLength( pvField); if (RC_BAD( rc = f_alloc( uiLen, &pucBuf))) { fnPrintf( m_pHRequest, "** Error occured allocating memory to retrieve binary field (Return Code = 0x%04X, %s) **\n", (unsigned) rc, FlmErrorString( rc)); goto Exit; } if (RC_BAD( rc = pRec->getBinary( pvField, pucBuf, &uiLen))) { if (rc != FERR_NOT_FOUND) { fnPrintf( m_pHRequest, "** Error occured retrieving binary field (Return Code = 0x%04X, %s) **\n", (unsigned) rc, FlmErrorString( rc)); goto Exit; } } if (RC_BAD( rc = f_alloc( RESP_WRITE_BUF_SIZE + 1, &pszTmpBuf))) { fnPrintf( m_pHRequest, "** Error occured allocating memory to format binary field (Return Code = 0x%04X, %s) **\n", (unsigned) rc, FlmErrorString( rc)); goto Exit; } if (!bReadOnly) { fnPrintf( m_pHRequest, ""); } // Scan through the binary data, present all data as Hex. for (pszTmp = pszTmpBuf, uiLoop = 0, uiBufLen = 0; uiLoop < uiLen; uiLoop++) { if (uiLoop) { *pszTmp++ = ' '; uiBufLen++; } f_sprintf( (char*) pszTmp, "%2.2X", (unsigned) pucBuf[uiLoop]); pszTmp += 2; uiBufLen += 2; if ((uiBufLen + 3) >= RESP_WRITE_BUF_SIZE) { // Flush the current buffer *pszTmp = '\0'; fnPrintf( m_pHRequest, "%s", pszTmpBuf); pszTmp = pszTmpBuf; uiBufLen = 0; } } *pszTmp = '\0'; if (bReadOnly) { fnPrintf( m_pHRequest, "%s", pszTmpBuf); } else { fnPrintf( m_pHRequest, "%s\" size=\"%d\">", pszTmpBuf, MAX_FIELD_SIZE( uiLen * 3)); } Exit: if (pucBuf) { f_free( &pucBuf); } if (pszTmpBuf) { f_free( &pszTmpBuf); } } /**************************************************************************** Desc: Prints out the value for the field, assuming the field is a context field. ****************************************************************************/ void F_WebPage::printContextField( FlmRecord * pRec, void * pvField, FLMUINT uiFieldCounter, FLMBOOL bReadOnly) { RCODE rc = FERR_OK; FLMUINT uiRecPointer; if (RC_OK( rc = pRec->getRecPointer( pvField, &uiRecPointer))) { if (bReadOnly) { fnPrintf( m_pHRequest, "%lu", (unsigned long) uiRecPointer); } else { fnPrintf( m_pHRequest, "", uiFieldCounter, (unsigned long) uiRecPointer, MAX_FIELD_SIZE( 0)); } } else { fnPrintf( m_pHRequest, "** Error retrieving context field (Return Code = 0x%04X, %s) **", (unsigned) rc, FlmErrorString( rc)); } } /**************************************************************************** Desc: Prints out the value for the field, assuming the field is a blob field. ****************************************************************************/ void F_WebPage::printBlobField( FlmRecord * pRec, void * pvField, FLMUINT uiFieldCounter, FLMBOOL bReadOnly) { RCODE rc = FERR_OK; FlmBlob * pBlob = NULL; char szPath[F_PATH_MAX_SIZE]; FLMUINT uiLen; if (RC_BAD( rc = pRec->getBlob( pvField, &pBlob))) { fnPrintf( m_pHRequest, "** Failed to retrieve Blob object (Return Code = 0x%04X, %s) **", (unsigned long) rc, FlmErrorString( rc)); goto Exit; } uiLen = ((FlmBlobImp *) pBlob)->getDataLength(); if (uiLen == 0) { if (!bReadOnly) { fnPrintf( m_pHRequest, "", uiFieldCounter, MAX_FIELD_SIZE( 0)); } goto Exit; } if (RC_BAD( rc = pBlob->buildFileName( szPath))) { fnPrintf( m_pHRequest, "** Failed to retrieve Blob filename (Return Code = 0x%04X, %s) **", (unsigned) rc, FlmErrorString( rc)); goto Exit; } if (bReadOnly) { fnPrintf( m_pHRequest, ""); printEncodedString( szPath, HTML_ENCODING); fnPrintf( m_pHRequest, ""); } else { fnPrintf( m_pHRequest, ""); } Exit: if (pBlob) { pBlob->Release(); } } /**************************************************************************** Desc: Prints out a string identifying this as a default field - error condition. ****************************************************************************/ void F_WebPage::printDefaultField( FlmRecord *, void *, FLMUINT, FLMBOOL) { fnPrintf( m_pHRequest, "**Default Field**"); } /**************************************************************************** Desc: Prints out the hidden field identifiers ****************************************************************************/ void F_WebPage::printFieldIds( FLMUINT uiFieldCounter, FLMUINT uiFieldLevel, FLMUINT uiType, FLMUINT uiTagNum) { char szTmp[20]; f_sprintf( szTmp, "fieldLevel%u", (unsigned) uiFieldCounter); printHiddenField( szTmp, uiFieldLevel); f_sprintf( szTmp, "fieldType%u", (unsigned) uiFieldCounter); printHiddenField( szTmp, uiType); f_sprintf( szTmp, "fieldTag%u", (unsigned) uiFieldCounter); printHiddenField( szTmp, uiTagNum); } /**************************************************************************** Desc: Prints a table listing the fields of the supplied Log Headers. Any of the log header pointers may be null, in which case a series of blank entries will be created in the table for that entry. ****************************************************************************/ void F_WebPage::printLogHeaders( FLMBYTE * pucLastCommitted, FLMBYTE * pucCheckpoint, FLMBYTE * pucUncommitted) { FLMBOOL bHighlight = FALSE; // Start the table and headings... printTableStart( NULL, 5, 100); printTableRowStart( FALSE); printColumnHeading( "Offset (hex)"); printColumnHeading( "Field"); printColumnHeading( "Last Committed"); printColumnHeading( "Checkpoint"); printColumnHeading( "Uncommitted"); printTableRowEnd(); // Fill in the table here. LOG_RFL_FILE_NUM printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_RFL_FILE_NUM); fnPrintf( m_pHRequest, "Current RFL file"); printLogFileEntryUD( pucLastCommitted, LOG_RFL_FILE_NUM); printLogFileEntryUD( pucCheckpoint, LOG_RFL_FILE_NUM); printLogFileEntryUD( pucUncommitted, LOG_RFL_FILE_NUM); printTableRowEnd(); // LOG_RFL_LAST_TRANS_OFFSET printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_RFL_LAST_TRANS_OFFSET); fnPrintf( m_pHRequest, "Current RFL offset"); printLogFileEntryUD( pucLastCommitted, LOG_RFL_LAST_TRANS_OFFSET); printLogFileEntryUD( pucCheckpoint, LOG_RFL_LAST_TRANS_OFFSET); printLogFileEntryUD( pucUncommitted, LOG_RFL_LAST_TRANS_OFFSET); printTableRowEnd(); // LOG_RFL_LAST_CP_FILE_NUM printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_RFL_LAST_CP_FILE_NUM); fnPrintf( m_pHRequest, "Last CP RFL file"); printLogFileEntryUD( pucLastCommitted, LOG_RFL_LAST_CP_FILE_NUM); printLogFileEntryUD( pucCheckpoint, LOG_RFL_LAST_CP_FILE_NUM); printLogFileEntryUD( pucUncommitted, LOG_RFL_LAST_CP_FILE_NUM); printTableRowEnd(); // LOG_RFL_LAST_CP_OFFSET printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_RFL_LAST_CP_OFFSET); fnPrintf( m_pHRequest, "Last CP RFL offset"); printLogFileEntryUD( pucLastCommitted, LOG_RFL_LAST_CP_OFFSET); printLogFileEntryUD( pucCheckpoint, LOG_RFL_LAST_CP_OFFSET); printLogFileEntryUD( pucUncommitted, LOG_RFL_LAST_CP_OFFSET); printTableRowEnd(); // LOG_ROLLBACK_EOF printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_ROLLBACK_EOF); fnPrintf( m_pHRequest, "End of file"); printLogFileEntryUD( pucLastCommitted, LOG_ROLLBACK_EOF); printLogFileEntryUD( pucCheckpoint, LOG_ROLLBACK_EOF); printLogFileEntryUD( pucUncommitted, LOG_ROLLBACK_EOF); printTableRowEnd(); // LOG_INC_BACKUP_SEQ_NUM printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_INC_BACKUP_SEQ_NUM); fnPrintf( m_pHRequest, "Incremental backup sequence number"); printLogFileEntryUD( pucLastCommitted, LOG_INC_BACKUP_SEQ_NUM); printLogFileEntryUD( pucCheckpoint, LOG_INC_BACKUP_SEQ_NUM); printLogFileEntryUD( pucUncommitted, LOG_INC_BACKUP_SEQ_NUM); printTableRowEnd(); // LOG_CURR_TRANS_ID printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_CURR_TRANS_ID); fnPrintf( m_pHRequest, "Transaction ID"); printLogFileEntryUD( pucLastCommitted, LOG_CURR_TRANS_ID); printLogFileEntryUD( pucCheckpoint, LOG_CURR_TRANS_ID); printLogFileEntryUD( pucUncommitted, LOG_CURR_TRANS_ID); printTableRowEnd(); // LOG_COMMIT_COUNT printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_COMMIT_COUNT); fnPrintf( m_pHRequest, "Commit count"); printLogFileEntryUD( pucLastCommitted, LOG_COMMIT_COUNT); printLogFileEntryUD( pucCheckpoint, LOG_COMMIT_COUNT); printLogFileEntryUD( pucUncommitted, LOG_COMMIT_COUNT); printTableRowEnd(); // LOG_PL_FIRST_CP_BLOCK_ADDR printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_PL_FIRST_CP_BLOCK_ADDR); fnPrintf( m_pHRequest, "First CP block address"); printLogFileEntryUDX( pucLastCommitted, LOG_PL_FIRST_CP_BLOCK_ADDR); printLogFileEntryUDX( pucCheckpoint, LOG_PL_FIRST_CP_BLOCK_ADDR); printLogFileEntryUDX( pucUncommitted, LOG_PL_FIRST_CP_BLOCK_ADDR); printTableRowEnd(); // LOG_LAST_RFL_FILE_DELETED printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_LAST_RFL_FILE_DELETED); fnPrintf( m_pHRequest, "Last RFL file deleted"); printLogFileEntryUD( pucLastCommitted, LOG_LAST_RFL_FILE_DELETED); printLogFileEntryUD( pucCheckpoint, LOG_LAST_RFL_FILE_DELETED); printLogFileEntryUD( pucUncommitted, LOG_LAST_RFL_FILE_DELETED); printTableRowEnd(); // LOG_RFL_MIN_FILE_SIZE printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_RFL_MIN_FILE_SIZE); fnPrintf( m_pHRequest, "Minimum RFL file size"); printLogFileEntryUD( pucLastCommitted, LOG_RFL_MIN_FILE_SIZE); printLogFileEntryUD( pucCheckpoint, LOG_RFL_MIN_FILE_SIZE); printLogFileEntryUD( pucUncommitted, LOG_RFL_MIN_FILE_SIZE); printTableRowEnd(); // LOG_HDR_CHECKSUM printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_HDR_CHECKSUM); fnPrintf( m_pHRequest, "Header checksum"); printLogFileEntryUW( pucLastCommitted, LOG_HDR_CHECKSUM); printLogFileEntryUW( pucCheckpoint, LOG_HDR_CHECKSUM); printLogFileEntryUW( pucUncommitted, LOG_HDR_CHECKSUM); printTableRowEnd(); // LOG_FLAIM_VERSION printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_FLAIM_VERSION); fnPrintf( m_pHRequest, "Flaim version"); printLogFileEntryUW( pucLastCommitted, LOG_FLAIM_VERSION); printLogFileEntryUW( pucCheckpoint, LOG_FLAIM_VERSION); printLogFileEntryUW( pucUncommitted, LOG_FLAIM_VERSION); printTableRowEnd(); // LOG_LAST_BACKUP_TRANS_ID printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_LAST_BACKUP_TRANS_ID); fnPrintf( m_pHRequest, "Last backup trans ID"); printLogFileEntryUD( pucLastCommitted, LOG_LAST_BACKUP_TRANS_ID); printLogFileEntryUD( pucCheckpoint, LOG_LAST_BACKUP_TRANS_ID); printLogFileEntryUD( pucUncommitted, LOG_LAST_BACKUP_TRANS_ID); printTableRowEnd(); // LOG_BLK_CHG_SINCE_BACKUP printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_BLK_CHG_SINCE_BACKUP); fnPrintf( m_pHRequest, "Blocks changed since backup"); printLogFileEntryUD( pucLastCommitted, LOG_BLK_CHG_SINCE_BACKUP); printLogFileEntryUD( pucCheckpoint, LOG_BLK_CHG_SINCE_BACKUP); printLogFileEntryUD( pucUncommitted, LOG_BLK_CHG_SINCE_BACKUP); printTableRowEnd(); // LOG_LAST_CP_TRANS_ID printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_LAST_CP_TRANS_ID); fnPrintf( m_pHRequest, "Last CP trans ID"); printLogFileEntryUD( pucLastCommitted, LOG_LAST_CP_TRANS_ID); printLogFileEntryUD( pucCheckpoint, LOG_LAST_CP_TRANS_ID); printLogFileEntryUD( pucUncommitted, LOG_LAST_CP_TRANS_ID); printTableRowEnd(); // LOG_PF_FIRST_BACKCHAIN printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_PF_FIRST_BACKCHAIN); fnPrintf( m_pHRequest, "Backchain block address"); if (pucLastCommitted && FB2UD( &pucLastCommitted[LOG_PF_FIRST_BACKCHAIN]) == BT_END) { fnPrintf( m_pHRequest, "none"); } else { printLogFileEntryUDX( pucLastCommitted, LOG_PF_FIRST_BACKCHAIN); } if (pucCheckpoint && FB2UD( &pucCheckpoint[LOG_PF_FIRST_BACKCHAIN]) == BT_END) { fnPrintf( m_pHRequest, "none"); } else { printLogFileEntryUDX( pucCheckpoint, LOG_PF_FIRST_BACKCHAIN); } if (pucUncommitted && FB2UD( &pucUncommitted[LOG_PF_FIRST_BACKCHAIN]) == BT_END) { fnPrintf( m_pHRequest, "none"); } else { printLogFileEntryUDX( pucUncommitted, LOG_PF_FIRST_BACKCHAIN); } printTableRowEnd(); // LOG_PF_AVAIL_BLKS printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_PF_AVAIL_BLKS); fnPrintf( m_pHRequest, "Available blocks"); if (pucLastCommitted && FB2UD( &pucLastCommitted[LOG_PF_AVAIL_BLKS]) == BT_END) { fnPrintf( m_pHRequest, "none"); } else { printLogFileEntryUDX( pucLastCommitted, LOG_PF_AVAIL_BLKS); } if (pucCheckpoint && FB2UD( &pucCheckpoint[LOG_PF_AVAIL_BLKS]) == BT_END) { fnPrintf( m_pHRequest, "none"); } else { printLogFileEntryUDX( pucCheckpoint, LOG_PF_AVAIL_BLKS); } if (pucUncommitted && FB2UD( &pucUncommitted[LOG_PF_AVAIL_BLKS]) == BT_END) { fnPrintf( m_pHRequest, "none"); } else { printLogFileEntryUDX( pucUncommitted, LOG_PF_AVAIL_BLKS); } printTableRowEnd(); // LOG_LOGICAL_EOF printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_LOGICAL_EOF); fnPrintf( m_pHRequest, "Logical EOF"); printLogFileEntryUD_X( pucLastCommitted, LOG_LOGICAL_EOF); printLogFileEntryUD_X( pucCheckpoint, LOG_LOGICAL_EOF); printLogFileEntryUD_X( pucUncommitted, LOG_LOGICAL_EOF); printTableRowEnd(); // LOG_LAST_RFL_COMMIT_ID printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_LAST_RFL_COMMIT_ID); fnPrintf( m_pHRequest, "Last RFL commit ID"); printLogFileEntryUD( pucLastCommitted, LOG_LAST_RFL_COMMIT_ID); printLogFileEntryUD( pucCheckpoint, LOG_LAST_RFL_COMMIT_ID); printLogFileEntryUD( pucUncommitted, LOG_LAST_RFL_COMMIT_ID); printTableRowEnd(); // LOG_KEEP_ABORTED_TRANS_IN_RFL printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_KEEP_ABORTED_TRANS_IN_RFL); fnPrintf( m_pHRequest, "Keep aborted trans in RFL"); printLogFileEntryBool( pucLastCommitted, LOG_KEEP_ABORTED_TRANS_IN_RFL); printLogFileEntryBool( pucCheckpoint, LOG_KEEP_ABORTED_TRANS_IN_RFL); printLogFileEntryBool( pucUncommitted, LOG_KEEP_ABORTED_TRANS_IN_RFL); printTableRowEnd(); // LOG_PF_FIRST_BC_CNT printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_PF_FIRST_BC_CNT); fnPrintf( m_pHRequest, "First BC count"); printLogFileEntryUC( pucLastCommitted, LOG_PF_FIRST_BC_CNT); printLogFileEntryUC( pucCheckpoint, LOG_PF_FIRST_BC_CNT); printLogFileEntryUC( pucUncommitted, LOG_PF_FIRST_BC_CNT); printTableRowEnd(); // LOG_KEEP_RFL_FILES printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_KEEP_RFL_FILES); fnPrintf( m_pHRequest, "Keep RFL files"); printLogFileEntryBool( pucLastCommitted, LOG_KEEP_RFL_FILES); printLogFileEntryBool( pucCheckpoint, LOG_KEEP_RFL_FILES); printLogFileEntryBool( pucUncommitted, LOG_KEEP_RFL_FILES); printTableRowEnd(); // LOG_AUTO_TURN_OFF_KEEP_RFL printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_AUTO_TURN_OFF_KEEP_RFL); fnPrintf( m_pHRequest, "Auto turn off keep RFL"); printLogFileEntryBool( pucLastCommitted, LOG_AUTO_TURN_OFF_KEEP_RFL); printLogFileEntryBool( pucCheckpoint, LOG_AUTO_TURN_OFF_KEEP_RFL); printLogFileEntryBool( pucUncommitted, LOG_AUTO_TURN_OFF_KEEP_RFL); printTableRowEnd(); // LOG_PF_NUM_AVAIL_BLKS printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_PF_NUM_AVAIL_BLKS); fnPrintf( m_pHRequest, "Avail Blocks"); printLogFileEntryUD( pucLastCommitted, LOG_PF_NUM_AVAIL_BLKS); printLogFileEntryUD( pucCheckpoint, LOG_PF_NUM_AVAIL_BLKS); printLogFileEntryUD( pucUncommitted, LOG_PF_NUM_AVAIL_BLKS); printTableRowEnd(); // LOG_RFL_MAX_FILE_SIZE printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_RFL_MAX_FILE_SIZE); fnPrintf( m_pHRequest, "Max file size"); printLogFileEntryUD( pucLastCommitted, LOG_RFL_MAX_FILE_SIZE); printLogFileEntryUD( pucCheckpoint, LOG_RFL_MAX_FILE_SIZE); printLogFileEntryUD( pucUncommitted, LOG_RFL_MAX_FILE_SIZE); printTableRowEnd(); // LOG_DB_SERIAL_NUM printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_DB_SERIAL_NUM); fnPrintf( m_pHRequest, "DB serial number"); printSerialNum( pucLastCommitted ? &pucLastCommitted[LOG_DB_SERIAL_NUM] : NULL); printSerialNum( pucCheckpoint ? &pucCheckpoint[LOG_DB_SERIAL_NUM] : NULL); printSerialNum( pucUncommitted ? &pucUncommitted[LOG_DB_SERIAL_NUM] : NULL); printTableRowEnd(); // LOG_LAST_TRANS_RFL_SERIAL_NUM printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_LAST_TRANS_RFL_SERIAL_NUM); fnPrintf( m_pHRequest, "Last Trans RFL serial number"); printSerialNum( pucLastCommitted ? &pucLastCommitted[LOG_LAST_TRANS_RFL_SERIAL_NUM] : NULL); printSerialNum( pucCheckpoint ? &pucCheckpoint[LOG_LAST_TRANS_RFL_SERIAL_NUM] : NULL); printSerialNum( pucUncommitted ? &pucUncommitted[LOG_LAST_TRANS_RFL_SERIAL_NUM] : NULL); printTableRowEnd(); // LOG_RFL_NEXT_SERIAL_NUM printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_RFL_NEXT_SERIAL_NUM); fnPrintf( m_pHRequest, "Next RFL serial number"); printSerialNum( pucLastCommitted ? &pucLastCommitted[LOG_RFL_NEXT_SERIAL_NUM] : NULL); printSerialNum( pucCheckpoint ? &pucCheckpoint[LOG_RFL_NEXT_SERIAL_NUM] : NULL); printSerialNum( pucUncommitted ? &pucUncommitted[LOG_RFL_NEXT_SERIAL_NUM] : NULL); printTableRowEnd(); // LOG_INC_BACKUP_SERIAL_NUM printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_INC_BACKUP_SERIAL_NUM); fnPrintf( m_pHRequest, "Incremental backup serial number"); printSerialNum( pucLastCommitted ? &pucLastCommitted[LOG_INC_BACKUP_SERIAL_NUM] : NULL); printSerialNum( pucCheckpoint ? &pucCheckpoint[LOG_INC_BACKUP_SERIAL_NUM] : NULL); printSerialNum( pucUncommitted ? &pucUncommitted[LOG_INC_BACKUP_SERIAL_NUM] : NULL); printTableRowEnd(); // LOG_MAX_FILE_SIZE printTableRowStart( bHighlight = !bHighlight); fnPrintf( m_pHRequest, "0x%X", LOG_MAX_FILE_SIZE); fnPrintf( m_pHRequest, "Maximum file size (64K units)"); printLogFileEntryUW( pucLastCommitted, LOG_MAX_FILE_SIZE); printLogFileEntryUW( pucCheckpoint, LOG_MAX_FILE_SIZE); printLogFileEntryUW( pucUncommitted, LOG_MAX_FILE_SIZE); printTableRowEnd(); printTableEnd(); } /******************************************************************* Desc: ********************************************************************/ void F_WebPage::printSerialNum( FLMBYTE * pucSerialNum) { if (pucSerialNum) { printTableDataStart( FALSE, JUSTIFY_LEFT); // fnPrintf( m_pHRequest, "0x"); for (int iLoop = 0; iLoop < F_SERIAL_NUM_SIZE; iLoop++) { fnPrintf( m_pHRequest, "%02X ", pucSerialNum[iLoop]); } printTableDataEnd(); } else { fnPrintf( m_pHRequest, "-"); } } /******************************************************************* Desc: Print a table entry as unsigned 4 digit hex minimum. ********************************************************************/ void F_WebPage::printLogFileEntryUDX( FLMBYTE * pucLog, FLMUINT uiOffset) { if (pucLog) { fnPrintf( m_pHRequest, "0x%04X", FB2UD( &pucLog[uiOffset])); } else { fnPrintf( m_pHRequest, "-"); } } /******************************************************************* Desc: Print a table entry as unsigned decimal hex in parenthesis. ********************************************************************/ void F_WebPage::printLogFileEntryUD_X( FLMBYTE * pucLog, FLMUINT uiOffset) { if (pucLog) { printTableDataStart( TRUE, JUSTIFY_LEFT); printCommaNumText( (FLMUINT64) FB2UD( &pucLog[uiOffset])); fnPrintf( m_pHRequest, " (0x%X)", FB2UD( &pucLog[uiOffset])); printTableDataEnd(); } else { fnPrintf( m_pHRequest, "-"); } } /******************************************************************* Desc: Print a table entry as unsigned decimal. ********************************************************************/ void F_WebPage::printLogFileEntryUD( FLMBYTE * pucLog, FLMUINT uiOffset) { if (pucLog) { printCommaNum( (FLMUINT64) FB2UD( &pucLog[uiOffset]), JUSTIFY_LEFT); } else { fnPrintf( m_pHRequest, "-"); } } /******************************************************************* Desc: Print a table entry as unsigned word. ********************************************************************/ void F_WebPage::printLogFileEntryUW( FLMBYTE * pucLog, FLMUINT uiOffset) { if (pucLog) { printCommaNum( (FLMUINT64) FB2UW( &pucLog[uiOffset]), JUSTIFY_LEFT); } else { fnPrintf( m_pHRequest, "-"); } } /******************************************************************* Desc: Print a table entry as unsigned char. ********************************************************************/ void F_WebPage::printLogFileEntryUC( FLMBYTE * pucLog, FLMUINT uiOffset) { if (pucLog) { fnPrintf( m_pHRequest, "%u", (unsigned char) pucLog[uiOffset]); } else { fnPrintf( m_pHRequest, "-"); } } /******************************************************************* Desc: Print a table entry as yes or no (FLMBOOL) ********************************************************************/ void F_WebPage::printLogFileEntryBool( FLMBYTE * pucLog, FLMUINT uiOffset) { if (pucLog) { printTableDataStart( TRUE, JUSTIFY_LEFT); printYesNo( (FLMBOOL) pucLog[uiOffset]); printTableDataEnd(); } else { fnPrintf( m_pHRequest, "-"); } }