-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSearchProvider.cpp
More file actions
140 lines (111 loc) · 3.53 KB
/
SearchProvider.cpp
File metadata and controls
140 lines (111 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <iostream>
#include <sstream>
// #include <unistd.h>
// Just differentiating V C++ 6 vs. everything else here.
#if _MSC_VER == 1200
#import "msxml6.dll" raw_interfaces_only
using namespace MSXML2;
#else
#include <msxml2.h>
#endif
#include "Common.h"
#include "SearchProvider.h"
SearchProvider::SearchProvider() {
m_hInternet = InternetOpen(TEXT("winmapviewer"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!m_hInternet) {
throw "Unable to initialize WinINet.";
}
}
SearchProvider::~SearchProvider() {
InternetCloseHandle(m_hInternet);
}
std::wstring* SearchProvider::doQuery(std::wstring locationName) {
// TODO: set up proxy and use proxy URL
std::stringstream strstr;
strstr << "http://nominatim.openstreetmap.org/search?format=xml&limit=35&q=" << urlEncode(locationName);
// TODO: Add user agent and explicit referer header
HINTERNET hUrl = InternetOpenUrl(m_hInternet, strstr.str().c_str(), NULL, 0, 0, 0);
if (!hUrl) {
throw "Unable to do nominatim request.";
}
std::string rawResult;
char buffer[10240];
DWORD bytesRead = 0;
while (InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead) && bytesRead != 0) {
rawResult.append(buffer, bytesRead);
}
InternetCloseHandle(hUrl);
int length = MultiByteToWideChar(CP_UTF8, 0, rawResult.c_str(), rawResult.size(), 0, 0);
std::wstring* result = new std::wstring(length, L'\0');
MultiByteToWideChar(CP_UTF8, 0, rawResult.c_str(), rawResult.size(), &((*result)[0]), length);
return result;
}
std::wstring getAttribute(IXMLDOMNamedNodeMap* attrs, const wchar_t* attributeName) {
IXMLDOMNode* attr = NULL;
attrs->getNamedItem(SysAllocString(attributeName), &attr);
if (!attr) {
throw "Missing attribute.";
}
BSTR rawValue;
attr->get_text(&rawValue);
std::wstring value(rawValue, SysStringLen(rawValue));
SysFreeString(rawValue);
attr->Release();
return value;
}
std::vector<SearchResult> SearchProvider::search(std::wstring locationName, std::vector<SearchResult> searchResults) {
std::wstring* rawXml = doQuery(locationName);
CoInitialize(NULL);
IXMLDOMDocument* doc = NULL;
HRESULT hr = CoCreateInstance(
__uuidof(DOMDocument60),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IXMLDOMDocument2),
(void**)&doc
);
if (FAILED(hr)) {
throw "MSXML not available.";
}
doc->put_async(VARIANT_FALSE);
doc->put_validateOnParse(VARIANT_FALSE);
doc->put_resolveExternals(VARIANT_FALSE);
VARIANT_BOOL ok = VARIANT_FALSE;
BSTR b = SysAllocString(rawXml->c_str());
doc->loadXML(b, &ok);
SysFreeString(b);
delete rawXml;
if (ok != VARIANT_TRUE) {
doc->Release();
CoUninitialize();
// throw "Failed to load XML.";
return searchResults;
}
IXMLDOMNodeList* places = NULL;
doc->selectNodes(SysAllocString(L"//place"), &places);
long count = 0;
places->get_length(&count);
for (long i = 0; i < count; i++) {
IXMLDOMNode* node = NULL;
places->get_item(i, &node);
IXMLDOMNamedNodeMap* attrs = NULL;
node->get_attributes(&attrs);
LonLat lonLat = {
wcstod(getAttribute(attrs, L"lon").c_str(), NULL),
wcstod(getAttribute(attrs, L"lat").c_str(), NULL)
};
SearchResult searchResult;
searchResult.m_displayName = getAttribute(attrs, L"display_name");
searchResult.m_osmType = getAttribute(attrs, L"osm_type");
searchResult.m_osmId = getAttribute(attrs, L"osm_id");
searchResult.m_class = getAttribute(attrs, L"class");
searchResult.m_type = getAttribute(attrs, L"type");
searchResult.m_lonLat = lonLat;
searchResults.push_back(searchResult);
attrs->Release();
node->Release();
}
doc->Release();
CoUninitialize();
return searchResults;
}