/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "file_path_helper.hxx" #include "uunxapi.hxx" #include #include #include const sal_Unicode FPH_CHAR_PATH_SEPARATOR = '/'; const sal_Unicode FPH_CHAR_DOT = '.'; const sal_Unicode FPH_CHAR_COLON = ':'; static inline const rtl::OUString FPH_PATH_SEPARATOR() { return rtl::OUString(FPH_CHAR_PATH_SEPARATOR); } static inline const rtl::OUString FPH_LOCAL_DIR_ENTRY() { return rtl::OUString(FPH_CHAR_DOT); } static inline const rtl::OUString FPH_PARENT_DIR_ENTRY() { return rtl::OUString(".."); } void osl_systemPathRemoveSeparator(rtl_uString* pustrPath) { OSL_PRECOND(nullptr != pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter"); if (pustrPath != nullptr) { // maybe there are more than one separator at end // so we run in a loop while ((pustrPath->length > 1) && (pustrPath->buffer[pustrPath->length - 1] == FPH_CHAR_PATH_SEPARATOR)) { pustrPath->length--; pustrPath->buffer[pustrPath->length] = '\0'; } SAL_WARN_IF( !((0 == pustrPath->length) || (1 == pustrPath->length) || (pustrPath->length > 1 && pustrPath->buffer[pustrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR)), "sal.osl", "osl_systemPathRemoveSeparator: Post condition failed"); } } void osl_systemPathEnsureSeparator(rtl_uString** ppustrPath) { OSL_PRECOND((nullptr != ppustrPath) && (nullptr != *ppustrPath), "osl_systemPathEnsureSeparator: Invalid parameter"); if ((ppustrPath != nullptr) && (*ppustrPath != nullptr)) { rtl::OUString path(*ppustrPath); sal_Int32 lp = path.getLength(); sal_Int32 i = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR); if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0)) { path += FPH_PATH_SEPARATOR(); rtl_uString_assign(ppustrPath, path.pData); } SAL_WARN_IF( !path.endsWith(FPH_PATH_SEPARATOR()), "sal.osl", "osl_systemPathEnsureSeparator: Post condition failed"); } } bool osl_systemPathIsRelativePath(const rtl_uString* pustrPath) { OSL_PRECOND(nullptr != pustrPath, "osl_systemPathIsRelativePath: Invalid parameter"); return ((pustrPath == nullptr) || (pustrPath->length == 0) || (pustrPath->buffer[0] != FPH_CHAR_PATH_SEPARATOR)); } void osl_systemPathMakeAbsolutePath( const rtl_uString* pustrBasePath, const rtl_uString* pustrRelPath, rtl_uString** ppustrAbsolutePath) { rtl::OUString base(rtl_uString_getStr(const_cast(pustrBasePath))); rtl::OUString rel(const_cast(pustrRelPath)); if (!base.isEmpty()) osl_systemPathEnsureSeparator(&base.pData); base += rel; rtl_uString_acquire(base.pData); *ppustrAbsolutePath = base.pData; } void osl_systemPathGetFileNameOrLastDirectoryPart( const rtl_uString* pustrPath, rtl_uString** ppustrFileNameOrLastDirPart) { OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter"); rtl::OUString path(const_cast(pustrPath)); osl_systemPathRemoveSeparator(path.pData); rtl::OUString last_part; if (path.getLength() > 1 || (path.getLength() == 1 && path[0] != FPH_CHAR_PATH_SEPARATOR)) { sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR); idx_ps++; // always right to increment by one even if idx_ps == -1! last_part = path.copy(idx_ps); } rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData); } bool osl_systemPathIsHiddenFileOrDirectoryEntry( const rtl_uString* pustrPath) { OSL_PRECOND(nullptr != pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter"); if ((pustrPath == nullptr) || (pustrPath->length == 0)) return false; rtl::OUString fdp; osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData); return ((fdp.pData->length > 0) && (fdp.pData->buffer[0] == FPH_CHAR_DOT) && !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData)); } bool osl_systemPathIsLocalOrParentDirectoryEntry( const rtl_uString* pustrPath) { OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter"); rtl::OUString dirent; osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData); return (dirent == FPH_LOCAL_DIR_ENTRY() || dirent == FPH_PARENT_DIR_ENTRY()); } /** Simple iterator for a path list separated by the specified character */ class path_list_iterator { public: /* after construction get_current_item returns the first path in list, no need to call reset first */ path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) : m_path_list(path_list), m_end(m_path_list.getStr() + m_path_list.getLength() + 1), m_separator(list_separator) { reset(); } path_list_iterator(const path_list_iterator&) = delete; path_list_iterator& operator=(const path_list_iterator&) = delete; void reset() { m_path_segment_begin = m_path_segment_end = m_path_list.getStr(); advance(); } void next() { OSL_PRECOND(!done(), "path_list_iterator: Already done!"); m_path_segment_begin = ++m_path_segment_end; advance(); } bool done() const { return (m_path_segment_end >= m_end); } rtl::OUString get_current_item() const { return rtl::OUString( m_path_segment_begin, (m_path_segment_end - m_path_segment_begin)); } private: /* move m_path_end to the next separator or to the end of the string */ void advance() { while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator)) ++m_path_segment_end; OSL_ASSERT(m_path_segment_end <= m_end); } private: rtl::OUString m_path_list; const sal_Unicode* m_end; const sal_Unicode m_separator; const sal_Unicode* m_path_segment_begin; const sal_Unicode* m_path_segment_end; }; bool osl_searchPath( const rtl_uString* pustrFilePath, const rtl_uString* pustrSearchPathList, rtl_uString** ppustrPathFound) { OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter"); bool bfound = false; rtl::OUString fp(const_cast(pustrFilePath)); rtl::OUString pl = rtl::OUString(const_cast(pustrSearchPathList)); path_list_iterator pli(pl); while (!pli.done()) { rtl::OUString p = pli.get_current_item(); osl::systemPathEnsureSeparator(p); p += fp; if (osl::access(p, F_OK) > -1) { bfound = true; rtl_uString_assign(ppustrPathFound, p.pData); break; } pli.next(); } return bfound; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */