xref: /aoo41x/main/sal/osl/os2/file_path_helper.cxx (revision cdf0e10c)
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  /*******************************************
29  	Includes
30   ******************************************/
31 
32  #ifndef _OSL_THREAD_H_
33  #include "osl/thread.h"
34  #endif
35 
36  #ifndef _OSL_FILE_PATH_HELPER_H_
37  #include "file_path_helper.h"
38  #endif
39 
40  #ifndef _OSL_FILE_PATH_HELPER_HXX_
41  #include "file_path_helper.hxx"
42  #endif
43 
44  #ifndef _OSL_UUNXAPI_HXX_
45  #include "uunxapi.hxx"
46  #endif
47 
48  #ifndef _OSL_DIAGNOSE_H_
49  #include <osl/diagnose.h>
50  #endif
51 
52  #ifndef _RTL_USTRING_HXX_
53  #include <rtl/ustring.hxx>
54  #endif
55 
56  /*******************************************
57  	Constants
58   ******************************************/
59 
60   const sal_Unicode FPH_CHAR_PATH_SEPARATOR = (sal_Unicode)'\\';
61   const sal_Unicode FPH_CHAR_DOT            = (sal_Unicode)'.';
62   const sal_Unicode FPH_CHAR_COLON          = (sal_Unicode)':';
63 
64   inline const rtl::OUString FPH_PATH_SEPARATOR()
65       { return rtl::OUString::createFromAscii("\\"); }
66   inline const rtl::OUString FPH_LOCAL_DIR_ENTRY()
67       { return rtl::OUString::createFromAscii("."); }
68   inline const rtl::OUString FPH_PARENT_DIR_ENTRY()
69       { return rtl::OUString::createFromAscii(".."); }
70 
71  /*******************************************
72   *  osl_systemPathRemoveSeparator
73   ******************************************/
74 
75  void SAL_CALL osl_systemPathRemoveSeparator(rtl_uString* pustrPath)
76  {
77  	OSL_PRECOND(pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
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     osl_systemPathEnsureSeparator
94   ******************************************/
95 
96  void SAL_CALL osl_systemPathEnsureSeparator(rtl_uString** ppustrPath)
97  {
98  	OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \
99 				"osl_systemPathEnsureSeparator: Invalid parameter");
100 
101  	rtl::OUString path(*ppustrPath);
102 	sal_Int32	  lp = path.getLength();
103 	sal_Int32     i  = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
104 
105 	if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
106 	{
107 		path += FPH_PATH_SEPARATOR();
108 		rtl_uString_assign(ppustrPath, path.pData);
109 	}
110 
111 	OSL_POSTCOND(path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR) == (path.getLength() - 1), \
112 				 "osl_systemPathEnsureSeparator: Post condition failed");
113  }
114 
115  /*******************************************
116   *  osl_systemPathIsRelativePath
117   ******************************************/
118 
119  sal_Bool SAL_CALL osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
120  {
121  	OSL_PRECOND(pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
122  	return (!osl_systemPathIsAbsolutePath(pustrPath));
123  }
124 
125  /******************************************
126   *  osl_systemPathIsAbsolutePath
127   *****************************************/
128 
129  sal_Bool SAL_CALL osl_systemPathIsAbsolutePath(const rtl_uString* pustrPath)
130  {
131  	OSL_PRECOND(pustrPath, "osl_systemPathIsAbsolutePath: Invalid parameter");
132 	if (pustrPath->length == 0)
133 		return sal_False;
134 	if (pustrPath->buffer[0] == FPH_CHAR_PATH_SEPARATOR)
135 		return sal_True;
136 	if (pustrPath->buffer[1] == FPH_CHAR_COLON
137 		    && pustrPath->buffer[2] == FPH_CHAR_PATH_SEPARATOR)
138 		return sal_True;
139 	return sal_False;
140  }
141 
142  /******************************************
143     osl_systemPathMakeAbsolutePath
144   *****************************************/
145 
146  void SAL_CALL osl_systemPathMakeAbsolutePath(
147  	const rtl_uString* pustrBasePath,
148 	const rtl_uString* pustrRelPath,
149 	rtl_uString** 	   ppustrAbsolutePath)
150 {
151 	rtl::OUString base(rtl_uString_getStr(const_cast<rtl_uString*>(pustrBasePath)));
152 	rtl::OUString rel(const_cast<rtl_uString*>(pustrRelPath));
153 
154 	if (base.getLength() > 0)
155 		osl_systemPathEnsureSeparator(&base.pData);
156 
157 	base += rel;
158 
159 	rtl_uString_acquire(base.pData);
160 	*ppustrAbsolutePath = base.pData;
161 }
162 
163 
164  /*****************************************
165 	osl_systemPathGetParent
166   ****************************************/
167 
168  sal_Int32 SAL_CALL osl_systemPathGetParent(rtl_uString* pustrPath)
169  {
170  	return 0;
171  }
172 
173  /*******************************************
174  	osl_systemPathGetFileOrLastDirectoryPart
175   ******************************************/
176 
177  void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
178  	const rtl_uString* 	pustrPath,
179 	rtl_uString** 		ppustrFileNameOrLastDirPart)
180 {
181 	OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, \
182 			    "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
183 
184 	rtl::OUString path(const_cast<rtl_uString*>(pustrPath));
185 
186 	osl_systemPathRemoveSeparator(path.pData);
187 
188 	rtl::OUString last_part;
189 
190 	if (path.getLength() > 1 || (1 == path.getLength() && *path.getStr() != FPH_CHAR_PATH_SEPARATOR))
191 	{
192 		sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
193 		idx_ps++; // always right to increment by one even if idx_ps == -1!
194 		last_part = rtl::OUString(path.getStr() + idx_ps);
195 	}
196 	rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData);
197 }
198 
199 
200  /********************************************
201  	osl_systemPathIsHiddenFileOrDirectoryEntry
202  *********************************************/
203 
204  sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
205  	const rtl_uString* pustrPath)
206 {
207 	OSL_PRECOND(pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
208 
209 	sal_Bool is_hidden = sal_False;
210 
211 	if (pustrPath->length > 0)
212 	{
213 		rtl::OUString fdp;
214 
215 		osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData);
216 
217 		is_hidden = ((fdp.pData->length > 0) && (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
218 					 !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
219  	}
220 
221 	return is_hidden;
222 }
223 
224 
225  /************************************************
226  	osl_systemPathIsLocalOrParentDirectoryEntry
227  ************************************************/
228 
229 sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
230 	const rtl_uString* pustrPath)
231 {
232 	OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
233 
234 	rtl::OUString dirent;
235 
236 	osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData);
237 
238 	return (
239 	        (dirent == FPH_LOCAL_DIR_ENTRY()) ||
240 	        (dirent == FPH_PARENT_DIR_ENTRY())
241 	       );
242 }
243 
244 /***********************************************
245  Simple iterator for a path list separated by
246  the specified character
247  **********************************************/
248 
249 class path_list_iterator
250 {
251 public:
252 
253 	/******************************************
254  	 constructor
255 
256 	 after construction get_current_item
257 	 returns the first path in list, no need
258 	 to call reset first
259 	 *****************************************/
260 	path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
261 		m_path_list(path_list),
262 		m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
263 		m_separator(list_separator)
264 	{
265 		reset();
266 	}
267 
268 	/******************************************
269 	 reset the iterator
270 	 *****************************************/
271 	void reset()
272 	{
273 		m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
274 		advance();
275 	}
276 
277 	/******************************************
278 	 move the iterator to the next position
279 	 *****************************************/
280 	void next()
281 	{
282 		OSL_PRECOND(!done(), "path_list_iterator: Already done!");
283 
284 		m_path_segment_begin = ++m_path_segment_end;
285 		advance();
286 	}
287 
288 	/******************************************
289 	 check if done
290 	 *****************************************/
291 	bool done() const
292 	{
293 		return (m_path_segment_end >= m_end);
294 	}
295 
296 	/******************************************
297 	 return the current item
298 	 *****************************************/
299 	rtl::OUString get_current_item() const
300 	{
301 		return rtl::OUString(
302 			m_path_segment_begin,
303 			(m_path_segment_end - m_path_segment_begin));
304 	}
305 
306 private:
307 
308 	/******************************************
309 	 move m_path_end to the next separator or
310 	 to the edn of the string
311 	 *****************************************/
312 	void advance()
313 	{
314 		while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
315 			++m_path_segment_end;
316 
317 		OSL_ASSERT(m_path_segment_end <= m_end);
318 	}
319 
320 private:
321 	rtl::OUString 		m_path_list;
322 	const sal_Unicode*  m_end;
323 	const sal_Unicode 	m_separator;
324 	const sal_Unicode*  m_path_segment_begin;
325 	const sal_Unicode*  m_path_segment_end;
326 
327 // prevent copy and assignment
328 private:
329 	/******************************************
330 	 copy constructor
331 	 remember: do not simply copy m_path_begin
332 	 and m_path_end because they point to
333 	 the memory of other.m_path_list!
334 	 *****************************************/
335 	path_list_iterator(const path_list_iterator& other);
336 
337 	/******************************************
338 	 assignment operator
339  	 remember: do not simply copy m_path_begin
340 	 and m_path_end because they point to
341 	 the memory of other.m_path_list!
342 	 *****************************************/
343 	path_list_iterator& operator=(const path_list_iterator& other);
344 };
345 
346  /************************************************
347   	osl_searchPath
348   ***********************************************/
349 
350 sal_Bool SAL_CALL osl_searchPath(
351  	const rtl_uString* pustrFilePath,
352 	const rtl_uString* pustrSearchPathList,
353 	rtl_uString**      ppustrPathFound)
354 {
355 	OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
356 
357 	bool               bfound = false;
358 	rtl::OUString      fp(const_cast<rtl_uString*>(pustrFilePath));
359 	rtl::OUString      pl = rtl::OUString(const_cast<rtl_uString*>(pustrSearchPathList));
360 	path_list_iterator pli(pl);
361 
362 	while (!pli.done())
363 	{
364 		rtl::OUString p = pli.get_current_item();
365 		osl::systemPathEnsureSeparator(p);
366 		p += fp;
367 
368 		if (osl::access(p, F_OK) > -1)
369 		{
370 			bfound = true;
371 			rtl_uString_assign(ppustrPathFound, p.pData);
372 			break;
373 		}
374 		pli.next();
375 	}
376 	return bfound;
377 }
378