12722ceddSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 32722ceddSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 42722ceddSAndrew Rist * or more contributor license agreements. See the NOTICE file 52722ceddSAndrew Rist * distributed with this work for additional information 62722ceddSAndrew Rist * regarding copyright ownership. The ASF licenses this file 72722ceddSAndrew Rist * to you under the Apache License, Version 2.0 (the 82722ceddSAndrew Rist * "License"); you may not use this file except in compliance 92722ceddSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 112722ceddSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 132722ceddSAndrew Rist * Unless required by applicable law or agreed to in writing, 142722ceddSAndrew Rist * software distributed under the License is distributed on an 152722ceddSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 162722ceddSAndrew Rist * KIND, either express or implied. See the License for the 172722ceddSAndrew Rist * specific language governing permissions and limitations 182722ceddSAndrew Rist * under the License. 19cdf0e10cSrcweir * 202722ceddSAndrew Rist *************************************************************/ 212722ceddSAndrew Rist 22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 23cdf0e10cSrcweir #include "precompiled_desktop.hxx" 24cdf0e10cSrcweir 25cdf0e10cSrcweir #include "dp_misc.h" 26cdf0e10cSrcweir #include "dp_persmap.h" 27cdf0e10cSrcweir #include "rtl/strbuf.hxx" 28cdf0e10cSrcweir 29*853aaf22SHerbert Dürr #ifndef DISABLE_BDB2PMAP 30*853aaf22SHerbert Dürr #include <vector> 31*853aaf22SHerbert Dürr #endif 32*853aaf22SHerbert Dürr 33cdf0e10cSrcweir using namespace ::rtl; 343a63f8e7SHerbert Dürr 353a63f8e7SHerbert Dürr // the persistent map is used to manage a handful of key-value string pairs 363a63f8e7SHerbert Dürr // this implementation replaces a rather heavy-weight berkeleydb integration 373a63f8e7SHerbert Dürr 383a63f8e7SHerbert Dürr // the file backing up a persistent map consists of line pairs with 39eaecd99eSHerbert Dürr // - a key string (encoded with chars 0x00..0x0F being escaped) 40eaecd99eSHerbert Dürr // - a value string (encoded with chars 0x00..0x0F being escaped) 41cdf0e10cSrcweir 42cdf0e10cSrcweir namespace dp_misc 43cdf0e10cSrcweir { 44cdf0e10cSrcweir 453a63f8e7SHerbert Dürr static const char PmapMagic[4] = {'P','m','p','1'}; 46cdf0e10cSrcweir 47cdf0e10cSrcweir //______________________________________________________________________________ 48cdf0e10cSrcweir PersistentMap::PersistentMap( OUString const & url_, bool readOnly ) 493a63f8e7SHerbert Dürr : m_MapFile( expandUnoRcUrl(url_) ) 503a63f8e7SHerbert Dürr , m_bReadOnly( readOnly) 513a63f8e7SHerbert Dürr , m_bIsOpen( false) 523a63f8e7SHerbert Dürr , m_bToBeCreated( !readOnly) 533a63f8e7SHerbert Dürr , m_bIsDirty( false) 54cdf0e10cSrcweir { 55*853aaf22SHerbert Dürr #ifndef DISABLE_BDB2PMAP 56*853aaf22SHerbert Dürr m_MapFileName = expandUnoRcUrl( url_); 57*853aaf22SHerbert Dürr #endif 58*853aaf22SHerbert Dürr 593a63f8e7SHerbert Dürr open(); 60cdf0e10cSrcweir } 61cdf0e10cSrcweir 62cdf0e10cSrcweir //______________________________________________________________________________ 63cdf0e10cSrcweir PersistentMap::PersistentMap() 643a63f8e7SHerbert Dürr : m_MapFile( OUString()) 653a63f8e7SHerbert Dürr , m_bReadOnly( false) 663a63f8e7SHerbert Dürr , m_bIsOpen( false) 673a63f8e7SHerbert Dürr , m_bToBeCreated( false) 683a63f8e7SHerbert Dürr , m_bIsDirty( false) 693a63f8e7SHerbert Dürr {} 703a63f8e7SHerbert Dürr 713a63f8e7SHerbert Dürr //______________________________________________________________________________ 723a63f8e7SHerbert Dürr PersistentMap::~PersistentMap() 73cdf0e10cSrcweir { 743a63f8e7SHerbert Dürr if( m_bIsDirty) 753a63f8e7SHerbert Dürr flush(); 763a63f8e7SHerbert Dürr if( m_bIsOpen) 773a63f8e7SHerbert Dürr m_MapFile.close(); 78cdf0e10cSrcweir } 793a63f8e7SHerbert Dürr 803a63f8e7SHerbert Dürr //______________________________________________________________________________ 813a63f8e7SHerbert Dürr 823a63f8e7SHerbert Dürr // replace 0x00..0x0F with "%0".."%F" 833a63f8e7SHerbert Dürr // replace "%" with "%%" 843a63f8e7SHerbert Dürr static OString encodeString( const OString& rStr) 853a63f8e7SHerbert Dürr { 863a63f8e7SHerbert Dürr const sal_Char* pChar = rStr.getStr(); 873a63f8e7SHerbert Dürr const sal_Int32 nLen = rStr.getLength(); 883a63f8e7SHerbert Dürr sal_Int32 i = nLen; 893a63f8e7SHerbert Dürr // short circuit for the simple non-encoded case 903a63f8e7SHerbert Dürr while( --i >= 0) 913a63f8e7SHerbert Dürr { 923a63f8e7SHerbert Dürr const sal_Char c = *(pChar++); 933a63f8e7SHerbert Dürr if( (0x00 <= c) && (c <= 0x0F)) 943a63f8e7SHerbert Dürr break; 953a63f8e7SHerbert Dürr if( c == '%') 963a63f8e7SHerbert Dürr break; 97cdf0e10cSrcweir } 983a63f8e7SHerbert Dürr if( i < 0) 993a63f8e7SHerbert Dürr return rStr; 1003a63f8e7SHerbert Dürr 1013a63f8e7SHerbert Dürr // escape chars 0x00..0x0F with "%0".."%F" 1023a63f8e7SHerbert Dürr OStringBuffer aEncStr( nLen + 32); 1033a63f8e7SHerbert Dürr aEncStr.append( pChar - (nLen-i), nLen - i); 1043a63f8e7SHerbert Dürr while( --i >= 0) 1053a63f8e7SHerbert Dürr { 1063a63f8e7SHerbert Dürr sal_Char c = *(pChar++); 1073a63f8e7SHerbert Dürr if( (0x00 <= c) && (c <= 0x0F)) 1083a63f8e7SHerbert Dürr { 1093a63f8e7SHerbert Dürr aEncStr.append( '%'); 1103a63f8e7SHerbert Dürr c += (c <= 0x09) ? '0' : 'A'-10; 1113a63f8e7SHerbert Dürr } else if( c == '%') 1123a63f8e7SHerbert Dürr aEncStr.append( '%'); 1133a63f8e7SHerbert Dürr aEncStr.append( c); 1143a63f8e7SHerbert Dürr } 1153a63f8e7SHerbert Dürr 1163a63f8e7SHerbert Dürr return aEncStr.makeStringAndClear(); 1173a63f8e7SHerbert Dürr } 1183a63f8e7SHerbert Dürr 1193a63f8e7SHerbert Dürr //______________________________________________________________________________ 1203a63f8e7SHerbert Dürr 1213a63f8e7SHerbert Dürr // replace "%0".."%F" with 0x00..0x0F 1223a63f8e7SHerbert Dürr // replace "%%" with "%" 1233a63f8e7SHerbert Dürr static OString decodeString( const sal_Char* pEncChars, int nLen) 1243a63f8e7SHerbert Dürr { 1253a63f8e7SHerbert Dürr const char* pChar = pEncChars; 1263a63f8e7SHerbert Dürr sal_Int32 i = nLen; 1273a63f8e7SHerbert Dürr // short circuit for the simple non-encoded case 1283a63f8e7SHerbert Dürr while( --i >= 0) 1293a63f8e7SHerbert Dürr if( *(pChar++) == '%') 1303a63f8e7SHerbert Dürr break; 1313a63f8e7SHerbert Dürr if( i < 0) 1323a63f8e7SHerbert Dürr return OString( pEncChars, nLen); 1333a63f8e7SHerbert Dürr 1343a63f8e7SHerbert Dürr // replace escaped chars with their decoded counterparts 1353a63f8e7SHerbert Dürr OStringBuffer aDecStr( nLen); 1363a63f8e7SHerbert Dürr pChar = pEncChars; 1373a63f8e7SHerbert Dürr for( i = nLen; --i >= 0;) 1383a63f8e7SHerbert Dürr { 1393a63f8e7SHerbert Dürr sal_Char c = *(pChar++); 1403a63f8e7SHerbert Dürr // handle escaped character 1413a63f8e7SHerbert Dürr if( c == '%') 1423a63f8e7SHerbert Dürr { 1433a63f8e7SHerbert Dürr --i; 1443a63f8e7SHerbert Dürr OSL_ASSERT( i >= 0); 1453a63f8e7SHerbert Dürr c = *(pChar++); 1463a63f8e7SHerbert Dürr if( ('0' <= c) && (c <= '9')) 1473a63f8e7SHerbert Dürr c -= '0'; 1483a63f8e7SHerbert Dürr else 1493a63f8e7SHerbert Dürr { 1503a63f8e7SHerbert Dürr OSL_ASSERT( ('A' <= c) && (c <= 'F')); 1513a63f8e7SHerbert Dürr c -= ('A'-10); 1523a63f8e7SHerbert Dürr } 1533a63f8e7SHerbert Dürr } 1543a63f8e7SHerbert Dürr aDecStr.append( c); 1553a63f8e7SHerbert Dürr } 1563a63f8e7SHerbert Dürr 1573a63f8e7SHerbert Dürr return aDecStr.makeStringAndClear(); 1583a63f8e7SHerbert Dürr } 1593a63f8e7SHerbert Dürr 1603a63f8e7SHerbert Dürr //______________________________________________________________________________ 1613a63f8e7SHerbert Dürr bool PersistentMap::open() 1623a63f8e7SHerbert Dürr { 1633a63f8e7SHerbert Dürr // open the existing file 1643a63f8e7SHerbert Dürr sal_uInt32 nOpenFlags = osl_File_OpenFlag_Read; 1653a63f8e7SHerbert Dürr if( !m_bReadOnly) 1663a63f8e7SHerbert Dürr nOpenFlags |= osl_File_OpenFlag_Write; 1673a63f8e7SHerbert Dürr 168*853aaf22SHerbert Dürr const osl::File::RC rcOpen = m_MapFile.open( nOpenFlags); 1693a63f8e7SHerbert Dürr m_bIsOpen = (rcOpen == osl::File::E_None); 1703a63f8e7SHerbert Dürr 1713a63f8e7SHerbert Dürr // or create later if needed 172eaecd99eSHerbert Dürr m_bToBeCreated &= (rcOpen == osl::File::E_NOENT) && !m_bIsOpen; 173*853aaf22SHerbert Dürr 174*853aaf22SHerbert Dürr #ifndef DISABLE_BDB2PMAP 175*853aaf22SHerbert Dürr if( m_bToBeCreated) 176*853aaf22SHerbert Dürr importFromBDB(); 177*853aaf22SHerbert Dürr #endif // DISABLE_BDB2PMAP 178*853aaf22SHerbert Dürr 1793a63f8e7SHerbert Dürr if( !m_bIsOpen) 1803a63f8e7SHerbert Dürr return m_bToBeCreated; 1813a63f8e7SHerbert Dürr 182eaecd99eSHerbert Dürr const bool readOK = readAll(); 183eaecd99eSHerbert Dürr return readOK; 184eaecd99eSHerbert Dürr } 185eaecd99eSHerbert Dürr 186eaecd99eSHerbert Dürr //______________________________________________________________________________ 187eaecd99eSHerbert Dürr bool PersistentMap::readAll() 188eaecd99eSHerbert Dürr { 189eaecd99eSHerbert Dürr // prepare for re-reading the map-file 190eaecd99eSHerbert Dürr m_MapFile.setPos( osl_Pos_Absolut, 0); 191eaecd99eSHerbert Dürr m_entries.clear(); 192eaecd99eSHerbert Dürr 1933a63f8e7SHerbert Dürr // read header and check magic 1943a63f8e7SHerbert Dürr char aHeaderBytes[ sizeof(PmapMagic)]; 1953a63f8e7SHerbert Dürr sal_uInt64 nBytesRead = 0; 1963a63f8e7SHerbert Dürr m_MapFile.read( aHeaderBytes, sizeof(aHeaderBytes), nBytesRead); 1973a63f8e7SHerbert Dürr OSL_ASSERT( nBytesRead == sizeof(aHeaderBytes)); 1983a63f8e7SHerbert Dürr if( nBytesRead != sizeof(aHeaderBytes)) 1993a63f8e7SHerbert Dürr return false; 2003a63f8e7SHerbert Dürr // check header magic 2013a63f8e7SHerbert Dürr for( int i = 0; i < (int)sizeof(PmapMagic); ++i) 2023a63f8e7SHerbert Dürr if( aHeaderBytes[i] != PmapMagic[i]) 2033a63f8e7SHerbert Dürr return false; 2043a63f8e7SHerbert Dürr 2053a63f8e7SHerbert Dürr // read key value pairs and add them to the map 2063a63f8e7SHerbert Dürr ByteSequence aKeyLine; 2073a63f8e7SHerbert Dürr ByteSequence aValLine; 2083a63f8e7SHerbert Dürr for(;;) 2093a63f8e7SHerbert Dürr { 2103a63f8e7SHerbert Dürr // read key-value line pair 2113a63f8e7SHerbert Dürr // an empty key name indicates the end of the line pairs 2123a63f8e7SHerbert Dürr if( m_MapFile.readLine( aKeyLine) != osl::File::E_None) 2133a63f8e7SHerbert Dürr return false; 2143a63f8e7SHerbert Dürr if( !aKeyLine.getLength()) 2153a63f8e7SHerbert Dürr break; 2163a63f8e7SHerbert Dürr if( m_MapFile.readLine( aValLine) != osl::File::E_None) 2173a63f8e7SHerbert Dürr return false; 2183a63f8e7SHerbert Dürr // decode key and value strings 2193a63f8e7SHerbert Dürr const OString aKeyName = decodeString( (sal_Char*)aKeyLine.getConstArray(), aKeyLine.getLength()); 2203a63f8e7SHerbert Dürr const OString aValName = decodeString( (sal_Char*)aValLine.getConstArray(), aValLine.getLength()); 2213a63f8e7SHerbert Dürr // insert key-value pair into map 222516e460fSHerbert Dürr add( aKeyName, aValName); 2233a63f8e7SHerbert Dürr // check end-of-file status 2243a63f8e7SHerbert Dürr sal_Bool bIsEOF = true; 2253a63f8e7SHerbert Dürr if( m_MapFile.isEndOfFile( &bIsEOF) != osl::File::E_None) 2263a63f8e7SHerbert Dürr return false; 2273a63f8e7SHerbert Dürr if( bIsEOF) 2283a63f8e7SHerbert Dürr break; 2293a63f8e7SHerbert Dürr } 2303a63f8e7SHerbert Dürr 231eaecd99eSHerbert Dürr m_bIsDirty = false; 2323a63f8e7SHerbert Dürr return true; 2333a63f8e7SHerbert Dürr } 2343a63f8e7SHerbert Dürr 2353a63f8e7SHerbert Dürr //______________________________________________________________________________ 2363a63f8e7SHerbert Dürr void PersistentMap::flush( void) 2373a63f8e7SHerbert Dürr { 2383a63f8e7SHerbert Dürr if( !m_bIsDirty) 2393a63f8e7SHerbert Dürr return; 2403a63f8e7SHerbert Dürr OSL_ASSERT( !m_bReadOnly); 2413a63f8e7SHerbert Dürr if( m_bToBeCreated && !m_entries.empty()) 2423a63f8e7SHerbert Dürr { 2433a63f8e7SHerbert Dürr const sal_uInt32 nOpenFlags = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write | osl_File_OpenFlag_Create; 244*853aaf22SHerbert Dürr const osl::File::RC rcOpen = m_MapFile.open( nOpenFlags); 2453a63f8e7SHerbert Dürr m_bIsOpen = (rcOpen == osl::File::E_None); 2463a63f8e7SHerbert Dürr m_bToBeCreated = !m_bIsOpen; 2473a63f8e7SHerbert Dürr } 2483a63f8e7SHerbert Dürr if( !m_bIsOpen) 2493a63f8e7SHerbert Dürr return; 2503a63f8e7SHerbert Dürr 2513a63f8e7SHerbert Dürr // write header magic 2523a63f8e7SHerbert Dürr m_MapFile.setPos( osl_Pos_Absolut, 0); 2533a63f8e7SHerbert Dürr sal_uInt64 nBytesWritten = 0; 2543a63f8e7SHerbert Dürr m_MapFile.write( PmapMagic, sizeof(PmapMagic), nBytesWritten); 2553a63f8e7SHerbert Dürr 2563a63f8e7SHerbert Dürr // write key value pairs 2573a63f8e7SHerbert Dürr t_string2string_map::const_iterator it = m_entries.begin(); 2583a63f8e7SHerbert Dürr for(; it != m_entries.end(); ++it) { 2593a63f8e7SHerbert Dürr // write line for key 2603a63f8e7SHerbert Dürr const OString aKeyString = encodeString( (*it).first); 2613a63f8e7SHerbert Dürr const sal_Int32 nKeyLen = aKeyString.getLength(); 2623a63f8e7SHerbert Dürr m_MapFile.write( aKeyString.getStr(), nKeyLen, nBytesWritten); 2633a63f8e7SHerbert Dürr OSL_ASSERT( nKeyLen == (sal_Int32)nBytesWritten); 2643a63f8e7SHerbert Dürr m_MapFile.write( "\n", 1, nBytesWritten); 2653a63f8e7SHerbert Dürr // write line for value 2663a63f8e7SHerbert Dürr const OString& rValString = encodeString( (*it).second); 2673a63f8e7SHerbert Dürr const sal_Int32 nValLen = rValString.getLength(); 2683a63f8e7SHerbert Dürr m_MapFile.write( rValString.getStr(), nValLen, nBytesWritten); 2693a63f8e7SHerbert Dürr OSL_ASSERT( nValLen == (sal_Int32)nBytesWritten); 2703a63f8e7SHerbert Dürr m_MapFile.write( "\n", 1, nBytesWritten); 2713a63f8e7SHerbert Dürr } 2723a63f8e7SHerbert Dürr 2733a63f8e7SHerbert Dürr // write a file delimiter (an empty key-string) 2743a63f8e7SHerbert Dürr m_MapFile.write( "\n", 1, nBytesWritten); 2753a63f8e7SHerbert Dürr // truncate file here 2763a63f8e7SHerbert Dürr sal_uInt64 nNewFileSize; 2773a63f8e7SHerbert Dürr if( m_MapFile.getPos( nNewFileSize) == osl::File::E_None) 2783a63f8e7SHerbert Dürr m_MapFile.setSize( nNewFileSize); 2793a63f8e7SHerbert Dürr // flush to disk 2803a63f8e7SHerbert Dürr m_MapFile.sync(); 2813a63f8e7SHerbert Dürr // the in-memory map now matches to the file on disk 2823a63f8e7SHerbert Dürr m_bIsDirty = false; 283cdf0e10cSrcweir } 284cdf0e10cSrcweir 285cdf0e10cSrcweir //______________________________________________________________________________ 286cdf0e10cSrcweir bool PersistentMap::has( OString const & key ) const 287cdf0e10cSrcweir { 2883a63f8e7SHerbert Dürr return get( NULL, key ); 289cdf0e10cSrcweir } 290cdf0e10cSrcweir 291cdf0e10cSrcweir //______________________________________________________________________________ 292cdf0e10cSrcweir bool PersistentMap::get( OString * value, OString const & key ) const 293cdf0e10cSrcweir { 2943a63f8e7SHerbert Dürr t_string2string_map::const_iterator it = m_entries.find( key); 2953a63f8e7SHerbert Dürr if( it == m_entries.end()) 296cdf0e10cSrcweir return false; 2973a63f8e7SHerbert Dürr if( value) 2983a63f8e7SHerbert Dürr *value = it->second; 299cdf0e10cSrcweir return true; 300cdf0e10cSrcweir } 301cdf0e10cSrcweir 302cdf0e10cSrcweir //______________________________________________________________________________ 303516e460fSHerbert Dürr void PersistentMap::add( OString const & key, OString const & value ) 304cdf0e10cSrcweir { 3053a63f8e7SHerbert Dürr if( m_bReadOnly) 3063a63f8e7SHerbert Dürr return; 3073a63f8e7SHerbert Dürr typedef std::pair<t_string2string_map::iterator,bool> InsertRC; 3083a63f8e7SHerbert Dürr InsertRC r = m_entries.insert( t_string2string_map::value_type(key,value)); 3093a63f8e7SHerbert Dürr m_bIsDirty = r.second; 310516e460fSHerbert Dürr } 311516e460fSHerbert Dürr 312516e460fSHerbert Dürr //______________________________________________________________________________ 313516e460fSHerbert Dürr void PersistentMap::put( OString const & key, OString const & value ) 314516e460fSHerbert Dürr { 315516e460fSHerbert Dürr add( key, value); 316de4a8351SHerbert Dürr // HACK: flush now as the extension manager does not seem 317de4a8351SHerbert Dürr // to properly destruct this object in some situations 318de4a8351SHerbert Dürr if( m_bIsDirty) 319de4a8351SHerbert Dürr flush(); 320cdf0e10cSrcweir } 321cdf0e10cSrcweir 322cdf0e10cSrcweir //______________________________________________________________________________ 323cdf0e10cSrcweir bool PersistentMap::erase( OString const & key, bool flush_immediately ) 324cdf0e10cSrcweir { 3253a63f8e7SHerbert Dürr if( m_bReadOnly) 326cdf0e10cSrcweir return false; 3273a63f8e7SHerbert Dürr size_t nCount = m_entries.erase( key); 3283a63f8e7SHerbert Dürr if( !nCount) 3293a63f8e7SHerbert Dürr return false; 3303a63f8e7SHerbert Dürr m_bIsDirty = true; 3313a63f8e7SHerbert Dürr if( flush_immediately) 3323a63f8e7SHerbert Dürr flush(); 3333a63f8e7SHerbert Dürr return true; 334cdf0e10cSrcweir } 335cdf0e10cSrcweir 336cdf0e10cSrcweir //______________________________________________________________________________ 337cdf0e10cSrcweir t_string2string_map PersistentMap::getEntries() const 338cdf0e10cSrcweir { 3393a63f8e7SHerbert Dürr // TODO: return by const reference instead? 3403a63f8e7SHerbert Dürr return m_entries; 341cdf0e10cSrcweir } 342cdf0e10cSrcweir 343*853aaf22SHerbert Dürr //______________________________________________________________________________ 344*853aaf22SHerbert Dürr #ifndef DISABLE_BDB2PMAP 345*853aaf22SHerbert Dürr bool PersistentMap::importFromBDB() 346*853aaf22SHerbert Dürr { 347*853aaf22SHerbert Dürr if( m_bReadOnly) 348*853aaf22SHerbert Dürr return false; 349*853aaf22SHerbert Dürr 350*853aaf22SHerbert Dürr // get the name of its BDB counterpart 351*853aaf22SHerbert Dürr rtl::OUString aDBName = m_MapFileName; 352*853aaf22SHerbert Dürr if( !aDBName.endsWithAsciiL( ".pmap", 5)) 353*853aaf22SHerbert Dürr return false; 354*853aaf22SHerbert Dürr aDBName = aDBName.replaceAt( aDBName.getLength()-5, 5, OUSTR(".db")); 355*853aaf22SHerbert Dürr 356*853aaf22SHerbert Dürr // open the corresponding BDB file for reading 357*853aaf22SHerbert Dürr osl::File aDBFile( aDBName); 358*853aaf22SHerbert Dürr osl::File::RC rc = aDBFile.open( osl_File_OpenFlag_Read); 359*853aaf22SHerbert Dürr if( rc != osl::File::E_None) 360*853aaf22SHerbert Dürr return false; 361*853aaf22SHerbert Dürr sal_uInt64 nFileSize = 0; 362*853aaf22SHerbert Dürr if( aDBFile.getSize( nFileSize) != osl::File::E_None) 363*853aaf22SHerbert Dürr return false; 364*853aaf22SHerbert Dürr 365*853aaf22SHerbert Dürr // read the BDB file 366*853aaf22SHerbert Dürr std::vector<sal_uInt8> aRawBDB( nFileSize); 367*853aaf22SHerbert Dürr for( sal_uInt64 nOfs = 0; nOfs < nFileSize;) { 368*853aaf22SHerbert Dürr sal_uInt64 nBytesRead = 0; 369*853aaf22SHerbert Dürr rc = aDBFile.read( (void*)&aRawBDB[nOfs], nFileSize - nOfs, nBytesRead); 370*853aaf22SHerbert Dürr if( (rc != osl::File::E_None) || !nBytesRead) 371*853aaf22SHerbert Dürr return false; 372*853aaf22SHerbert Dürr nOfs += nBytesRead; 373cdf0e10cSrcweir } 374*853aaf22SHerbert Dürr 375*853aaf22SHerbert Dürr // check BDB file header for non_encrypted Hash_v9 format 376*853aaf22SHerbert Dürr if( nFileSize < 0x1000) 377*853aaf22SHerbert Dürr return false; 378*853aaf22SHerbert Dürr if( (aRawBDB[12]!=0x61 || aRawBDB[13]!=0x15 || aRawBDB[14]!=0x06) 379*853aaf22SHerbert Dürr && (aRawBDB[15]!=0x61 || aRawBDB[14]!=0x15 || aRawBDB[13]!=0x06)) 380*853aaf22SHerbert Dürr return false; 381*853aaf22SHerbert Dürr if( aRawBDB[16]!=0x09) 382*853aaf22SHerbert Dürr return false; 383*853aaf22SHerbert Dürr 384*853aaf22SHerbert Dürr // find PackageManagers new_style entries 385*853aaf22SHerbert Dürr // using a simple heuristic for BDB_Hash_v9 files 386*853aaf22SHerbert Dürr int nEntryCount = 0; 387*853aaf22SHerbert Dürr const sal_uInt8* pBeg = &aRawBDB[0] + 0x1000; 388*853aaf22SHerbert Dürr const sal_uInt8* pEnd = pBeg + nFileSize; 389*853aaf22SHerbert Dürr for( const sal_uInt8* pCur = pBeg; pCur < pEnd; ++pCur) { 390*853aaf22SHerbert Dürr if( pCur[0] != 0x01) 391*853aaf22SHerbert Dürr continue; 392*853aaf22SHerbert Dürr // get the value-candidate 393*853aaf22SHerbert Dürr const sal_uInt8* pVal = pCur + 1; 394*853aaf22SHerbert Dürr while( ++pCur < pEnd) 395*853aaf22SHerbert Dürr if( (*pCur < ' ') || ((*pCur > 0x7F) && (*pCur != 0xFF))) 396*853aaf22SHerbert Dürr break; 397*853aaf22SHerbert Dürr if( pCur >= pEnd) 398*853aaf22SHerbert Dürr break; 399*853aaf22SHerbert Dürr if( (pCur[0] != 0x01) || (pCur[1] != 0xFF)) 400*853aaf22SHerbert Dürr continue; 401*853aaf22SHerbert Dürr const OString aVal( (sal_Char*)pVal, pCur - pVal); 402*853aaf22SHerbert Dürr // get the key-candidate 403*853aaf22SHerbert Dürr const sal_uInt8* pKey = pCur + 1; 404*853aaf22SHerbert Dürr while( ++pCur < pEnd) 405*853aaf22SHerbert Dürr if( (*pCur < ' ') || ((*pCur > 0x7F) && (*pCur != 0xFF))) 406*853aaf22SHerbert Dürr break; 407*853aaf22SHerbert Dürr if( (pCur < pEnd) && (*pCur > 0x01)) 408*853aaf22SHerbert Dürr continue; 409*853aaf22SHerbert Dürr const OString aKey( (sal_Char*)pKey, pCur - pKey); 410*853aaf22SHerbert Dürr 411*853aaf22SHerbert Dürr // add the key/value pair 412*853aaf22SHerbert Dürr add( aKey, aVal); 413*853aaf22SHerbert Dürr ++nEntryCount; 414*853aaf22SHerbert Dürr } 415*853aaf22SHerbert Dürr 416*853aaf22SHerbert Dürr return (nEntryCount > 0); 417*853aaf22SHerbert Dürr } 418*853aaf22SHerbert Dürr #endif // DISABLE_BDB2PMAP 419*853aaf22SHerbert Dürr 420*853aaf22SHerbert Dürr } 421*853aaf22SHerbert Dürr 422