//-------------------------------------------------------------------------
// 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");
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, "