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