LCOV - code coverage report
Current view: top level - vcl/unx/generic/printer - cupsmgr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 107 474 22.6 %
Date: 2012-08-25 Functions: 16 53 30.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 81 776 10.4 %

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

Generated by: LCOV version 1.10