939 lines
24 KiB
C++
939 lines
24 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#ifndef XP_MAC
|
|
#include "memory.h"
|
|
#else
|
|
#include "cstring"
|
|
#endif
|
|
|
|
//#include "nspr.h"
|
|
#include "nscore.h"
|
|
#include "prmem.h"
|
|
#include "prprf.h"
|
|
#include "plstr.h"
|
|
#include "prinrval.h"
|
|
|
|
// #include "nsStream.h"
|
|
// #include "nsCacheTrace.h"
|
|
#include "nsICacheModule.h"
|
|
#include "nsICacheManager.h"
|
|
|
|
#include "nsCacheObject.h"
|
|
|
|
/*
|
|
* nsCacheObject
|
|
*
|
|
* Gagan Saksena 02/02/98
|
|
*
|
|
*/
|
|
|
|
static const PRIntervalTime DEFAULT_EXPIRES = PR_SecondsToInterval(86400);
|
|
//static const PRIntervalTime DEFAULT_EXPIRES = 1000;
|
|
//static const PRIntervalTime DEFAULT_EXPIRES = PR_IntervalNow();
|
|
|
|
// Globals, need to check if safe to unload module
|
|
static PRInt32 gLockCnt = 0;
|
|
static PRInt32 gInstanceCnt = 0;
|
|
|
|
// Define constants for easy use
|
|
static NS_DEFINE_IID(kICACHEOBJECTIID, NS_ICACHEOBJECT_IID);
|
|
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
static NS_DEFINE_IID(kICACHEMANAGERIID, NS_ICACHEMANAGER_IID);
|
|
static NS_DEFINE_IID(kCacheManagerCID, NS_CACHEMANAGER_CID);
|
|
|
|
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
|
|
ERROR! Must have a byte order
|
|
#endif
|
|
|
|
#ifdef IS_LITTLE_ENDIAN
|
|
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
|
|
#else
|
|
#define COPY_INT32(_a,_b) /* swap */ \
|
|
do { \
|
|
((char *)(_a))[0] = ((char *)(_b))[3]; \
|
|
((char *)(_a))[1] = ((char *)(_b))[2]; \
|
|
((char *)(_a))[2] = ((char *)(_b))[1]; \
|
|
((char *)(_a))[3] = ((char *)(_b))[0]; \
|
|
} while(0)
|
|
#endif
|
|
|
|
/* Convenient macros used in stuffing and reading back cache object to a void * */
|
|
/* TODO: Change these to file scope functions */
|
|
#define STUFF_STRING(string) \
|
|
{ \
|
|
len = (string ? PL_strlen(string)+1 : 0); \
|
|
COPY_INT32((void *)cur_ptr, &len); \
|
|
cur_ptr = cur_ptr + sizeof(int32); \
|
|
if(len) \
|
|
memcpy((void *)cur_ptr, string, len); \
|
|
cur_ptr += len; \
|
|
}
|
|
|
|
#define STUFF_NUMBER(number) \
|
|
{ \
|
|
COPY_INT32((void *)cur_ptr, &number); \
|
|
cur_ptr = cur_ptr + sizeof(PRUint32); \
|
|
}
|
|
|
|
#define STUFF_TIME(number) \
|
|
{ \
|
|
COPY_INT32((void *)cur_ptr, &number); \
|
|
cur_ptr = cur_ptr + sizeof(PRIntervalTime); \
|
|
}
|
|
|
|
#define STUFF_BOOL(bool_val) \
|
|
{ \
|
|
if(bool_val) \
|
|
((char *)(cur_ptr))[0] = 1; \
|
|
else \
|
|
((char *)(cur_ptr))[0] = 0; \
|
|
cur_ptr = cur_ptr + sizeof(char); \
|
|
}
|
|
|
|
/* if any strings are larger than this then
|
|
* there was a serious database error
|
|
*/
|
|
#define MAX_HUGE_STRING_SIZE 10000
|
|
|
|
#define RETRIEVE_STRING(string) \
|
|
{ \
|
|
if(cur_ptr > max_ptr) \
|
|
{ \
|
|
return PR_TRUE; \
|
|
} \
|
|
COPY_INT32(&len, cur_ptr); \
|
|
cur_ptr += sizeof(int32); \
|
|
if(len) \
|
|
{ \
|
|
if(len > MAX_HUGE_STRING_SIZE) \
|
|
{ \
|
|
return PR_FALSE; \
|
|
} \
|
|
string = new char[len]; \
|
|
if(!string) \
|
|
{ \
|
|
return PR_FALSE; \
|
|
} \
|
|
memcpy(string, cur_ptr, len); \
|
|
cur_ptr += len; \
|
|
} \
|
|
}
|
|
|
|
#define RETRIEVE_NUMBER(number) \
|
|
{ \
|
|
if(cur_ptr > max_ptr) \
|
|
return PR_TRUE; \
|
|
COPY_INT32(&number, cur_ptr); \
|
|
cur_ptr += sizeof(int32); \
|
|
}
|
|
|
|
#define RETRIEVE_TIME(number) \
|
|
{ \
|
|
if(cur_ptr > max_ptr) \
|
|
return PR_TRUE; \
|
|
COPY_INT32(&number, cur_ptr); \
|
|
cur_ptr += sizeof(PRIntervalTime); \
|
|
}
|
|
|
|
#define RETRIEVE_BOOL(bool) \
|
|
{ \
|
|
if(cur_ptr > max_ptr) \
|
|
return PR_TRUE; \
|
|
if(((char *)(cur_ptr))[0]) \
|
|
bool = TRUE; \
|
|
else \
|
|
bool = FALSE; \
|
|
cur_ptr += sizeof(char); \
|
|
}
|
|
|
|
/* TODO- Further optimization, initialize these to null,
|
|
but that will add more work on copy constructor which is ok */
|
|
nsCacheObject::nsCacheObject():
|
|
m_Charset(new char[1]),
|
|
m_ContentEncoding(new char[1]),
|
|
m_ContentType(new char[1]),
|
|
m_Etag(new char[1]),
|
|
m_Filename(new char[1]),
|
|
m_State(INIT),
|
|
m_bIsCompleted(PR_FALSE),
|
|
m_Module(-1),
|
|
m_pInfo(0),
|
|
m_PageServicesURL(new char[1]),
|
|
m_PostData(new char[1]),
|
|
m_PostDataLen(0),
|
|
m_pStream(0),
|
|
m_URL(new char[1])
|
|
{
|
|
Init();
|
|
*m_Charset = '\0';
|
|
*m_ContentEncoding = '\0';
|
|
*m_ContentType = '\0';
|
|
*m_Etag = '\0';
|
|
*m_Filename = '\0';
|
|
*m_PageServicesURL = '\0';
|
|
*m_PostData = '\0';
|
|
*m_URL = '\0';
|
|
|
|
NS_INIT_ISUPPORTS() ;
|
|
PR_AtomicIncrement(&gInstanceCnt) ;
|
|
}
|
|
|
|
nsCacheObject::~nsCacheObject()
|
|
{
|
|
if (m_Charset)
|
|
delete[] m_Charset;
|
|
if (m_ContentEncoding)
|
|
delete[] m_ContentEncoding;
|
|
if (m_ContentType)
|
|
delete[] m_ContentType;
|
|
if (m_Etag)
|
|
delete[] m_Etag;
|
|
if (m_Filename)
|
|
delete[] m_Filename;
|
|
if (m_PageServicesURL)
|
|
delete[] m_PageServicesURL;
|
|
if (m_PostData)
|
|
delete[] m_PostData;
|
|
if (m_URL)
|
|
delete[] m_URL;
|
|
if (m_pStream)
|
|
delete m_pStream;
|
|
|
|
PR_AtomicDecrement(&gInstanceCnt) ;
|
|
}
|
|
|
|
nsCacheObject::nsCacheObject(const nsCacheObject& another):
|
|
m_Charset(new char[PL_strlen(another.m_Charset)+1]),
|
|
m_ContentEncoding(new char[PL_strlen(another.m_ContentEncoding)+1]),
|
|
m_ContentType(new char[PL_strlen(another.m_ContentType)+1]),
|
|
m_Etag(new char[PL_strlen(another.m_Etag)+1]),
|
|
m_Filename(new char[PL_strlen(another.m_Filename)+1]),
|
|
m_State(another.m_State),
|
|
m_bIsCompleted(another.m_bIsCompleted),
|
|
m_pInfo(0), /* Should this be copied as well? */
|
|
m_PageServicesURL(new char[PL_strlen(another.m_PageServicesURL)+1]),
|
|
m_PostData(new char[another.m_PostDataLen+1]),
|
|
m_PostDataLen(another.m_PostDataLen),
|
|
m_pStream(0),
|
|
m_URL(new char[PL_strlen(another.m_URL)+1])
|
|
{
|
|
PL_strncpyz(m_Charset, another.m_Charset, PL_strlen(another.m_Charset)+1);
|
|
PL_strncpyz(m_ContentEncoding, another.m_ContentEncoding, PL_strlen(another.m_ContentEncoding)+1);
|
|
PL_strncpyz(m_ContentType, another.m_ContentType, PL_strlen(another.m_ContentType)+1);
|
|
PL_strncpyz(m_Etag, another.m_Etag, PL_strlen(another.m_Etag)+1);
|
|
PL_strncpyz(m_Filename, another.m_Filename, PL_strlen(another.m_Filename)+1);
|
|
PL_strncpyz(m_PageServicesURL, another.m_PageServicesURL, PL_strlen(another.m_PageServicesURL)+1);
|
|
PL_strncpyz(m_PostData, another.m_PostData, another.m_PostDataLen+1);
|
|
PL_strncpyz(m_URL, another.m_URL, PL_strlen(another.m_URL)+1);
|
|
|
|
m_Hits = another.m_Hits;
|
|
m_LastAccessed = another.m_LastAccessed;
|
|
m_LastModified = another.m_LastModified;
|
|
m_Size = another.m_Size;
|
|
m_Module = another.m_Module;
|
|
|
|
NS_INIT_ISUPPORTS() ;
|
|
PR_AtomicIncrement(&gInstanceCnt) ;
|
|
|
|
}
|
|
|
|
nsCacheObject::nsCacheObject(const char* i_url):
|
|
m_Charset(new char[1]),
|
|
m_ContentEncoding(new char[1]),
|
|
m_ContentType(new char[1]),
|
|
m_Etag(new char[1]),
|
|
m_Filename(new char[1]),
|
|
m_State(INIT),
|
|
m_bIsCompleted(PR_FALSE),
|
|
m_Module(-1),
|
|
m_pInfo(0),
|
|
m_PageServicesURL(new char[1]),
|
|
m_PostData(new char[1]),
|
|
m_PostDataLen(0),
|
|
m_pStream(0),
|
|
m_URL(new char[PL_strlen(i_url)+1])
|
|
{
|
|
Init();
|
|
PR_ASSERT(i_url);
|
|
PL_strncpyz(m_URL, i_url, PL_strlen(i_url)+1);
|
|
|
|
*m_Charset = '\0';
|
|
*m_ContentEncoding = '\0';
|
|
*m_ContentType = '\0';
|
|
*m_Etag = '\0';
|
|
*m_Filename = '\0';
|
|
*m_PageServicesURL = '\0';
|
|
*m_PostData = '\0';
|
|
|
|
NS_INIT_ISUPPORTS() ;
|
|
PR_AtomicIncrement(&gInstanceCnt) ;
|
|
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(nsCacheObject, nsCOMTypeInfo<nsICacheObject>::GetIID( )) ;
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetAddress(const char* i_url)
|
|
{
|
|
PR_ASSERT(i_url && *i_url);
|
|
if (!i_url)
|
|
return NS_ERROR_NULL_POINTER ;
|
|
if (m_URL)
|
|
delete[] m_URL;
|
|
int len = PL_strlen(i_url);
|
|
m_URL = new char[len + 1];
|
|
PL_strncpyz(m_URL, i_url, len+1);
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetCharset(const char* i_Charset)
|
|
{
|
|
// PR_ASSERT(i_Charset && *i_Charset);
|
|
if (!i_Charset) //TODO reset m_charset here
|
|
return NS_ERROR_NULL_POINTER ;
|
|
if (m_Charset)
|
|
delete[] m_Charset;
|
|
int len = PL_strlen(i_Charset);
|
|
m_Charset = new char[len + 1];
|
|
PL_strncpyz(m_Charset, i_Charset, len+1);
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetContentEncoding(const char* i_Encoding)
|
|
{
|
|
// PR_ASSERT(i_Encoding && *i_Encoding);
|
|
if (!i_Encoding)
|
|
return NS_ERROR_NULL_POINTER ;
|
|
if (m_ContentEncoding)
|
|
delete[] m_ContentEncoding;
|
|
int len = PL_strlen(i_Encoding);
|
|
m_ContentEncoding = new char[len + 1];
|
|
PL_strncpyz(m_ContentEncoding, i_Encoding, len+1);
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetContentType(const char* i_Type)
|
|
{
|
|
// PR_ASSERT(i_Type && *i_Type);
|
|
if (!i_Type)
|
|
{
|
|
/* Reset to empty */ // TODO ??
|
|
return NS_ERROR_NULL_POINTER ;
|
|
}
|
|
if (m_ContentType)
|
|
delete[] m_ContentType;
|
|
int len = PL_strlen(i_Type);
|
|
m_ContentType = new char[len + 1];
|
|
PL_strncpyz(m_ContentType, i_Type, len+1);
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetEtag(const char* i_etag)
|
|
{
|
|
// PR_ASSERT(i_etag && *i_etag);
|
|
if (!i_etag)
|
|
return NS_ERROR_NULL_POINTER ;
|
|
if (m_Etag)
|
|
delete[] m_Etag;
|
|
m_Etag = new char[PL_strlen(i_etag) + 1];
|
|
PL_strncpyz(m_Etag, i_etag, PL_strlen(i_etag)+1);
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetFilename(const char* i_Filename)
|
|
{
|
|
// PR_ASSERT(i_Filename && *i_Filename);
|
|
if (!i_Filename)
|
|
return NS_ERROR_NULL_POINTER ;
|
|
if (m_Filename)
|
|
delete[] m_Filename;
|
|
int len = PL_strlen(i_Filename);
|
|
m_Filename = new char[len +1];
|
|
PL_strncpyz(m_Filename, i_Filename, len+1);
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::GetInfo(void** o_info)
|
|
{
|
|
if (!o_info)
|
|
return NS_ERROR_NULL_POINTER ;
|
|
|
|
if (m_pInfo) {
|
|
*o_info = m_pInfo;
|
|
return NS_OK ;
|
|
}
|
|
|
|
nsCacheObject* pThis = (nsCacheObject*) this;
|
|
|
|
if (m_URL){
|
|
|
|
pThis->m_info_size = sizeof(nsCacheObject);
|
|
|
|
pThis->m_info_size -= sizeof(void*); // m_info itself is not being serialized
|
|
pThis->m_info_size -= sizeof(char*); // neither is m_PostData
|
|
pThis->m_info_size -= sizeof(nsStream*); // nor the stream
|
|
pThis->m_info_size -= sizeof(PRBool); // bIsCompleted.
|
|
//todo -optimize till here
|
|
|
|
//Add the strings sizes
|
|
pThis->m_info_size += PL_strlen(m_Charset)+1;
|
|
pThis->m_info_size += PL_strlen(m_ContentEncoding)+1;
|
|
pThis->m_info_size += PL_strlen(m_ContentType)+1;
|
|
pThis->m_info_size += PL_strlen(m_Etag)+1;
|
|
pThis->m_info_size += PL_strlen(m_Filename)+1;
|
|
pThis->m_info_size += PL_strlen(m_PageServicesURL)+1;
|
|
pThis->m_info_size += PL_strlen(m_URL)+1;
|
|
|
|
//Add the Postdata len
|
|
pThis->m_info_size += m_PostDataLen+1;
|
|
|
|
//For the virtual function table. This is really nasty, yixiong
|
|
pThis->m_info_size -= sizeof(void*) ;
|
|
|
|
void* new_obj = PR_Calloc(1, m_info_size * sizeof(char));
|
|
|
|
if (!new_obj)
|
|
{
|
|
PR_Free(new_obj);
|
|
return NS_ERROR_OUT_OF_MEMORY ;
|
|
}
|
|
|
|
PRUint32 len;
|
|
|
|
char* cur_ptr = (char*) new_obj;
|
|
/* put the total size of the struct into
|
|
* the first field so that we have
|
|
* a cross check against corruption
|
|
*/
|
|
COPY_INT32((void *)cur_ptr, &m_info_size);
|
|
|
|
cur_ptr += sizeof(PRUint32);
|
|
|
|
/* put the version number of the structure
|
|
* format that we are using. By using a version
|
|
* string when writting we can support
|
|
* backwards compatibility in our reading code
|
|
*/
|
|
COPY_INT32((void *)cur_ptr, &kCACHE_VERSION);
|
|
cur_ptr += sizeof(PRUint32);
|
|
|
|
STUFF_STRING(m_Charset);
|
|
STUFF_STRING(m_ContentEncoding);
|
|
STUFF_NUMBER(m_ContentLength);
|
|
STUFF_STRING(m_ContentType);
|
|
STUFF_STRING(m_Etag);
|
|
STUFF_TIME(m_Expires);
|
|
STUFF_STRING(m_Filename);
|
|
STUFF_NUMBER(m_Hits);
|
|
STUFF_TIME(m_LastAccessed);
|
|
STUFF_TIME(m_LastModified);
|
|
STUFF_NUMBER(m_Module);
|
|
STUFF_STRING(m_PageServicesURL);
|
|
STUFF_NUMBER(m_PostDataLen);
|
|
|
|
/* There is a possibility of it not being a string! */
|
|
if (m_PostData)
|
|
{
|
|
// 4 bytes missing, yixiong
|
|
memcpy(cur_ptr, m_PostData, m_PostDataLen+1);
|
|
cur_ptr += m_PostDataLen+1;
|
|
}
|
|
STUFF_NUMBER(m_Size);
|
|
STUFF_NUMBER(m_State);
|
|
STUFF_STRING(m_URL);
|
|
|
|
// Important Assertion. Dont remove!
|
|
// If this fails then you or somebody has added a variable to the
|
|
// nsCacheObject class and a decision on its "cacheability" has
|
|
// not yet been made.
|
|
PR_ASSERT(cur_ptr == (char*) new_obj + m_info_size);
|
|
pThis->m_pInfo = new_obj;
|
|
|
|
*o_info = pThis->m_pInfo ;
|
|
}
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetInfo(void* i_data)
|
|
{
|
|
if (!i_data)
|
|
return NS_ERROR_NULL_POINTER ;
|
|
|
|
char* cur_ptr = (char*) i_data;
|
|
|
|
//Reset the m_pInfo;
|
|
if (m_pInfo)
|
|
{
|
|
PR_Free(m_pInfo);
|
|
m_pInfo = 0;
|
|
}
|
|
|
|
//Reset all strings
|
|
if (m_Charset)
|
|
delete[] m_Charset;
|
|
if (m_ContentEncoding)
|
|
delete[] m_ContentEncoding;
|
|
if (m_ContentType)
|
|
delete[] m_ContentType;
|
|
if (m_Etag)
|
|
delete[] m_Etag;
|
|
if (m_Filename)
|
|
delete[] m_Filename;
|
|
if (m_PageServicesURL)
|
|
delete[] m_PageServicesURL;
|
|
if (m_URL)
|
|
delete[] m_URL;
|
|
if (m_PostData)
|
|
delete[] m_PostData;
|
|
|
|
m_PostDataLen = 0;
|
|
|
|
COPY_INT32(&m_info_size, cur_ptr);
|
|
char* max_ptr = cur_ptr + m_info_size;
|
|
cur_ptr += sizeof(PRUint32);
|
|
|
|
PRUint32 version;
|
|
COPY_INT32(&version, cur_ptr);
|
|
cur_ptr += sizeof(PRUint32);
|
|
|
|
PR_ASSERT(version == kCACHE_VERSION);
|
|
if (version != kCACHE_VERSION)
|
|
{
|
|
//TODO Bad cache version
|
|
return NS_ERROR_FAILURE ;
|
|
}
|
|
|
|
PRUint32 len;
|
|
|
|
RETRIEVE_STRING(m_Charset);
|
|
RETRIEVE_STRING(m_ContentEncoding);
|
|
RETRIEVE_NUMBER(m_ContentLength);
|
|
RETRIEVE_STRING(m_ContentType);
|
|
RETRIEVE_STRING(m_Etag);
|
|
RETRIEVE_TIME(m_Expires);
|
|
RETRIEVE_STRING(m_Filename);
|
|
RETRIEVE_NUMBER(m_Hits);
|
|
RETRIEVE_TIME(m_LastAccessed);
|
|
RETRIEVE_TIME(m_LastModified);
|
|
RETRIEVE_NUMBER(m_Module);
|
|
RETRIEVE_STRING(m_PageServicesURL);
|
|
RETRIEVE_NUMBER(m_PostDataLen);
|
|
// Special case-
|
|
m_PostData = new char[m_PostDataLen + 1];
|
|
if (m_PostData)
|
|
{
|
|
memcpy(m_PostData, cur_ptr, m_PostDataLen+1);
|
|
}
|
|
cur_ptr += m_PostDataLen +1;
|
|
|
|
RETRIEVE_NUMBER(m_Size);
|
|
RETRIEVE_NUMBER(m_State);
|
|
RETRIEVE_STRING(m_URL);
|
|
|
|
// Most important assertion! Don't ever remove!
|
|
PR_ASSERT(cur_ptr == max_ptr);
|
|
|
|
// Since we are reading off its info from an indexed entry
|
|
m_bIsCompleted = PR_TRUE;
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::GetInfoSize(PRUint32 *o_size)
|
|
{
|
|
if (!m_pInfo)
|
|
{
|
|
GetInfo(&m_pInfo);
|
|
}
|
|
*o_size = m_info_size;
|
|
return NS_OK ;
|
|
}
|
|
|
|
void nsCacheObject::Init()
|
|
{
|
|
m_Size = 0;
|
|
m_Expires = PR_IntervalNow() + DEFAULT_EXPIRES;
|
|
m_Hits = 0;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetPageServicesURL(const char* i_Url)
|
|
{
|
|
// PR_ASSERT(i_Url && *i_Url);
|
|
if (!i_Url)
|
|
return NS_ERROR_NULL_POINTER ;
|
|
if (m_PageServicesURL)
|
|
delete[] m_PageServicesURL;
|
|
m_PageServicesURL = new char[PL_strlen(i_Url) + 1];
|
|
PL_strncpyz(m_PageServicesURL, i_Url, PL_strlen(i_Url)+1);
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::SetPostData(const char* i_data, const PRUint32 i_Len)
|
|
{
|
|
if (!i_data || (0 ==i_Len))
|
|
return NS_ERROR_NULL_POINTER ;
|
|
if (m_PostData)
|
|
delete[] m_PostData;
|
|
m_PostData = new char[i_Len+1];
|
|
PL_strncpyz(m_PostData, i_data, i_Len+1);
|
|
m_PostDataLen = i_Len;
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::Read(char* o_Buffer, PRUint32 len, PRUint32 * pLeng)
|
|
{
|
|
nsresult rv ;
|
|
|
|
if (!m_pStream)
|
|
{
|
|
PR_ASSERT(m_Module >=0);
|
|
if (0 <= m_Module)
|
|
{
|
|
nsICacheModule* pModule ;
|
|
nsICacheManager* cacheManager ;
|
|
rv = nsServiceManager::GetService(kCacheManagerCID,
|
|
kICACHEMANAGERIID,
|
|
(nsISupports **)&cacheManager) ;
|
|
|
|
rv = cacheManager->GetModule(m_Module, &pModule);
|
|
|
|
if (NS_SUCCEEDED(rv) && pModule)
|
|
{
|
|
rv = pModule->GetStreamFor(this, &m_pStream);
|
|
if (NS_SUCCEEDED(rv) && m_pStream)
|
|
{
|
|
*pLeng = m_pStream->Read(o_Buffer, len);
|
|
return NS_OK ;
|
|
}
|
|
}
|
|
}
|
|
return NS_ERROR_FAILURE ;
|
|
}
|
|
*pLeng = m_pStream->Read(o_Buffer, len);
|
|
return NS_OK ;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::Reset(void)
|
|
{
|
|
if (m_pStream)
|
|
m_pStream->Reset();
|
|
// TODO change states too.
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
#if 0
|
|
/* Caller must free returned string */
|
|
// TODO change to use PR_stuff...
|
|
const char* nsCacheObject::Trace() const
|
|
{
|
|
char linebuffer[256];
|
|
char* total;
|
|
|
|
PR_Sprintf(linebuffer, "nsCacheObject:URL=%s,SIZE=%d,ET=%s,\n\tLM=%d,LA=%d,EXP=%d,HITS=%d\n",
|
|
m_URL,
|
|
m_Size,
|
|
m_Etag,
|
|
m_LastModified,
|
|
m_LastAccessed,
|
|
m_Expires,
|
|
m_Hits);
|
|
|
|
total = new char[PL_strlen(linebuffer) +1];
|
|
PL_strcpy(total, linebuffer);
|
|
|
|
return total;
|
|
}
|
|
#endif
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObject::Write(const char* i_Buffer, const PRUint32 len, PRUint32 * oLeng)
|
|
{
|
|
nsresult rv ;
|
|
|
|
if (!oLeng)
|
|
return NS_ERROR_NULL_POINTER ;
|
|
|
|
PRUint32 amountWritten = 0;
|
|
if (!m_pStream)
|
|
{
|
|
PR_ASSERT(m_Module >=0);
|
|
if (0 <= m_Module)
|
|
{
|
|
nsICacheModule* pModule ;
|
|
nsICacheManager* cacheManager ;
|
|
|
|
rv = nsServiceManager::GetService(kCacheManagerCID,
|
|
kICACHEMANAGERIID,
|
|
(nsISupports **)&cacheManager) ;
|
|
|
|
rv = cacheManager->GetModule(m_Module, &pModule);
|
|
|
|
if (NS_SUCCEEDED(rv) && pModule)
|
|
{
|
|
rv = pModule->GetStreamFor(this, &m_pStream);
|
|
PR_ASSERT(m_pStream);
|
|
if (!m_pStream)
|
|
return NS_ERROR_FAILURE ;
|
|
}
|
|
}
|
|
else
|
|
return NS_ERROR_FAILURE ;
|
|
}
|
|
amountWritten = m_pStream->Write(i_Buffer, len);
|
|
m_Size += amountWritten;
|
|
*oLeng = amountWritten;
|
|
|
|
return NS_OK ;
|
|
}
|
|
|
|
nsCacheObjectFactory::nsCacheObjectFactory ()
|
|
{
|
|
NS_INIT_ISUPPORTS();
|
|
PR_AtomicIncrement(&gInstanceCnt);
|
|
}
|
|
|
|
nsCacheObjectFactory::~nsCacheObjectFactory ()
|
|
{
|
|
PR_AtomicDecrement(&gInstanceCnt);
|
|
}
|
|
|
|
/*
|
|
NS_IMETHODIMP
|
|
nsCacheObjectFactory::QueryInterface(const nsIID &aIID, void **aResult)
|
|
{
|
|
if (!aResult)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if (aIID.Equals(kISupportsIID)) {
|
|
*aResult = NS_STATIC_CAST(nsISupports*,this);
|
|
} else if (aIID.Equals(kIFactoryIID)) {
|
|
*aResult = NS_STATIC_CAST(nsISupports*,NS_STATIC_CAST(nsIFactory*,this));
|
|
} else {
|
|
*aResult = nsnull;
|
|
return NS_ERROR_NO_INTERFACE;
|
|
}
|
|
|
|
NS_ADDREF(NS_REINTERPRET_CAST(nsISupports*,*aResult));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_ADDREF(nsCacheObjectFactory)
|
|
NS_IMPL_RELEASE(nsCacheObjectFactory)
|
|
*/
|
|
|
|
NS_IMPL_ISUPPORTS(nsCacheObjectFactory, kIFactoryIID) ;
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObjectFactory::CreateInstance(nsISupports *aOuter,
|
|
const nsIID &aIID,
|
|
void **aResult)
|
|
{
|
|
if (!aResult)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aResult = nsnull;
|
|
|
|
nsISupports *inst = new nsCacheObject();
|
|
|
|
if (!inst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
// All XPCOM methods return nsresult
|
|
nsresult rv = inst->QueryInterface(aIID, aResult);
|
|
|
|
// There are handy macros, NS_SUCCEEDED and NS_FAILED
|
|
// to test the return value of an XPCOM method.
|
|
if (NS_FAILED(rv)) {
|
|
// We didn't get the right interface, so clean up
|
|
delete inst;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCacheObjectFactory::LockFactory(PRBool aLock)
|
|
{
|
|
if (aLock) {
|
|
PR_AtomicIncrement(&gLockCnt);
|
|
} else {
|
|
PR_AtomicDecrement(&gLockCnt);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Exported functions. With these in place we can compile
|
|
// this module into a dynamically loaded and registered
|
|
// component.
|
|
|
|
static NS_DEFINE_CID(kCacheObjectCID, NS_CACHEOBJECT_CID);
|
|
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
|
|
|
|
// The "name" of our component
|
|
static const char* g_desc = "Cache Object XPCOM Module";
|
|
|
|
extern "C" NS_EXPORT nsresult
|
|
NSGetFactory(nsISupports *serviceMgr,
|
|
const nsCID &aCID,
|
|
const char *aClassName,
|
|
const char *aProgID,
|
|
nsIFactory **aResult)
|
|
{
|
|
if (!aResult)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aResult = nsnull;
|
|
|
|
nsISupports *inst;
|
|
|
|
if (aCID.Equals(kCacheObjectCID)) {
|
|
// Ok, we know this CID and here is the factory
|
|
// that can manufacture the objects
|
|
inst = new nsCacheObjectFactory();
|
|
} else {
|
|
return NS_ERROR_NO_INTERFACE;
|
|
}
|
|
|
|
if (!inst)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
nsresult rv = inst->QueryInterface(kIFactoryIID,
|
|
(void **) aResult);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
delete inst;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
extern "C" NS_EXPORT PRBool
|
|
NSCanUnload(nsISupports* serviceMgr)
|
|
{
|
|
return PRBool(gInstanceCnt == 0 && gLockCnt == 0);
|
|
}
|
|
|
|
extern "C" NS_EXPORT nsresult
|
|
NSRegisterSelf(nsISupports *aServMgr, const char *path)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
// We will use the service manager to obtain the component
|
|
// manager, which will enable us to register a component
|
|
// with a ProgID (text string) instead of just the CID.
|
|
|
|
nsIServiceManager *sm;
|
|
|
|
// We can get the IID of an interface with the static GetIID() method as
|
|
// well.
|
|
rv = aServMgr->QueryInterface(nsIServiceManager::GetIID(), (void **)&sm);
|
|
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsIComponentManager *cm;
|
|
|
|
rv = sm->GetService(kComponentManagerCID, nsIComponentManager::GetIID(), (nsISupports **)&cm);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
NS_RELEASE(sm);
|
|
|
|
return rv;
|
|
}
|
|
|
|
// Note the text string, we can access the hello component with just this
|
|
// string without knowing the CID
|
|
rv = cm->RegisterComponent(kCacheObjectCID, g_desc, "component://cacheobject",
|
|
path, PR_TRUE, PR_TRUE);
|
|
|
|
sm->ReleaseService(kComponentManagerCID, cm);
|
|
|
|
NS_RELEASE(sm);
|
|
|
|
#ifdef NS_DEBUG
|
|
printf("*** %s registered\n",g_desc);
|
|
#endif
|
|
|
|
return rv;
|
|
}
|
|
|
|
extern "C" NS_EXPORT nsresult
|
|
NSUnregisterSelf(nsISupports* aServMgr, const char *path)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsIServiceManager *sm;
|
|
|
|
rv = aServMgr->QueryInterface(nsIServiceManager::GetIID(), (void **)&sm);
|
|
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsIComponentManager *cm;
|
|
|
|
rv = sm->GetService(kComponentManagerCID, nsIComponentManager::GetIID(), (nsISupports **)&cm);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
NS_RELEASE(sm);
|
|
|
|
return rv;
|
|
}
|
|
|
|
rv = cm->UnregisterComponent(kCacheObjectCID, path);
|
|
|
|
sm->ReleaseService(kComponentManagerCID, cm);
|
|
|
|
NS_RELEASE(sm);
|
|
|
|
return rv;
|
|
}
|
|
|
|
|