1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <desktop/minidump.hxx>
18 #include <curl/curl.h>
20 static const char kUserAgent
[] = "Breakpad/1.0 (Linux)";
22 static std::map
<std::string
, std::string
> readStrings(std::istream
& file
)
24 std::map
<std::string
, std::string
> parameters
;
26 // when file is not readable, the status eof would not be set
27 // better test of state is okay
31 std::getline(file
, line
);
32 int sep
= line
.find('=');
35 std::string key
= line
.substr(0, sep
);
36 std::string value
= line
.substr(sep
+ 1);
37 parameters
[key
] = value
;
44 // Callback to get the response data from server.
45 static size_t WriteCallback(void const *ptr
, size_t size
,
46 size_t nmemb
, void *userp
)
51 std::string
* response
= static_cast<std::string
*>(userp
);
52 size_t real_size
= size
* nmemb
;
53 response
->append(static_cast<char const *>(ptr
), real_size
);
57 static void getProperty(const std::string
& key
, std::string
& value
,
58 std::map
<std::string
, std::string
>& parameters
)
60 auto itr
= parameters
.find(key
);
61 if (itr
!= parameters
.end())
64 parameters
.erase(itr
);
68 static std::string
generate_json(const std::map
<std::string
, std::string
>& parameters
)
70 std::ostringstream stream
;
73 for (auto itr
= parameters
.begin(), itrEnd
= parameters
.end(); itr
!= itrEnd
; ++itr
)
80 stream
<< "\"" << itr
->first
<< "\": \"" << itr
->second
<< "\"";
87 static bool uploadContent(std::map
<std::string
, std::string
>& parameters
, std::string
& response
)
89 CURL
* curl
= curl_easy_init();
93 std::string proxy
, proxy_user_pwd
, ca_certificate_file
, file
, url
, version
;
95 getProperty("Proxy", proxy
, parameters
);
96 getProperty("ProxyUserPW", proxy_user_pwd
, parameters
);
97 getProperty("CAFile", ca_certificate_file
, parameters
);
99 getProperty("DumpFile", file
, parameters
);
100 getProperty("URL", url
, parameters
);
101 getProperty("Version", version
, parameters
);
111 curl_easy_setopt(curl
, CURLOPT_URL
, url
.c_str());
112 curl_easy_setopt(curl
, CURLOPT_USERAGENT
, kUserAgent
);
113 curl_easy_setopt(curl
, CURLOPT_SSL_VERIFYPEER
, false);
114 // Set proxy information if necessary.
117 curl_easy_setopt(curl
, CURLOPT_PROXY
, proxy
.c_str());
119 curl_easy_setopt(curl
, CURLOPT_PROXYAUTH
, CURLAUTH_ANYSAFE
);
121 if (!proxy_user_pwd
.empty())
122 curl_easy_setopt(curl
, CURLOPT_PROXYUSERPWD
, proxy_user_pwd
.c_str());
124 curl_easy_setopt(curl
, CURLOPT_PROXYUSERPWD
, ":");
127 if (!ca_certificate_file
.empty())
128 curl_easy_setopt(curl
, CURLOPT_CAINFO
, ca_certificate_file
.c_str());
130 curl_httppost
* formpost
= nullptr;
131 curl_httppost
* lastptr
= nullptr;
132 std::string additional_data
= generate_json(parameters
);
133 curl_formadd(&formpost
, &lastptr
,
134 CURLFORM_COPYNAME
, "AdditionalData",
135 CURLFORM_COPYCONTENTS
, additional_data
.c_str(),
138 curl_formadd(&formpost
, &lastptr
,
139 CURLFORM_COPYNAME
, "Version",
140 CURLFORM_COPYCONTENTS
, version
.c_str(),
143 std::string response_body
;
145 curl_formadd(&formpost
, &lastptr
,
146 CURLFORM_COPYNAME
, "upload_file_minidump",
147 CURLFORM_FILE
, file
.c_str(),
150 curl_easy_setopt(curl
, CURLOPT_HTTPPOST
, formpost
);
153 // Disable 100-continue header.
154 char buf
[] = "Expect:";
155 curl_slist
* headerlist
= nullptr;
156 headerlist
= curl_slist_append(headerlist
, buf
);
157 curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, headerlist
);
159 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, WriteCallback
);
160 curl_easy_setopt(curl
, CURLOPT_WRITEDATA
,
161 static_cast<void *>(&response_body
));
163 // Fail if 400+ is returned from the web server.
164 curl_easy_setopt(curl
, CURLOPT_FAILONERROR
, 1);
166 CURLcode cc
= curl_easy_perform(curl
);
167 curl_easy_getinfo(curl
, CURLINFO_RESPONSE_CODE
, &response_code
);
170 fprintf(stderr
, "Failed to send http request to %s, error: %s\n",
172 curl_easy_strerror(cc
));
175 if (formpost
!= nullptr)
177 curl_formfree(formpost
);
179 if (headerlist
!= nullptr)
181 curl_slist_free_all(headerlist
);
184 response
= response_body
;
192 namespace crashreport
{
194 bool readConfig(const std::string
& iniPath
, std::string
* response
)
196 std::ifstream
file(iniPath
);
197 std::map
<std::string
, std::string
> parameters
= readStrings(file
);
199 // make sure that at least the mandatory parameters are in there
200 if (parameters
.find("DumpFile") == parameters
.end())
202 if(response
!= nullptr)
203 *response
= "ini file needs to contain a key DumpFile!";
207 if (parameters
.find("Version") == parameters
.end())
209 if (response
!= nullptr)
210 *response
= "ini file needs to contain a key Version!";
214 if (parameters
.find("URL") == parameters
.end())
216 if (response
!= nullptr)
217 *response
= "ini file needs to contain a key URL!";
221 if (response
!= nullptr)
222 return uploadContent(parameters
, *response
);
229 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */