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 "file_path_helper.hxx"
21 : #include "uunxapi.hxx"
22 :
23 : #include <boost/noncopyable.hpp>
24 : #include <osl/diagnose.h>
25 : #include <rtl/ustring.hxx>
26 : #include <sal/log.hxx>
27 :
28 : const sal_Unicode FPH_CHAR_PATH_SEPARATOR = (sal_Unicode)'/';
29 : const sal_Unicode FPH_CHAR_DOT = (sal_Unicode)'.';
30 : const sal_Unicode FPH_CHAR_COLON = (sal_Unicode)':';
31 :
32 107566 : inline const rtl::OUString FPH_PATH_SEPARATOR()
33 107566 : { return rtl::OUString(FPH_CHAR_PATH_SEPARATOR); }
34 :
35 294 : inline const rtl::OUString FPH_LOCAL_DIR_ENTRY()
36 294 : { return rtl::OUString(FPH_CHAR_DOT); }
37 :
38 294 : inline const rtl::OUString FPH_PARENT_DIR_ENTRY()
39 294 : { return rtl::OUString(".."); }
40 :
41 679533 : void SAL_CALL osl_systemPathRemoveSeparator(rtl_uString* pustrPath)
42 : {
43 : OSL_PRECOND(0 != pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
44 679533 : if (0 != pustrPath)
45 : {
46 : // maybe there are more than one separator at end
47 : // so we run in a loop
48 1361478 : while ((pustrPath->length > 1) && (FPH_CHAR_PATH_SEPARATOR == pustrPath->buffer[pustrPath->length - 1]))
49 : {
50 2412 : pustrPath->length--;
51 2412 : pustrPath->buffer[pustrPath->length] = (sal_Unicode)'\0';
52 : }
53 :
54 : SAL_WARN_IF( !((0 == pustrPath->length) || (1 == pustrPath->length) ||
55 : (pustrPath->length > 1 && pustrPath->buffer[pustrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR)),
56 : "sal.osl",
57 : "osl_systemPathRemoveSeparator: Post condition failed");
58 : }
59 679533 : }
60 :
61 107819 : void SAL_CALL osl_systemPathEnsureSeparator(rtl_uString** ppustrPath)
62 : {
63 : OSL_PRECOND((0 != ppustrPath) && (0 != *ppustrPath), "osl_systemPathEnsureSeparator: Invalid parameter");
64 107819 : if ((0 != ppustrPath) && (0 != *ppustrPath))
65 : {
66 107819 : rtl::OUString path(*ppustrPath);
67 107819 : sal_Int32 lp = path.getLength();
68 107819 : sal_Int32 i = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
69 :
70 107819 : if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
71 : {
72 107566 : path += FPH_PATH_SEPARATOR();
73 107566 : rtl_uString_assign(ppustrPath, path.pData);
74 : }
75 :
76 : SAL_WARN_IF( !path.endsWith(FPH_PATH_SEPARATOR()),
77 : "sal.osl",
78 107819 : "osl_systemPathEnsureSeparator: Post condition failed");
79 : }
80 107819 : }
81 :
82 49392 : bool SAL_CALL osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
83 : {
84 : OSL_PRECOND(0 != pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
85 49392 : return ((0 == pustrPath) || (0 == pustrPath->length) || (pustrPath->buffer[0] != FPH_CHAR_PATH_SEPARATOR));
86 : }
87 :
88 106585 : void SAL_CALL osl_systemPathMakeAbsolutePath(
89 : const rtl_uString* pustrBasePath,
90 : const rtl_uString* pustrRelPath,
91 : rtl_uString** ppustrAbsolutePath)
92 : {
93 106585 : rtl::OUString base(rtl_uString_getStr(const_cast<rtl_uString*>(pustrBasePath)));
94 213170 : rtl::OUString rel(const_cast<rtl_uString*>(pustrRelPath));
95 :
96 106585 : if (!base.isEmpty())
97 106585 : osl_systemPathEnsureSeparator(&base.pData);
98 :
99 106585 : base += rel;
100 :
101 106585 : rtl_uString_acquire(base.pData);
102 213170 : *ppustrAbsolutePath = base.pData;
103 106585 : }
104 :
105 188674 : void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
106 : const rtl_uString* pustrPath,
107 : rtl_uString** ppustrFileNameOrLastDirPart)
108 : {
109 : OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, \
110 : "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
111 :
112 188674 : rtl::OUString path(const_cast<rtl_uString*>(pustrPath));
113 :
114 188674 : osl_systemPathRemoveSeparator(path.pData);
115 :
116 377348 : rtl::OUString last_part;
117 :
118 188674 : if (path.getLength() > 1 || (1 == path.getLength() && *path.getStr() != FPH_CHAR_PATH_SEPARATOR))
119 : {
120 188674 : sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
121 188674 : idx_ps++; // always right to increment by one even if idx_ps == -1!
122 188674 : last_part = rtl::OUString(path.getStr() + idx_ps);
123 : }
124 377348 : rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData);
125 188674 : }
126 :
127 83014 : bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
128 : const rtl_uString* pustrPath)
129 : {
130 : OSL_PRECOND(0 != pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
131 83014 : if ((0 == pustrPath) || (0 == pustrPath->length))
132 0 : return false;
133 :
134 83014 : rtl::OUString fdp;
135 83014 : osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData);
136 :
137 166028 : return ((fdp.pData->length > 0) &&
138 83308 : (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
139 83308 : !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
140 : }
141 :
142 294 : bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
143 : const rtl_uString* pustrPath)
144 : {
145 : OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
146 :
147 294 : rtl::OUString dirent;
148 :
149 294 : osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData);
150 :
151 1470 : return (dirent == FPH_LOCAL_DIR_ENTRY() ||
152 1176 : dirent == FPH_PARENT_DIR_ENTRY());
153 : }
154 :
155 : /***********************************************
156 : Simple iterator for a path list separated by
157 : the specified character
158 : **********************************************/
159 :
160 328 : class path_list_iterator: private boost::noncopyable
161 : {
162 : public:
163 :
164 : /* after construction get_current_item
165 : returns the first path in list, no need
166 : to call reset first
167 : */
168 328 : path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
169 : m_path_list(path_list),
170 328 : m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
171 656 : m_separator(list_separator)
172 : {
173 328 : reset();
174 328 : }
175 :
176 328 : void reset()
177 : {
178 328 : m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
179 328 : advance();
180 328 : }
181 :
182 913 : void next()
183 : {
184 : OSL_PRECOND(!done(), "path_list_iterator: Already done!");
185 :
186 913 : m_path_segment_begin = ++m_path_segment_end;
187 913 : advance();
188 913 : }
189 :
190 54290 : bool done() const
191 : {
192 54290 : return (m_path_segment_end >= m_end);
193 : }
194 :
195 1234 : rtl::OUString get_current_item() const
196 : {
197 : return rtl::OUString(
198 : m_path_segment_begin,
199 1234 : (m_path_segment_end - m_path_segment_begin));
200 : }
201 :
202 : private:
203 : /* move m_path_end to the next separator or
204 : to the end of the string
205 : */
206 1241 : void advance()
207 : {
208 54290 : while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
209 51808 : ++m_path_segment_end;
210 :
211 : OSL_ASSERT(m_path_segment_end <= m_end);
212 1241 : }
213 :
214 : private:
215 : rtl::OUString m_path_list;
216 : const sal_Unicode* m_end;
217 : const sal_Unicode m_separator;
218 : const sal_Unicode* m_path_segment_begin;
219 : const sal_Unicode* m_path_segment_end;
220 : };
221 :
222 328 : bool SAL_CALL osl_searchPath(
223 : const rtl_uString* pustrFilePath,
224 : const rtl_uString* pustrSearchPathList,
225 : rtl_uString** ppustrPathFound)
226 : {
227 : OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
228 :
229 328 : bool bfound = false;
230 328 : rtl::OUString fp(const_cast<rtl_uString*>(pustrFilePath));
231 656 : rtl::OUString pl = rtl::OUString(const_cast<rtl_uString*>(pustrSearchPathList));
232 656 : path_list_iterator pli(pl);
233 :
234 1569 : while (!pli.done())
235 : {
236 1234 : rtl::OUString p = pli.get_current_item();
237 1234 : osl::systemPathEnsureSeparator(p);
238 1234 : p += fp;
239 :
240 1234 : if (osl::access(p, F_OK) > -1)
241 : {
242 321 : bfound = true;
243 321 : rtl_uString_assign(ppustrPathFound, p.pData);
244 321 : break;
245 : }
246 913 : pli.next();
247 913 : }
248 656 : return bfound;
249 : }
250 :
251 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|