Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <config_folders.h>
21 :
22 : #include <cstring>
23 : #include <sys/stat.h>
24 : #include <unistd.h>
25 : #include <limits.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>
35 :
36 : using ::rtl::Bootstrap;
37 :
38 : namespace psp {
39 :
40 1688 : OUString getOfficePath( enum whichOfficePath ePath )
41 : {
42 1688 : static OUString aInstallationRootPath;
43 1688 : static OUString aUserPath;
44 1688 : static OUString aConfigPath;
45 1688 : static OUString aEmpty;
46 : static bool bOnce = false;
47 :
48 1688 : if( ! bOnce )
49 : {
50 306 : bOnce = true;
51 306 : OUString aIni;
52 306 : Bootstrap::get( "BRAND_BASE_DIR", aInstallationRootPath );
53 306 : aIni = aInstallationRootPath + "/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( "bootstrap" );
54 612 : Bootstrap aBootstrap( aIni );
55 306 : aBootstrap.getFrom( "CustomDataUrl", aConfigPath );
56 306 : aBootstrap.getFrom( "UserInstallation", aUserPath );
57 612 : OUString aUPath = aUserPath;
58 :
59 306 : if( aConfigPath.startsWith( "file://" ) )
60 : {
61 0 : OUString aSysPath;
62 0 : if( osl_getSystemPathFromFileURL( aConfigPath.pData, &aSysPath.pData ) == osl_File_E_None )
63 0 : aConfigPath = aSysPath;
64 : }
65 306 : if( aInstallationRootPath.startsWith( "file://" ) )
66 : {
67 306 : OUString aSysPath;
68 306 : if( osl_getSystemPathFromFileURL( aInstallationRootPath.pData, &aSysPath.pData ) == osl_File_E_None )
69 306 : aInstallationRootPath = aSysPath;
70 : }
71 306 : if( aUserPath.startsWith( "file://" ) )
72 : {
73 306 : OUString aSysPath;
74 306 : if( osl_getSystemPathFromFileURL( aUserPath.pData, &aSysPath.pData ) == osl_File_E_None )
75 306 : aUserPath = aSysPath;
76 : }
77 : // ensure user path exists
78 306 : aUPath += "/user/psprint";
79 : #if OSL_DEBUG_LEVEL > 1
80 : oslFileError eErr =
81 : #endif
82 612 : 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 );
85 : #endif
86 : }
87 :
88 1688 : switch( ePath )
89 : {
90 306 : case ConfigPath: return aConfigPath;
91 538 : case InstallationRootPath: return aInstallationRootPath;
92 844 : case UserPath: return aUserPath;
93 : }
94 0 : return aEmpty;
95 : }
96 :
97 232 : static OString getEnvironmentPath( const char* pKey )
98 : {
99 232 : OString aPath;
100 :
101 232 : const char* pValue = getenv( pKey );
102 232 : if( pValue && *pValue )
103 : {
104 0 : aPath = OString( pValue );
105 : }
106 232 : return aPath;
107 : }
108 :
109 : } // namespace psp
110 :
111 232 : void psp::getPrinterPathList( std::list< OUString >& rPathList, const char* pSubDir )
112 : {
113 232 : rPathList.clear();
114 232 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
115 :
116 232 : OUStringBuffer aPathBuffer( 256 );
117 :
118 : // append net path
119 232 : aPathBuffer.append( getOfficePath( psp::InstallationRootPath ) );
120 232 : if( !aPathBuffer.isEmpty() )
121 : {
122 232 : aPathBuffer.appendAscii( "/" LIBO_SHARE_FOLDER "/psprint" );
123 232 : if( pSubDir )
124 : {
125 116 : aPathBuffer.append( '/' );
126 116 : aPathBuffer.appendAscii( pSubDir );
127 : }
128 232 : rPathList.push_back( aPathBuffer.makeStringAndClear() );
129 : }
130 : // append user path
131 232 : aPathBuffer.append( getOfficePath( psp::UserPath ) );
132 232 : if( !aPathBuffer.isEmpty() )
133 : {
134 232 : aPathBuffer.appendAscii( "/user/psprint" );
135 232 : if( pSubDir )
136 : {
137 116 : aPathBuffer.append( '/' );
138 116 : aPathBuffer.appendAscii( pSubDir );
139 : }
140 232 : rPathList.push_back( aPathBuffer.makeStringAndClear() );
141 : }
142 :
143 464 : OString aPath( getEnvironmentPath("SAL_PSPRINT") );
144 232 : sal_Int32 nIndex = 0;
145 232 : do
146 : {
147 232 : OString aDir( aPath.getToken( 0, ':', nIndex ) );
148 232 : if( aDir.isEmpty() )
149 232 : continue;
150 :
151 0 : if( pSubDir )
152 : {
153 0 : aDir += "/";
154 0 : aDir += pSubDir;
155 : }
156 : struct stat aStat;
157 0 : if( stat( aDir.getStr(), &aStat ) || ! S_ISDIR( aStat.st_mode ) )
158 0 : continue;
159 :
160 0 : rPathList.push_back( OStringToOUString( aDir, aEncoding ) );
161 232 : } while( nIndex != -1 );
162 :
163 : #ifdef SYSTEM_PPD_DIR
164 : if( pSubDir && rtl_str_compare( pSubDir, PRINTER_PPDDIR ) == 0 )
165 : {
166 : rPathList.push_back( OStringToOUString( OString( SYSTEM_PPD_DIR ), RTL_TEXTENCODING_UTF8 ) );
167 : }
168 : #endif
169 :
170 232 : if( rPathList.empty() )
171 : {
172 : // last resort: next to program file (mainly for setup)
173 0 : OUString aExe;
174 0 : if( osl_getExecutableFile( &aExe.pData ) == osl_Process_E_None )
175 : {
176 0 : INetURLObject aDir( aExe );
177 0 : aDir.removeSegment();
178 0 : aExe = aDir.GetMainURL( INetURLObject::NO_DECODE );
179 0 : OUString aSysPath;
180 0 : if( osl_getSystemPathFromFileURL( aExe.pData, &aSysPath.pData ) == osl_File_E_None )
181 : {
182 0 : rPathList.push_back( aSysPath );
183 0 : }
184 0 : }
185 232 : }
186 232 : }
187 :
188 306 : OUString psp::getFontPath()
189 : {
190 306 : static OUString aPath;
191 :
192 306 : if (aPath.isEmpty())
193 : {
194 306 : OUStringBuffer aPathBuffer( 512 );
195 :
196 612 : OUString aConfigPath( getOfficePath( psp::ConfigPath ) );
197 612 : OUString aInstallationRootPath( getOfficePath( psp::InstallationRootPath ) );
198 612 : OUString aUserPath( getOfficePath( psp::UserPath ) );
199 306 : if( !aConfigPath.isEmpty() )
200 : {
201 : // #i53530# Path from CustomDataUrl will completely
202 : // replace net and user paths if the path exists
203 0 : aPathBuffer.append(aConfigPath);
204 0 : aPathBuffer.appendAscii("/" LIBO_SHARE_FOLDER "/fonts");
205 : // check existence of config path
206 : struct stat aStat;
207 0 : if( 0 != stat( OUStringToOString( aPathBuffer.makeStringAndClear(), osl_getThreadTextEncoding() ).getStr(), &aStat )
208 0 : || ! S_ISDIR( aStat.st_mode ) )
209 0 : aConfigPath = OUString();
210 : else
211 : {
212 0 : aPathBuffer.append(aConfigPath);
213 0 : aPathBuffer.appendAscii("/" LIBO_SHARE_FOLDER "/fonts");
214 : }
215 : }
216 306 : if( aConfigPath.isEmpty() )
217 : {
218 306 : if( !aInstallationRootPath.isEmpty() )
219 : {
220 306 : aPathBuffer.append( aInstallationRootPath );
221 306 : aPathBuffer.appendAscii( "/" LIBO_SHARE_FOLDER "/fonts/truetype;");
222 306 : aPathBuffer.append( aInstallationRootPath );
223 306 : aPathBuffer.appendAscii( "/" LIBO_SHARE_FOLDER "/fonts/type1;" );
224 : }
225 306 : if( !aUserPath.isEmpty() )
226 : {
227 306 : aPathBuffer.append( aUserPath );
228 306 : aPathBuffer.appendAscii( "/user/fonts" );
229 : }
230 : }
231 :
232 612 : 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() );
235 : #endif
236 : }
237 306 : return aPath;
238 : }
239 :
240 0 : bool psp::convertPfbToPfa( ::osl::File& rInFile, ::osl::File& rOutFile )
241 : {
242 : static const unsigned char hexDigits[] =
243 : {
244 : '0', '1', '2', '3', '4', '5', '6', '7',
245 : '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
246 : };
247 :
248 0 : bool bSuccess = true;
249 0 : bool bEof = false;
250 : unsigned char buffer[256];
251 0 : sal_uInt64 nSize(0);
252 0 : rInFile.getSize(nSize);
253 :
254 0 : while( bSuccess && ! bEof )
255 : {
256 : sal_uInt64 nRead;
257 : // read leading bytes
258 0 : bEof = ((0 != rInFile.read( buffer, 6, nRead)) || (nRead != 6));
259 0 : if( bEof )
260 0 : break;
261 0 : unsigned int nType = buffer[ 1 ];
262 0 : unsigned int nBytesToRead = buffer[2] | buffer[3] << 8 | buffer[4] << 16 | buffer[5] << 24;
263 0 : if( buffer[0] != 0x80 ) // test for pfb magic number
264 : {
265 : // this might be a pfa font already
266 0 : if( ! rInFile.read( buffer+6, 9, nRead ) && nRead == 9 &&
267 0 : ( ! std::strncmp( (char*)buffer, "%!FontType1-", 12 ) ||
268 0 : ! std::strncmp( (char*)buffer, "%!PS-AdobeFont-", 15 ) ) )
269 : {
270 0 : sal_uInt64 nWrite = 0;
271 0 : if( rOutFile.write( buffer, 15, nWrite ) || nWrite != 15 )
272 0 : bSuccess = false;
273 0 : while( bSuccess &&
274 0 : ! rInFile.read( buffer, sizeof( buffer ), nRead ) &&
275 0 : nRead != 0 )
276 : {
277 0 : if( rOutFile.write( buffer, nRead, nWrite ) ||
278 0 : nWrite != nRead )
279 0 : bSuccess = false;
280 : }
281 0 : bEof = true;
282 : }
283 : else
284 0 : bSuccess = false;
285 : }
286 0 : else if( nType == 1 || nType == 2 )
287 : {
288 0 : sal_uInt64 nOrgPos(0);
289 0 : rInFile.getPos(nOrgPos);
290 0 : nBytesToRead = std::min<sal_uInt64>(nBytesToRead, nSize - nOrgPos);
291 :
292 0 : boost::scoped_array<unsigned char> pBuffer(new unsigned char[nBytesToRead+1]);
293 0 : pBuffer[nBytesToRead] = 0;
294 :
295 0 : if( ! rInFile.read( pBuffer.get(), nBytesToRead, nRead ) && nRead == nBytesToRead )
296 : {
297 0 : if( nType == 1 )
298 : {
299 : // ascii data, convert dos lineends( \r\n ) and
300 : // m_ac lineends( \r ) to \n
301 0 : boost::scoped_array<unsigned char> pWriteBuffer(new unsigned char[ nBytesToRead ]);
302 0 : unsigned int nBytesToWrite = 0;
303 0 : for( unsigned int i = 0; i < nBytesToRead; i++ )
304 : {
305 0 : if( pBuffer[i] != '\r' )
306 0 : pWriteBuffer[ nBytesToWrite++ ] = pBuffer[i];
307 0 : else if( pBuffer[ i+1 ] == '\n' )
308 : {
309 0 : i++;
310 0 : pWriteBuffer[ nBytesToWrite++ ] = '\n';
311 : }
312 : else
313 0 : pWriteBuffer[ nBytesToWrite++ ] = '\n';
314 : }
315 0 : if( rOutFile.write( pWriteBuffer.get(), nBytesToWrite, nRead ) || nRead != nBytesToWrite )
316 0 : bSuccess = false;
317 : }
318 : else
319 : {
320 : // binary data
321 0 : unsigned int nBuffer = 0;
322 0 : for( unsigned int i = 0; i < nBytesToRead && bSuccess; i++ )
323 : {
324 0 : buffer[ nBuffer++ ] = hexDigits[ pBuffer[ i ] >> 4 ];
325 0 : buffer[ nBuffer++ ] = hexDigits[ pBuffer[ i ] & 15 ];
326 0 : if( nBuffer >= 80 )
327 : {
328 0 : buffer[ nBuffer++ ] = '\n';
329 0 : if( rOutFile.write( buffer, nBuffer, nRead ) || nRead != nBuffer )
330 0 : bSuccess = false;
331 0 : nBuffer = 0;
332 : }
333 : }
334 0 : if( nBuffer > 0 && bSuccess )
335 : {
336 0 : buffer[ nBuffer++ ] = '\n';
337 0 : if( rOutFile.write( buffer, nBuffer, nRead ) || nRead != nBuffer )
338 0 : bSuccess = false;
339 : }
340 : }
341 : }
342 : else
343 0 : bSuccess = false;
344 : }
345 0 : else if( nType == 3 )
346 0 : bEof = true;
347 : else
348 0 : bSuccess = false;
349 : }
350 :
351 0 : return bSuccess;
352 : }
353 :
354 59690 : void psp::normPath( OString& rPath )
355 : {
356 : char buf[PATH_MAX];
357 :
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 59690 : OString aPath = rPath.replaceAll("//", "/");
362 :
363 59690 : if( aPath.endsWith("/") )
364 0 : aPath = aPath.copy(0, aPath.getLength()-1);
365 :
366 178742 : if( ( aPath.indexOf("./") != -1 ||
367 59362 : aPath.indexOf( '~' ) != -1 )
368 60018 : && realpath( aPath.getStr(), buf ) )
369 : {
370 164 : rPath = buf;
371 : }
372 : else
373 : {
374 59526 : rPath = aPath;
375 59690 : }
376 59690 : }
377 :
378 58772 : void psp::splitPath( OString& rPath, OString& rDir, OString& rBase )
379 : {
380 58772 : normPath( rPath );
381 58772 : sal_Int32 nIndex = rPath.lastIndexOf( '/' );
382 58772 : if( nIndex > 0 )
383 58772 : rDir = rPath.copy( 0, nIndex );
384 0 : else if( nIndex == 0 ) // root dir
385 0 : rDir = rPath.copy( 0, 1 );
386 58772 : if( rPath.getLength() > nIndex+1 )
387 58772 : rBase = rPath.copy( nIndex+1 );
388 58772 : }
389 :
390 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|