net_util_win.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
14e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis// Copyright (c) 2011 The Chromium Authors. All rights reserved. 24e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis// Use of this source code is governed by a BSD-style license that can be 34e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis// found in the LICENSE file. 44e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 54e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "net/base/net_util.h" 64e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 74e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include <iphlpapi.h> 84e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 94e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include <algorithm> 104e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 114e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "base/file_path.h" 124e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "base/memory/scoped_ptr.h" 134e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "base/string_piece.h" 144e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "base/string_util.h" 154e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "base/sys_string_conversions.h" 164e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "base/threading/thread_restrictions.h" 174e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "base/utf_string_conversions.h" 184e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "googleurl/src/gurl.h" 194e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "net/base/escape.h" 20dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis#include "net/base/ip_endpoint.h" 214e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "net/base/net_errors.h" 224e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 234e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisnamespace net { 244e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 25dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidisbool FileURLToFilePath(const GURL& url, FilePath* file_path) { 26dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis *file_path = FilePath(); 27dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis std::wstring& file_path_str = const_cast<std::wstring&>(file_path->value()); 28dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis file_path_str.clear(); 29dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis 30dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis if (!url.is_valid()) 31dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis return false; 32dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis 33dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis std::string path; 34dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis std::string host = url.host(); 35dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis if (host.empty()) { 36dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // URL contains no host, the path is the filename. In this case, the path 37dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // will probably be preceeded with a slash, as in "/C:/foo.txt", so we 38dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // trim out that here. 39dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis path = url.path(); 40dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis size_t first_non_slash = path.find_first_not_of("/\\"); 414e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis if (first_non_slash != std::string::npos && first_non_slash > 0) 424e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis path.erase(0, first_non_slash); 434e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } else { 444e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // URL contains a host: this means it's UNC. We keep the preceeding slash 454e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // on the path. 464e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis path = "\\\\"; 474e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis path.append(host); 48dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis path.append(url.path()); 49dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis } 50dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis 51dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis if (path.empty()) 524e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis return false; 534e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis std::replace(path.begin(), path.end(), '/', '\\'); 544e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 554e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // GURL stores strings as percent-encoded UTF-8, this will undo if possible. 564e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis path = UnescapeURLComponent(path, 574e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); 584e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 594e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis if (!IsStringUTF8(path)) { 60dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // Not UTF-8, assume encoding is native codepage and we're done. We know we 614e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // are giving the conversion function a nonempty string, and it may fail if 624e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // the given string is not in the current encoding and give us an empty 634e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // string back. We detect this and report failure. 64dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis file_path_str = base::SysNativeMBToWide(path); 654e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis return !file_path_str.empty(); 664e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } 67dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis file_path_str.assign(UTF8ToWide(path)); 68dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis 69dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // We used to try too hard and see if |path| made up entirely of 70dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // the 1st 256 characters in the Unicode was a zero-extended UTF-16. 71dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // If so, we converted it to 'Latin-1' and checked if the result was UTF-8. 72dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // If the check passed, we converted the result to UTF-8. 73dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // Otherwise, we treated the result as the native OS encoding. 74dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis // However, that led to http://crbug.com/4619 and http://crbug.com/14153 75dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis return true; 76dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis} 774e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 784e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisbool GetNetworkList(NetworkInterfaceList* networks) { 794e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // GetAdaptersAddresses() may require IO operations. 804e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis base::ThreadRestrictions::AssertIOAllowed(); 814e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 824e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis IP_ADAPTER_ADDRESSES info_temp; 834e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis ULONG len = 0; 844e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 854e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // First get number of networks. 864e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis ULONG result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, &info_temp, &len); 874e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis if (result != ERROR_BUFFER_OVERFLOW) { 884e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // There are 0 networks. 894e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis return true; 904e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } 914e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 924e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis scoped_array<char> buf(new char[len]); 934e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis IP_ADAPTER_ADDRESSES *adapters = 94dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get()); 954e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len); 964e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis if (result != NO_ERROR) { 974e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis LOG(ERROR) << "GetAdaptersAddresses failed: " << result; 984e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis return false; 994e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } 100dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis 101dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL; 1024e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis adapter = adapter->Next) { 1034e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis // Ignore the loopback device. 1044e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) { 1054e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis continue; 1064e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } 1074e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 1084e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis IP_ADAPTER_UNICAST_ADDRESS* address; 1094e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis for (address = adapter->FirstUnicastAddress; address != NULL; 1104e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis address = address->Next) { 1114e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis int family = address->Address.lpSockaddr->sa_family; 1124e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis if (family == AF_INET || family == AF_INET6) { 1134e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis IPEndPoint endpoint; 1144e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis if (endpoint.FromSockAddr(address->Address.lpSockaddr, 1154e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis address->Address.iSockaddrLength)) { 1164e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis std::string name = adapter->AdapterName; 1174e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis networks->push_back(NetworkInterface(name, endpoint.address())); 1184e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } 1194e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } 1204e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } 1214e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis } 1224e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 1234e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis return true; 1244e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis} 1254e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis 1264e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis} // namespace net 1274e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis