From 90d04981598090422eeba8aba6980d7260b799a5 Mon Sep 17 00:00:00 2001 From: "rayw%netscape.com" Date: Fri, 12 May 2000 01:24:36 +0000 Subject: [PATCH] Per bug 3690: Added new functions to the registry for reading / writing byte arrays of binary content and escaping registry keys that contain binary content. Modified code which reads/writes location of dll or javascript for components to use new ReadBytesUTF8/WriteBytesUTF8 and which uses or reads the keys to use EscapeKey and UnescapeKey. r=dveditz git-svn-id: svn://10.0.0.236/trunk@69307 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/modules/libreg/xpcom/nsIRegistry.idl | 13 + mozilla/modules/libreg/xpcom/nsRegistry.cpp | 305 ++++++++++++++++-- .../xpcom/components/nsComponentManager.cpp | 245 ++++++++------ mozilla/xpcom/components/nsComponentManager.h | 3 +- mozilla/xpcom/components/nsIRegistry.idl | 13 + .../components/nsNativeComponentLoader.cpp | 148 ++++++--- mozilla/xpcom/components/nsRegistry.cpp | 305 ++++++++++++++++-- mozilla/xpcom/ds/nsHashtable.cpp | 5 + 8 files changed, 835 insertions(+), 202 deletions(-) diff --git a/mozilla/modules/libreg/xpcom/nsIRegistry.idl b/mozilla/modules/libreg/xpcom/nsIRegistry.idl index 787340457e6..da6bd006908 100644 --- a/mozilla/modules/libreg/xpcom/nsIRegistry.idl +++ b/mozilla/modules/libreg/xpcom/nsIRegistry.idl @@ -51,11 +51,17 @@ interface nsIRegistry : nsISupports string getStringUTF8(in nsRegistryKey baseKey, in string path); void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value); + void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray); + void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray); PRInt32 getInt(in nsRegistryKey baseKey, in string path); void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value); PRInt64 getLongLong(in nsRegistryKey baseKey, in string path); void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value); + /** + * addSubtree() and friends need to be renamed to addKeyUTF8(). + * If you are using these forms make sure you pass UTF8 data + */ nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path); void removeSubtree(in nsRegistryKey baseKey, in string path); nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path); @@ -77,6 +83,13 @@ interface nsIRegistry : nsISupports PRUint32 getValueLength(in nsRegistryKey baseKey, in string path); void deleteValue(in nsRegistryKey baseKey, in string path); + /** + * escapeKey() takes arbitrary binary data and converts it into + * valid ASCII which can be used as registry key or value names + */ + void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped); + void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key); + attribute string currentUserName; void pack(); diff --git a/mozilla/modules/libreg/xpcom/nsRegistry.cpp b/mozilla/modules/libreg/xpcom/nsRegistry.cpp index 29ca33064cc..cf99b460eff 100644 --- a/mozilla/modules/libreg/xpcom/nsRegistry.cpp +++ b/mozilla/modules/libreg/xpcom/nsRegistry.cpp @@ -73,9 +73,9 @@ struct nsRegistry : public nsIRegistry { protected: HREG mReg; // Registry handle. #ifdef EXTRA_THREADSAFE - PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize. + PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize. #endif - char *mCurRegFile; // these are to prevent open from opening the registry again + char *mCurRegFile; // these are to prevent open from opening the registry again nsWellKnownRegistry mCurRegID; NS_IMETHOD Close(); @@ -167,7 +167,7 @@ struct nsRegistryNode : public nsIRegistryNode { protected: HREG mReg; // Handle to registry this node is part of. char mName[MAXREGPATHLEN]; // Buffer to hold name. - RKEY mChildKey; // Key corresponding to mName + RKEY mChildKey; // Key corresponding to mName #ifdef EXTRA_THREADSAFE PRLock *mregLock; #endif @@ -735,6 +735,94 @@ NS_IMETHODIMP nsRegistry::SetStringUTF8( nsRegistryKey baseKey, const char *path return regerr2nsresult( err ); } +/*---------------------------- nsRegistry::GetBytesUTF8 ------------------------------ +| This function is just shorthand for fetching a char array. We | +| implement it "manually" using NR_RegGetEntry | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32* length, PRUint8** result) { + nsresult rv = NS_OK; + REGERR err = REGERR_OK; + + if ( !result ) + return NS_ERROR_NULL_POINTER; + + char regStr[MAXREGPATHLEN]; + + // initialize the return value + *length = 0; + *result = 0; + + // Get info about the requested entry. + PRUint32 type; + rv = GetValueType( baseKey, path, &type ); + // See if that worked. + if( rv == NS_OK ) + { + // Make sure the entry is an PRInt8 array. + if( type == Bytes ) + { + // Attempt to get string into our fixed buffer + PR_Lock(mregLock); + uint32 length2 = sizeof regStr; + err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), regStr, &length2); + PR_Unlock(mregLock); + + if ( err == REGERR_OK ) + { + *length = length2; + *result = (PRUint8*)(nsCRT::strdup(regStr)); + if (!*result) + { + rv = NS_ERROR_OUT_OF_MEMORY; + *length = 0; + } + else + { + *length = length2; + } + } + else if ( err == REGERR_BUFTOOSMALL ) + { + // find the real size and malloc it + rv = GetValueLength( baseKey, path, length ); + // See if that worked. + if( rv == NS_OK ) + { + *result = NS_REINTERPRET_CAST(PRUint8*,nsAllocator::Alloc( *length )); + if( *result ) + { + // Get bytes from registry into result field. + PR_Lock(mregLock); + length2 = *length; + err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), *result, &length2); + *length = length2; + PR_Unlock(mregLock); + // Convert status. + rv = regerr2nsresult( err ); + if ( rv != NS_OK ) + { + // Didn't get result, free buffer + nsCRT::free( NS_REINTERPRET_CAST(char*, *result) ); + *result = 0; + *length = 0; + } + } + else + { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + } + } + else + { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + return rv; +} + /*---------------------------- nsRegistry::GetInt ------------------------------ | This function is just shorthand for fetching a 1-element PRInt32 array. We | | implement it "manually" using NR_RegGetEntry | @@ -788,6 +876,24 @@ NS_IMETHODIMP nsRegistry::GetLongLong( nsRegistryKey baseKey, const char *path, // Convert status. return regerr2nsresult( err ); } +/*---------------------------- nsRegistry::SetBytesUTF8 ------------------------------ +| Write out the value as a char array, using NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32 length, PRUint8* value) { + REGERR err = REGERR_OK; + // Set the contents. + PR_Lock(mregLock); + err = NR_RegSetEntry( mReg, + (RKEY)baseKey, + (char*)path, + REGTYPE_ENTRY_BYTES, + (char*)value, + length); + PR_Unlock(mregLock); + // Convert result. + return regerr2nsresult( err ); +} + /*---------------------------- nsRegistry::SetInt ------------------------------ | Write out the value as a one-element PRInt32 array, using NR_RegSetEntry. | ------------------------------------------------------------------------------*/ @@ -862,8 +968,8 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path nsresult rv = NS_OK; REGERR err = REGERR_OK; - // libreg doesn't delete keys if there are subkeys under the key - // Hence we have to recurse through to delete the subtree + // libreg doesn't delete keys if there are subkeys under the key + // Hence we have to recurse through to delete the subtree RKEY key; @@ -871,13 +977,13 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path err = NR_RegGetKey(mReg, baseKey, (char *)path, &key); PR_Unlock(mregLock); if (err != REGERR_OK) - { - rv = regerr2nsresult( err ); + { + rv = regerr2nsresult( err ); return rv; - } + } // Now recurse through and delete all keys under hierarchy - + char subkeyname[MAXREGPATHLEN+1]; REGENUM state = 0; subkeyname[0] = '\0'; @@ -885,7 +991,7 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path REGENUM_NORMAL) == REGERR_OK) { #ifdef DEBUG_dp - printf("...recursing into %s\n", subkeyname); + printf("...recursing into %s\n", subkeyname); #endif /* DEBUG_dp */ // Even though this is not a "Raw" API the subkeys may still, in fact, // *be* raw. Since we're recursively deleting this will work either way. @@ -899,15 +1005,15 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path if (err == REGERR_OK) { #ifdef DEBUG_dp - printf("...deleting %s\n", path); + printf("...deleting %s\n", path); #endif /* DEBUG_dp */ PR_Lock(mregLock); err = NR_RegDeleteKey(mReg, baseKey, (char *)path); PR_Unlock(mregLock); } - // Convert result. - rv = regerr2nsresult( err ); + // Convert result. + rv = regerr2nsresult( err ); return rv; } @@ -919,8 +1025,8 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k nsresult rv = NS_OK; REGERR err = REGERR_OK; - // libreg doesn't delete keys if there are subkeys under the key - // Hence we have to recurse through to delete the subtree + // libreg doesn't delete keys if there are subkeys under the key + // Hence we have to recurse through to delete the subtree RKEY key; char subkeyname[MAXREGPATHLEN+1]; @@ -931,18 +1037,18 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k err = NR_RegGetKeyRaw(mReg, baseKey, (char *)keyname, &key); PR_Unlock(mregLock); if (err != REGERR_OK) - { - rv = regerr2nsresult( err ); + { + rv = regerr2nsresult( err ); return rv; - } + } // Now recurse through and delete all keys under hierarchy - + subkeyname[0] = '\0'; while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, n, REGENUM_NORMAL) == REGERR_OK) { #ifdef DEBUG_dp - printf("...recursing into %s\n", subkeyname); + printf("...recursing into %s\n", subkeyname); #endif /* DEBUG_dp */ err = RemoveSubtreeRaw(key, subkeyname); if (err != REGERR_OK) break; @@ -952,15 +1058,15 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k if (err == REGERR_OK) { #ifdef DEBUG_dp - printf("...deleting %s\n", keyname); + printf("...deleting %s\n", keyname); #endif /* DEBUG_dp */ PR_Lock(mregLock); err = NR_RegDeleteKeyRaw(mReg, baseKey, (char *)keyname); PR_Unlock(mregLock); } - // Convert result. - rv = regerr2nsresult( err ); + // Convert result. + rv = regerr2nsresult( err ); return rv; } /*-------------------------- nsRegistry::GetSubtree ---------------------------- @@ -1196,6 +1302,157 @@ NS_IMETHODIMP nsRegistry::Pack() { return rv; } +/*----------------------------- nsRegistry::EscapeKey ------------------------------- +| Escape a binary key so that the registry works OK, since it expects UTF8 +| with no slashes or control characters. This is probably better than raw. +| If no escaping is required, then the method is successful and a null is +| returned, indicating that the caller should use the original string. +------------------------------------------------------------------------------*/ +static const char sEscapeKeyHex[] = "0123456789abcdef0123456789ABCDEF"; +NS_IMETHODIMP nsRegistry::EscapeKey(PRUint8* key, PRUint32 termination, PRUint32* length, PRUint8** escaped) +{ + nsresult rv = NS_OK; + char* value = (char*)key; + char* b = value; + char* e = b + *length; + int escapees = 0; + while (b < e) // Count characters outside legal range or slash + { + int c = *b++; + if (c <= ' ' + || c > '~' + || c == '/' + || c == '%') + { + escapees++; + } + } + if (escapees == 0) // If no escapees, then no results + { + *length = 0; + *escaped = nsnull; + return NS_OK; + } + // New length includes two extra chars for escapees. + *length += escapees * 2; + *escaped = (PRUint8*)nsAllocator::Alloc(*length + termination); + if (*escaped == nsnull) + { + *length = 0; + *escaped = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + char* n = (char*)*escaped; + b = value; + while (escapees && b < e) + { + char c = *b++; + if (c < ' ' + || c > '~' + || c == '/' + || c == '%') + { + *(n++) = '%'; + *(n++) = sEscapeKeyHex[ 0xF & (c >> 4) ]; + *(n++) = sEscapeKeyHex[ 0xF & c ]; + escapees--; + } + else + { + *(n++) = c; + } + } + e += termination; + if (b < e) + { + strncpy(n, b, e - b); + } + return rv; +} + +/*----------------------------- nsRegistry::UnescapeKey ------------------------------- +| Unscape a binary key so that the registry works OK, since it expects UTF8 +| with no slashes or control characters. This is probably better than raw. +| If no escaping is required, then the method is successful and a null is +| returned, indicating that the caller should use the original string. +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::UnescapeKey(PRUint8* escaped, PRUint32 termination, PRUint32* length, PRUint8** key) +{ + nsresult rv = NS_OK; + char* value = (char*)escaped; + char* b = value; + char* e = b + *length; + int escapees = 0; + while (b < e) // Count characters outside legal range or slash + { + if (*b++ == '%') + { + escapees++; + } + } + if (escapees == 0) // If no escapees, then no results + { + *length = 0; + *key = nsnull; + return NS_OK; + } + // New length includes two extra chars for escapees. + *length -= escapees * 2; + *key = (PRUint8*)nsAllocator::Alloc(*length + termination); + if (*key == nsnull) + { + *length = 0; + *key = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + char* n = (char*)*key; + b = value; + while (escapees && b < e) + { + char c = *(b++); + if (c == '%') + { + if (e - b >= 2) + { + char* c1 = strchr(sEscapeKeyHex, *(b++)); + char* c2 = strchr(sEscapeKeyHex, *(b++)); + if (c1 != nsnull + && c2 != nsnull) + { + *(n++) = ((c2 - sEscapeKeyHex) & 0xF) + | (((c1 - sEscapeKeyHex) & 0xF) << 4); + } + else + { + escapees = -1; + } + } + else + { + escapees = -1; + } + escapees--; + } + else + { + *(n++) = c; + } + } + if (escapees < 0) + { + nsAllocator::Free(*key); + *length = 0; + *key = nsnull; + return NS_ERROR_INVALID_ARG; + } + e += termination; + if (b < e) + { + strncpy(n, b, e - b); + } + return rv; +} + /*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ---------------- | The ctor simply stashes all the information that will be needed to enumerate | | the subkeys. | @@ -1437,7 +1694,7 @@ NS_IMETHODIMP nsRegistryNode::GetNameUTF8( char **result ) { } /*-------------------------- nsRegistryNode::GetKey ---------------------------- -| Get the subkey corresponding to this node | +| Get the subkey corresponding to this node | | using NR_RegEnumSubkeys. | ------------------------------------------------------------------------------*/ NS_IMETHODIMP nsRegistryNode::GetKey( nsRegistryKey *r_key ) { diff --git a/mozilla/xpcom/components/nsComponentManager.cpp b/mozilla/xpcom/components/nsComponentManager.cpp index 15524e718ae..c96580ea427 100644 --- a/mozilla/xpcom/components/nsComponentManager.cpp +++ b/mozilla/xpcom/components/nsComponentManager.cpp @@ -123,32 +123,32 @@ extern PRBool gShuttingDown; nsresult nsCreateInstanceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const - { - nsresult status = nsComponentManager::CreateInstance(mCID, mOuter, aIID, aInstancePtr); - if ( !NS_SUCCEEDED(status) ) - *aInstancePtr = 0; + { + nsresult status = nsComponentManager::CreateInstance(mCID, mOuter, aIID, aInstancePtr); + if ( !NS_SUCCEEDED(status) ) + *aInstancePtr = 0; - if ( mErrorPtr ) - *mErrorPtr = status; - return status; - } + if ( mErrorPtr ) + *mErrorPtr = status; + return status; + } nsresult nsCreateInstanceByProgID::operator()( const nsIID& aIID, void** aInstancePtr ) const - { - nsresult status; - if ( mProgID ) - { - if ( !NS_SUCCEEDED(status = nsComponentManager::CreateInstance(mProgID, mOuter, aIID, aInstancePtr)) ) - *aInstancePtr = 0; - } - else - status = NS_ERROR_NULL_POINTER; + { + nsresult status; + if ( mProgID ) + { + if ( !NS_SUCCEEDED(status = nsComponentManager::CreateInstance(mProgID, mOuter, aIID, aInstancePtr)) ) + *aInstancePtr = 0; + } + else + status = NS_ERROR_NULL_POINTER; - if ( mErrorPtr ) - *mErrorPtr = status; - return status; - } + if ( mErrorPtr ) + *mErrorPtr = status; + return status; + } /* prototypes for the Mac */ PRBool PR_CALLBACK @@ -211,7 +211,7 @@ nsCID_Destroy(nsHashKey *aKey, void *aData, void* closure) nsCID* entry = NS_STATIC_CAST(nsCID*, aData); // nasty hack. We "know" that kNoCID was entered into the hash table. if (entry != &kNoCID) - delete entry; + delete entry; return PR_TRUE; } @@ -260,11 +260,11 @@ nsresult nsComponentManagerImpl::Init(void) } if (mLoaders == nsnull) { - mLoaders = new nsSupportsHashtable(16, /* Thread safe */ PR_TRUE); - if (mLoaders == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - nsStringKey loaderKey(nativeComponentType); - mLoaders->Put(&loaderKey, mNativeComponentLoader); + mLoaders = new nsSupportsHashtable(16, /* Thread safe */ PR_TRUE); + if (mLoaders == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + nsStringKey loaderKey(nativeComponentType); + mLoaders->Put(&loaderKey, mNativeComponentLoader); } #ifdef USE_REGISTRY @@ -306,12 +306,12 @@ nsresult nsComponentManagerImpl::Shutdown(void) #endif /* USE_REGISTRY */ // This is were the nsFileSpec was deleted, so I am - // going to assign zero to - mComponentsDir = 0; + // going to assign zero to + mComponentsDir = 0; // Release all the component loaders if (mLoaders) - delete mLoaders; + delete mLoaders; // we have an extra reference on this one, which is probably a good thing NS_IF_RELEASE(mNativeComponentLoader); @@ -358,7 +358,7 @@ nsComponentManagerImpl::PlatformInit(void) // We need to create our registry. Since we are in the constructor // we haven't gone as far as registering the registry factory. // Hence, we hand create a registry. - if (mRegistry == NULL) { + if (mRegistry == NULL) { nsIFactory *registryFactory = NULL; rv = NS_RegistryGetFactory(®istryFactory); if (NS_SUCCEEDED(rv)) @@ -452,15 +452,15 @@ nsComponentManagerImpl::PlatformInit(void) if (!mComponentsDir) return NS_ERROR_OUT_OF_MEMORY; - char* componentDescriptor; - mComponentsDir->GetPath(&componentDescriptor); - if (!componentDescriptor) - return NS_ERROR_NULL_POINTER; + char* componentDescriptor; + mComponentsDir->GetPath(&componentDescriptor); + if (!componentDescriptor) + return NS_ERROR_NULL_POINTER; - mComponentsOffset = strlen(componentDescriptor); - - if (componentDescriptor) - nsAllocator::Free(componentDescriptor); + mComponentsOffset = strlen(componentDescriptor); + + if (componentDescriptor) + nsAllocator::Free(componentDescriptor); @@ -549,6 +549,7 @@ nsComponentManagerImpl::PlatformVersionCheck(nsRegistryKey *aXPCOMRootKey) } #if 0 +// If ever revived, this code is not fully updated to escape the dll location void nsComponentManagerImpl::PlatformSetFileInfo(nsRegistryKey key, PRUint32 lastModifiedTime, PRUint32 fileSize) { @@ -561,7 +562,7 @@ nsComponentManagerImpl::PlatformSetFileInfo(nsRegistryKey key, PRUint32 lastModi * * Stores the dll name, last modified time, size and 0 for number of * components in dll in the registry at location - * ROOTKEY_COMMON/Software/Mozilla/XPCOM/Components/dllname + * ROOTKEY_COMMON/Software/Mozilla/XPCOM/Components/dllname */ nsresult nsComponentManagerImpl::PlatformMarkNoComponents(nsDll *dll) @@ -576,7 +577,7 @@ nsComponentManagerImpl::PlatformMarkNoComponents(nsDll *dll) { return rv; } - + PlatformSetFileInfo(dllPathKey, dll->GetLastModifiedTime(), dll->GetSize()); rv = mRegistry->SetInt(dllPathKey, componentCountValueName, 0); @@ -605,7 +606,9 @@ nsComponentManagerImpl::PlatformRegister(const char *cidString, { rv = mRegistry->SetStringUTF8(IDkey,progIDValueName, progID); } - rv = mRegistry->SetStringUTF8(IDkey, inprocServerValueName, dll->GetPersistentDescriptorString()); + rv = mRegistry->SetBytesUTF8(IDkey, inprocServerValueName, + strlen(dll->GetPersistentDescriptorString()) + 1, + NS_REINTERPRET_CAST(char*, dll->GetPersistentDescriptorString())); if (progID) { @@ -631,10 +634,21 @@ nsComponentManagerImpl::PlatformRegister(const char *cidString, nsresult nsComponentManagerImpl::PlatformUnregister(const char *cidString, const char *aLibrary) -{ +{ + nsresult rv; + PRUint32 length = strlen(aLibrary); + char* eLibrary; + rv = mRegistry->EscapeKey((PRUint8*)aLibrary, 1, &length, (PRUint8**)&eLibrary); + if (rv != NS_OK) + { + return rv; + } + if (eLibrary == nsnull) // No escaping required + eLibrary = (char*)aLibrary; + + PR_ASSERT(mRegistry!=NULL); - nsresult rv; nsRegistryKey cidKey; rv = mRegistry->AddSubtreeRaw(mCLSIDKey, cidString, &cidKey); @@ -648,9 +662,9 @@ nsComponentManagerImpl::PlatformUnregister(const char *cidString, } mRegistry->RemoveSubtree(mCLSIDKey, cidString); - + nsRegistryKey libKey; - rv = mRegistry->GetSubtreeRaw(mXPCOMKey, aLibrary, &libKey); + rv = mRegistry->GetSubtreeRaw(mXPCOMKey, eLibrary, &libKey); if(NS_FAILED(rv)) return rv; // We need to reduce the ComponentCount by 1. @@ -662,13 +676,16 @@ nsComponentManagerImpl::PlatformUnregister(const char *cidString, if (nComponents <= 0) { - rv = mRegistry->RemoveSubtreeRaw(mXPCOMKey, aLibrary); + rv = mRegistry->RemoveSubtreeRaw(mXPCOMKey, eLibrary); } else { rv = mRegistry->SetInt(libKey, componentCountValueName, nComponents); } + if (eLibrary != aLibrary) + nsAllocator::Free(eLibrary); + return rv; } @@ -688,8 +705,9 @@ nsComponentManagerImpl::PlatformFind(const nsCID &aCID, nsFactoryEntry* *result) if (NS_FAILED(rv)) return rv; nsXPIDLCString library; - rv = mRegistry->GetStringUTF8(cidKey, inprocServerValueName, - getter_Copies(library)); + PRUint32 tmp; + rv = mRegistry->GetBytesUTF8(cidKey, inprocServerValueName, + &tmp, (PRUint8**)getter_Copies(library).operator char**()); if (NS_FAILED(rv)) { // Registry inconsistent. No File name for CLSID. @@ -729,7 +747,7 @@ nsComponentManagerImpl::PlatformProgIDToCLSID(const char *aProgID, nsCID *aClass PR_ASSERT(mRegistry); nsresult rv; - + nsRegistryKey progIDKey; rv = mRegistry->GetSubtreeRaw(mClassesKey, aProgID, &progIDKey); if (NS_FAILED(rv)) return NS_ERROR_FACTORY_NOT_REGISTERED; @@ -750,7 +768,7 @@ nsresult nsComponentManagerImpl::PlatformCLSIDToProgID(const nsCID *aClass, char* *aClassName, char* *aProgID) { - + PR_ASSERT(aClass); PR_ASSERT(mRegistry); @@ -809,8 +827,9 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry() // Create the CID entry nsXPIDLCString library; - rv = mRegistry->GetStringUTF8(cidKey, inprocServerValueName, - getter_Copies(library)); + PRUint32 tmp; + rv = mRegistry->GetBytesUTF8(cidKey, inprocServerValueName, + &tmp, (PRUint8**)getter_Copies(library).operator char**()); if (NS_FAILED(rv)) continue; nsCID aClass; @@ -864,7 +883,7 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry() if (NS_FAILED(rv)) continue; nsCID *aClass = new nsCID(); - if (!aClass) continue; // Protect against out of memory. + if (!aClass) continue; // Protect against out of memory. if (!(aClass->Parse(cidString))) { delete aClass; @@ -948,7 +967,7 @@ nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry, (const char *)aEntry->location, (const char *)aEntry->type)); return rv; } - + return NS_OK; } @@ -1031,7 +1050,7 @@ nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID, PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED")); - + return rv; } @@ -1164,7 +1183,7 @@ nsComponentManagerImpl::CreateInstance(const nsCID &aClass, return NS_ERROR_NULL_POINTER; } *aResult = NULL; - + nsIFactory *factory = NULL; nsresult res = FindFactory(aClass, &factory); if (NS_SUCCEEDED(res)) @@ -1270,14 +1289,14 @@ nsComponentManagerImpl::RegistryLocationForSpec(nsIFile *aSpec, char *persistentDescriptor; if (containedIn){ - - rv = aSpec->GetPath(&persistentDescriptor); + + rv = aSpec->GetPath(&persistentDescriptor); if (NS_FAILED(rv)) return rv; - char* relativeLocation = persistentDescriptor + mComponentsOffset + 1; - - rv = MakeRegistryName(relativeLocation, XPCOM_RELCOMPONENT_PREFIX, + char* relativeLocation = persistentDescriptor + mComponentsOffset + 1; + + rv = MakeRegistryName(relativeLocation, XPCOM_RELCOMPONENT_PREFIX, aRegistryName); } else { /* absolute names include volume info on Mac, so persistent descriptor */ @@ -1400,11 +1419,11 @@ nsComponentManagerImpl::RegisterFactory(const nsCID &aClass, return rv; } } - + PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, ("\t\tFactory register succeeded progid=%s.", aProgID ? aProgID : "")); - + return NS_OK; } @@ -1535,17 +1554,17 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass, rv = AddComponentToRegistry(aClass, className, progID, aRegistryName, aType); if (NS_FAILED(rv)) { - PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, - ("\t\tadding %s %s to registry FAILED", className, progID)); + PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, + ("\t\tadding %s %s to registry FAILED", className, progID)); goto out; - } + } } #endif rv = GetLoaderForType(aType, getter_AddRefs(loader)); if (NS_FAILED(rv)) { - PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, - ("\t\tgetting loader for %s FAILED\n", aType)); + PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, + ("\t\tgetting loader for %s FAILED\n", aType)); goto out; } @@ -1556,7 +1575,7 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass, } if (entry) { // aReplace implicit from test above - delete entry; + delete entry; } /* unless the fabric of the universe bends, we'll get entry back */ @@ -1565,7 +1584,7 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass, /* don't try to clean up, just drop everything and run */ if (!sanity) - return NS_ERROR_FACTORY_NOT_REGISTERED; + return NS_ERROR_FACTORY_NOT_REGISTERED; /* we've put the new entry in the hash table, so don't delete on error */ newEntry = nsnull; @@ -1578,10 +1597,10 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass, ) { rv = HashProgID(progID, aClass); if (NS_FAILED(rv)) { - PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, - ("\t\tHashProgID(%s) FAILED\n", progID)); + PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, + ("\t\tHashProgID(%s) FAILED\n", progID)); goto out; - } + } } // Let the loader do magic things now @@ -1615,9 +1634,9 @@ nsComponentManagerImpl::GetLoaderForType(const char *aType, loader = (nsIComponentLoader *)mLoaders->Get(&typeKey); if (loader) { - // nsSupportsHashtable does the AddRef - *aLoader = loader; - return NS_OK; + // nsSupportsHashtable does the AddRef + *aLoader = loader; + return NS_OK; } nsRegistryKey loaderKey; @@ -1634,7 +1653,7 @@ nsComponentManagerImpl::GetLoaderForType(const char *aType, fprintf(stderr, "nCMI: constructing loader for type %s = %s\n", aType, progID); #endif - rv = CreateInstanceByProgID(progID, nsnull, NS_GET_IID(nsIComponentLoader), (void **)&loader); + rv = CreateInstanceByProgID(progID, nsnull, NS_GET_IID(nsIComponentLoader), (void **)&loader); PR_FREEIF(progID); if (NS_FAILED(rv)) return rv; @@ -1642,8 +1661,8 @@ nsComponentManagerImpl::GetLoaderForType(const char *aType, rv = loader->Init(this, mRegistry); if (NS_SUCCEEDED(rv)) { - mLoaders->Put(&typeKey, loader); - *aLoader = loader; + mLoaders->Put(&typeKey, loader); + *aLoader = loader; } return rv; } @@ -1676,6 +1695,16 @@ nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass, const char *aType) { nsresult rv; + PRUint32 length = strlen(aRegistryName); + char* eRegistryName; + rv = mRegistry->EscapeKey((PRUint8*)aRegistryName, 1, &length, (PRUint8**)&eRegistryName); + if (rv != NS_OK) + { + return rv; + } + if (eRegistryName == nsnull) // No escaping required + eRegistryName = (char*)aRegistryName; + nsRegistryKey IDKey; PRInt32 nComponents = 0; @@ -1693,7 +1722,9 @@ nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass, goto out; } - rv = mRegistry->SetStringUTF8(IDKey, inprocServerValueName, aRegistryName); + rv = mRegistry->SetBytesUTF8(IDKey, inprocServerValueName, + strlen(aRegistryName) + 1, + (PRUint8*)aRegistryName); if (NS_FAILED(rv)) goto out; @@ -1716,7 +1747,7 @@ nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass, } nsRegistryKey compKey; - rv = mRegistry->AddSubtreeRaw(mXPCOMKey, aRegistryName, &compKey); + rv = mRegistry->AddSubtreeRaw(mXPCOMKey, eRegistryName, &compKey); // update component count rv = mRegistry->GetInt(compKey, componentCountValueName, &nComponents); @@ -1728,6 +1759,8 @@ nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass, out: // XXX if failed, undo registry adds or set invalid bit? How? nsCRT::free(cidString); + if (eRegistryName != aRegistryName) + nsAllocator::Free(eRegistryName); return rv; } @@ -1742,7 +1775,7 @@ nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass, ("nsComponentManager: UnregisterFactory(%s)", buf)); delete [] buf; } - + nsIDKey key(aClass); nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED; nsFactoryEntry *old = (nsFactoryEntry *) mFactories->Get(&key); @@ -1790,9 +1823,9 @@ nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass, rv = PlatformUnregister(cidString, registryName); delete [] cidString; #endif - + PR_ExitMonitor(mMon); - + PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, ("nsComponentManager: Factory unregister(%s) %s.", registryName, NS_SUCCEEDED(rv) ? "succeeded" : "FAILED")); @@ -1821,18 +1854,18 @@ CanUnload_enumerate(nsHashKey *key, void *aData, void *aClosure) { nsIComponentLoader *loader = (nsIComponentLoader *)aData; struct CanUnload_closure *closure = - (struct CanUnload_closure *)aClosure; + (struct CanUnload_closure *)aClosure; if (loader == closure->native) { #ifdef DEBUG - fprintf(stderr, "CanUnload_enumerate: skipping native\n"); + fprintf(stderr, "CanUnload_enumerate: skipping native\n"); #endif - return PR_TRUE; + return PR_TRUE; } closure->status = loader->UnloadAll(closure->when); if (NS_FAILED(closure->status)) - return PR_FALSE; + return PR_FALSE; return PR_TRUE; } @@ -1854,7 +1887,7 @@ nsComponentManagerImpl::UnloadLibraries(nsIServiceManager *serviceMgr, PRInt32 a nsresult rv = NS_OK; PR_EnterMonitor(mMon); - + PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS, ("nsComponentManager: Unloading Libraries.")); @@ -1883,9 +1916,9 @@ nsComponentManagerImpl::UnloadLibraries(nsIServiceManager *serviceMgr, PRInt32 a * of all components. No default director is looked at. * * Directory and fullname are what NSPR will accept. For eg. - * WIN y:/home/dp/mozilla/dist/bin - * UNIX /home/dp/mozilla/dist/bin - * MAC /Hard drive/mozilla/dist/apprunner + * WIN y:/home/dp/mozilla/dist/bin + * UNIX /home/dp/mozilla/dist/bin + * MAC /Hard drive/mozilla/dist/apprunner * * This will take care not loading already registered dlls, finding and * registering new dlls, re-registration of modified dlls @@ -1905,10 +1938,10 @@ AutoRegister_enumerate(nsHashKey *key, void *aData, void *aClosure) { nsIComponentLoader *loader = NS_STATIC_CAST(nsIComponentLoader *, aData); struct AutoReg_closure *closure = - (struct AutoReg_closure *)aClosure; + (struct AutoReg_closure *)aClosure; if (loader == closure->native) - return PR_TRUE; + return PR_TRUE; PR_ASSERT(NS_SUCCEEDED(closure->status)); @@ -1922,7 +1955,7 @@ RegisterDeferred_enumerate(nsHashKey *key, void *aData, void *aClosure) { nsIComponentLoader *loader = NS_STATIC_CAST(nsIComponentLoader *, aData); struct AutoReg_closure *closure = - (struct AutoReg_closure *)aClosure; + (struct AutoReg_closure *)aClosure; PR_ASSERT(NS_SUCCEEDED(closure->status)); PRBool registered; @@ -1947,7 +1980,7 @@ nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec) { // Use supplied components' directory dir = inDirSpec; - + // Set components' directory for AutoRegisterInterfces to query NS_WITH_SERVICE(nsIProperties, directoryService, NS_DIRECTORY_SERVICE_PROGID, &rv); if (NS_FAILED(rv)) return rv; @@ -1976,12 +2009,12 @@ nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec) rv = iim->AutoRegisterInterfaces(); if (NS_FAILED(rv)) - return rv; + return rv; /* do the native loader first, so we can find other loaders */ rv = mNativeComponentLoader->AutoRegisterComponents((PRInt32)when, dir); if (NS_FAILED(rv)) - return rv; + return rv; /* XXX eagerly instantiate all known loaders */ nsCOMPtr loaderEnum; @@ -2043,14 +2076,14 @@ AutoRegisterComponent_enumerate(nsHashKey *key, void *aData, void *aClosure) PRBool didRegister; nsIComponentLoader *loader = (nsIComponentLoader *)aData; struct AutoReg_closure *closure = - (struct AutoReg_closure *)aClosure; + (struct AutoReg_closure *)aClosure; closure->status = loader->AutoRegisterComponent(closure->when, - closure->spec, - &didRegister); + closure->spec, + &didRegister); if (NS_SUCCEEDED(closure->status) && didRegister) - return PR_FALSE; // Stop enumeration as we are done + return PR_FALSE; // Stop enumeration as we are done return PR_TRUE; } @@ -2060,7 +2093,7 @@ AutoUnregisterComponent_enumerate(nsHashKey *key, void *aData, void *aClosure) PRBool didUnregister; nsIComponentLoader *loader = (nsIComponentLoader *)aData; struct AutoReg_closure *closure = - (struct AutoReg_closure *)aClosure; + (struct AutoReg_closure *)aClosure; closure->status = loader->AutoUnregisterComponent(closure->when, closure->spec, @@ -2088,7 +2121,7 @@ nsComponentManagerImpl::AutoRegisterComponent(PRInt32 when, */ mLoaders->Enumerate(AutoRegisterComponent_enumerate, &closure); return NS_FAILED(closure.status) - ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK; + ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK; } @@ -2106,7 +2139,7 @@ nsComponentManagerImpl::AutoUnregisterComponent(PRInt32 when, mLoaders->Enumerate(AutoUnregisterComponent_enumerate, &closure); return NS_FAILED(closure.status) - ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK; + ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK; } diff --git a/mozilla/xpcom/components/nsComponentManager.h b/mozilla/xpcom/components/nsComponentManager.h index 48f4ff7a4e5..e774f9a9c33 100644 --- a/mozilla/xpcom/components/nsComponentManager.h +++ b/mozilla/xpcom/components/nsComponentManager.h @@ -170,8 +170,9 @@ protected: * alpha0.70 : using nsIFileSpec. PRTime -> PRUint32 * alpha0.90 : using nsIComponentLoader, abs:/rel:/lib:, shaver-cleanup * alpha0.92 : restructured registry keys + * alpha0.93 : changed component names to native strings instead of UTF8 */ -#define NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING "alpha0.92" +#define NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING "alpha0.93" //////////////////////////////////////////////////////////////////////////////// /** diff --git a/mozilla/xpcom/components/nsIRegistry.idl b/mozilla/xpcom/components/nsIRegistry.idl index 787340457e6..da6bd006908 100644 --- a/mozilla/xpcom/components/nsIRegistry.idl +++ b/mozilla/xpcom/components/nsIRegistry.idl @@ -51,11 +51,17 @@ interface nsIRegistry : nsISupports string getStringUTF8(in nsRegistryKey baseKey, in string path); void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value); + void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray); + void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray); PRInt32 getInt(in nsRegistryKey baseKey, in string path); void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value); PRInt64 getLongLong(in nsRegistryKey baseKey, in string path); void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value); + /** + * addSubtree() and friends need to be renamed to addKeyUTF8(). + * If you are using these forms make sure you pass UTF8 data + */ nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path); void removeSubtree(in nsRegistryKey baseKey, in string path); nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path); @@ -77,6 +83,13 @@ interface nsIRegistry : nsISupports PRUint32 getValueLength(in nsRegistryKey baseKey, in string path); void deleteValue(in nsRegistryKey baseKey, in string path); + /** + * escapeKey() takes arbitrary binary data and converts it into + * valid ASCII which can be used as registry key or value names + */ + void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped); + void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key); + attribute string currentUserName; void pack(); diff --git a/mozilla/xpcom/components/nsNativeComponentLoader.cpp b/mozilla/xpcom/components/nsNativeComponentLoader.cpp index 08c96c40d61..723e5db0c56 100644 --- a/mozilla/xpcom/components/nsNativeComponentLoader.cpp +++ b/mozilla/xpcom/components/nsNativeComponentLoader.cpp @@ -202,19 +202,35 @@ nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg) // Get library name nsXPIDLCString library; rv = node->GetNameUTF8(getter_Copies(library)); + if (NS_FAILED(rv)) continue; + char* uLibrary; + char* eLibrary = (char*)library.operator const char*(); + PRUint32 length = strlen(eLibrary); + rv = mRegistry->UnescapeKey((PRUint8*)eLibrary, 1, &length, (PRUint8**)&uLibrary); + + if (NS_FAILED(rv)) continue; + + if (uLibrary == nsnull) + uLibrary = eLibrary; + // Get key associated with library nsRegistryKey libKey; rv = node->GetKey(&libKey); - if (NS_FAILED(rv)) continue; + if (!NS_FAILED(rv)) // Cannot continue here, because we have to free unescape + { + // Create nsDll with this name + nsDll *dll = NULL; + PRInt64 lastModTime; + PRInt64 fileSize; + GetRegistryDllInfo(libKey, &lastModTime, &fileSize); + rv = CreateDll(NULL, uLibrary, &lastModTime, &fileSize, &dll); + } + if (uLibrary != eLibrary + && uLibrary != nsnull) + nsAllocator::Free(uLibrary); - // Create nsDll with this name - nsDll *dll = NULL; - PRInt64 lastModTime; - PRInt64 fileSize; - GetRegistryDllInfo(libKey, &lastModTime, &fileSize); - rv = CreateDll(NULL, library, &lastModTime, &fileSize, &dll); if (NS_FAILED(rv)) continue; } @@ -337,7 +353,7 @@ nsFreeLibrary(nsDll *dll, nsIServiceManager *serviceMgr, PRInt32 when) if (proc) { canUnload = proc(serviceMgr); - rv = NS_OK; // No error status returned by call. + rv = NS_OK; // No error status returned by call. } else { @@ -527,13 +543,13 @@ nsNativeComponentLoader::DumpLoadError(nsDll *dll, nsCAutoString errorMsg(aNsprErrorMsg); #if defined(MOZ_DEMANGLE_SYMBOLS) - // Demangle undefined symbols - nsCAutoString undefinedMagicString("undefined symbol:"); + // Demangle undefined symbols + nsCAutoString undefinedMagicString("undefined symbol:"); - PRInt32 offset = errorMsg.Find(undefinedMagicString, PR_TRUE); + PRInt32 offset = errorMsg.Find(undefinedMagicString, PR_TRUE); - if (offset != kNotFound) - { + if (offset != kNotFound) + { nsCAutoString symbol(errorMsg); nsCAutoString demangledSymbol(""); @@ -563,8 +579,8 @@ nsNativeComponentLoader::DumpLoadError(nsDll *dll, tmp += demangledSymbol; errorMsg = tmp; - } - } + } + } #endif // MOZ_DEMANGLE_SYMBOLS // Do NSPR log @@ -708,24 +724,24 @@ nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when, #ifdef XP_MAC // sdagley dougt fix // rjc - on Mac, check the file's type code (skip checking the creator code) - - nsCOMPtr localFileMac = do_QueryInterface(component); - if (localFileMac) - { - OSType type; - OSType creator; - rv = localFileMac->GetFileTypeAndCreator(&type, &creator); - if (NS_SUCCEEDED(rv)) - { - // on Mac, Mozilla shared libraries are of type 'shlb' - // Note: we don't check the creator (which for Mozilla is 'MOZZ') - // so that 3rd party shared libraries will be noticed! - if (type == 'shlb') - { - validExtension = PR_TRUE; - } - } - } + + nsCOMPtr localFileMac = do_QueryInterface(component); + if (localFileMac) + { + OSType type; + OSType creator; + rv = localFileMac->GetFileTypeAndCreator(&type, &creator); + if (NS_SUCCEEDED(rv)) + { + // on Mac, Mozilla shared libraries are of type 'shlb' + // Note: we don't check the creator (which for Mozilla is 'MOZZ') + // so that 3rd party shared libraries will be noticed! + if (type == 'shlb') + { + validExtension = PR_TRUE; + } + } + } #else char *leafName = NULL; @@ -934,12 +950,25 @@ nsNativeComponentLoader::GetRegistryDllInfo(const char *aLocation, PRInt64 *fileSize) { nsresult rv; + PRUint32 length = strlen(aLocation); + char* eLocation; + rv = mRegistry->EscapeKey((PRUint8*)aLocation, 1, &length, (PRUint8**)&eLocation); + if (rv != NS_OK) + { + return rv; + } + if (eLocation == nsnull) // No escaping required + eLocation = (char*)aLocation; + nsRegistryKey key; - rv = mRegistry->GetSubtreeRaw(mXPCOMKey, aLocation, &key); + rv = mRegistry->GetSubtreeRaw(mXPCOMKey, eLocation, &key); if (NS_FAILED(rv)) return rv; - return GetRegistryDllInfo(key, lastModifiedTime, fileSize); + rv = GetRegistryDllInfo(key, lastModifiedTime, fileSize); + if (aLocation != eLocation) + nsAllocator::Free(eLocation); + return rv; } nsresult @@ -955,8 +984,7 @@ nsNativeComponentLoader::GetRegistryDllInfo(nsRegistryKey key, PRInt64 fsize; rv = mRegistry->GetLongLong(key, fileSizeValueName, &fsize); if (NS_FAILED(rv)) return rv; - *fileSize = fsize; - + *fileSize = fsize; return NS_OK; } @@ -966,20 +994,46 @@ nsNativeComponentLoader::SetRegistryDllInfo(const char *aLocation, PRInt64 *fileSize) { nsresult rv; + PRUint32 length = strlen(aLocation); + char* eLocation; + rv = mRegistry->EscapeKey((PRUint8*)aLocation, 1, &length, (PRUint8**)&eLocation); + if (rv != NS_OK) + { + return rv; + } + if (eLocation == nsnull) // No escaping required + eLocation = (char*)aLocation; + nsRegistryKey key; - rv = mRegistry->GetSubtreeRaw(mXPCOMKey, aLocation, &key); + rv = mRegistry->GetSubtreeRaw(mXPCOMKey, eLocation, &key); if (NS_FAILED(rv)) return rv; rv = mRegistry->SetLongLong(key, lastModValueName, lastModifiedTime); if (NS_FAILED(rv)) return rv; rv = mRegistry->SetLongLong(key, fileSizeValueName, fileSize); + if (aLocation != eLocation) + nsAllocator::Free(eLocation); return rv; } nsresult nsNativeComponentLoader::RemoveRegistryDllInfo(const char *aLocation) { - return mRegistry->RemoveSubtree(mXPCOMKey, aLocation); + nsresult rv; + PRUint32 length = strlen(aLocation); + char* eLocation; + rv = mRegistry->EscapeKey((PRUint8*)aLocation, 1, &length, (PRUint8**)&eLocation); + if (rv != NS_OK) + { + return rv; + } + if (eLocation == nsnull) // No escaping required + eLocation = (char*)aLocation; + + rv = mRegistry->RemoveSubtree(mXPCOMKey, eLocation); + if (aLocation != eLocation) + nsAllocator::Free(eLocation); + return rv; } // @@ -988,18 +1042,18 @@ nsNativeComponentLoader::RemoveRegistryDllInfo(const char *aLocation) // be called in multiple situations: // // 1. Autoregister will create one for each dll it is trying to register. This -// call will be passing a spec in. -// {spec, NULL, 0, 0} +// call will be passing a spec in. +// {spec, NULL, 0, 0} // // 2. GetFactory() This will call CreateDll() with a null spec but will give -// the registry represented name of the dll. If modtime and size are zero, -// we will go the registry to find the right modtime and size. -// {NULL, rel:libpref.so, 0, 0} +// the registry represented name of the dll. If modtime and size are zero, +// we will go the registry to find the right modtime and size. +// {NULL, rel:libpref.so, 0, 0} // // 3. Prepopulation of dllCache A dll object created off a registry entry. -// Specifically dll name is stored in rel: or abs: or lib: formats in the -// registry along with its lastModTime and fileSize. -// {NULL, rel:libpref.so, 8985659, 20987} +// Specifically dll name is stored in rel: or abs: or lib: formats in the +// registry along with its lastModTime and fileSize. +// {NULL, rel:libpref.so, 8985659, 20987} nsresult nsNativeComponentLoader::CreateDll(nsIFile *aSpec, const char *aLocation, PRInt64 *modificationTime, PRInt64 *fileSize, diff --git a/mozilla/xpcom/components/nsRegistry.cpp b/mozilla/xpcom/components/nsRegistry.cpp index 29ca33064cc..cf99b460eff 100644 --- a/mozilla/xpcom/components/nsRegistry.cpp +++ b/mozilla/xpcom/components/nsRegistry.cpp @@ -73,9 +73,9 @@ struct nsRegistry : public nsIRegistry { protected: HREG mReg; // Registry handle. #ifdef EXTRA_THREADSAFE - PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize. + PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize. #endif - char *mCurRegFile; // these are to prevent open from opening the registry again + char *mCurRegFile; // these are to prevent open from opening the registry again nsWellKnownRegistry mCurRegID; NS_IMETHOD Close(); @@ -167,7 +167,7 @@ struct nsRegistryNode : public nsIRegistryNode { protected: HREG mReg; // Handle to registry this node is part of. char mName[MAXREGPATHLEN]; // Buffer to hold name. - RKEY mChildKey; // Key corresponding to mName + RKEY mChildKey; // Key corresponding to mName #ifdef EXTRA_THREADSAFE PRLock *mregLock; #endif @@ -735,6 +735,94 @@ NS_IMETHODIMP nsRegistry::SetStringUTF8( nsRegistryKey baseKey, const char *path return regerr2nsresult( err ); } +/*---------------------------- nsRegistry::GetBytesUTF8 ------------------------------ +| This function is just shorthand for fetching a char array. We | +| implement it "manually" using NR_RegGetEntry | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32* length, PRUint8** result) { + nsresult rv = NS_OK; + REGERR err = REGERR_OK; + + if ( !result ) + return NS_ERROR_NULL_POINTER; + + char regStr[MAXREGPATHLEN]; + + // initialize the return value + *length = 0; + *result = 0; + + // Get info about the requested entry. + PRUint32 type; + rv = GetValueType( baseKey, path, &type ); + // See if that worked. + if( rv == NS_OK ) + { + // Make sure the entry is an PRInt8 array. + if( type == Bytes ) + { + // Attempt to get string into our fixed buffer + PR_Lock(mregLock); + uint32 length2 = sizeof regStr; + err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), regStr, &length2); + PR_Unlock(mregLock); + + if ( err == REGERR_OK ) + { + *length = length2; + *result = (PRUint8*)(nsCRT::strdup(regStr)); + if (!*result) + { + rv = NS_ERROR_OUT_OF_MEMORY; + *length = 0; + } + else + { + *length = length2; + } + } + else if ( err == REGERR_BUFTOOSMALL ) + { + // find the real size and malloc it + rv = GetValueLength( baseKey, path, length ); + // See if that worked. + if( rv == NS_OK ) + { + *result = NS_REINTERPRET_CAST(PRUint8*,nsAllocator::Alloc( *length )); + if( *result ) + { + // Get bytes from registry into result field. + PR_Lock(mregLock); + length2 = *length; + err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), *result, &length2); + *length = length2; + PR_Unlock(mregLock); + // Convert status. + rv = regerr2nsresult( err ); + if ( rv != NS_OK ) + { + // Didn't get result, free buffer + nsCRT::free( NS_REINTERPRET_CAST(char*, *result) ); + *result = 0; + *length = 0; + } + } + else + { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + } + } + else + { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + return rv; +} + /*---------------------------- nsRegistry::GetInt ------------------------------ | This function is just shorthand for fetching a 1-element PRInt32 array. We | | implement it "manually" using NR_RegGetEntry | @@ -788,6 +876,24 @@ NS_IMETHODIMP nsRegistry::GetLongLong( nsRegistryKey baseKey, const char *path, // Convert status. return regerr2nsresult( err ); } +/*---------------------------- nsRegistry::SetBytesUTF8 ------------------------------ +| Write out the value as a char array, using NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32 length, PRUint8* value) { + REGERR err = REGERR_OK; + // Set the contents. + PR_Lock(mregLock); + err = NR_RegSetEntry( mReg, + (RKEY)baseKey, + (char*)path, + REGTYPE_ENTRY_BYTES, + (char*)value, + length); + PR_Unlock(mregLock); + // Convert result. + return regerr2nsresult( err ); +} + /*---------------------------- nsRegistry::SetInt ------------------------------ | Write out the value as a one-element PRInt32 array, using NR_RegSetEntry. | ------------------------------------------------------------------------------*/ @@ -862,8 +968,8 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path nsresult rv = NS_OK; REGERR err = REGERR_OK; - // libreg doesn't delete keys if there are subkeys under the key - // Hence we have to recurse through to delete the subtree + // libreg doesn't delete keys if there are subkeys under the key + // Hence we have to recurse through to delete the subtree RKEY key; @@ -871,13 +977,13 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path err = NR_RegGetKey(mReg, baseKey, (char *)path, &key); PR_Unlock(mregLock); if (err != REGERR_OK) - { - rv = regerr2nsresult( err ); + { + rv = regerr2nsresult( err ); return rv; - } + } // Now recurse through and delete all keys under hierarchy - + char subkeyname[MAXREGPATHLEN+1]; REGENUM state = 0; subkeyname[0] = '\0'; @@ -885,7 +991,7 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path REGENUM_NORMAL) == REGERR_OK) { #ifdef DEBUG_dp - printf("...recursing into %s\n", subkeyname); + printf("...recursing into %s\n", subkeyname); #endif /* DEBUG_dp */ // Even though this is not a "Raw" API the subkeys may still, in fact, // *be* raw. Since we're recursively deleting this will work either way. @@ -899,15 +1005,15 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path if (err == REGERR_OK) { #ifdef DEBUG_dp - printf("...deleting %s\n", path); + printf("...deleting %s\n", path); #endif /* DEBUG_dp */ PR_Lock(mregLock); err = NR_RegDeleteKey(mReg, baseKey, (char *)path); PR_Unlock(mregLock); } - // Convert result. - rv = regerr2nsresult( err ); + // Convert result. + rv = regerr2nsresult( err ); return rv; } @@ -919,8 +1025,8 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k nsresult rv = NS_OK; REGERR err = REGERR_OK; - // libreg doesn't delete keys if there are subkeys under the key - // Hence we have to recurse through to delete the subtree + // libreg doesn't delete keys if there are subkeys under the key + // Hence we have to recurse through to delete the subtree RKEY key; char subkeyname[MAXREGPATHLEN+1]; @@ -931,18 +1037,18 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k err = NR_RegGetKeyRaw(mReg, baseKey, (char *)keyname, &key); PR_Unlock(mregLock); if (err != REGERR_OK) - { - rv = regerr2nsresult( err ); + { + rv = regerr2nsresult( err ); return rv; - } + } // Now recurse through and delete all keys under hierarchy - + subkeyname[0] = '\0'; while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, n, REGENUM_NORMAL) == REGERR_OK) { #ifdef DEBUG_dp - printf("...recursing into %s\n", subkeyname); + printf("...recursing into %s\n", subkeyname); #endif /* DEBUG_dp */ err = RemoveSubtreeRaw(key, subkeyname); if (err != REGERR_OK) break; @@ -952,15 +1058,15 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k if (err == REGERR_OK) { #ifdef DEBUG_dp - printf("...deleting %s\n", keyname); + printf("...deleting %s\n", keyname); #endif /* DEBUG_dp */ PR_Lock(mregLock); err = NR_RegDeleteKeyRaw(mReg, baseKey, (char *)keyname); PR_Unlock(mregLock); } - // Convert result. - rv = regerr2nsresult( err ); + // Convert result. + rv = regerr2nsresult( err ); return rv; } /*-------------------------- nsRegistry::GetSubtree ---------------------------- @@ -1196,6 +1302,157 @@ NS_IMETHODIMP nsRegistry::Pack() { return rv; } +/*----------------------------- nsRegistry::EscapeKey ------------------------------- +| Escape a binary key so that the registry works OK, since it expects UTF8 +| with no slashes or control characters. This is probably better than raw. +| If no escaping is required, then the method is successful and a null is +| returned, indicating that the caller should use the original string. +------------------------------------------------------------------------------*/ +static const char sEscapeKeyHex[] = "0123456789abcdef0123456789ABCDEF"; +NS_IMETHODIMP nsRegistry::EscapeKey(PRUint8* key, PRUint32 termination, PRUint32* length, PRUint8** escaped) +{ + nsresult rv = NS_OK; + char* value = (char*)key; + char* b = value; + char* e = b + *length; + int escapees = 0; + while (b < e) // Count characters outside legal range or slash + { + int c = *b++; + if (c <= ' ' + || c > '~' + || c == '/' + || c == '%') + { + escapees++; + } + } + if (escapees == 0) // If no escapees, then no results + { + *length = 0; + *escaped = nsnull; + return NS_OK; + } + // New length includes two extra chars for escapees. + *length += escapees * 2; + *escaped = (PRUint8*)nsAllocator::Alloc(*length + termination); + if (*escaped == nsnull) + { + *length = 0; + *escaped = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + char* n = (char*)*escaped; + b = value; + while (escapees && b < e) + { + char c = *b++; + if (c < ' ' + || c > '~' + || c == '/' + || c == '%') + { + *(n++) = '%'; + *(n++) = sEscapeKeyHex[ 0xF & (c >> 4) ]; + *(n++) = sEscapeKeyHex[ 0xF & c ]; + escapees--; + } + else + { + *(n++) = c; + } + } + e += termination; + if (b < e) + { + strncpy(n, b, e - b); + } + return rv; +} + +/*----------------------------- nsRegistry::UnescapeKey ------------------------------- +| Unscape a binary key so that the registry works OK, since it expects UTF8 +| with no slashes or control characters. This is probably better than raw. +| If no escaping is required, then the method is successful and a null is +| returned, indicating that the caller should use the original string. +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::UnescapeKey(PRUint8* escaped, PRUint32 termination, PRUint32* length, PRUint8** key) +{ + nsresult rv = NS_OK; + char* value = (char*)escaped; + char* b = value; + char* e = b + *length; + int escapees = 0; + while (b < e) // Count characters outside legal range or slash + { + if (*b++ == '%') + { + escapees++; + } + } + if (escapees == 0) // If no escapees, then no results + { + *length = 0; + *key = nsnull; + return NS_OK; + } + // New length includes two extra chars for escapees. + *length -= escapees * 2; + *key = (PRUint8*)nsAllocator::Alloc(*length + termination); + if (*key == nsnull) + { + *length = 0; + *key = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + char* n = (char*)*key; + b = value; + while (escapees && b < e) + { + char c = *(b++); + if (c == '%') + { + if (e - b >= 2) + { + char* c1 = strchr(sEscapeKeyHex, *(b++)); + char* c2 = strchr(sEscapeKeyHex, *(b++)); + if (c1 != nsnull + && c2 != nsnull) + { + *(n++) = ((c2 - sEscapeKeyHex) & 0xF) + | (((c1 - sEscapeKeyHex) & 0xF) << 4); + } + else + { + escapees = -1; + } + } + else + { + escapees = -1; + } + escapees--; + } + else + { + *(n++) = c; + } + } + if (escapees < 0) + { + nsAllocator::Free(*key); + *length = 0; + *key = nsnull; + return NS_ERROR_INVALID_ARG; + } + e += termination; + if (b < e) + { + strncpy(n, b, e - b); + } + return rv; +} + /*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ---------------- | The ctor simply stashes all the information that will be needed to enumerate | | the subkeys. | @@ -1437,7 +1694,7 @@ NS_IMETHODIMP nsRegistryNode::GetNameUTF8( char **result ) { } /*-------------------------- nsRegistryNode::GetKey ---------------------------- -| Get the subkey corresponding to this node | +| Get the subkey corresponding to this node | | using NR_RegEnumSubkeys. | ------------------------------------------------------------------------------*/ NS_IMETHODIMP nsRegistryNode::GetKey( nsRegistryKey *r_key ) { diff --git a/mozilla/xpcom/ds/nsHashtable.cpp b/mozilla/xpcom/ds/nsHashtable.cpp index 951c6e44c10..c0ccf0e3e53 100644 --- a/mozilla/xpcom/ds/nsHashtable.cpp +++ b/mozilla/xpcom/ds/nsHashtable.cpp @@ -260,24 +260,29 @@ void nsHashtable::Reset(nsHashtableEnumFunc destroyFunc, void* closure) nsStringKey::nsStringKey(const char* str) { + MOZ_COUNT_CTOR(nsStringKey); mStr.AssignWithConversion(str); } nsStringKey::nsStringKey(const PRUnichar* str) { + MOZ_COUNT_CTOR(nsStringKey); mStr.Assign(str); } nsStringKey::nsStringKey(const nsString& str) { + MOZ_COUNT_CTOR(nsStringKey); mStr.Assign(str); } nsStringKey::nsStringKey(const nsCString& str) { + MOZ_COUNT_CTOR(nsStringKey); mStr.AssignWithConversion(str); } nsStringKey::~nsStringKey(void) { + MOZ_COUNT_DTOR(nsStringKey); } PRUint32 nsStringKey::HashValue(void) const