1*c82f2877SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*c82f2877SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*c82f2877SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*c82f2877SAndrew Rist * distributed with this work for additional information 6*c82f2877SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*c82f2877SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*c82f2877SAndrew Rist * "License"); you may not use this file except in compliance 9*c82f2877SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*c82f2877SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*c82f2877SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*c82f2877SAndrew Rist * software distributed under the License is distributed on an 15*c82f2877SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*c82f2877SAndrew Rist * KIND, either express or implied. See the License for the 17*c82f2877SAndrew Rist * specific language governing permissions and limitations 18*c82f2877SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*c82f2877SAndrew Rist *************************************************************/ 21*c82f2877SAndrew Rist 22*c82f2877SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_vcl.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #ifdef ENABLE_CUPS 28cdf0e10cSrcweir #include <cups/cups.h> 29cdf0e10cSrcweir #include <cups/ppd.h> 30cdf0e10cSrcweir 31cdf0e10cSrcweir #else // !ENABLE_CUPS 32cdf0e10cSrcweir typedef void ppd_file_t; 33cdf0e10cSrcweir typedef void cups_dest_t; 34cdf0e10cSrcweir typedef void cups_option_t; 35cdf0e10cSrcweir #endif 36cdf0e10cSrcweir 37cdf0e10cSrcweir #include <unistd.h> 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include "cupsmgr.hxx" 40cdf0e10cSrcweir 41cdf0e10cSrcweir #include "osl/thread.h" 42cdf0e10cSrcweir #include "osl/diagnose.h" 43cdf0e10cSrcweir #include "osl/conditn.hxx" 44cdf0e10cSrcweir 45cdf0e10cSrcweir #include "rtl/ustrbuf.hxx" 46cdf0e10cSrcweir 47cdf0e10cSrcweir #include <algorithm> 48cdf0e10cSrcweir #include <setjmp.h> 49cdf0e10cSrcweir #include <signal.h> 50cdf0e10cSrcweir 51cdf0e10cSrcweir #define CUPS_LIB_NAME "libcups.so.2" 52cdf0e10cSrcweir 53cdf0e10cSrcweir namespace psp 54cdf0e10cSrcweir { 55cdf0e10cSrcweir class CUPSWrapper 56cdf0e10cSrcweir { 57cdf0e10cSrcweir oslModule m_pLib; 58cdf0e10cSrcweir osl::Mutex m_aGetPPDMutex; 59cdf0e10cSrcweir bool m_bPPDThreadRunning; 60cdf0e10cSrcweir 61cdf0e10cSrcweir int (*m_pcupsPrintFile)(const char*, const char*, const char*, int, cups_option_t*); 62cdf0e10cSrcweir int (*m_pcupsGetDests)(cups_dest_t**); 63cdf0e10cSrcweir void (*m_pcupsSetDests)(int,cups_dest_t*); 64cdf0e10cSrcweir void (*m_pcupsFreeDests)(int,cups_dest_t*); 65cdf0e10cSrcweir const char* (*m_pcupsGetPPD)(const char*); 66cdf0e10cSrcweir int (*m_pcupsMarkOptions)(ppd_file_t*,int,cups_option_t*); 67cdf0e10cSrcweir int (*m_pcupsAddOption)(const char*,const char*,int,cups_option_t**); 68cdf0e10cSrcweir void (*m_pcupsFreeOptions)(int,cups_option_t*); 69cdf0e10cSrcweir ppd_file_t* (*m_pppdOpenFile)(const char* pFile); 70cdf0e10cSrcweir void (*m_pppdClose)(ppd_file_t*); 71cdf0e10cSrcweir const char* (*m_pcupsServer)(); 72cdf0e10cSrcweir void (*m_pcupsSetPasswordCB)(const char*(cb)(const char*)); 73cdf0e10cSrcweir const char* (*m_pcupsUser)(); 74cdf0e10cSrcweir void (*m_pcupsSetUser)(const char*); 75cdf0e10cSrcweir const char* (*m_pcupsGetOption)(const char*,int,cups_option_t*); 76cdf0e10cSrcweir 77cdf0e10cSrcweir oslGenericFunction loadSymbol( const char* ); 78cdf0e10cSrcweir public: 79cdf0e10cSrcweir CUPSWrapper(); 80cdf0e10cSrcweir ~CUPSWrapper(); 81cdf0e10cSrcweir 82cdf0e10cSrcweir bool isValid(); 83cdf0e10cSrcweir 84cdf0e10cSrcweir int cupsGetDests(cups_dest_t** pDests) 85cdf0e10cSrcweir { return m_pcupsGetDests(pDests); } 86cdf0e10cSrcweir 87cdf0e10cSrcweir void cupsSetDests( int nDests, cups_dest_t* pDests ) 88cdf0e10cSrcweir { m_pcupsSetDests( nDests, pDests ); } 89cdf0e10cSrcweir 90cdf0e10cSrcweir void cupsFreeDests(int nDests, cups_dest_t* pDests) 91cdf0e10cSrcweir { m_pcupsFreeDests(nDests, pDests); } 92cdf0e10cSrcweir 93cdf0e10cSrcweir int cupsPrintFile( const char* pPrinter, 94cdf0e10cSrcweir const char* pFileName, 95cdf0e10cSrcweir const char* pTitle, 96cdf0e10cSrcweir int nOptions, 97cdf0e10cSrcweir cups_option_t* pOptions ) 98cdf0e10cSrcweir { return m_pcupsPrintFile( pPrinter, pFileName, pTitle, nOptions, pOptions ); } 99cdf0e10cSrcweir 100cdf0e10cSrcweir rtl::OString cupsGetPPD( const char* pPrinter ); 101cdf0e10cSrcweir 102cdf0e10cSrcweir int cupsMarkOptions(ppd_file_t* pPPD, int nOptions, cups_option_t* pOptions ) 103cdf0e10cSrcweir { return m_pcupsMarkOptions(pPPD, nOptions, pOptions); } 104cdf0e10cSrcweir 105cdf0e10cSrcweir int cupsAddOption( const char* pName, const char* pValue, int nOptions, cups_option_t** pOptions ) 106cdf0e10cSrcweir { return m_pcupsAddOption( pName, pValue, nOptions, pOptions ); } 107cdf0e10cSrcweir 108cdf0e10cSrcweir void cupsFreeOptions( int nOptions, cups_option_t* pOptions ) 109cdf0e10cSrcweir { m_pcupsFreeOptions( nOptions, pOptions ); } 110cdf0e10cSrcweir 111cdf0e10cSrcweir ppd_file_t* ppdOpenFile( const char* pFileName ) 112cdf0e10cSrcweir { return m_pppdOpenFile( pFileName ); } 113cdf0e10cSrcweir 114cdf0e10cSrcweir void ppdClose( ppd_file_t* pPPD ) 115cdf0e10cSrcweir { m_pppdClose( pPPD ); } 116cdf0e10cSrcweir 117cdf0e10cSrcweir const char *cupsServer(void) 118cdf0e10cSrcweir { return m_pcupsServer(); } 119cdf0e10cSrcweir 120cdf0e10cSrcweir const char *cupsUser(void) 121cdf0e10cSrcweir { return m_pcupsUser(); } 122cdf0e10cSrcweir 123cdf0e10cSrcweir void cupsSetPasswordCB(const char *(*cb)(const char *)) 124cdf0e10cSrcweir { m_pcupsSetPasswordCB( cb ); } 125cdf0e10cSrcweir 126cdf0e10cSrcweir void cupsSetUser(const char *user) 127cdf0e10cSrcweir { m_pcupsSetUser( user ); } 128cdf0e10cSrcweir 129cdf0e10cSrcweir const char* cupsGetOption(const char* name, int num_options, cups_option_t* options) 130cdf0e10cSrcweir { return m_pcupsGetOption( name, num_options, options ); } 131cdf0e10cSrcweir 132cdf0e10cSrcweir }; 133cdf0e10cSrcweir } 134cdf0e10cSrcweir 135cdf0e10cSrcweir using namespace psp; 136cdf0e10cSrcweir using namespace osl; 137cdf0e10cSrcweir using namespace rtl; 138cdf0e10cSrcweir 139cdf0e10cSrcweir /* 140cdf0e10cSrcweir * CUPSWrapper class 141cdf0e10cSrcweir */ 142cdf0e10cSrcweir 143cdf0e10cSrcweir oslGenericFunction CUPSWrapper::loadSymbol( const char* pSymbol ) 144cdf0e10cSrcweir { 145cdf0e10cSrcweir OUString aSym( OUString::createFromAscii( pSymbol ) ); 146cdf0e10cSrcweir oslGenericFunction pSym = osl_getFunctionSymbol( m_pLib, aSym.pData ); 147cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 148cdf0e10cSrcweir fprintf( stderr, "%s %s\n", pSymbol, pSym ? "found" : "not found" ); 149cdf0e10cSrcweir #endif 150cdf0e10cSrcweir return pSym; 151cdf0e10cSrcweir } 152cdf0e10cSrcweir 153cdf0e10cSrcweir CUPSWrapper::CUPSWrapper() 154cdf0e10cSrcweir : m_pLib( NULL ), 155cdf0e10cSrcweir m_bPPDThreadRunning( false ) 156cdf0e10cSrcweir { 157cdf0e10cSrcweir #ifdef ENABLE_CUPS 158cdf0e10cSrcweir OUString aLib( RTL_CONSTASCII_USTRINGPARAM( CUPS_LIB_NAME ) ); 159cdf0e10cSrcweir m_pLib = osl_loadModule( aLib.pData, SAL_LOADMODULE_LAZY ); 160cdf0e10cSrcweir if( ! m_pLib ) 161cdf0e10cSrcweir { 162cdf0e10cSrcweir aLib = OUString( RTL_CONSTASCII_USTRINGPARAM( SAL_MODULENAME( "cups" ) ) ); 163cdf0e10cSrcweir m_pLib = osl_loadModule( aLib.pData, SAL_LOADMODULE_LAZY ); 164cdf0e10cSrcweir } 165cdf0e10cSrcweir #endif 166cdf0e10cSrcweir 167cdf0e10cSrcweir if( ! m_pLib ) 168cdf0e10cSrcweir { 169cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 170cdf0e10cSrcweir fprintf( stderr, "no cups library found\n" ); 171cdf0e10cSrcweir #endif 172cdf0e10cSrcweir return; 173cdf0e10cSrcweir } 174cdf0e10cSrcweir 175cdf0e10cSrcweir m_pcupsPrintFile = (int(*)(const char*,const char*,const char*,int,cups_option_t*)) 176cdf0e10cSrcweir loadSymbol( "cupsPrintFile" ); 177cdf0e10cSrcweir m_pcupsGetDests = (int(*)(cups_dest_t**)) 178cdf0e10cSrcweir loadSymbol( "cupsGetDests" ); 179cdf0e10cSrcweir m_pcupsSetDests = (void(*)(int,cups_dest_t*)) 180cdf0e10cSrcweir loadSymbol( "cupsSetDests" ); 181cdf0e10cSrcweir m_pcupsFreeDests = (void(*)(int,cups_dest_t*)) 182cdf0e10cSrcweir loadSymbol( "cupsFreeDests" ); 183cdf0e10cSrcweir m_pcupsGetPPD = (const char*(*)(const char*)) 184cdf0e10cSrcweir loadSymbol( "cupsGetPPD" ); 185cdf0e10cSrcweir m_pcupsMarkOptions = (int(*)(ppd_file_t*,int,cups_option_t*)) 186cdf0e10cSrcweir loadSymbol( "cupsMarkOptions" ); 187cdf0e10cSrcweir m_pcupsAddOption = (int(*)(const char*,const char*,int,cups_option_t**)) 188cdf0e10cSrcweir loadSymbol( "cupsAddOption" ); 189cdf0e10cSrcweir m_pcupsFreeOptions = (void(*)(int,cups_option_t*)) 190cdf0e10cSrcweir loadSymbol( "cupsFreeOptions" ); 191cdf0e10cSrcweir m_pppdOpenFile = (ppd_file_t*(*)(const char*)) 192cdf0e10cSrcweir loadSymbol( "ppdOpenFile" ); 193cdf0e10cSrcweir m_pppdClose = (void(*)(ppd_file_t*)) 194cdf0e10cSrcweir loadSymbol( "ppdClose" ); 195cdf0e10cSrcweir m_pcupsServer = (const char*(*)()) 196cdf0e10cSrcweir loadSymbol( "cupsServer" ); 197cdf0e10cSrcweir m_pcupsUser = (const char*(*)()) 198cdf0e10cSrcweir loadSymbol( "cupsUser" ); 199cdf0e10cSrcweir m_pcupsSetPasswordCB = (void(*)(const char*(*)(const char*))) 200cdf0e10cSrcweir loadSymbol( "cupsSetPasswordCB" ); 201cdf0e10cSrcweir m_pcupsSetUser = (void(*)(const char*)) 202cdf0e10cSrcweir loadSymbol( "cupsSetUser" ); 203cdf0e10cSrcweir m_pcupsGetOption = (const char*(*)(const char*,int,cups_option_t*)) 204cdf0e10cSrcweir loadSymbol( "cupsGetOption" ); 205cdf0e10cSrcweir 206cdf0e10cSrcweir if( ! ( 207cdf0e10cSrcweir m_pcupsPrintFile && 208cdf0e10cSrcweir m_pcupsGetDests && 209cdf0e10cSrcweir m_pcupsSetDests && 210cdf0e10cSrcweir m_pcupsFreeDests && 211cdf0e10cSrcweir m_pcupsGetPPD && 212cdf0e10cSrcweir m_pcupsMarkOptions && 213cdf0e10cSrcweir m_pcupsAddOption && 214cdf0e10cSrcweir m_pcupsServer && 215cdf0e10cSrcweir m_pcupsUser && 216cdf0e10cSrcweir m_pcupsSetPasswordCB && 217cdf0e10cSrcweir m_pcupsSetUser && 218cdf0e10cSrcweir m_pcupsFreeOptions && 219cdf0e10cSrcweir m_pppdOpenFile && 220cdf0e10cSrcweir m_pppdClose && 221cdf0e10cSrcweir m_pcupsGetOption 222cdf0e10cSrcweir ) ) 223cdf0e10cSrcweir { 224cdf0e10cSrcweir osl_unloadModule( m_pLib ); 225cdf0e10cSrcweir m_pLib = NULL; 226cdf0e10cSrcweir } 227cdf0e10cSrcweir } 228cdf0e10cSrcweir 229cdf0e10cSrcweir CUPSWrapper::~CUPSWrapper() 230cdf0e10cSrcweir { 231cdf0e10cSrcweir if( m_pLib ) 232cdf0e10cSrcweir osl_unloadModule( m_pLib ); 233cdf0e10cSrcweir } 234cdf0e10cSrcweir 235cdf0e10cSrcweir bool CUPSWrapper::isValid() 236cdf0e10cSrcweir { 237cdf0e10cSrcweir return m_pLib != NULL; 238cdf0e10cSrcweir } 239cdf0e10cSrcweir 240cdf0e10cSrcweir typedef const char*(*PPDFunction)(const char*); 241cdf0e10cSrcweir struct GetPPDAttribs 242cdf0e10cSrcweir { 243cdf0e10cSrcweir PPDFunction m_pFunction; 244cdf0e10cSrcweir osl::Condition m_aCondition; 245cdf0e10cSrcweir OString m_aParameter; 246cdf0e10cSrcweir OString m_aResult; 247cdf0e10cSrcweir oslThread m_aThread; 248cdf0e10cSrcweir int m_nRefs; 249cdf0e10cSrcweir bool* m_pResetRunning; 250cdf0e10cSrcweir osl::Mutex* m_pSyncMutex; 251cdf0e10cSrcweir 252cdf0e10cSrcweir GetPPDAttribs( PPDFunction pFn, const char * m_pParameter, 253cdf0e10cSrcweir bool* pResetRunning, osl::Mutex* pSyncMutex ) 254cdf0e10cSrcweir : m_pFunction( pFn ), 255cdf0e10cSrcweir m_aParameter( m_pParameter ), 256cdf0e10cSrcweir m_pResetRunning( pResetRunning ), 257cdf0e10cSrcweir m_pSyncMutex( pSyncMutex ) 258cdf0e10cSrcweir { 259cdf0e10cSrcweir m_nRefs = 2; 260cdf0e10cSrcweir m_aCondition.reset(); 261cdf0e10cSrcweir } 262cdf0e10cSrcweir 263cdf0e10cSrcweir ~GetPPDAttribs() 264cdf0e10cSrcweir { 265cdf0e10cSrcweir if( m_aResult.getLength() ) 266cdf0e10cSrcweir unlink( m_aResult.getStr() ); 267cdf0e10cSrcweir } 268cdf0e10cSrcweir 269cdf0e10cSrcweir void unref() 270cdf0e10cSrcweir { 271cdf0e10cSrcweir if( --m_nRefs == 0 ) 272cdf0e10cSrcweir { 273cdf0e10cSrcweir *m_pResetRunning = false; 274cdf0e10cSrcweir delete this; 275cdf0e10cSrcweir } 276cdf0e10cSrcweir } 277cdf0e10cSrcweir 278cdf0e10cSrcweir void executeCall() 279cdf0e10cSrcweir { 280cdf0e10cSrcweir // This CUPS method is not at all thread-safe we need 281cdf0e10cSrcweir // to dup the pointer to a static buffer it returns ASAP 282cdf0e10cSrcweir OString aResult = m_pFunction( m_aParameter ); 283cdf0e10cSrcweir MutexGuard aGuard( *m_pSyncMutex ); 284cdf0e10cSrcweir m_aResult = aResult; 285cdf0e10cSrcweir m_aCondition.set(); 286cdf0e10cSrcweir unref(); 287cdf0e10cSrcweir } 288cdf0e10cSrcweir 289cdf0e10cSrcweir OString waitResult( TimeValue *pDelay ) 290cdf0e10cSrcweir { 291cdf0e10cSrcweir m_pSyncMutex->release(); 292cdf0e10cSrcweir 293cdf0e10cSrcweir if (m_aCondition.wait( pDelay ) != Condition::result_ok 294cdf0e10cSrcweir ) 295cdf0e10cSrcweir { 296cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 297cdf0e10cSrcweir fprintf( stderr, "cupsGetPPD %s timed out\n", 298cdf0e10cSrcweir (const sal_Char *) m_aParameter 299cdf0e10cSrcweir ); 300cdf0e10cSrcweir #endif 301cdf0e10cSrcweir } 302cdf0e10cSrcweir m_pSyncMutex->acquire(); 303cdf0e10cSrcweir 304cdf0e10cSrcweir OString aRetval = m_aResult; 305cdf0e10cSrcweir m_aResult = OString(); 306cdf0e10cSrcweir unref(); 307cdf0e10cSrcweir 308cdf0e10cSrcweir return aRetval; 309cdf0e10cSrcweir } 310cdf0e10cSrcweir }; 311cdf0e10cSrcweir 312cdf0e10cSrcweir extern "C" { 313cdf0e10cSrcweir static void getPPDWorker(void* pData) 314cdf0e10cSrcweir { 315cdf0e10cSrcweir GetPPDAttribs* pAttribs = (GetPPDAttribs*)pData; 316cdf0e10cSrcweir pAttribs->executeCall(); 317cdf0e10cSrcweir } 318cdf0e10cSrcweir } 319cdf0e10cSrcweir 320cdf0e10cSrcweir OString CUPSWrapper::cupsGetPPD( const char* pPrinter ) 321cdf0e10cSrcweir { 322cdf0e10cSrcweir OString aResult; 323cdf0e10cSrcweir 324cdf0e10cSrcweir m_aGetPPDMutex.acquire(); 325cdf0e10cSrcweir // if one thread hangs in cupsGetPPD already, don't start another 326cdf0e10cSrcweir if( ! m_bPPDThreadRunning ) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir m_bPPDThreadRunning = true; 329cdf0e10cSrcweir GetPPDAttribs* pAttribs = new GetPPDAttribs( m_pcupsGetPPD, 330cdf0e10cSrcweir pPrinter, 331cdf0e10cSrcweir &m_bPPDThreadRunning, 332cdf0e10cSrcweir &m_aGetPPDMutex ); 333cdf0e10cSrcweir 334cdf0e10cSrcweir oslThread aThread = osl_createThread( getPPDWorker, pAttribs ); 335cdf0e10cSrcweir 336cdf0e10cSrcweir TimeValue aValue; 337cdf0e10cSrcweir aValue.Seconds = 5; 338cdf0e10cSrcweir aValue.Nanosec = 0; 339cdf0e10cSrcweir 340cdf0e10cSrcweir // NOTE: waitResult release and acquires the GetPPD mutex 341cdf0e10cSrcweir aResult = pAttribs->waitResult( &aValue ); 342cdf0e10cSrcweir osl_destroyThread( aThread ); 343cdf0e10cSrcweir } 344cdf0e10cSrcweir m_aGetPPDMutex.release(); 345cdf0e10cSrcweir 346cdf0e10cSrcweir return aResult; 347cdf0e10cSrcweir } 348cdf0e10cSrcweir 349cdf0e10cSrcweir #ifdef ENABLE_CUPS 350cdf0e10cSrcweir static const char* setPasswordCallback( const char* pIn ) 351cdf0e10cSrcweir { 352cdf0e10cSrcweir const char* pRet = NULL; 353cdf0e10cSrcweir 354cdf0e10cSrcweir PrinterInfoManager& rMgr = PrinterInfoManager::get(); 355cdf0e10cSrcweir if( rMgr.getType() == PrinterInfoManager::CUPS ) // sanity check 356cdf0e10cSrcweir pRet = static_cast<CUPSManager&>(rMgr).authenticateUser( pIn ); 357cdf0e10cSrcweir return pRet; 358cdf0e10cSrcweir } 359cdf0e10cSrcweir #endif 360cdf0e10cSrcweir 361cdf0e10cSrcweir /* 362cdf0e10cSrcweir * CUPSManager class 363cdf0e10cSrcweir */ 364cdf0e10cSrcweir 365cdf0e10cSrcweir CUPSManager* CUPSManager::tryLoadCUPS() 366cdf0e10cSrcweir { 367cdf0e10cSrcweir CUPSManager* pManager = NULL; 368cdf0e10cSrcweir #ifdef ENABLE_CUPS 369cdf0e10cSrcweir static const char* pEnv = getenv( "SAL_DISABLE_CUPS" ); 370cdf0e10cSrcweir 371cdf0e10cSrcweir if( ! pEnv || ! *pEnv ) 372cdf0e10cSrcweir { 373cdf0e10cSrcweir // try to load CUPS 374cdf0e10cSrcweir CUPSWrapper* pWrapper = new CUPSWrapper(); 375cdf0e10cSrcweir if( pWrapper->isValid() ) 376cdf0e10cSrcweir pManager = new CUPSManager( pWrapper ); 377cdf0e10cSrcweir else 378cdf0e10cSrcweir delete pWrapper; 379cdf0e10cSrcweir } 380cdf0e10cSrcweir #endif 381cdf0e10cSrcweir return pManager; 382cdf0e10cSrcweir } 383cdf0e10cSrcweir 384cdf0e10cSrcweir extern "C" 385cdf0e10cSrcweir { 386cdf0e10cSrcweir static void run_dest_thread_stub( void* pThis ) 387cdf0e10cSrcweir { 388cdf0e10cSrcweir CUPSManager::runDestThread( pThis ); 389cdf0e10cSrcweir } 390cdf0e10cSrcweir } 391cdf0e10cSrcweir 392cdf0e10cSrcweir CUPSManager::CUPSManager( CUPSWrapper* pWrapper ) : 393cdf0e10cSrcweir PrinterInfoManager( CUPS ), 394cdf0e10cSrcweir m_pCUPSWrapper( pWrapper ), 395cdf0e10cSrcweir m_nDests( 0 ), 396cdf0e10cSrcweir m_pDests( NULL ), 397cdf0e10cSrcweir m_bNewDests( false ) 398cdf0e10cSrcweir { 399cdf0e10cSrcweir m_aDestThread = osl_createThread( run_dest_thread_stub, this ); 400cdf0e10cSrcweir } 401cdf0e10cSrcweir 402cdf0e10cSrcweir CUPSManager::~CUPSManager() 403cdf0e10cSrcweir { 404cdf0e10cSrcweir if( m_aDestThread ) 405cdf0e10cSrcweir { 406cdf0e10cSrcweir // if the thread is still running here, then 407cdf0e10cSrcweir // cupsGetDests is hung; terminate the thread instead of joining 408cdf0e10cSrcweir osl_terminateThread( m_aDestThread ); 409cdf0e10cSrcweir osl_destroyThread( m_aDestThread ); 410cdf0e10cSrcweir } 411cdf0e10cSrcweir 412cdf0e10cSrcweir if( m_nDests && m_pDests ) 413cdf0e10cSrcweir m_pCUPSWrapper->cupsFreeDests( m_nDests, (cups_dest_t*)m_pDests ); 414cdf0e10cSrcweir delete m_pCUPSWrapper; 415cdf0e10cSrcweir } 416cdf0e10cSrcweir 417cdf0e10cSrcweir void CUPSManager::runDestThread( void* pThis ) 418cdf0e10cSrcweir { 419cdf0e10cSrcweir ((CUPSManager*)pThis)->runDests(); 420cdf0e10cSrcweir } 421cdf0e10cSrcweir 422cdf0e10cSrcweir static sigjmp_buf aViolationBuffer; 423cdf0e10cSrcweir 424cdf0e10cSrcweir extern "C" 425cdf0e10cSrcweir { 426cdf0e10cSrcweir static void lcl_signal_action(int nSignal) 427cdf0e10cSrcweir { 428cdf0e10cSrcweir fprintf( stderr, "Signal %d during fontconfig initialization called, ignoring fontconfig\n", nSignal ); 429cdf0e10cSrcweir siglongjmp( aViolationBuffer, 1 ); 430cdf0e10cSrcweir } 431cdf0e10cSrcweir } 432cdf0e10cSrcweir 433cdf0e10cSrcweir void CUPSManager::runDests() 434cdf0e10cSrcweir { 435cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 436cdf0e10cSrcweir fprintf( stderr, "starting cupsGetDests\n" ); 437cdf0e10cSrcweir #endif 438cdf0e10cSrcweir int nDests = 0; 439cdf0e10cSrcweir cups_dest_t* pDests = NULL; 440cdf0e10cSrcweir 441cdf0e10cSrcweir // #i86306# prepare against really broken CUPS installations / missing servers 442cdf0e10cSrcweir 443cdf0e10cSrcweir // install signal handler for SEGV, BUS and ABRT 444cdf0e10cSrcweir struct sigaction act; 445cdf0e10cSrcweir struct sigaction oact[3]; 446cdf0e10cSrcweir 447cdf0e10cSrcweir act.sa_handler = lcl_signal_action; 448cdf0e10cSrcweir act.sa_flags = 0; 449cdf0e10cSrcweir sigemptyset(&(act.sa_mask)); 450cdf0e10cSrcweir 451cdf0e10cSrcweir int nSegvSignalInstalled = sigaction(SIGSEGV, &act, &oact[0]); 452cdf0e10cSrcweir int nBusSignalInstalled = sigaction(SIGBUS, &act, &oact[1]); 453cdf0e10cSrcweir int nAbortSignalInstalled = sigaction(SIGABRT, &act, &oact[2]); 454cdf0e10cSrcweir 455cdf0e10cSrcweir // prepare against a signal during FcInit or FcConfigGetCurrent 456cdf0e10cSrcweir if( sigsetjmp( aViolationBuffer, ~0 ) == 0 ) 457cdf0e10cSrcweir { 458cdf0e10cSrcweir nDests = m_pCUPSWrapper->cupsGetDests( &pDests ); 459cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 460cdf0e10cSrcweir fprintf( stderr, "came out of cupsGetDests\n" ); 461cdf0e10cSrcweir #endif 462cdf0e10cSrcweir 463cdf0e10cSrcweir osl::MutexGuard aGuard( m_aCUPSMutex ); 464cdf0e10cSrcweir m_nDests = nDests; 465cdf0e10cSrcweir m_pDests = pDests; 466cdf0e10cSrcweir m_bNewDests = true; 467cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 468cdf0e10cSrcweir fprintf( stderr, "finished cupsGetDests\n" ); 469cdf0e10cSrcweir #endif 470cdf0e10cSrcweir } 471cdf0e10cSrcweir else 472cdf0e10cSrcweir { 473cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 474cdf0e10cSrcweir fprintf( stderr, "cupsGetDests crashed, not using CUPS\n" ); 475cdf0e10cSrcweir #endif 476cdf0e10cSrcweir } 477cdf0e10cSrcweir 478cdf0e10cSrcweir // restore old signal handlers 479cdf0e10cSrcweir if( nSegvSignalInstalled == 0 ) 480cdf0e10cSrcweir sigaction( SIGSEGV, &oact[0], NULL ); 481cdf0e10cSrcweir if( nBusSignalInstalled == 0 ) 482cdf0e10cSrcweir sigaction( SIGBUS, &oact[1], NULL ); 483cdf0e10cSrcweir if( nAbortSignalInstalled == 0 ) 484cdf0e10cSrcweir sigaction( SIGABRT, &oact[2], NULL ); 485cdf0e10cSrcweir } 486cdf0e10cSrcweir 487cdf0e10cSrcweir void CUPSManager::initialize() 488cdf0e10cSrcweir { 489cdf0e10cSrcweir // get normal printers, clear printer list 490cdf0e10cSrcweir PrinterInfoManager::initialize(); 491cdf0e10cSrcweir 492cdf0e10cSrcweir #ifdef ENABLE_CUPS 493cdf0e10cSrcweir // check whether thread has completed 494cdf0e10cSrcweir // if not behave like old printing system 495cdf0e10cSrcweir osl::MutexGuard aGuard( m_aCUPSMutex ); 496cdf0e10cSrcweir 497cdf0e10cSrcweir if( ! m_bNewDests ) 498cdf0e10cSrcweir return; 499cdf0e10cSrcweir 500cdf0e10cSrcweir // dest thread has run, clean up 501cdf0e10cSrcweir if( m_aDestThread ) 502cdf0e10cSrcweir { 503cdf0e10cSrcweir osl_joinWithThread( m_aDestThread ); 504cdf0e10cSrcweir osl_destroyThread( m_aDestThread ); 505cdf0e10cSrcweir m_aDestThread = NULL; 506cdf0e10cSrcweir } 507cdf0e10cSrcweir m_bNewDests = false; 508cdf0e10cSrcweir 509cdf0e10cSrcweir // clear old stuff 510cdf0e10cSrcweir m_aCUPSDestMap.clear(); 511cdf0e10cSrcweir 512cdf0e10cSrcweir if( ! (m_nDests && m_pDests ) ) 513cdf0e10cSrcweir return; 514cdf0e10cSrcweir 515cdf0e10cSrcweir if( isCUPSDisabled() ) 516cdf0e10cSrcweir return; 517cdf0e10cSrcweir 518cdf0e10cSrcweir // check for CUPS server(?) > 1.2 519cdf0e10cSrcweir // since there is no API to query, check for options that were 520cdf0e10cSrcweir // introduced in dests with 1.2 521cdf0e10cSrcweir // this is needed to check for %%IncludeFeature support 522cdf0e10cSrcweir // (#i65684#, #i65491#) 523cdf0e10cSrcweir bool bUsePDF = false; 524cdf0e10cSrcweir cups_dest_t* pDest = ((cups_dest_t*)m_pDests); 525cdf0e10cSrcweir const char* pOpt = m_pCUPSWrapper->cupsGetOption( "printer-info", 526cdf0e10cSrcweir pDest->num_options, 527cdf0e10cSrcweir pDest->options ); 528cdf0e10cSrcweir if( pOpt ) 529cdf0e10cSrcweir { 530cdf0e10cSrcweir m_bUseIncludeFeature = true; 531cdf0e10cSrcweir bUsePDF = true; 532cdf0e10cSrcweir if( m_aGlobalDefaults.m_nPSLevel == 0 && m_aGlobalDefaults.m_nPDFDevice == 0 ) 533cdf0e10cSrcweir m_aGlobalDefaults.m_nPDFDevice = 1; 534cdf0e10cSrcweir } 535cdf0e10cSrcweir // do not send include JobPatch; CUPS will insert that itself 536cdf0e10cSrcweir // TODO: currently unknwon which versions of CUPS insert JobPatches 537cdf0e10cSrcweir // so currently it is assumed CUPS = don't insert JobPatch files 538cdf0e10cSrcweir m_bUseJobPatch = false; 539cdf0e10cSrcweir 540cdf0e10cSrcweir rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 541cdf0e10cSrcweir int nPrinter = m_nDests; 542cdf0e10cSrcweir 543cdf0e10cSrcweir // reset global default PPD options; these are queried on demand from CUPS 544cdf0e10cSrcweir m_aGlobalDefaults.m_pParser = NULL; 545cdf0e10cSrcweir m_aGlobalDefaults.m_aContext = PPDContext(); 546cdf0e10cSrcweir 547cdf0e10cSrcweir // add CUPS printers, should there be a printer 548cdf0e10cSrcweir // with the same name as a CUPS printer, overwrite it 549cdf0e10cSrcweir while( nPrinter-- ) 550cdf0e10cSrcweir { 551cdf0e10cSrcweir pDest = ((cups_dest_t*)m_pDests)+nPrinter; 552cdf0e10cSrcweir OUString aPrinterName = OStringToOUString( pDest->name, aEncoding ); 553cdf0e10cSrcweir if( pDest->instance && *pDest->instance ) 554cdf0e10cSrcweir { 555cdf0e10cSrcweir OUStringBuffer aBuf( 256 ); 556cdf0e10cSrcweir aBuf.append( aPrinterName ); 557cdf0e10cSrcweir aBuf.append( sal_Unicode( '/' ) ); 558cdf0e10cSrcweir aBuf.append( OStringToOUString( pDest->instance, aEncoding ) ); 559cdf0e10cSrcweir aPrinterName = aBuf.makeStringAndClear(); 560cdf0e10cSrcweir } 561cdf0e10cSrcweir 562cdf0e10cSrcweir // initialize printer with possible configuration from psprint.conf 563cdf0e10cSrcweir bool bSetToGlobalDefaults = m_aPrinters.find( aPrinterName ) == m_aPrinters.end(); 564cdf0e10cSrcweir Printer aPrinter = m_aPrinters[ aPrinterName ]; 565cdf0e10cSrcweir if( bSetToGlobalDefaults ) 566cdf0e10cSrcweir aPrinter.m_aInfo = m_aGlobalDefaults; 567cdf0e10cSrcweir aPrinter.m_aInfo.m_aPrinterName = aPrinterName; 568cdf0e10cSrcweir if( pDest->is_default ) 569cdf0e10cSrcweir m_aDefaultPrinter = aPrinterName; 570cdf0e10cSrcweir 571cdf0e10cSrcweir for( int k = 0; k < pDest->num_options; k++ ) 572cdf0e10cSrcweir { 573cdf0e10cSrcweir if(!strcmp(pDest->options[k].name, "printer-info")) 574cdf0e10cSrcweir aPrinter.m_aInfo.m_aComment=OStringToOUString(pDest->options[k].value, aEncoding); 575cdf0e10cSrcweir if(!strcmp(pDest->options[k].name, "printer-location")) 576cdf0e10cSrcweir aPrinter.m_aInfo.m_aLocation=OStringToOUString(pDest->options[k].value, aEncoding); 577cdf0e10cSrcweir } 578cdf0e10cSrcweir 579cdf0e10cSrcweir 580cdf0e10cSrcweir OUStringBuffer aBuf( 256 ); 581cdf0e10cSrcweir aBuf.appendAscii( "CUPS:" ); 582cdf0e10cSrcweir aBuf.append( aPrinterName ); 583cdf0e10cSrcweir // note: the parser that goes with the PrinterInfo 584cdf0e10cSrcweir // is created implicitly by the JobData::operator=() 585cdf0e10cSrcweir // when it detects the NULL ptr m_pParser. 586cdf0e10cSrcweir // if we wanted to fill in the parser here this 587cdf0e10cSrcweir // would mean we'd have to download PPDs for each and 588cdf0e10cSrcweir // every printer - which would be really bad runtime 589cdf0e10cSrcweir // behaviour 590cdf0e10cSrcweir aPrinter.m_aInfo.m_pParser = NULL; 591cdf0e10cSrcweir aPrinter.m_aInfo.m_aContext.setParser( NULL ); 592cdf0e10cSrcweir std::hash_map< OUString, PPDContext, OUStringHash >::const_iterator c_it = m_aDefaultContexts.find( aPrinterName ); 593cdf0e10cSrcweir if( c_it != m_aDefaultContexts.end() ) 594cdf0e10cSrcweir { 595cdf0e10cSrcweir aPrinter.m_aInfo.m_pParser = c_it->second.getParser(); 596cdf0e10cSrcweir aPrinter.m_aInfo.m_aContext = c_it->second; 597cdf0e10cSrcweir } 598cdf0e10cSrcweir if( bUsePDF && aPrinter.m_aInfo.m_nPSLevel == 0 && aPrinter.m_aInfo.m_nPDFDevice == 0 ) 599cdf0e10cSrcweir aPrinter.m_aInfo.m_nPDFDevice = 1; 600cdf0e10cSrcweir aPrinter.m_aInfo.m_aDriverName = aBuf.makeStringAndClear(); 601cdf0e10cSrcweir aPrinter.m_bModified = false; 602cdf0e10cSrcweir 603cdf0e10cSrcweir m_aPrinters[ aPrinter.m_aInfo.m_aPrinterName ] = aPrinter; 604cdf0e10cSrcweir m_aCUPSDestMap[ aPrinter.m_aInfo.m_aPrinterName ] = nPrinter; 605cdf0e10cSrcweir } 606cdf0e10cSrcweir 607cdf0e10cSrcweir // remove everything that is not a CUPS printer and not 608cdf0e10cSrcweir // a special purpose printer (PDF, Fax) 609cdf0e10cSrcweir std::list< OUString > aRemovePrinters; 610cdf0e10cSrcweir for( std::hash_map< OUString, Printer, OUStringHash >::iterator it = m_aPrinters.begin(); 611cdf0e10cSrcweir it != m_aPrinters.end(); ++it ) 612cdf0e10cSrcweir { 613cdf0e10cSrcweir if( m_aCUPSDestMap.find( it->first ) != m_aCUPSDestMap.end() ) 614cdf0e10cSrcweir continue; 615cdf0e10cSrcweir 616cdf0e10cSrcweir if( it->second.m_aInfo.m_aFeatures.getLength() > 0 ) 617cdf0e10cSrcweir continue; 618cdf0e10cSrcweir aRemovePrinters.push_back( it->first ); 619cdf0e10cSrcweir } 620cdf0e10cSrcweir while( aRemovePrinters.begin() != aRemovePrinters.end() ) 621cdf0e10cSrcweir { 622cdf0e10cSrcweir m_aPrinters.erase( aRemovePrinters.front() ); 623cdf0e10cSrcweir aRemovePrinters.pop_front(); 624cdf0e10cSrcweir } 625cdf0e10cSrcweir 626cdf0e10cSrcweir m_pCUPSWrapper->cupsSetPasswordCB( setPasswordCallback ); 627cdf0e10cSrcweir #endif // ENABLE_CUPS 628cdf0e10cSrcweir } 629cdf0e10cSrcweir 630cdf0e10cSrcweir #ifdef ENABLE_CUPS 631cdf0e10cSrcweir static void updatePrinterContextInfo( ppd_group_t* pPPDGroup, PPDContext& rContext ) 632cdf0e10cSrcweir { 633cdf0e10cSrcweir rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 634cdf0e10cSrcweir for( int i = 0; i < pPPDGroup->num_options; i++ ) 635cdf0e10cSrcweir { 636cdf0e10cSrcweir ppd_option_t* pOption = pPPDGroup->options + i; 637cdf0e10cSrcweir for( int n = 0; n < pOption->num_choices; n++ ) 638cdf0e10cSrcweir { 639cdf0e10cSrcweir ppd_choice_t* pChoice = pOption->choices + n; 640cdf0e10cSrcweir if( pChoice->marked ) 641cdf0e10cSrcweir { 642cdf0e10cSrcweir const PPDKey* pKey = rContext.getParser()->getKey( OStringToOUString( pOption->keyword, aEncoding ) ); 643cdf0e10cSrcweir if( pKey ) 644cdf0e10cSrcweir { 645cdf0e10cSrcweir const PPDValue* pValue = pKey->getValue( OStringToOUString( pChoice->choice, aEncoding ) ); 646cdf0e10cSrcweir if( pValue ) 647cdf0e10cSrcweir { 648cdf0e10cSrcweir if( pValue != pKey->getDefaultValue() ) 649cdf0e10cSrcweir { 650cdf0e10cSrcweir rContext.setValue( pKey, pValue, true ); 651cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 652cdf0e10cSrcweir fprintf( stderr, "key %s is set to %s\n", pOption->keyword, pChoice->choice ); 653cdf0e10cSrcweir #endif 654cdf0e10cSrcweir 655cdf0e10cSrcweir } 656cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 657cdf0e10cSrcweir else 658cdf0e10cSrcweir fprintf( stderr, "key %s is defaulted to %s\n", pOption->keyword, pChoice->choice ); 659cdf0e10cSrcweir #endif 660cdf0e10cSrcweir } 661cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 662cdf0e10cSrcweir else 663cdf0e10cSrcweir fprintf( stderr, "caution: value %s not found in key %s\n", pChoice->choice, pOption->keyword ); 664cdf0e10cSrcweir #endif 665cdf0e10cSrcweir } 666cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 667cdf0e10cSrcweir else 668cdf0e10cSrcweir fprintf( stderr, "caution: key %s not found in parser\n", pOption->keyword ); 669cdf0e10cSrcweir #endif 670cdf0e10cSrcweir } 671cdf0e10cSrcweir } 672cdf0e10cSrcweir } 673cdf0e10cSrcweir 674cdf0e10cSrcweir // recurse through subgroups 675cdf0e10cSrcweir for( int g = 0; g < pPPDGroup->num_subgroups; g++ ) 676cdf0e10cSrcweir { 677cdf0e10cSrcweir updatePrinterContextInfo( pPPDGroup->subgroups + g, rContext ); 678cdf0e10cSrcweir } 679cdf0e10cSrcweir } 680cdf0e10cSrcweir #endif // ENABLE_CUPS 681cdf0e10cSrcweir 682cdf0e10cSrcweir const PPDParser* CUPSManager::createCUPSParser( const OUString& rPrinter ) 683cdf0e10cSrcweir { 684cdf0e10cSrcweir const PPDParser* pNewParser = NULL; 685cdf0e10cSrcweir OUString aPrinter; 686cdf0e10cSrcweir 687cdf0e10cSrcweir if( rPrinter.compareToAscii( "CUPS:", 5 ) == 0 ) 688cdf0e10cSrcweir aPrinter = rPrinter.copy( 5 ); 689cdf0e10cSrcweir else 690cdf0e10cSrcweir aPrinter = rPrinter; 691cdf0e10cSrcweir 692cdf0e10cSrcweir #ifdef ENABLE_CUPS 693cdf0e10cSrcweir if( m_aCUPSMutex.tryToAcquire() ) 694cdf0e10cSrcweir { 695cdf0e10cSrcweir if( m_nDests && m_pDests && ! isCUPSDisabled() ) 696cdf0e10cSrcweir { 697cdf0e10cSrcweir std::hash_map< OUString, int, OUStringHash >::iterator dest_it = 698cdf0e10cSrcweir m_aCUPSDestMap.find( aPrinter ); 699cdf0e10cSrcweir if( dest_it != m_aCUPSDestMap.end() ) 700cdf0e10cSrcweir { 701cdf0e10cSrcweir cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second; 702cdf0e10cSrcweir OString aPPDFile = m_pCUPSWrapper->cupsGetPPD( pDest->name ); 703cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 704cdf0e10cSrcweir fprintf( stderr, "PPD for %s is %s\n", OUStringToOString( aPrinter, osl_getThreadTextEncoding() ).getStr(), aPPDFile.getStr() ); 705cdf0e10cSrcweir #endif 706cdf0e10cSrcweir if( aPPDFile.getLength() ) 707cdf0e10cSrcweir { 708cdf0e10cSrcweir rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 709cdf0e10cSrcweir OUString aFileName( OStringToOUString( aPPDFile, aEncoding ) ); 710cdf0e10cSrcweir // update the printer info with context information 711cdf0e10cSrcweir ppd_file_t* pPPD = m_pCUPSWrapper->ppdOpenFile( aPPDFile.getStr() ); 712cdf0e10cSrcweir if( pPPD ) 713cdf0e10cSrcweir { 714cdf0e10cSrcweir // create the new parser 715cdf0e10cSrcweir PPDParser* pCUPSParser = new PPDParser( aFileName ); 716cdf0e10cSrcweir pCUPSParser->m_aFile = rPrinter; 717cdf0e10cSrcweir pNewParser = pCUPSParser; 718cdf0e10cSrcweir 719cdf0e10cSrcweir /*int nConflicts =*/ m_pCUPSWrapper->cupsMarkOptions( pPPD, pDest->num_options, pDest->options ); 720cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 721cdf0e10cSrcweir fprintf( stderr, "processing the following options for printer %s (instance %s):\n", 722cdf0e10cSrcweir pDest->name, pDest->instance ); 723cdf0e10cSrcweir for( int k = 0; k < pDest->num_options; k++ ) 724cdf0e10cSrcweir fprintf( stderr, " \"%s\" = \"%s\"\n", 725cdf0e10cSrcweir pDest->options[k].name, 726cdf0e10cSrcweir pDest->options[k].value ); 727cdf0e10cSrcweir #endif 728cdf0e10cSrcweir PrinterInfo& rInfo = m_aPrinters[ aPrinter ].m_aInfo; 729cdf0e10cSrcweir 730cdf0e10cSrcweir // remember the default context for later use 731cdf0e10cSrcweir PPDContext& rContext = m_aDefaultContexts[ aPrinter ]; 732cdf0e10cSrcweir rContext.setParser( pNewParser ); 733cdf0e10cSrcweir // set system default paper; printer CUPS PPD options 734cdf0e10cSrcweir // may overwrite it 735cdf0e10cSrcweir setDefaultPaper( rContext ); 736cdf0e10cSrcweir for( int i = 0; i < pPPD->num_groups; i++ ) 737cdf0e10cSrcweir updatePrinterContextInfo( pPPD->groups + i, rContext ); 738cdf0e10cSrcweir 739cdf0e10cSrcweir rInfo.m_pParser = pNewParser; 740cdf0e10cSrcweir rInfo.m_aContext = rContext; 741cdf0e10cSrcweir 742cdf0e10cSrcweir // clean up the mess 743cdf0e10cSrcweir m_pCUPSWrapper->ppdClose( pPPD ); 744cdf0e10cSrcweir } 745cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 746cdf0e10cSrcweir else 747cdf0e10cSrcweir fprintf( stderr, "ppdOpenFile failed, falling back to generic driver\n" ); 748cdf0e10cSrcweir #endif 749cdf0e10cSrcweir 750cdf0e10cSrcweir // remove temporary PPD file 751cdf0e10cSrcweir unlink( aPPDFile.getStr() ); 752cdf0e10cSrcweir } 753cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 754cdf0e10cSrcweir else 755cdf0e10cSrcweir fprintf( stderr, "cupsGetPPD failed, falling back to generic driver\n" ); 756cdf0e10cSrcweir #endif 757cdf0e10cSrcweir } 758cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 759cdf0e10cSrcweir else 760cdf0e10cSrcweir fprintf( stderr, "no dest found for printer %s\n", OUStringToOString( aPrinter, osl_getThreadTextEncoding() ).getStr() ); 761cdf0e10cSrcweir #endif 762cdf0e10cSrcweir } 763cdf0e10cSrcweir m_aCUPSMutex.release(); 764cdf0e10cSrcweir } 765cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >1 766cdf0e10cSrcweir else 767cdf0e10cSrcweir fprintf( stderr, "could not acquire CUPS mutex !!!\n" ); 768cdf0e10cSrcweir #endif 769cdf0e10cSrcweir #endif // ENABLE_CUPS 770cdf0e10cSrcweir 771cdf0e10cSrcweir if( ! pNewParser ) 772cdf0e10cSrcweir { 773cdf0e10cSrcweir // get the default PPD 774cdf0e10cSrcweir pNewParser = PPDParser::getParser( String( RTL_CONSTASCII_USTRINGPARAM( "SGENPRT" ) ) ); 775cdf0e10cSrcweir 776cdf0e10cSrcweir PrinterInfo& rInfo = m_aPrinters[ aPrinter ].m_aInfo; 777cdf0e10cSrcweir 778cdf0e10cSrcweir rInfo.m_pParser = pNewParser; 779cdf0e10cSrcweir rInfo.m_aContext.setParser( pNewParser ); 780cdf0e10cSrcweir } 781cdf0e10cSrcweir 782cdf0e10cSrcweir return pNewParser; 783cdf0e10cSrcweir } 784cdf0e10cSrcweir 785cdf0e10cSrcweir void CUPSManager::setupJobContextData( 786cdf0e10cSrcweir JobData& 787cdf0e10cSrcweir #ifdef ENABLE_CUPS 788cdf0e10cSrcweir rData 789cdf0e10cSrcweir #endif 790cdf0e10cSrcweir ) 791cdf0e10cSrcweir { 792cdf0e10cSrcweir #ifdef ENABLE_CUPS 793cdf0e10cSrcweir std::hash_map< OUString, int, OUStringHash >::iterator dest_it = 794cdf0e10cSrcweir m_aCUPSDestMap.find( rData.m_aPrinterName ); 795cdf0e10cSrcweir 796cdf0e10cSrcweir if( dest_it == m_aCUPSDestMap.end() ) 797cdf0e10cSrcweir return PrinterInfoManager::setupJobContextData( rData ); 798cdf0e10cSrcweir 799cdf0e10cSrcweir std::hash_map< OUString, Printer, OUStringHash >::iterator p_it = 800cdf0e10cSrcweir m_aPrinters.find( rData.m_aPrinterName ); 801cdf0e10cSrcweir if( p_it == m_aPrinters.end() ) // huh ? 802cdf0e10cSrcweir { 803cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 804cdf0e10cSrcweir fprintf( stderr, "CUPS printer list in disorder, no dest for printer %s !\n", OUStringToOString( rData.m_aPrinterName, osl_getThreadTextEncoding() ).getStr() ); 805cdf0e10cSrcweir #endif 806cdf0e10cSrcweir return; 807cdf0e10cSrcweir } 808cdf0e10cSrcweir 809cdf0e10cSrcweir if( p_it->second.m_aInfo.m_pParser == NULL ) 810cdf0e10cSrcweir { 811cdf0e10cSrcweir // in turn calls createCUPSParser 812cdf0e10cSrcweir // which updates the printer info 813cdf0e10cSrcweir p_it->second.m_aInfo.m_pParser = PPDParser::getParser( p_it->second.m_aInfo.m_aDriverName ); 814cdf0e10cSrcweir } 815cdf0e10cSrcweir if( p_it->second.m_aInfo.m_aContext.getParser() == NULL ) 816cdf0e10cSrcweir { 817cdf0e10cSrcweir OUString aPrinter; 818cdf0e10cSrcweir if( p_it->second.m_aInfo.m_aDriverName.compareToAscii( "CUPS:", 5 ) == 0 ) 819cdf0e10cSrcweir aPrinter = p_it->second.m_aInfo.m_aDriverName.copy( 5 ); 820cdf0e10cSrcweir else 821cdf0e10cSrcweir aPrinter = p_it->second.m_aInfo.m_aDriverName; 822cdf0e10cSrcweir 823cdf0e10cSrcweir p_it->second.m_aInfo.m_aContext = m_aDefaultContexts[ aPrinter ]; 824cdf0e10cSrcweir } 825cdf0e10cSrcweir 826cdf0e10cSrcweir rData.m_pParser = p_it->second.m_aInfo.m_pParser; 827cdf0e10cSrcweir rData.m_aContext = p_it->second.m_aInfo.m_aContext; 828cdf0e10cSrcweir #endif 829cdf0e10cSrcweir } 830cdf0e10cSrcweir 831cdf0e10cSrcweir FILE* CUPSManager::startSpool( const OUString& rPrintername, bool bQuickCommand ) 832cdf0e10cSrcweir { 833cdf0e10cSrcweir OSL_TRACE( "endSpool: %s, %s", 834cdf0e10cSrcweir rtl::OUStringToOString( rPrintername, RTL_TEXTENCODING_UTF8 ).getStr(), 835cdf0e10cSrcweir bQuickCommand ? "true" : "false" ); 836cdf0e10cSrcweir 837cdf0e10cSrcweir if( m_aCUPSDestMap.find( rPrintername ) == m_aCUPSDestMap.end() ) 838cdf0e10cSrcweir { 839cdf0e10cSrcweir OSL_TRACE( "defer to PrinterInfoManager::startSpool" ); 840cdf0e10cSrcweir return PrinterInfoManager::startSpool( rPrintername, bQuickCommand ); 841cdf0e10cSrcweir } 842cdf0e10cSrcweir 843cdf0e10cSrcweir #ifdef ENABLE_CUPS 844cdf0e10cSrcweir OUString aTmpURL, aTmpFile; 845cdf0e10cSrcweir osl_createTempFile( NULL, NULL, &aTmpURL.pData ); 846cdf0e10cSrcweir osl_getSystemPathFromFileURL( aTmpURL.pData, &aTmpFile.pData ); 847cdf0e10cSrcweir OString aSysFile = OUStringToOString( aTmpFile, osl_getThreadTextEncoding() ); 848cdf0e10cSrcweir FILE* fp = fopen( aSysFile.getStr(), "w" ); 849cdf0e10cSrcweir if( fp ) 850cdf0e10cSrcweir m_aSpoolFiles[fp] = aSysFile; 851cdf0e10cSrcweir 852cdf0e10cSrcweir return fp; 853cdf0e10cSrcweir #else 854cdf0e10cSrcweir return NULL; 855cdf0e10cSrcweir #endif 856cdf0e10cSrcweir } 857cdf0e10cSrcweir 858cdf0e10cSrcweir struct less_ppd_key : public ::std::binary_function<double, double, bool> 859cdf0e10cSrcweir { 860cdf0e10cSrcweir bool operator()(const PPDKey* left, const PPDKey* right) 861cdf0e10cSrcweir { return left->getOrderDependency() < right->getOrderDependency(); } 862cdf0e10cSrcweir }; 863cdf0e10cSrcweir 864cdf0e10cSrcweir void CUPSManager::getOptionsFromDocumentSetup( const JobData& rJob, bool bBanner, int& rNumOptions, void** rOptions ) const 865cdf0e10cSrcweir { 866cdf0e10cSrcweir rNumOptions = 0; 867cdf0e10cSrcweir *rOptions = NULL; 868cdf0e10cSrcweir int i; 869cdf0e10cSrcweir 870cdf0e10cSrcweir // emit features ordered to OrderDependency 871cdf0e10cSrcweir // ignore features that are set to default 872cdf0e10cSrcweir 873cdf0e10cSrcweir // sanity check 874cdf0e10cSrcweir if( rJob.m_pParser == rJob.m_aContext.getParser() && rJob.m_pParser ) 875cdf0e10cSrcweir { 876cdf0e10cSrcweir int nKeys = rJob.m_aContext.countValuesModified(); 877cdf0e10cSrcweir ::std::vector< const PPDKey* > aKeys( nKeys ); 878cdf0e10cSrcweir for( i = 0; i < nKeys; i++ ) 879cdf0e10cSrcweir aKeys[i] = rJob.m_aContext.getModifiedKey( i ); 880cdf0e10cSrcweir ::std::sort( aKeys.begin(), aKeys.end(), less_ppd_key() ); 881cdf0e10cSrcweir 882cdf0e10cSrcweir for( i = 0; i < nKeys; i++ ) 883cdf0e10cSrcweir { 884cdf0e10cSrcweir const PPDKey* pKey = aKeys[i]; 885cdf0e10cSrcweir const PPDValue* pValue = rJob.m_aContext.getValue( pKey ); 886cdf0e10cSrcweir if(pValue && pValue->m_eType == eInvocation && pValue->m_aValue.Len() ) 887cdf0e10cSrcweir { 888cdf0e10cSrcweir OString aKey = OUStringToOString( pKey->getKey(), RTL_TEXTENCODING_ASCII_US ); 889cdf0e10cSrcweir OString aValue = OUStringToOString( pValue->m_aOption, RTL_TEXTENCODING_ASCII_US ); 890cdf0e10cSrcweir rNumOptions = m_pCUPSWrapper->cupsAddOption( aKey.getStr(), aValue.getStr(), rNumOptions, (cups_option_t**)rOptions ); 891cdf0e10cSrcweir } 892cdf0e10cSrcweir } 893cdf0e10cSrcweir } 894cdf0e10cSrcweir 895cdf0e10cSrcweir if( rJob.m_nPDFDevice > 0 && rJob.m_nCopies > 1 ) 896cdf0e10cSrcweir { 897cdf0e10cSrcweir rtl::OString aVal( rtl::OString::valueOf( sal_Int32( rJob.m_nCopies ) ) ); 898cdf0e10cSrcweir rNumOptions = m_pCUPSWrapper->cupsAddOption( "copies", aVal.getStr(), rNumOptions, (cups_option_t**)rOptions ); 899cdf0e10cSrcweir } 900cdf0e10cSrcweir if( ! bBanner ) 901cdf0e10cSrcweir { 902cdf0e10cSrcweir rNumOptions = m_pCUPSWrapper->cupsAddOption( "job-sheets", "none", rNumOptions, (cups_option_t**)rOptions ); 903cdf0e10cSrcweir } 904cdf0e10cSrcweir } 905cdf0e10cSrcweir 906cdf0e10cSrcweir int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner ) 907cdf0e10cSrcweir { 908cdf0e10cSrcweir OSL_TRACE( "endSpool: %s, %s, copy count = %d", 909cdf0e10cSrcweir rtl::OUStringToOString( rPrintername, RTL_TEXTENCODING_UTF8 ).getStr(), 910cdf0e10cSrcweir rtl::OUStringToOString( rJobTitle, RTL_TEXTENCODING_UTF8 ).getStr(), 911cdf0e10cSrcweir rDocumentJobData.m_nCopies 912cdf0e10cSrcweir ); 913cdf0e10cSrcweir 914cdf0e10cSrcweir int nJobID = 0; 915cdf0e10cSrcweir 916cdf0e10cSrcweir osl::MutexGuard aGuard( m_aCUPSMutex ); 917cdf0e10cSrcweir 918cdf0e10cSrcweir std::hash_map< OUString, int, OUStringHash >::iterator dest_it = 919cdf0e10cSrcweir m_aCUPSDestMap.find( rPrintername ); 920cdf0e10cSrcweir if( dest_it == m_aCUPSDestMap.end() ) 921cdf0e10cSrcweir { 922cdf0e10cSrcweir OSL_TRACE( "defer to PrinterInfoManager::endSpool" ); 923cdf0e10cSrcweir return PrinterInfoManager::endSpool( rPrintername, rJobTitle, pFile, rDocumentJobData, bBanner ); 924cdf0e10cSrcweir } 925cdf0e10cSrcweir 926cdf0e10cSrcweir #ifdef ENABLE_CUPS 927cdf0e10cSrcweir std::hash_map< FILE*, OString, FPtrHash >::const_iterator it = m_aSpoolFiles.find( pFile ); 928cdf0e10cSrcweir if( it != m_aSpoolFiles.end() ) 929cdf0e10cSrcweir { 930cdf0e10cSrcweir fclose( pFile ); 931cdf0e10cSrcweir rtl_TextEncoding aEnc = osl_getThreadTextEncoding(); 932cdf0e10cSrcweir 933cdf0e10cSrcweir // setup cups options 934cdf0e10cSrcweir int nNumOptions = 0; 935cdf0e10cSrcweir cups_option_t* pOptions = NULL; 936cdf0e10cSrcweir getOptionsFromDocumentSetup( rDocumentJobData, bBanner, nNumOptions, (void**)&pOptions ); 937cdf0e10cSrcweir 938cdf0e10cSrcweir cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second; 939cdf0e10cSrcweir nJobID = m_pCUPSWrapper->cupsPrintFile( pDest->name, 940cdf0e10cSrcweir it->second.getStr(), 941cdf0e10cSrcweir OUStringToOString( rJobTitle, aEnc ).getStr(), 942cdf0e10cSrcweir nNumOptions, pOptions ); 943cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 944cdf0e10cSrcweir fprintf( stderr, "cupsPrintFile( %s, %s, %s, %d, %p ) returns %d\n", 945cdf0e10cSrcweir pDest->name, 946cdf0e10cSrcweir it->second.getStr(), 947cdf0e10cSrcweir OUStringToOString( rJobTitle, aEnc ).getStr(), 948cdf0e10cSrcweir nNumOptions, 949cdf0e10cSrcweir pOptions, 950cdf0e10cSrcweir nJobID 951cdf0e10cSrcweir ); 952cdf0e10cSrcweir for( int n = 0; n < nNumOptions; n++ ) 953cdf0e10cSrcweir fprintf( stderr, " option %s=%s\n", pOptions[n].name, pOptions[n].value ); 954cdf0e10cSrcweir OString aCmd( "cp " ); 955cdf0e10cSrcweir aCmd = aCmd + it->second; 956cdf0e10cSrcweir aCmd = aCmd + OString( " $HOME/cupsprint.ps" ); 957cdf0e10cSrcweir system( aCmd.getStr() ); 958cdf0e10cSrcweir #endif 959cdf0e10cSrcweir 960cdf0e10cSrcweir unlink( it->second.getStr() ); 961cdf0e10cSrcweir m_aSpoolFiles.erase( pFile ); 962cdf0e10cSrcweir if( pOptions ) 963cdf0e10cSrcweir m_pCUPSWrapper->cupsFreeOptions( nNumOptions, pOptions ); 964cdf0e10cSrcweir } 965cdf0e10cSrcweir #endif // ENABLE_CUPS 966cdf0e10cSrcweir 967cdf0e10cSrcweir return nJobID; 968cdf0e10cSrcweir } 969cdf0e10cSrcweir 970cdf0e10cSrcweir 971cdf0e10cSrcweir void CUPSManager::changePrinterInfo( const OUString& rPrinter, const PrinterInfo& rNewInfo ) 972cdf0e10cSrcweir { 973cdf0e10cSrcweir PrinterInfoManager::changePrinterInfo( rPrinter, rNewInfo ); 974cdf0e10cSrcweir } 975cdf0e10cSrcweir 976cdf0e10cSrcweir bool CUPSManager::checkPrintersChanged( bool bWait ) 977cdf0e10cSrcweir { 978cdf0e10cSrcweir bool bChanged = false; 979cdf0e10cSrcweir if( bWait ) 980cdf0e10cSrcweir { 981cdf0e10cSrcweir if( m_aDestThread ) 982cdf0e10cSrcweir { 983cdf0e10cSrcweir // initial asynchronous detection still running 984cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 985cdf0e10cSrcweir fprintf( stderr, "syncing cups discovery thread\n" ); 986cdf0e10cSrcweir #endif 987cdf0e10cSrcweir osl_joinWithThread( m_aDestThread ); 988cdf0e10cSrcweir osl_destroyThread( m_aDestThread ); 989cdf0e10cSrcweir m_aDestThread = NULL; 990cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 991cdf0e10cSrcweir fprintf( stderr, "done: syncing cups discovery thread\n" ); 992cdf0e10cSrcweir #endif 993cdf0e10cSrcweir } 994cdf0e10cSrcweir else 995cdf0e10cSrcweir { 996cdf0e10cSrcweir // #i82321# check for cups printer updates 997cdf0e10cSrcweir // with this change the whole asynchronous detection in a thread is 998cdf0e10cSrcweir // almost useless. The only relevance left is for some stalled systems 999cdf0e10cSrcweir // where the user can set SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION 1000cdf0e10cSrcweir // (see vcl/unx/source/gdi/salprnpsp.cxx) 1001cdf0e10cSrcweir // so that checkPrintersChanged( true ) will never be called 1002cdf0e10cSrcweir 1003cdf0e10cSrcweir // there is no way to query CUPS whether the printer list has changed 1004cdf0e10cSrcweir // so get the dest list anew 1005cdf0e10cSrcweir if( m_nDests && m_pDests ) 1006cdf0e10cSrcweir m_pCUPSWrapper->cupsFreeDests( m_nDests, (cups_dest_t*)m_pDests ); 1007cdf0e10cSrcweir m_nDests = 0; 1008cdf0e10cSrcweir m_pDests = NULL; 1009cdf0e10cSrcweir runDests(); 1010cdf0e10cSrcweir } 1011cdf0e10cSrcweir } 1012cdf0e10cSrcweir if( m_aCUPSMutex.tryToAcquire() ) 1013cdf0e10cSrcweir { 1014cdf0e10cSrcweir bChanged = m_bNewDests; 1015cdf0e10cSrcweir m_aCUPSMutex.release(); 1016cdf0e10cSrcweir } 1017cdf0e10cSrcweir 1018cdf0e10cSrcweir if( ! bChanged ) 1019cdf0e10cSrcweir { 1020cdf0e10cSrcweir bChanged = PrinterInfoManager::checkPrintersChanged( bWait ); 1021cdf0e10cSrcweir // #i54375# ensure new merging with CUPS list in :initialize 1022cdf0e10cSrcweir if( bChanged ) 1023cdf0e10cSrcweir m_bNewDests = true; 1024cdf0e10cSrcweir } 1025cdf0e10cSrcweir 1026cdf0e10cSrcweir if( bChanged ) 1027cdf0e10cSrcweir initialize(); 1028cdf0e10cSrcweir 1029cdf0e10cSrcweir return bChanged; 1030cdf0e10cSrcweir } 1031cdf0e10cSrcweir 1032cdf0e10cSrcweir bool CUPSManager::addPrinter( const OUString& rName, const OUString& rDriver ) 1033cdf0e10cSrcweir { 1034cdf0e10cSrcweir // don't touch the CUPS printers 1035cdf0e10cSrcweir if( m_aCUPSDestMap.find( rName ) != m_aCUPSDestMap.end() || 1036cdf0e10cSrcweir rDriver.compareToAscii( "CUPS:", 5 ) == 0 1037cdf0e10cSrcweir ) 1038cdf0e10cSrcweir return false; 1039cdf0e10cSrcweir return PrinterInfoManager::addPrinter( rName, rDriver ); 1040cdf0e10cSrcweir } 1041cdf0e10cSrcweir 1042cdf0e10cSrcweir bool CUPSManager::removePrinter( const OUString& rName, bool bCheck ) 1043cdf0e10cSrcweir { 1044cdf0e10cSrcweir // don't touch the CUPS printers 1045cdf0e10cSrcweir if( m_aCUPSDestMap.find( rName ) != m_aCUPSDestMap.end() ) 1046cdf0e10cSrcweir return false; 1047cdf0e10cSrcweir return PrinterInfoManager::removePrinter( rName, bCheck ); 1048cdf0e10cSrcweir } 1049cdf0e10cSrcweir 1050cdf0e10cSrcweir bool CUPSManager::setDefaultPrinter( const OUString& rName ) 1051cdf0e10cSrcweir { 1052cdf0e10cSrcweir bool bSuccess = false; 1053cdf0e10cSrcweir #ifdef ENABLE_CUPS 1054cdf0e10cSrcweir std::hash_map< OUString, int, OUStringHash >::iterator nit = 1055cdf0e10cSrcweir m_aCUPSDestMap.find( rName ); 1056cdf0e10cSrcweir if( nit != m_aCUPSDestMap.end() && m_aCUPSMutex.tryToAcquire() ) 1057cdf0e10cSrcweir { 1058cdf0e10cSrcweir cups_dest_t* pDests = (cups_dest_t*)m_pDests; 1059cdf0e10cSrcweir for( int i = 0; i < m_nDests; i++ ) 1060cdf0e10cSrcweir pDests[i].is_default = 0; 1061cdf0e10cSrcweir pDests[ nit->second ].is_default = 1; 1062cdf0e10cSrcweir m_pCUPSWrapper->cupsSetDests( m_nDests, (cups_dest_t*)m_pDests ); 1063cdf0e10cSrcweir m_aDefaultPrinter = rName; 1064cdf0e10cSrcweir m_aCUPSMutex.release(); 1065cdf0e10cSrcweir bSuccess = true; 1066cdf0e10cSrcweir } 1067cdf0e10cSrcweir else 1068cdf0e10cSrcweir #endif 1069cdf0e10cSrcweir bSuccess = PrinterInfoManager::setDefaultPrinter( rName ); 1070cdf0e10cSrcweir 1071cdf0e10cSrcweir return bSuccess; 1072cdf0e10cSrcweir } 1073cdf0e10cSrcweir 1074cdf0e10cSrcweir bool CUPSManager::writePrinterConfig() 1075cdf0e10cSrcweir { 1076cdf0e10cSrcweir #ifdef ENABLE_CUPS 1077cdf0e10cSrcweir bool bDestModified = false; 1078cdf0e10cSrcweir rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 1079cdf0e10cSrcweir 1080cdf0e10cSrcweir for( std::hash_map< OUString, Printer, OUStringHash >::iterator prt = 1081cdf0e10cSrcweir m_aPrinters.begin(); prt != m_aPrinters.end(); ++prt ) 1082cdf0e10cSrcweir { 1083cdf0e10cSrcweir std::hash_map< OUString, int, OUStringHash >::iterator nit = 1084cdf0e10cSrcweir m_aCUPSDestMap.find( prt->first ); 1085cdf0e10cSrcweir if( nit == m_aCUPSDestMap.end() ) 1086cdf0e10cSrcweir continue; 1087cdf0e10cSrcweir 1088cdf0e10cSrcweir if( ! prt->second.m_bModified ) 1089cdf0e10cSrcweir continue; 1090cdf0e10cSrcweir 1091cdf0e10cSrcweir if( m_aCUPSMutex.tryToAcquire() ) 1092cdf0e10cSrcweir { 1093cdf0e10cSrcweir bDestModified = true; 1094cdf0e10cSrcweir cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + nit->second; 1095cdf0e10cSrcweir PrinterInfo& rInfo = prt->second.m_aInfo; 1096cdf0e10cSrcweir 1097cdf0e10cSrcweir // create new option list 1098cdf0e10cSrcweir int nNewOptions = 0; 1099cdf0e10cSrcweir cups_option_t* pNewOptions = NULL; 1100cdf0e10cSrcweir int nValues = rInfo.m_aContext.countValuesModified(); 1101cdf0e10cSrcweir for( int i = 0; i < nValues; i++ ) 1102cdf0e10cSrcweir { 1103cdf0e10cSrcweir const PPDKey* pKey = rInfo.m_aContext.getModifiedKey( i ); 1104cdf0e10cSrcweir const PPDValue* pValue = rInfo.m_aContext.getValue( pKey ); 1105cdf0e10cSrcweir if( pKey && pValue ) // sanity check 1106cdf0e10cSrcweir { 1107cdf0e10cSrcweir OString aName = OUStringToOString( pKey->getKey(), aEncoding ); 1108cdf0e10cSrcweir OString aValue = OUStringToOString( pValue->m_aOption, aEncoding ); 1109cdf0e10cSrcweir nNewOptions = m_pCUPSWrapper->cupsAddOption( aName.getStr(), aValue.getStr(), nNewOptions, &pNewOptions ); 1110cdf0e10cSrcweir } 1111cdf0e10cSrcweir } 1112cdf0e10cSrcweir // set PPD options on CUPS dest 1113cdf0e10cSrcweir m_pCUPSWrapper->cupsFreeOptions( pDest->num_options, pDest->options ); 1114cdf0e10cSrcweir pDest->num_options = nNewOptions; 1115cdf0e10cSrcweir pDest->options = pNewOptions; 1116cdf0e10cSrcweir m_aCUPSMutex.release(); 1117cdf0e10cSrcweir } 1118cdf0e10cSrcweir } 1119cdf0e10cSrcweir if( bDestModified && m_aCUPSMutex.tryToAcquire() ) 1120cdf0e10cSrcweir { 1121cdf0e10cSrcweir m_pCUPSWrapper->cupsSetDests( m_nDests, (cups_dest_t*)m_pDests ); 1122cdf0e10cSrcweir m_aCUPSMutex.release(); 1123cdf0e10cSrcweir } 1124cdf0e10cSrcweir #endif // ENABLE_CUPS 1125cdf0e10cSrcweir 1126cdf0e10cSrcweir return PrinterInfoManager::writePrinterConfig(); 1127cdf0e10cSrcweir } 1128cdf0e10cSrcweir 1129cdf0e10cSrcweir bool CUPSManager::addOrRemovePossible() const 1130cdf0e10cSrcweir { 1131cdf0e10cSrcweir return (m_nDests && m_pDests && ! isCUPSDisabled())? false : PrinterInfoManager::addOrRemovePossible(); 1132cdf0e10cSrcweir } 1133cdf0e10cSrcweir 1134cdf0e10cSrcweir const char* CUPSManager::authenticateUser( const char* /*pIn*/ ) 1135cdf0e10cSrcweir { 1136cdf0e10cSrcweir const char* pRet = NULL; 1137cdf0e10cSrcweir 1138cdf0e10cSrcweir #ifdef ENABLE_CUPS 1139cdf0e10cSrcweir OUString aLib = OUString::createFromAscii( _XSALSET_LIBNAME ); 1140cdf0e10cSrcweir oslModule pLib = osl_loadModule( aLib.pData, SAL_LOADMODULE_LAZY ); 1141cdf0e10cSrcweir if( pLib ) 1142cdf0e10cSrcweir { 1143cdf0e10cSrcweir OUString aSym( RTL_CONSTASCII_USTRINGPARAM( "Sal_authenticateQuery" ) ); 1144cdf0e10cSrcweir bool (*getpw)( const OString& rServer, OString& rUser, OString& rPw) = 1145cdf0e10cSrcweir (bool(*)(const OString&,OString&,OString&))osl_getFunctionSymbol( pLib, aSym.pData ); 1146cdf0e10cSrcweir if( getpw ) 1147cdf0e10cSrcweir { 1148cdf0e10cSrcweir osl::MutexGuard aGuard( m_aCUPSMutex ); 1149cdf0e10cSrcweir 1150cdf0e10cSrcweir OString aUser = m_pCUPSWrapper->cupsUser(); 1151cdf0e10cSrcweir OString aServer = m_pCUPSWrapper->cupsServer(); 1152cdf0e10cSrcweir OString aPassword; 1153cdf0e10cSrcweir if( getpw( aServer, aUser, aPassword ) ) 1154cdf0e10cSrcweir { 1155cdf0e10cSrcweir m_aPassword = aPassword; 1156cdf0e10cSrcweir m_aUser = aUser; 1157cdf0e10cSrcweir m_pCUPSWrapper->cupsSetUser( m_aUser.getStr() ); 1158cdf0e10cSrcweir pRet = m_aPassword.getStr(); 1159cdf0e10cSrcweir } 1160cdf0e10cSrcweir } 1161cdf0e10cSrcweir osl_unloadModule( pLib ); 1162cdf0e10cSrcweir } 1163cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 1164cdf0e10cSrcweir else fprintf( stderr, "loading of module %s failed\n", OUStringToOString( aLib, osl_getThreadTextEncoding() ).getStr() ); 1165cdf0e10cSrcweir #endif 1166cdf0e10cSrcweir #endif // ENABLE_CUPS 1167cdf0e10cSrcweir 1168cdf0e10cSrcweir return pRet; 1169cdf0e10cSrcweir } 1170