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