xref: /trunk/main/sal/osl/os2/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  /*******************************************
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