1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/policy/policy_path_parser.h" 6 7#include "base/basictypes.h" 8#include "base/files/file_path.h" 9#include "base/logging.h" 10#import "base/mac/scoped_nsautorelease_pool.h" 11#include "base/strings/sys_string_conversions.h" 12#include "policy/policy_constants.h" 13 14#import <Cocoa/Cocoa.h> 15#import <SystemConfiguration/SCDynamicStore.h> 16#import <SystemConfiguration/SCDynamicStoreCopySpecific.h> 17 18#include <string> 19 20namespace policy { 21 22namespace path_parser { 23 24const char* kUserNamePolicyVarName = "${user_name}"; 25const char* kMachineNamePolicyVarName = "${machine_name}"; 26const char* kMacUsersDirectory = "${users}"; 27const char* kMacDocumentsFolderVarName = "${documents}"; 28 29struct MacFolderNamesToSPDMaping { 30 const char* name; 31 NSSearchPathDirectory id; 32}; 33 34// Mapping from variable names to MacOS NSSearchPathDirectory ids. 35const MacFolderNamesToSPDMaping mac_folder_mapping[] = { 36 { kMacUsersDirectory, NSUserDirectory}, 37 { kMacDocumentsFolderVarName, NSDocumentDirectory} 38}; 39 40// Replaces all variable occurrences in the policy string with the respective 41// system settings values. 42base::FilePath::StringType ExpandPathVariables( 43 const base::FilePath::StringType& untranslated_string) { 44 base::FilePath::StringType result(untranslated_string); 45 if (result.length() == 0) 46 return result; 47 // Sanitize quotes in case of any around the whole string. 48 if (result.length() > 1 && 49 ((result[0] == '"' && result[result.length() - 1] == '"') || 50 (result[0] == '\'' && result[result.length() - 1] == '\''))) { 51 // Strip first and last char which should be matching quotes now. 52 result = result.substr(1, result.length() - 2); 53 } 54 // First translate all path variables we recognize. 55 for (size_t i = 0; i < arraysize(mac_folder_mapping); ++i) { 56 size_t position = result.find(mac_folder_mapping[i].name); 57 if (position != std::string::npos) { 58 NSArray* searchpaths = NSSearchPathForDirectoriesInDomains( 59 mac_folder_mapping[i].id, NSAllDomainsMask, true); 60 if ([searchpaths count] > 0) { 61 NSString *variable_value = [searchpaths objectAtIndex:0]; 62 result.replace(position, strlen(mac_folder_mapping[i].name), 63 base::SysNSStringToUTF8(variable_value)); 64 } 65 } 66 } 67 // Next translate two special variables ${user_name} and ${machine_name} 68 size_t position = result.find(kUserNamePolicyVarName); 69 if (position != std::string::npos) { 70 NSString* username = NSUserName(); 71 if (username) { 72 result.replace(position, strlen(kUserNamePolicyVarName), 73 base::SysNSStringToUTF8(username)); 74 } else { 75 LOG(ERROR) << "Username variable can not be resolved."; 76 } 77 } 78 position = result.find(kMachineNamePolicyVarName); 79 if (position != std::string::npos) { 80 SCDynamicStoreContext context = { 0, NULL, NULL, NULL }; 81 SCDynamicStoreRef store = SCDynamicStoreCreate(kCFAllocatorDefault, 82 CFSTR("policy_subsystem"), 83 NULL, &context); 84 CFStringRef machinename = SCDynamicStoreCopyLocalHostName(store); 85 if (machinename) { 86 result.replace(position, strlen(kMachineNamePolicyVarName), 87 base::SysCFStringRefToUTF8(machinename)); 88 CFRelease(machinename); 89 } else { 90 LOG(ERROR) << "Machine name variable can not be resolved."; 91 } 92 CFRelease(store); 93 } 94 return result; 95} 96 97void CheckUserDataDirPolicy(base::FilePath* user_data_dir) { 98 base::mac::ScopedNSAutoreleasePool pool; 99 100 // Since the configuration management infrastructure is not initialized when 101 // this code runs, read the policy preference directly. 102 NSString* key = base::SysUTF8ToNSString(policy::key::kUserDataDir); 103 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; 104 NSString* value = [defaults stringForKey:key]; 105 if (value && [defaults objectIsForcedForKey:key]) { 106 std::string string_value = base::SysNSStringToUTF8(value); 107 // Now replace any vars the user might have used. 108 string_value = policy::path_parser::ExpandPathVariables(string_value); 109 *user_data_dir = base::FilePath(string_value); 110 } 111} 112 113} // namespace path_parser 114 115} // namespace policy 116