xref: /aoo41x/main/vcl/unx/generic/printer/cupsmgr.cxx (revision cdf0e10c)
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