1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_folders.h>
26 #include <osl/file.hxx>
27 #include <osl/process.h>
28 #include <osl/thread.h>
29 #include <rtl/bootstrap.hxx>
30 #include <rtl/ustring.hxx>
31 #include <tools/urlobj.hxx>
32 #include "vcl/helper.hxx"
33 #include "vcl/ppdparser.hxx"
34 #include <boost/scoped_array.hpp>
36 using ::rtl::Bootstrap
;
40 OUString
getOfficePath( enum whichOfficePath ePath
)
42 static OUString aInstallationRootPath
;
43 static OUString aUserPath
;
44 static OUString aConfigPath
;
45 static OUString aEmpty
;
46 static bool bOnce
= false;
52 Bootstrap::get( "BRAND_BASE_DIR", aInstallationRootPath
);
53 aIni
= aInstallationRootPath
+ "/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE( "bootstrap" );
54 Bootstrap
aBootstrap( aIni
);
55 aBootstrap
.getFrom( "CustomDataUrl", aConfigPath
);
56 aBootstrap
.getFrom( "UserInstallation", aUserPath
);
57 OUString aUPath
= aUserPath
;
59 if( aConfigPath
.startsWith( "file://" ) )
62 if( osl_getSystemPathFromFileURL( aConfigPath
.pData
, &aSysPath
.pData
) == osl_File_E_None
)
63 aConfigPath
= aSysPath
;
65 if( aInstallationRootPath
.startsWith( "file://" ) )
68 if( osl_getSystemPathFromFileURL( aInstallationRootPath
.pData
, &aSysPath
.pData
) == osl_File_E_None
)
69 aInstallationRootPath
= aSysPath
;
71 if( aUserPath
.startsWith( "file://" ) )
74 if( osl_getSystemPathFromFileURL( aUserPath
.pData
, &aSysPath
.pData
) == osl_File_E_None
)
77 // ensure user path exists
78 aUPath
+= "/user/psprint";
79 #if OSL_DEBUG_LEVEL > 1
82 osl_createDirectoryPath( aUPath
.pData
, NULL
, NULL
);
83 #if OSL_DEBUG_LEVEL > 1
84 fprintf( stderr
, "try to create \"%s\" = %d\n", OUStringToOString( aUPath
, RTL_TEXTENCODING_UTF8
).getStr(), eErr
);
90 case ConfigPath
: return aConfigPath
;
91 case InstallationRootPath
: return aInstallationRootPath
;
92 case UserPath
: return aUserPath
;
97 static OString
getEnvironmentPath( const char* pKey
)
101 const char* pValue
= getenv( pKey
);
102 if( pValue
&& *pValue
)
104 aPath
= OString( pValue
);
111 void psp::getPrinterPathList( std::list
< OUString
>& rPathList
, const char* pSubDir
)
114 rtl_TextEncoding aEncoding
= osl_getThreadTextEncoding();
116 OUStringBuffer
aPathBuffer( 256 );
119 aPathBuffer
.append( getOfficePath( psp::InstallationRootPath
) );
120 if( !aPathBuffer
.isEmpty() )
122 aPathBuffer
.appendAscii( "/" LIBO_SHARE_FOLDER
"/psprint" );
125 aPathBuffer
.append( '/' );
126 aPathBuffer
.appendAscii( pSubDir
);
128 rPathList
.push_back( aPathBuffer
.makeStringAndClear() );
131 aPathBuffer
.append( getOfficePath( psp::UserPath
) );
132 if( !aPathBuffer
.isEmpty() )
134 aPathBuffer
.appendAscii( "/user/psprint" );
137 aPathBuffer
.append( '/' );
138 aPathBuffer
.appendAscii( pSubDir
);
140 rPathList
.push_back( aPathBuffer
.makeStringAndClear() );
143 OString
aPath( getEnvironmentPath("SAL_PSPRINT") );
144 sal_Int32 nIndex
= 0;
147 OString
aDir( aPath
.getToken( 0, ':', nIndex
) );
157 if( stat( aDir
.getStr(), &aStat
) || ! S_ISDIR( aStat
.st_mode
) )
160 rPathList
.push_back( OStringToOUString( aDir
, aEncoding
) );
161 } while( nIndex
!= -1 );
163 #ifdef SYSTEM_PPD_DIR
164 if( pSubDir
&& rtl_str_compare( pSubDir
, PRINTER_PPDDIR
) == 0 )
166 rPathList
.push_back( OStringToOUString( OString( SYSTEM_PPD_DIR
), RTL_TEXTENCODING_UTF8
) );
170 if( rPathList
.empty() )
172 // last resort: next to program file (mainly for setup)
174 if( osl_getExecutableFile( &aExe
.pData
) == osl_Process_E_None
)
176 INetURLObject
aDir( aExe
);
177 aDir
.removeSegment();
178 aExe
= aDir
.GetMainURL( INetURLObject::NO_DECODE
);
180 if( osl_getSystemPathFromFileURL( aExe
.pData
, &aSysPath
.pData
) == osl_File_E_None
)
182 rPathList
.push_back( aSysPath
);
188 OUString
psp::getFontPath()
190 static OUString aPath
;
194 OUStringBuffer
aPathBuffer( 512 );
196 OUString
aConfigPath( getOfficePath( psp::ConfigPath
) );
197 OUString
aInstallationRootPath( getOfficePath( psp::InstallationRootPath
) );
198 OUString
aUserPath( getOfficePath( psp::UserPath
) );
199 if( !aConfigPath
.isEmpty() )
201 // #i53530# Path from CustomDataUrl will completely
202 // replace net and user paths if the path exists
203 aPathBuffer
.append(aConfigPath
);
204 aPathBuffer
.appendAscii("/" LIBO_SHARE_FOLDER
"/fonts");
205 // check existence of config path
207 if( 0 != stat( OUStringToOString( aPathBuffer
.makeStringAndClear(), osl_getThreadTextEncoding() ).getStr(), &aStat
)
208 || ! S_ISDIR( aStat
.st_mode
) )
212 aPathBuffer
.append(aConfigPath
);
213 aPathBuffer
.appendAscii("/" LIBO_SHARE_FOLDER
"/fonts");
216 if( aConfigPath
.isEmpty() )
218 if( !aInstallationRootPath
.isEmpty() )
220 aPathBuffer
.append( aInstallationRootPath
);
221 aPathBuffer
.appendAscii( "/" LIBO_SHARE_FOLDER
"/fonts/truetype;");
222 aPathBuffer
.append( aInstallationRootPath
);
223 aPathBuffer
.appendAscii( "/" LIBO_SHARE_FOLDER
"/fonts/type1;" );
225 if( !aUserPath
.isEmpty() )
227 aPathBuffer
.append( aUserPath
);
228 aPathBuffer
.appendAscii( "/user/fonts" );
232 aPath
= aPathBuffer
.makeStringAndClear();
233 #if OSL_DEBUG_LEVEL > 1
234 fprintf( stderr
, "initializing font path to \"%s\"\n", OUStringToOString( aPath
, RTL_TEXTENCODING_ISO_8859_1
).getStr() );
240 bool psp::convertPfbToPfa( ::osl::File
& rInFile
, ::osl::File
& rOutFile
)
242 static const unsigned char hexDigits
[] =
244 '0', '1', '2', '3', '4', '5', '6', '7',
245 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
248 bool bSuccess
= true;
250 unsigned char buffer
[256];
252 rInFile
.getSize(nSize
);
254 while( bSuccess
&& ! bEof
)
257 // read leading bytes
258 bEof
= ((0 != rInFile
.read( buffer
, 6, nRead
)) || (nRead
!= 6));
261 unsigned int nType
= buffer
[ 1 ];
262 unsigned int nBytesToRead
= buffer
[2] | buffer
[3] << 8 | buffer
[4] << 16 | buffer
[5] << 24;
263 if( buffer
[0] != 0x80 ) // test for pfb magic number
265 // this might be a pfa font already
266 if( ! rInFile
.read( buffer
+6, 9, nRead
) && nRead
== 9 &&
267 ( ! std::strncmp( reinterpret_cast<char*>(buffer
), "%!FontType1-", 12 ) ||
268 ! std::strncmp( reinterpret_cast<char*>(buffer
), "%!PS-AdobeFont-", 15 ) ) )
270 sal_uInt64 nWrite
= 0;
271 if( rOutFile
.write( buffer
, 15, nWrite
) || nWrite
!= 15 )
274 ! rInFile
.read( buffer
, sizeof( buffer
), nRead
) &&
277 if( rOutFile
.write( buffer
, nRead
, nWrite
) ||
286 else if( nType
== 1 || nType
== 2 )
288 sal_uInt64
nOrgPos(0);
289 rInFile
.getPos(nOrgPos
);
290 nBytesToRead
= std::min
<sal_uInt64
>(nBytesToRead
, nSize
- nOrgPos
);
292 boost::scoped_array
<unsigned char> pBuffer(new unsigned char[nBytesToRead
+1]);
293 pBuffer
[nBytesToRead
] = 0;
295 if( ! rInFile
.read( pBuffer
.get(), nBytesToRead
, nRead
) && nRead
== nBytesToRead
)
299 // ascii data, convert dos lineends( \r\n ) and
300 // m_ac lineends( \r ) to \n
301 boost::scoped_array
<unsigned char> pWriteBuffer(new unsigned char[ nBytesToRead
]);
302 unsigned int nBytesToWrite
= 0;
303 for( unsigned int i
= 0; i
< nBytesToRead
; i
++ )
305 if( pBuffer
[i
] != '\r' )
306 pWriteBuffer
[ nBytesToWrite
++ ] = pBuffer
[i
];
307 else if( pBuffer
[ i
+1 ] == '\n' )
310 pWriteBuffer
[ nBytesToWrite
++ ] = '\n';
313 pWriteBuffer
[ nBytesToWrite
++ ] = '\n';
315 if( rOutFile
.write( pWriteBuffer
.get(), nBytesToWrite
, nRead
) || nRead
!= nBytesToWrite
)
321 unsigned int nBuffer
= 0;
322 for( unsigned int i
= 0; i
< nBytesToRead
&& bSuccess
; i
++ )
324 buffer
[ nBuffer
++ ] = hexDigits
[ pBuffer
[ i
] >> 4 ];
325 buffer
[ nBuffer
++ ] = hexDigits
[ pBuffer
[ i
] & 15 ];
328 buffer
[ nBuffer
++ ] = '\n';
329 if( rOutFile
.write( buffer
, nBuffer
, nRead
) || nRead
!= nBuffer
)
334 if( nBuffer
> 0 && bSuccess
)
336 buffer
[ nBuffer
++ ] = '\n';
337 if( rOutFile
.write( buffer
, nBuffer
, nRead
) || nRead
!= nBuffer
)
345 else if( nType
== 3 )
354 void psp::normPath( OString
& rPath
)
358 // double slashes and slash at end are probably
359 // removed by realpath anyway, but since this runs
360 // on many different platforms let's play it safe
361 OString aPath
= rPath
.replaceAll("//", "/");
363 if( aPath
.endsWith("/") )
364 aPath
= aPath
.copy(0, aPath
.getLength()-1);
366 if( ( aPath
.indexOf("./") != -1 ||
367 aPath
.indexOf( '~' ) != -1 )
368 && realpath( aPath
.getStr(), buf
) )
378 void psp::splitPath( OString
& rPath
, OString
& rDir
, OString
& rBase
)
381 sal_Int32 nIndex
= rPath
.lastIndexOf( '/' );
383 rDir
= rPath
.copy( 0, nIndex
);
384 else if( nIndex
== 0 ) // root dir
385 rDir
= rPath
.copy( 0, 1 );
386 if( rPath
.getLength() > nIndex
+1 )
387 rBase
= rPath
.copy( nIndex
+1 );
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */