aboutsummaryrefslogtreecommitdiff
path: root/Src/omBrowser/cacheGroup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/omBrowser/cacheGroup.cpp')
-rw-r--r--Src/omBrowser/cacheGroup.cpp472
1 files changed, 472 insertions, 0 deletions
diff --git a/Src/omBrowser/cacheGroup.cpp b/Src/omBrowser/cacheGroup.cpp
new file mode 100644
index 00000000..dab4d5d8
--- /dev/null
+++ b/Src/omBrowser/cacheGroup.cpp
@@ -0,0 +1,472 @@
+#include "main.h"
+#include "./cacheGroup.h"
+#include "./cacheRecord.h"
+#include "./cacheManager.h"
+
+#include <wininet.h>
+#include <shlwapi.h>
+#include <strsafe.h>
+#include <algorithm>
+
+CacheGroup::CacheGroup(LPCWSTR pszName)
+ : ref(1), name(NULL), owner(NULL)
+{
+ name = Plugin_CopyString(pszName);
+}
+
+CacheGroup::~CacheGroup()
+{
+ Clear();
+
+ Plugin_FreeString(name);
+}
+
+HRESULT CacheGroup::CreateInstance(LPCWSTR pszName, CacheGroup **instance)
+{
+ if (NULL == instance) return E_POINTER;
+ *instance = NULL;
+
+ *instance = new CacheGroup(pszName);
+ if (NULL == *instance) return E_OUTOFMEMORY;
+
+ return S_OK;
+
+}
+
+size_t CacheGroup::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t CacheGroup::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int CacheGroup::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_OmCacheGroup))
+ *object = static_cast<ifc_omcachegroup*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+HRESULT CacheGroup::SetOwner(CacheManager *group)
+{
+ owner = group;
+ return S_OK;
+}
+
+HRESULT CacheGroup::GetName(LPWSTR pszBuffer, UINT cchBufferMax)
+{
+ if (NULL == pszBuffer || 0 == cchBufferMax)
+ return E_INVALIDARG;
+
+ return StringCchCopyEx(pszBuffer, cchBufferMax, name, NULL, NULL, STRSAFE_IGNORE_NULLS);
+}
+
+HRESULT CacheGroup::IsEqualName(LPCWSTR pszGroup)
+{
+ if (NULL == pszGroup)
+ return (NULL == name) ? S_OK : S_FALSE;
+
+ if (NULL == name) return S_FALSE;
+
+ INT result = CompareString(CSTR_INVARIANT, NORM_IGNORECASE, pszGroup, -1, name, -1);
+ if (0 == result)
+ {
+ DWORD error = GetLastError();
+ return HRESULT_FROM_WIN32(error);
+ }
+ return (CSTR_EQUAL == result) ? S_OK : S_FALSE;
+}
+
+HRESULT CacheGroup::IsEqual(CacheGroup *group)
+{
+ return (NULL != group) ? IsEqualName(group->name) : E_INVALIDARG;
+}
+
+HRESULT CacheGroup::IsEmpty()
+{
+ return (0 == recordList.size()) ? S_OK : S_FALSE;
+}
+
+HRESULT CacheGroup::Delete(LPCWSTR pszName)
+{
+ HRESULT hr = S_FALSE;
+ size_t index = recordList.size();
+
+ while(index--)
+ {
+ CacheRecord *record = recordList[index];
+ if (NULL != record && S_OK == record->IsEqualName(pszName))
+ {
+ recordList.erase(recordList.begin() + index);
+ record->Release();
+ hr = S_OK;
+ break;
+ }
+ }
+
+ return hr;
+}
+
+HRESULT CacheGroup::Clear()
+{
+ size_t index = recordList.size();
+
+ while(index--)
+ {
+ CacheRecord *record = recordList[index];
+ if (NULL != record) record->Release();
+ }
+
+ recordList.clear();
+
+ return S_OK;
+}
+
+__inline static int __cdecl CacheGroup_RecordSearch(const void *elem1, const void *elem2)
+{
+ int r = ((CacheRecord*)elem2)->CompareTo((LPCWSTR)elem1);
+ return -r;
+}
+
+HRESULT CacheGroup::Find(LPCWSTR pszName, BOOL fInsertMissing, CacheRecord **recordOut, BOOL *created)
+{
+ if (NULL != created)
+ *created = FALSE;
+
+ if (NULL == recordOut)
+ return E_POINTER;
+
+ HRESULT hr = S_FALSE;
+ size_t index = recordList.size();
+ if (0 != index)
+ {
+ //CacheRecord *rec = (CacheRecord*)bsearch(pszName, recordList.at(0), recordList.size(), sizeof(CacheRecord*), CacheGroup_RecordSearch);
+ auto it = std::find_if(recordList.begin(), recordList.end(),
+ [&](CacheRecord* upT) -> bool
+ {
+ return upT->CompareTo(pszName) == 0;
+ }
+ );
+ if (it != recordList.end())
+ {
+ *recordOut = *it;
+ (*recordOut)->AddRef();
+ hr = S_OK;
+ }
+ }
+
+ if (S_FALSE == hr && FALSE != fInsertMissing)
+ {
+ hr = CacheRecord::CreateInstance(pszName, NULL, 0, recordOut);
+ if (SUCCEEDED(hr))
+ {
+ recordList.push_back(*recordOut);
+ Sort();
+
+ (*recordOut)->AddRef();
+ (*recordOut)->SetOwner(this);
+
+ if (NULL != created)
+ *created = TRUE;
+ }
+ }
+
+ if (S_OK != hr)
+ *recordOut = NULL;
+
+ return hr;
+}
+
+HRESULT CacheGroup::GetPath(LPWSTR pszBuffer, UINT cchBufferMax)
+{
+ if (NULL == pszBuffer || 0 == cchBufferMax)
+ return E_INVALIDARG;
+
+ HRESULT hr;
+
+ if (NULL != owner)
+ {
+ hr = owner->GetPath(pszBuffer, cchBufferMax);
+ if (SUCCEEDED(hr) && NULL != name)
+ {
+ if (FALSE == PathAppend(pszBuffer, name))
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ *pszBuffer = L'\0';
+ hr = E_UNEXPECTED;
+ }
+
+ return hr;
+}
+
+static HRESULT CacheGroup_FormatStoreData(LPWSTR pszBuffer, size_t cchBufferMax, LPCWSTR pszPath, UINT *cchLength)
+{
+ if (NULL == pszBuffer)
+ return E_INVALIDARG;
+
+ size_t remaining = cchBufferMax;
+ HRESULT hr;
+ hr = StringCchCopyEx(pszBuffer, remaining, L"path=", &pszBuffer, &remaining, 0);
+ if (FAILED(hr)) return hr;
+
+ hr = StringCchCopyEx(pszBuffer, remaining, pszPath, &pszBuffer, &remaining, 0);
+ if (FAILED(hr)) return hr;
+
+ if (0 == remaining)
+ return E_OUTOFMEMORY;
+
+ remaining--;
+ pszBuffer++;
+ *pszBuffer = L'\0';
+
+ if (NULL != cchLength)
+ *cchLength = (UINT)(cchBufferMax - remaining) + 1;
+
+ return S_OK;
+}
+
+HRESULT CacheGroup::Store(LPCWSTR pszName, LPCWSTR pszPath)
+{
+ HRESULT hr;
+ WCHAR szBuffer[2048] = {0};
+
+ hr = GetPath(szBuffer, ARRAYSIZE(szBuffer));
+ if (FAILED(hr)) return hr;
+
+ Plugin_EnsurePathExist(szBuffer);
+
+ if (FALSE == PathAppend(szBuffer, L"cache.ini"))
+ return E_OUTOFMEMORY;
+
+ LPSTR pathAnsi = Plugin_WideCharToMultiByte(CP_UTF8, 0, szBuffer, -1, NULL, NULL);
+ if (NULL == pathAnsi) return E_OUTOFMEMORY;
+
+ LPSTR nameAnsi = Plugin_WideCharToMultiByte(CP_UTF8, 0, pszName, -1, NULL, NULL);
+ if (NULL == nameAnsi) return E_OUTOFMEMORY;
+
+ LPSTR dataAnsi = NULL;
+ if (NULL != pszPath)
+ {
+ UINT cchData;
+ hr = CacheGroup_FormatStoreData(szBuffer, ARRAYSIZE(szBuffer), pszPath, &cchData);
+ if (SUCCEEDED(hr))
+ {
+ dataAnsi = Plugin_WideCharToMultiByte(CP_UTF8, 0, szBuffer, cchData, NULL, NULL);
+ if (NULL == dataAnsi)
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ if (SUCCEEDED(hr) && 0 == WritePrivateProfileSectionA(nameAnsi, dataAnsi, pathAnsi))
+ {
+ DWORD error = GetLastError();
+ hr = HRESULT_FROM_WIN32(error);
+ }
+
+ Plugin_FreeAnsiString(dataAnsi);
+ Plugin_FreeAnsiString(nameAnsi);
+ Plugin_FreeAnsiString(pathAnsi);
+
+ return hr;
+}
+
+HRESULT CacheGroup::Load()
+{
+ HRESULT hr;
+ WCHAR szBuffer[4096] = {0};
+
+ hr = GetPath(szBuffer, ARRAYSIZE(szBuffer));
+ if (FAILED(hr)) return hr;
+
+ if (FALSE == PathAppend(szBuffer, L"cache.ini"))
+ return E_OUTOFMEMORY;
+
+ HANDLE hFile = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+ if (INVALID_HANDLE_VALUE == hFile)
+ {
+ DWORD error = GetLastError();
+ return HRESULT_FROM_WIN32(error);
+ }
+
+ DWORD read = 0;
+ CHAR szLine[INTERNET_MAX_URL_LENGTH + 3] = {0};
+ WCHAR szUnicode[ARRAYSIZE(szLine)] = {0};
+ UINT lineIndex = 0;
+ CacheRecord *record = NULL;
+ UINT recordSet = 0;
+ size_t inserted = 0;
+
+ RecordList cleanupList;
+
+ while (0 != ReadFile(hFile, szBuffer, sizeof(szBuffer), &read, NULL))
+ {
+ LPCSTR cursor = (LPCSTR)szBuffer;
+ LPCSTR end = cursor + read;
+
+ for(;;)
+ {
+ if (cursor >= end)
+ break;
+
+ if (cursor == end || ('\r' == *cursor && '\n' == *(cursor+1)))
+ {
+ szLine[lineIndex] = '\0';
+
+ if (lineIndex > 0)
+ {
+ if ('[' == szLine[0] && ']' == szLine[lineIndex-1])
+ {
+ if (NULL != record)
+ {
+ if (0 != (0x00000001 & recordSet))
+ {
+ recordList.push_back(record);
+ inserted++;
+ }
+ else
+ {
+ cleanupList.push_back(record);
+ }
+
+ record = NULL;
+ }
+
+ szLine[lineIndex-1] = '\0';
+ if (0 != MultiByteToWideChar(CP_UTF8, 0, szLine + 1, -1, szUnicode, ARRAYSIZE(szUnicode)) &&
+ SUCCEEDED(CacheRecord::CreateInstance(szUnicode, NULL, 0, &record)))
+ {
+ record->SetOwner(this);
+ recordSet = 0;
+ }
+ }
+ else
+ {
+ const char kw_path[] = "path=";
+ UINT cchKey = ARRAYSIZE(kw_path) - 1;
+ if (NULL != record &&
+ lineIndex > cchKey &&
+ CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, kw_path, cchKey, szLine, cchKey) &&
+ 0 != MultiByteToWideChar(CP_UTF8, 0, szLine + cchKey, -1, szUnicode, ARRAYSIZE(szUnicode)))
+ {
+ if(SUCCEEDED(record->SetPath(szUnicode)) &&
+ SUCCEEDED(record->GetPath(szUnicode, ARRAYSIZE(szUnicode))) &&
+ FALSE != PathFileExists(szUnicode))
+ {
+ recordSet |= 0x00000001;
+ }
+ }
+ }
+
+ }
+
+ lineIndex = 0;
+ cursor += 2;
+ continue;
+ }
+
+ if (lineIndex < ARRAYSIZE(szLine) - 2)
+ {
+ szLine[lineIndex++] = *cursor;
+ }
+
+ cursor++;
+ }
+
+ if (0 == read)
+ {
+ if (NULL != record)
+ {
+ if (0 != (0x00000001 & recordSet))
+ {
+ recordList.push_back(record);
+ inserted++;
+ }
+ else
+ record->Release();
+ }
+ break;
+ }
+ }
+ CloseHandle(hFile);
+
+ if (0 != inserted)
+ {
+ Sort();
+ }
+
+ size_t i = cleanupList.size();
+ if (0 != i)
+ {
+ while (i--)
+ {
+ aTRACE_LINE("ADD CACHE CLEANUP!!!!");
+ cleanupList[i]->Release();
+ }
+ }
+ return S_OK;
+}
+
+__inline static int __cdecl CacheGroup_RecordComparer(const void *elem1, const void *elem2)
+{
+ return CacheRecord::Compare((CacheRecord*)elem1, (CacheRecord*)elem2);
+}
+
+__inline static bool __cdecl CacheGroup_RecordComparer_V2(const void* elem1, const void* elem2)
+{
+ return CacheGroup_RecordComparer(elem1, elem2) < 0;
+}
+
+HRESULT CacheGroup::Sort()
+{
+ HRESULT hr;
+ if (0 == recordList.size())
+ {
+ hr = S_FALSE;
+ }
+ else
+ {
+ //qsort(recordList.first(), recordList.size(), sizeof(CacheRecord*), CacheGroup_RecordComparer);
+ std::sort(recordList.begin(), recordList.end(), CacheGroup_RecordComparer_V2);
+ hr = S_OK;
+ }
+
+ return hr;
+
+}
+
+#define CBCLASS CacheGroup
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+CB(API_GETNAME, GetName)
+CB(API_FIND, Find)
+CB(API_DELETE, Delete)
+CB(API_CLEAR, Clear)
+
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file