1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/url-classifier/Entries.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,314 @@ 1.4 +//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// This header file defines the storage types of the actual safebrowsing 1.10 +// chunk data, which may be either 32-bit hashes or complete 256-bit hashes. 1.11 +// Chunk numbers are represented in ChunkSet.h. 1.12 + 1.13 +#ifndef SBEntries_h__ 1.14 +#define SBEntries_h__ 1.15 + 1.16 +#include "nsTArray.h" 1.17 +#include "nsString.h" 1.18 +#include "nsICryptoHash.h" 1.19 +#include "nsNetUtil.h" 1.20 + 1.21 +#if DEBUG 1.22 +#include "plbase64.h" 1.23 +#endif 1.24 + 1.25 +namespace mozilla { 1.26 +namespace safebrowsing { 1.27 + 1.28 +#define PREFIX_SIZE 4 1.29 +#define COMPLETE_SIZE 32 1.30 + 1.31 +// This is the struct that contains 4-byte hash prefixes. 1.32 +template <uint32_t S, class Comparator> 1.33 +struct SafebrowsingHash 1.34 +{ 1.35 + static const uint32_t sHashSize = S; 1.36 + typedef SafebrowsingHash<S, Comparator> self_type; 1.37 + uint8_t buf[S]; 1.38 + 1.39 + nsresult FromPlaintext(const nsACString& aPlainText, nsICryptoHash* aHash) { 1.40 + // From the protocol doc: 1.41 + // Each entry in the chunk is composed 1.42 + // of the SHA 256 hash of a suffix/prefix expression. 1.43 + 1.44 + nsresult rv = aHash->Init(nsICryptoHash::SHA256); 1.45 + NS_ENSURE_SUCCESS(rv, rv); 1.46 + 1.47 + rv = aHash->Update 1.48 + (reinterpret_cast<const uint8_t*>(aPlainText.BeginReading()), 1.49 + aPlainText.Length()); 1.50 + NS_ENSURE_SUCCESS(rv, rv); 1.51 + 1.52 + nsAutoCString hashed; 1.53 + rv = aHash->Finish(false, hashed); 1.54 + NS_ENSURE_SUCCESS(rv, rv); 1.55 + 1.56 + NS_ASSERTION(hashed.Length() >= sHashSize, 1.57 + "not enough characters in the hash"); 1.58 + 1.59 + memcpy(buf, hashed.BeginReading(), sHashSize); 1.60 + 1.61 + return NS_OK; 1.62 + } 1.63 + 1.64 + void Assign(const nsACString& aStr) { 1.65 + NS_ASSERTION(aStr.Length() >= sHashSize, 1.66 + "string must be at least sHashSize characters long"); 1.67 + memcpy(buf, aStr.BeginReading(), sHashSize); 1.68 + } 1.69 + 1.70 + int Compare(const self_type& aOther) const { 1.71 + return Comparator::Compare(buf, aOther.buf); 1.72 + } 1.73 + 1.74 + bool operator==(const self_type& aOther) const { 1.75 + return Comparator::Compare(buf, aOther.buf) == 0; 1.76 + } 1.77 + 1.78 + bool operator!=(const self_type& aOther) const { 1.79 + return Comparator::Compare(buf, aOther.buf) != 0; 1.80 + } 1.81 + 1.82 + bool operator<(const self_type& aOther) const { 1.83 + return Comparator::Compare(buf, aOther.buf) < 0; 1.84 + } 1.85 + 1.86 +#ifdef DEBUG 1.87 + void ToString(nsACString& aStr) const { 1.88 + uint32_t len = ((sHashSize + 2) / 3) * 4; 1.89 + aStr.SetCapacity(len + 1); 1.90 + PL_Base64Encode((char*)buf, sHashSize, aStr.BeginWriting()); 1.91 + aStr.BeginWriting()[len] = '\0'; 1.92 + } 1.93 + 1.94 + void ToHexString(nsACString& aStr) const { 1.95 + static const char* const lut = "0123456789ABCDEF"; 1.96 + // 32 bytes is the longest hash 1.97 + size_t len = 32; 1.98 + 1.99 + aStr.SetCapacity(2 * len); 1.100 + for (size_t i = 0; i < len; ++i) { 1.101 + const char c = static_cast<const char>(buf[i]); 1.102 + aStr.Append(lut[(c >> 4) & 0x0F]); 1.103 + aStr.Append(lut[c & 15]); 1.104 + } 1.105 + } 1.106 +#endif 1.107 + uint32_t ToUint32() const { 1.108 + return *((uint32_t*)buf); 1.109 + } 1.110 + void FromUint32(uint32_t aHash) { 1.111 + *((uint32_t*)buf) = aHash; 1.112 + } 1.113 +}; 1.114 + 1.115 +class PrefixComparator { 1.116 +public: 1.117 + static int Compare(const uint8_t* a, const uint8_t* b) { 1.118 + uint32_t first = *((uint32_t*)a); 1.119 + uint32_t second = *((uint32_t*)b); 1.120 + if (first > second) { 1.121 + return 1; 1.122 + } else if (first == second) { 1.123 + return 0; 1.124 + } else { 1.125 + return -1; 1.126 + } 1.127 + } 1.128 +}; 1.129 +// Use this for 4-byte hashes 1.130 +typedef SafebrowsingHash<PREFIX_SIZE, PrefixComparator> Prefix; 1.131 +typedef nsTArray<Prefix> PrefixArray; 1.132 + 1.133 +class CompletionComparator { 1.134 +public: 1.135 + static int Compare(const uint8_t* a, const uint8_t* b) { 1.136 + return memcmp(a, b, COMPLETE_SIZE); 1.137 + } 1.138 +}; 1.139 +// Use this for 32-byte hashes 1.140 +typedef SafebrowsingHash<COMPLETE_SIZE, CompletionComparator> Completion; 1.141 +typedef nsTArray<Completion> CompletionArray; 1.142 + 1.143 +struct AddPrefix { 1.144 + // The truncated hash. 1.145 + Prefix prefix; 1.146 + // The chunk number to which it belongs. 1.147 + uint32_t addChunk; 1.148 + 1.149 + AddPrefix() : addChunk(0) {} 1.150 + 1.151 + // Returns the chunk number. 1.152 + uint32_t Chunk() const { return addChunk; } 1.153 + const Prefix &PrefixHash() const { return prefix; } 1.154 + 1.155 + template<class T> 1.156 + int Compare(const T& other) const { 1.157 + int cmp = prefix.Compare(other.PrefixHash()); 1.158 + if (cmp != 0) { 1.159 + return cmp; 1.160 + } 1.161 + return addChunk - other.addChunk; 1.162 + } 1.163 +}; 1.164 + 1.165 +struct AddComplete { 1.166 + Completion complete; 1.167 + uint32_t addChunk; 1.168 + 1.169 + AddComplete() : addChunk(0) {} 1.170 + 1.171 + uint32_t Chunk() const { return addChunk; } 1.172 + // The 4-byte prefix of the sha256 hash. 1.173 + uint32_t ToUint32() const { return complete.ToUint32(); } 1.174 + // The 32-byte sha256 hash. 1.175 + const Completion &CompleteHash() const { return complete; } 1.176 + 1.177 + template<class T> 1.178 + int Compare(const T& other) const { 1.179 + int cmp = complete.Compare(other.CompleteHash()); 1.180 + if (cmp != 0) { 1.181 + return cmp; 1.182 + } 1.183 + return addChunk - other.addChunk; 1.184 + } 1.185 +}; 1.186 + 1.187 +struct SubPrefix { 1.188 + // The hash to subtract. 1.189 + Prefix prefix; 1.190 + // The chunk number of the add chunk to which the hash belonged. 1.191 + uint32_t addChunk; 1.192 + // The chunk number of this sub chunk. 1.193 + uint32_t subChunk; 1.194 + 1.195 + SubPrefix(): addChunk(0), subChunk(0) {} 1.196 + 1.197 + uint32_t Chunk() const { return subChunk; } 1.198 + uint32_t AddChunk() const { return addChunk; } 1.199 + const Prefix &PrefixHash() const { return prefix; } 1.200 + 1.201 + template<class T> 1.202 + // Returns 0 if and only if the chunks are the same in every way. 1.203 + int Compare(const T& aOther) const { 1.204 + int cmp = prefix.Compare(aOther.PrefixHash()); 1.205 + if (cmp != 0) 1.206 + return cmp; 1.207 + if (addChunk != aOther.addChunk) 1.208 + return addChunk - aOther.addChunk; 1.209 + return subChunk - aOther.subChunk; 1.210 + } 1.211 + 1.212 + template<class T> 1.213 + int CompareAlt(const T& aOther) const { 1.214 + Prefix other; 1.215 + other.FromUint32(aOther.ToUint32()); 1.216 + int cmp = prefix.Compare(other); 1.217 + if (cmp != 0) 1.218 + return cmp; 1.219 + return addChunk - aOther.addChunk; 1.220 + } 1.221 +}; 1.222 + 1.223 +struct SubComplete { 1.224 + Completion complete; 1.225 + uint32_t addChunk; 1.226 + uint32_t subChunk; 1.227 + 1.228 + SubComplete() : addChunk(0), subChunk(0) {} 1.229 + 1.230 + uint32_t Chunk() const { return subChunk; } 1.231 + uint32_t AddChunk() const { return addChunk; } 1.232 + const Completion &CompleteHash() const { return complete; } 1.233 + // The 4-byte prefix of the sha256 hash. 1.234 + uint32_t ToUint32() const { return complete.ToUint32(); } 1.235 + 1.236 + int Compare(const SubComplete& aOther) const { 1.237 + int cmp = complete.Compare(aOther.complete); 1.238 + if (cmp != 0) 1.239 + return cmp; 1.240 + if (addChunk != aOther.addChunk) 1.241 + return addChunk - aOther.addChunk; 1.242 + return subChunk - aOther.subChunk; 1.243 + } 1.244 +}; 1.245 + 1.246 +typedef FallibleTArray<AddPrefix> AddPrefixArray; 1.247 +typedef FallibleTArray<AddComplete> AddCompleteArray; 1.248 +typedef FallibleTArray<SubPrefix> SubPrefixArray; 1.249 +typedef FallibleTArray<SubComplete> SubCompleteArray; 1.250 + 1.251 +/** 1.252 + * Compares chunks by their add chunk, then their prefix. 1.253 + */ 1.254 +template<class T> 1.255 +class EntryCompare { 1.256 +public: 1.257 + typedef T elem_type; 1.258 + static int Compare(const void* e1, const void* e2) { 1.259 + const elem_type* a = static_cast<const elem_type*>(e1); 1.260 + const elem_type* b = static_cast<const elem_type*>(e2); 1.261 + return a->Compare(*b); 1.262 + } 1.263 +}; 1.264 + 1.265 +/** 1.266 + * Sort an array of store entries. nsTArray::Sort uses Equal/LessThan 1.267 + * to sort, this does a single Compare so it's a bit quicker over the 1.268 + * large sorts we do. 1.269 + */ 1.270 +template<class T, class Alloc> 1.271 +void 1.272 +EntrySort(nsTArray_Impl<T, Alloc>& aArray) 1.273 +{ 1.274 + qsort(aArray.Elements(), aArray.Length(), sizeof(T), 1.275 + EntryCompare<T>::Compare); 1.276 +} 1.277 + 1.278 +template<class T, class Alloc> 1.279 +nsresult 1.280 +ReadTArray(nsIInputStream* aStream, nsTArray_Impl<T, Alloc>* aArray, uint32_t aNumElements) 1.281 +{ 1.282 + aArray->SetLength(aNumElements); 1.283 + 1.284 + void *buffer = aArray->Elements(); 1.285 + nsresult rv = NS_ReadInputStreamToBuffer(aStream, &buffer, 1.286 + (aNumElements * sizeof(T))); 1.287 + NS_ENSURE_SUCCESS(rv, rv); 1.288 + return NS_OK; 1.289 +} 1.290 + 1.291 +template<class T> 1.292 +nsresult 1.293 +ReadTArray(nsIInputStream* aStream, FallibleTArray<T>* aArray, uint32_t aNumElements) 1.294 +{ 1.295 + if (!aArray->SetLength(aNumElements)) 1.296 + return NS_ERROR_OUT_OF_MEMORY; 1.297 + 1.298 + void *buffer = aArray->Elements(); 1.299 + nsresult rv = NS_ReadInputStreamToBuffer(aStream, &buffer, 1.300 + (aNumElements * sizeof(T))); 1.301 + NS_ENSURE_SUCCESS(rv, rv); 1.302 + return NS_OK; 1.303 +} 1.304 + 1.305 +template<class T, class Alloc> 1.306 +nsresult 1.307 +WriteTArray(nsIOutputStream* aStream, nsTArray_Impl<T, Alloc>& aArray) 1.308 +{ 1.309 + uint32_t written; 1.310 + return aStream->Write(reinterpret_cast<char*>(aArray.Elements()), 1.311 + aArray.Length() * sizeof(T), 1.312 + &written); 1.313 +} 1.314 + 1.315 +} // namespace safebrowsing 1.316 +} // namespace mozilla 1.317 +#endif // SBEntries_h__