xref: /aosp_15_r20/external/google-breakpad/src/common/windows/symbol_collector_client.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>  // Must come first
3 #endif
4 
5 #include "common/windows/symbol_collector_client.h"
6 
7 #include <stdio.h>
8 
9 #include <regex>
10 
11 #include "common/windows/http_upload.h"
12 
13 namespace google_breakpad {
14 
15   // static
CreateUploadUrl(wstring & api_url,wstring & api_key,int * timeout_ms,UploadUrlResponse * uploadUrlResponse)16   bool SymbolCollectorClient::CreateUploadUrl(
17       wstring& api_url,
18       wstring& api_key,
19       int* timeout_ms,
20       UploadUrlResponse *uploadUrlResponse) {
21     wstring url = api_url +
22         L"/v1/uploads:create"
23         L"?key=" + api_key;
24     wstring response;
25     int response_code;
26 
27     if (!HTTPUpload::SendSimplePostRequest(
28         url,
29         L"",
30         L"",
31         timeout_ms,
32         &response,
33         &response_code)) {
34       wprintf(L"Failed to create upload url.\n");
35       wprintf(L"Response code: %ld\n", response_code);
36       wprintf(L"Response:\n");
37       wprintf(L"%s\n", response.c_str());
38       return false;
39     }
40 
41     // Note camel-case rather than underscores.
42     std::wregex upload_url_regex(L"\"uploadUrl\": \"([^\"]+)\"");
43     std::wregex upload_key_regex(L"\"uploadKey\": \"([^\"]+)\"");
44 
45     std::wsmatch upload_url_match;
46     if (!std::regex_search(response, upload_url_match, upload_url_regex) ||
47         upload_url_match.size() != 2) {
48       wprintf(L"Failed to parse create url response.");
49       wprintf(L"Response:\n");
50       wprintf(L"%s\n", response.c_str());
51       return false;
52     }
53     wstring upload_url = upload_url_match[1].str();
54 
55     std::wsmatch upload_key_match;
56     if (!std::regex_search(response, upload_key_match, upload_key_regex) ||
57         upload_key_match.size() != 2) {
58       wprintf(L"Failed to parse create url response.");
59       wprintf(L"Response:\n");
60       wprintf(L"%s\n", response.c_str());
61       return false;
62     }
63     wstring upload_key = upload_key_match[1].str();
64 
65     uploadUrlResponse->upload_url = upload_url;
66     uploadUrlResponse->upload_key = upload_key;
67     return true;
68   }
69 
70   // static
CompleteUpload(wstring & api_url,wstring & api_key,int * timeout_ms,const wstring & upload_key,const wstring & debug_file,const wstring & debug_id,const wstring & type,const wstring & product_name)71   CompleteUploadResult SymbolCollectorClient::CompleteUpload(
72       wstring& api_url,
73       wstring& api_key,
74       int* timeout_ms,
75       const wstring& upload_key,
76       const wstring& debug_file,
77       const wstring& debug_id,
78       const wstring& type,
79       const wstring& product_name) {
80     wstring url = api_url +
81         L"/v1/uploads/" + upload_key + L":complete"
82         L"?key=" + api_key;
83     wstring body =
84         L"{ symbol_id: {"
85         L"debug_file: \"" +
86         debug_file +
87         L"\", "
88         L"debug_id: \"" +
89         debug_id +
90         L"\" "
91         L"}, ";
92     if (!product_name.empty()) {
93       body +=
94           L"metadata: {"
95           L"product_name: \"" +
96           product_name +
97           L"\""
98           L"},";
99     }
100     body += L"symbol_upload_type: \"" + type +
101             L"\", "
102             L"use_async_processing: true }";
103     wstring response;
104     int response_code;
105 
106     if (!HTTPUpload::SendSimplePostRequest(
107         url,
108         body,
109         L"application/json",
110         timeout_ms,
111         &response,
112         &response_code)) {
113       wprintf(L"Failed to complete upload.\n");
114       wprintf(L"Response code: %ld\n", response_code);
115       wprintf(L"Response:\n");
116       wprintf(L"%s\n", response.c_str());
117       return CompleteUploadResult::Error;
118     }
119 
120     std::wregex result_regex(L"\"result\": \"([^\"]+)\"");
121     std::wsmatch result_match;
122     if (!std::regex_search(response, result_match, result_regex) ||
123         result_match.size() != 2) {
124       wprintf(L"Failed to parse complete upload response.");
125       wprintf(L"Response:\n");
126       wprintf(L"%s\n", response.c_str());
127       return CompleteUploadResult::Error;
128     }
129     wstring result = result_match[1].str();
130 
131     if (result.compare(L"DUPLICATE_DATA") == 0) {
132       return CompleteUploadResult::DuplicateData;
133     }
134 
135     return CompleteUploadResult::Ok;
136   }
137 
138   // static
CheckSymbolStatus(wstring & api_url,wstring & api_key,int * timeout_ms,const wstring & debug_file,const wstring & debug_id)139   SymbolStatus SymbolCollectorClient::CheckSymbolStatus(
140       wstring& api_url,
141       wstring& api_key,
142       int* timeout_ms,
143       const wstring& debug_file,
144       const wstring& debug_id) {
145     wstring response;
146     int response_code;
147     wstring url = api_url +
148         L"/v1/symbols/" + debug_file + L"/" + debug_id + L":checkStatus"
149         L"?key=" + api_key;
150 
151     if (!HTTPUpload::SendGetRequest(
152         url,
153         timeout_ms,
154         &response,
155         &response_code)) {
156       wprintf(L"Failed to check symbol status.\n");
157       wprintf(L"Response code: %ld\n", response_code);
158       wprintf(L"Response:\n");
159       wprintf(L"%s\n", response.c_str());
160       return SymbolStatus::Unknown;
161     }
162 
163     std::wregex status_regex(L"\"status\": \"([^\"]+)\"");
164     std::wsmatch status_match;
165     if (!std::regex_search(response, status_match, status_regex) ||
166         status_match.size() != 2) {
167       wprintf(L"Failed to parse check symbol status response.");
168       wprintf(L"Response:\n");
169       wprintf(L"%s\n", response.c_str());
170       return SymbolStatus::Unknown;
171     }
172     wstring status = status_match[1].str();
173 
174     return (status.compare(L"FOUND") == 0) ?
175       SymbolStatus::Found :
176       SymbolStatus::Missing;
177   }
178 
179 }  // namespace google_breakpad