1/* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#if defined(WEBRTC_WIN) 12#include "webrtc/base/win32.h" 13#include <shellapi.h> 14#include <shlobj.h> 15#include <tchar.h> 16#endif // WEBRTC_WIN 17 18#include "webrtc/base/common.h" 19#include "webrtc/base/fileutils.h" 20#include "webrtc/base/logging.h" 21#include "webrtc/base/pathutils.h" 22#include "webrtc/base/stringutils.h" 23#include "webrtc/base/urlencode.h" 24 25namespace rtc { 26 27static const char EMPTY_STR[] = ""; 28 29// EXT_DELIM separates a file basename from extension 30const char EXT_DELIM = '.'; 31 32// FOLDER_DELIMS separate folder segments and the filename 33const char* const FOLDER_DELIMS = "/\\"; 34 35// DEFAULT_FOLDER_DELIM is the preferred delimiter for this platform 36#if WEBRTC_WIN 37const char DEFAULT_FOLDER_DELIM = '\\'; 38#else // !WEBRTC_WIN 39const char DEFAULT_FOLDER_DELIM = '/'; 40#endif // !WEBRTC_WIN 41 42/////////////////////////////////////////////////////////////////////////////// 43// Pathname - parsing of pathnames into components, and vice versa 44/////////////////////////////////////////////////////////////////////////////// 45 46bool Pathname::IsFolderDelimiter(char ch) { 47 return (NULL != ::strchr(FOLDER_DELIMS, ch)); 48} 49 50char Pathname::DefaultFolderDelimiter() { 51 return DEFAULT_FOLDER_DELIM; 52} 53 54Pathname::Pathname() 55 : folder_delimiter_(DEFAULT_FOLDER_DELIM) { 56} 57 58Pathname::Pathname(const std::string& pathname) 59 : folder_delimiter_(DEFAULT_FOLDER_DELIM) { 60 SetPathname(pathname); 61} 62 63Pathname::Pathname(const std::string& folder, const std::string& filename) 64 : folder_delimiter_(DEFAULT_FOLDER_DELIM) { 65 SetPathname(folder, filename); 66} 67 68void Pathname::SetFolderDelimiter(char delimiter) { 69 ASSERT(IsFolderDelimiter(delimiter)); 70 folder_delimiter_ = delimiter; 71} 72 73void Pathname::Normalize() { 74 for (size_t i=0; i<folder_.length(); ++i) { 75 if (IsFolderDelimiter(folder_[i])) { 76 folder_[i] = folder_delimiter_; 77 } 78 } 79} 80 81void Pathname::clear() { 82 folder_.clear(); 83 basename_.clear(); 84 extension_.clear(); 85} 86 87bool Pathname::empty() const { 88 return folder_.empty() && basename_.empty() && extension_.empty(); 89} 90 91std::string Pathname::pathname() const { 92 std::string pathname(folder_); 93 pathname.append(basename_); 94 pathname.append(extension_); 95 if (pathname.empty()) { 96 // Instead of the empty pathname, return the current working directory. 97 pathname.push_back('.'); 98 pathname.push_back(folder_delimiter_); 99 } 100 return pathname; 101} 102 103std::string Pathname::url() const { 104 std::string s = "file:///"; 105 for (size_t i=0; i<folder_.length(); ++i) { 106 if (IsFolderDelimiter(folder_[i])) 107 s += '/'; 108 else 109 s += folder_[i]; 110 } 111 s += basename_; 112 s += extension_; 113 return UrlEncodeStringForOnlyUnsafeChars(s); 114} 115 116void Pathname::SetPathname(const std::string& pathname) { 117 std::string::size_type pos = pathname.find_last_of(FOLDER_DELIMS); 118 if (pos != std::string::npos) { 119 SetFolder(pathname.substr(0, pos + 1)); 120 SetFilename(pathname.substr(pos + 1)); 121 } else { 122 SetFolder(EMPTY_STR); 123 SetFilename(pathname); 124 } 125} 126 127void Pathname::SetPathname(const std::string& folder, 128 const std::string& filename) { 129 SetFolder(folder); 130 SetFilename(filename); 131} 132 133void Pathname::AppendPathname(const std::string& pathname) { 134 std::string full_pathname(folder_); 135 full_pathname.append(pathname); 136 SetPathname(full_pathname); 137} 138 139std::string Pathname::folder() const { 140 return folder_; 141} 142 143std::string Pathname::folder_name() const { 144 std::string::size_type pos = std::string::npos; 145 if (folder_.size() >= 2) { 146 pos = folder_.find_last_of(FOLDER_DELIMS, folder_.length() - 2); 147 } 148 if (pos != std::string::npos) { 149 return folder_.substr(pos + 1); 150 } else { 151 return folder_; 152 } 153} 154 155std::string Pathname::parent_folder() const { 156 std::string::size_type pos = std::string::npos; 157 if (folder_.size() >= 2) { 158 pos = folder_.find_last_of(FOLDER_DELIMS, folder_.length() - 2); 159 } 160 if (pos != std::string::npos) { 161 return folder_.substr(0, pos + 1); 162 } else { 163 return EMPTY_STR; 164 } 165} 166 167void Pathname::SetFolder(const std::string& folder) { 168 folder_.assign(folder); 169 // Ensure folder ends in a path delimiter 170 if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) { 171 folder_.push_back(folder_delimiter_); 172 } 173} 174 175void Pathname::AppendFolder(const std::string& folder) { 176 folder_.append(folder); 177 // Ensure folder ends in a path delimiter 178 if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) { 179 folder_.push_back(folder_delimiter_); 180 } 181} 182 183std::string Pathname::basename() const { 184 return basename_; 185} 186 187bool Pathname::SetBasename(const std::string& basename) { 188 if(basename.find_first_of(FOLDER_DELIMS) != std::string::npos) { 189 return false; 190 } 191 basename_.assign(basename); 192 return true; 193} 194 195std::string Pathname::extension() const { 196 return extension_; 197} 198 199bool Pathname::SetExtension(const std::string& extension) { 200 if (extension.find_first_of(FOLDER_DELIMS) != std::string::npos || 201 extension.find_first_of(EXT_DELIM, 1) != std::string::npos) { 202 return false; 203 } 204 extension_.assign(extension); 205 // Ensure extension begins with the extension delimiter 206 if (!extension_.empty() && (extension_[0] != EXT_DELIM)) { 207 extension_.insert(extension_.begin(), EXT_DELIM); 208 } 209 return true; 210} 211 212std::string Pathname::filename() const { 213 std::string filename(basename_); 214 filename.append(extension_); 215 return filename; 216} 217 218bool Pathname::SetFilename(const std::string& filename) { 219 std::string::size_type pos = filename.rfind(EXT_DELIM); 220 if ((pos == std::string::npos) || (pos == 0)) { 221 return SetExtension(EMPTY_STR) && SetBasename(filename); 222 } else { 223 return SetExtension(filename.substr(pos)) && SetBasename(filename.substr(0, pos)); 224 } 225} 226 227#if defined(WEBRTC_WIN) 228bool Pathname::GetDrive(char* drive, uint32_t bytes) const { 229 return GetDrive(drive, bytes, folder_); 230} 231 232// static 233bool Pathname::GetDrive(char* drive, 234 uint32_t bytes, 235 const std::string& pathname) { 236 // need at lease 4 bytes to save c: 237 if (bytes < 4 || pathname.size() < 3) { 238 return false; 239 } 240 241 memcpy(drive, pathname.c_str(), 3); 242 drive[3] = 0; 243 // sanity checking 244 return (isalpha(drive[0]) && 245 drive[1] == ':' && 246 drive[2] == '\\'); 247} 248#endif 249 250/////////////////////////////////////////////////////////////////////////////// 251 252} // namespace rtc 253