1 // Copyright 2014 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 "extensions/browser/computed_hashes.h" 6 7 #include "base/base64.h" 8 #include "base/file_util.h" 9 #include "base/files/file_path.h" 10 #include "base/json/json_reader.h" 11 #include "base/json/json_writer.h" 12 13 namespace { 14 const char kPathKey[] = "path"; 15 const char kBlockSizeKey[] = "block_size"; 16 const char kBlockHashesKey[] = "block_hashes"; 17 } 18 19 namespace extensions { 20 21 ComputedHashes::Reader::Reader() { 22 } 23 ComputedHashes::Reader::~Reader() { 24 } 25 26 bool ComputedHashes::Reader::InitFromFile(const base::FilePath& path) { 27 std::string contents; 28 if (!base::ReadFileToString(path, &contents)) 29 return false; 30 31 base::ListValue* all_hashes = NULL; 32 scoped_ptr<base::Value> value(base::JSONReader::Read(contents)); 33 if (!value.get() || !value->GetAsList(&all_hashes)) 34 return false; 35 36 for (size_t i = 0; i < all_hashes->GetSize(); i++) { 37 base::DictionaryValue* dictionary = NULL; 38 if (!all_hashes->GetDictionary(i, &dictionary)) 39 return false; 40 41 std::string relative_path_utf8; 42 if (!dictionary->GetString(kPathKey, &relative_path_utf8)) 43 return false; 44 45 int block_size; 46 if (!dictionary->GetInteger(kBlockSizeKey, &block_size)) 47 return false; 48 if (block_size <= 0 || ((block_size % 1024) != 0)) { 49 LOG(ERROR) << "Invalid block size: " << block_size; 50 block_size = 0; 51 return false; 52 } 53 54 base::ListValue* hashes_list = NULL; 55 if (!dictionary->GetList(kBlockHashesKey, &hashes_list)) 56 return false; 57 58 base::FilePath relative_path = 59 base::FilePath::FromUTF8Unsafe(relative_path_utf8); 60 61 data_[relative_path] = HashInfo(block_size, std::vector<std::string>()); 62 std::vector<std::string>* hashes = &(data_[relative_path].second); 63 64 for (size_t j = 0; j < hashes_list->GetSize(); j++) { 65 std::string encoded; 66 if (!hashes_list->GetString(j, &encoded)) 67 return false; 68 69 hashes->push_back(std::string()); 70 std::string* decoded = &hashes->back(); 71 if (!base::Base64Decode(encoded, decoded)) { 72 hashes->clear(); 73 return false; 74 } 75 } 76 } 77 return true; 78 } 79 80 bool ComputedHashes::Reader::GetHashes(const base::FilePath& relative_path, 81 int* block_size, 82 std::vector<std::string>* hashes) { 83 std::map<base::FilePath, HashInfo>::iterator i = data_.find(relative_path); 84 if (i == data_.end()) 85 return false; 86 HashInfo& info = i->second; 87 *block_size = info.first; 88 *hashes = info.second; 89 return true; 90 } 91 92 ComputedHashes::Writer::Writer() { 93 } 94 ComputedHashes::Writer::~Writer() { 95 } 96 97 void ComputedHashes::Writer::AddHashes(const base::FilePath& relative_path, 98 int block_size, 99 const std::vector<std::string>& hashes) { 100 base::DictionaryValue* dict = new base::DictionaryValue(); 101 base::ListValue* block_hashes = new base::ListValue(); 102 file_list_.Append(dict); 103 dict->SetString(kPathKey, relative_path.AsUTF8Unsafe()); 104 dict->SetInteger(kBlockSizeKey, block_size); 105 dict->Set(kBlockHashesKey, block_hashes); 106 107 for (std::vector<std::string>::const_iterator i = hashes.begin(); 108 i != hashes.end(); 109 ++i) { 110 std::string encoded; 111 base::Base64Encode(*i, &encoded); 112 block_hashes->AppendString(encoded); 113 } 114 } 115 116 bool ComputedHashes::Writer::WriteToFile(const base::FilePath& path) { 117 std::string json; 118 if (!base::JSONWriter::Write(&file_list_, &json)) 119 return false; 120 int written = base::WriteFile(path, json.data(), json.size()); 121 if (static_cast<unsigned>(written) != json.size()) { 122 LOG(ERROR) << "Error writing " << path.MaybeAsASCII() 123 << " ; write result:" << written << " expected:" << json.size(); 124 return false; 125 } 126 return true; 127 } 128 129 } // namespace extensions 130