OLD | NEW |
| (Empty) |
1 // Copyright 2008 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 #include "omaha/client/help_url_builder.h" | |
16 #include <windows.h> | |
17 #include <atlstr.h> | |
18 #include <vector> | |
19 #include "omaha/base/debug.h" | |
20 #include "omaha/base/logging.h" | |
21 #include "omaha/base/omaha_version.h" | |
22 #include "omaha/base/string.h" | |
23 #include "omaha/base/utils.h" | |
24 #include "omaha/base/vistautil.h" | |
25 #include "omaha/common/config_manager.h" | |
26 #include "omaha/common/goopdate_utils.h" | |
27 #include "goopdate/omaha3_idl.h" | |
28 #include "omaha/net/http_client.h" | |
29 | |
30 namespace omaha { | |
31 | |
32 namespace { | |
33 | |
34 // Query element name-value pair. | |
35 typedef std::pair<CString, CString> QueryElement; | |
36 | |
37 // Builds a query string from the provided name-value pairs. | |
38 // The string does not begin or end in a pair separator. | |
39 HRESULT BuildQueryString(const std::vector<QueryElement>& elements, | |
40 CString* query) { | |
41 ASSERT1(query); | |
42 | |
43 query->Empty(); | |
44 | |
45 for (size_t i = 0; i < elements.size(); ++i) { | |
46 CString escaped_str; | |
47 HRESULT hr = StringEscape(elements[i].second, false, &escaped_str); | |
48 if (FAILED(hr)) { | |
49 CORE_LOG(LEVEL_WARNING, (_T("[StringEscape failed][0x%08x]"), hr)); | |
50 return hr; | |
51 } | |
52 | |
53 CString element; | |
54 element.FormatMessage(_T("%1=%2"), elements[i].first, escaped_str); | |
55 | |
56 if (0 < i) { | |
57 query->Append(_T("&")); | |
58 } | |
59 query->Append(element); | |
60 } | |
61 | |
62 return S_OK; | |
63 } | |
64 | |
65 } // namespace | |
66 | |
67 HRESULT HelpUrlBuilder::BuildUrl(const std::vector<AppResult>& app_results, | |
68 CString* help_url) const { | |
69 ASSERT1(help_url); | |
70 help_url->Empty(); | |
71 | |
72 CString more_info_url; | |
73 VERIFY1(SUCCEEDED(ConfigManager::Instance()->GetMoreInfoUrl(&more_info_url))); | |
74 | |
75 const TCHAR* const kHelpLinkSourceId = _T("gethelp"); | |
76 HRESULT hr = BuildHttpGetString(more_info_url, | |
77 app_results, | |
78 GetVersionString(), | |
79 kHelpLinkSourceId, | |
80 help_url); | |
81 if (FAILED(hr)) { | |
82 // Make sure a failed URL is not displayed. | |
83 help_url->Empty(); | |
84 return hr; | |
85 } | |
86 | |
87 return S_OK; | |
88 } | |
89 | |
90 HRESULT HelpUrlBuilder::BuildHttpGetString( | |
91 const CString& service_url, | |
92 const std::vector<AppResult>& app_results, | |
93 const CString& goopdate_version, | |
94 const CString& source_id, | |
95 CString* get_request) const { | |
96 ASSERT1(get_request); | |
97 if (service_url.IsEmpty()) { | |
98 return E_INVALIDARG; | |
99 } | |
100 ASSERT1(_T('?') == service_url.GetAt(service_url.GetLength() - 1) || | |
101 _T('&') == service_url.GetAt(service_url.GetLength() - 1)); | |
102 | |
103 CString os_version; | |
104 CString service_pack; | |
105 HRESULT hr = goopdate_utils::GetOSInfo(&os_version, &service_pack); | |
106 if (FAILED(hr)) { | |
107 CORE_LOG(LEVEL_WARNING, (_T("[GetOSInfo failed][0x%08x]"), hr)); | |
108 } | |
109 const CString iid_string = | |
110 ::IsEqualGUID(GUID_NULL, iid_) ? _T("") : GuidToString(iid_); | |
111 | |
112 std::vector<QueryElement> elements; | |
113 elements.push_back(QueryElement(_T("hl"), language_)); | |
114 | |
115 CString error_code_str; | |
116 CString extra_code_str; | |
117 CString element_name; | |
118 for (std::vector<AppResult>::size_type i = 0; i < app_results.size(); ++i) { | |
119 error_code_str.Format(_T("0x%x"), app_results[i].error_code); | |
120 extra_code_str.Format(_T("%d"), app_results[i].extra_code); | |
121 element_name.Format(_T("app.%d"), i); | |
122 elements.push_back(QueryElement(element_name, app_results[i].guid)); | |
123 element_name.Format(_T("ec.%d"), i); | |
124 elements.push_back(QueryElement(element_name, error_code_str)); | |
125 element_name.Format(_T("ex.%d"), i); | |
126 elements.push_back(QueryElement(element_name, extra_code_str)); | |
127 } | |
128 | |
129 elements.push_back(QueryElement(_T("guver"), goopdate_version)); | |
130 elements.push_back(QueryElement(_T("m"), is_machine_ ? _T("1") : _T("0"))); | |
131 elements.push_back(QueryElement(_T("os"), os_version)); | |
132 elements.push_back(QueryElement(_T("sp"), service_pack)); | |
133 elements.push_back(QueryElement(_T("iid"), iid_string)); | |
134 elements.push_back(QueryElement(_T("brand"), brand_)); | |
135 elements.push_back(QueryElement(_T("source"), source_id)); | |
136 | |
137 CString test_source = ConfigManager::Instance()->GetTestSource(); | |
138 if (!test_source.IsEmpty()) { | |
139 elements.push_back(QueryElement(_T("testsource"), test_source)); | |
140 } | |
141 | |
142 CString query; | |
143 hr = BuildQueryString(elements, &query); | |
144 if (FAILED(hr)) { | |
145 CORE_LOG(LEVEL_WARNING, (_T("[BuildQueryString failed][0x%08x]"), hr)); | |
146 return hr; | |
147 } | |
148 get_request->FormatMessage(_T("%1%2"), service_url, query); | |
149 | |
150 // The length should be smaller than the maximum allowed get length. | |
151 ASSERT1(get_request->GetLength() <= INTERNET_MAX_URL_LENGTH); | |
152 if (get_request->GetLength() > INTERNET_MAX_URL_LENGTH) { | |
153 return E_FAIL; | |
154 } | |
155 | |
156 return S_OK; | |
157 } | |
158 | |
159 } // namespace omaha | |
OLD | NEW |