xref: /AOO41X/main/sal/osl/unx/file_path_helper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sal.hxx"
30 
31  /*******************************************
32  	Includes
33   ******************************************/
34 
35  #ifndef _OSL_FILE_PATH_HELPER_H_
36  #include "file_path_helper.h"
37  #endif
38 
39  #ifndef _OSL_FILE_PATH_HELPER_HXX_
40  #include "file_path_helper.hxx"
41  #endif
42 
43  #ifndef _OSL_UUNXAPI_HXX_
44  #include "uunxapi.hxx"
45  #endif
46 
47  #ifndef _OSL_DIAGNOSE_H_
48  #include <osl/diagnose.h>
49  #endif
50 
51  #ifndef _RTL_USTRING_HXX_
52  #include <rtl/ustring.hxx>
53  #endif
54 
55  /*******************************************
56  	Constants
57   ******************************************/
58 
59   const sal_Unicode FPH_CHAR_PATH_SEPARATOR = (sal_Unicode)'/';
60   const sal_Unicode FPH_CHAR_DOT            = (sal_Unicode)'.';
61   const sal_Unicode FPH_CHAR_COLON          = (sal_Unicode)':';
62 
63   inline const rtl::OUString FPH_PATH_SEPARATOR()
64       { return rtl::OUString::createFromAscii("/"); }
65   inline const rtl::OUString FPH_LOCAL_DIR_ENTRY()
66       { return rtl::OUString::createFromAscii("."); }
67   inline const rtl::OUString FPH_PARENT_DIR_ENTRY()
68       { return rtl::OUString::createFromAscii(".."); }
69 
70  /*******************************************
71   *  osl_systemPathRemoveSeparator
72   ******************************************/
73 
74  void SAL_CALL osl_systemPathRemoveSeparator(rtl_uString* pustrPath)
75  {
76  	OSL_PRECOND(0 != pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
77     if (0 != pustrPath)
78     {
79         // maybe there are more than one separator at end
80         // so we run in a loop
81         while ((pustrPath->length > 1) && (FPH_CHAR_PATH_SEPARATOR == pustrPath->buffer[pustrPath->length - 1]))
82         {
83             pustrPath->length--;
84             pustrPath->buffer[pustrPath->length] = (sal_Unicode)'\0';
85         }
86 
87         OSL_POSTCOND((0 == pustrPath->length) || (1 == pustrPath->length) || \
88                      (pustrPath->length > 1 && pustrPath->buffer[pustrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR), \
89                      "osl_systemPathRemoveSeparator: Post condition failed");
90     }
91  }
92 
93  /*******************************************
94     osl_systemPathEnsureSeparator
95   ******************************************/
96 
97  void SAL_CALL osl_systemPathEnsureSeparator(rtl_uString** ppustrPath)
98  {
99      OSL_PRECOND((0 != ppustrPath) && (0 != *ppustrPath), "osl_systemPathEnsureSeparator: Invalid parameter");
100      if ((0 != ppustrPath) && (0 != *ppustrPath))
101      {
102          rtl::OUString path(*ppustrPath);
103          sal_Int32	  lp = path.getLength();
104          sal_Int32    i  = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
105 
106          if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
107          {
108              path += FPH_PATH_SEPARATOR();
109              rtl_uString_assign(ppustrPath, path.pData);
110          }
111 
112          OSL_POSTCOND(path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR) == (path.getLength() - 1), \
113                       "osl_systemPathEnsureSeparator: Post condition failed");
114      }
115  }
116 
117  /*******************************************
118   *  osl_systemPathIsRelativePath
119   ******************************************/
120 
121  sal_Bool SAL_CALL osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
122  {
123      OSL_PRECOND(0 != pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
124      return ((0 == pustrPath) || (0 == pustrPath->length) || (pustrPath->buffer[0] != FPH_CHAR_PATH_SEPARATOR));
125  }
126 
127  /******************************************
128     osl_systemPathMakeAbsolutePath
129   *****************************************/
130 
131  void SAL_CALL osl_systemPathMakeAbsolutePath(
132  	const rtl_uString* pustrBasePath,
133 	const rtl_uString* pustrRelPath,
134 	rtl_uString** 	   ppustrAbsolutePath)
135 {
136 	rtl::OUString base(rtl_uString_getStr(const_cast<rtl_uString*>(pustrBasePath)));
137 	rtl::OUString rel(const_cast<rtl_uString*>(pustrRelPath));
138 
139 	if (base.getLength() > 0)
140 		osl_systemPathEnsureSeparator(&base.pData);
141 
142 	base += rel;
143 
144 	rtl_uString_acquire(base.pData);
145 	*ppustrAbsolutePath = base.pData;
146 }
147 
148 
149  /*******************************************
150  	osl_systemPathGetFileOrLastDirectoryPart
151   ******************************************/
152 
153  void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
154  	const rtl_uString* 	pustrPath,
155 	rtl_uString** 		ppustrFileNameOrLastDirPart)
156 {
157 	OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, \
158 			    "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
159 
160 	rtl::OUString path(const_cast<rtl_uString*>(pustrPath));
161 
162 	osl_systemPathRemoveSeparator(path.pData);
163 
164 	rtl::OUString last_part;
165 
166 	if (path.getLength() > 1 || (1 == path.getLength() && *path.getStr() != FPH_CHAR_PATH_SEPARATOR))
167 	{
168 		sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
169 		idx_ps++; // always right to increment by one even if idx_ps == -1!
170 		last_part = rtl::OUString(path.getStr() + idx_ps);
171 	}
172 	rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData);
173 }
174 
175 
176  /********************************************
177  	osl_systemPathIsHiddenFileOrDirectoryEntry
178  *********************************************/
179 
180  sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
181  	const rtl_uString* pustrPath)
182 {
183 	OSL_PRECOND(0 != pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
184     if ((0 == pustrPath) || (0 == pustrPath->length))
185         return sal_False;
186 
187     rtl::OUString fdp;
188     osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData);
189 
190     return ((fdp.pData->length > 0) &&
191             (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
192             !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
193 }
194 
195 
196  /************************************************
197  	osl_systemPathIsLocalOrParentDirectoryEntry
198  ************************************************/
199 
200 sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
201 	const rtl_uString* pustrPath)
202 {
203 	OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
204 
205 	rtl::OUString dirent;
206 
207 	osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData);
208 
209 	return (
210 	        (dirent == FPH_LOCAL_DIR_ENTRY()) ||
211 	        (dirent == FPH_PARENT_DIR_ENTRY())
212 	       );
213 }
214 
215 /***********************************************
216  Simple iterator for a path list separated by
217  the specified character
218  **********************************************/
219 
220 class path_list_iterator
221 {
222 public:
223 
224 	/******************************************
225  	 constructor
226 
227 	 after construction get_current_item
228 	 returns the first path in list, no need
229 	 to call reset first
230 	 *****************************************/
231 	path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
232 		m_path_list(path_list),
233 		m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
234 		m_separator(list_separator)
235 	{
236 		reset();
237 	}
238 
239 	/******************************************
240 	 reset the iterator
241 	 *****************************************/
242 	void reset()
243 	{
244 		m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
245 		advance();
246 	}
247 
248 	/******************************************
249 	 move the iterator to the next position
250 	 *****************************************/
251 	void next()
252 	{
253 		OSL_PRECOND(!done(), "path_list_iterator: Already done!");
254 
255 		m_path_segment_begin = ++m_path_segment_end;
256 		advance();
257 	}
258 
259 	/******************************************
260 	 check if done
261 	 *****************************************/
262 	bool done() const
263 	{
264 		return (m_path_segment_end >= m_end);
265 	}
266 
267 	/******************************************
268 	 return the current item
269 	 *****************************************/
270 	rtl::OUString get_current_item() const
271 	{
272 		return rtl::OUString(
273 			m_path_segment_begin,
274 			(m_path_segment_end - m_path_segment_begin));
275 	}
276 
277 private:
278 
279 	/******************************************
280 	 move m_path_end to the next separator or
281 	 to the edn of the string
282 	 *****************************************/
283 	void advance()
284 	{
285 		while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
286 			++m_path_segment_end;
287 
288 		OSL_ASSERT(m_path_segment_end <= m_end);
289 	}
290 
291 private:
292 	rtl::OUString 		m_path_list;
293 	const sal_Unicode*  m_end;
294 	const sal_Unicode 	m_separator;
295 	const sal_Unicode*  m_path_segment_begin;
296 	const sal_Unicode*  m_path_segment_end;
297 
298 // prevent copy and assignment
299 private:
300 	/******************************************
301 	 copy constructor
302 	 remember: do not simply copy m_path_begin
303 	 and m_path_end because they point to
304 	 the memory of other.m_path_list!
305 	 *****************************************/
306 	path_list_iterator(const path_list_iterator& other);
307 
308 	/******************************************
309 	 assignment operator
310  	 remember: do not simply copy m_path_begin
311 	 and m_path_end because they point to
312 	 the memory of other.m_path_list!
313 	 *****************************************/
314 	path_list_iterator& operator=(const path_list_iterator& other);
315 };
316 
317  /************************************************
318   	osl_searchPath
319   ***********************************************/
320 
321 sal_Bool SAL_CALL osl_searchPath(
322  	const rtl_uString* pustrFilePath,
323 	const rtl_uString* pustrSearchPathList,
324 	rtl_uString**      ppustrPathFound)
325 {
326 	OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
327 
328 	bool               bfound = false;
329 	rtl::OUString      fp(const_cast<rtl_uString*>(pustrFilePath));
330 	rtl::OUString      pl = rtl::OUString(const_cast<rtl_uString*>(pustrSearchPathList));
331 	path_list_iterator pli(pl);
332 
333 	while (!pli.done())
334 	{
335 		rtl::OUString p = pli.get_current_item();
336 		osl::systemPathEnsureSeparator(p);
337 		p += fp;
338 
339 		if (osl::access(p, F_OK) > -1)
340 		{
341 			bfound = true;
342 			rtl_uString_assign(ppustrPathFound, p.pData);
343 			break;
344 		}
345 		pli.next();
346 	}
347 	return bfound;
348 }
349