1// Copyright (c) 2009, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
31#include "common/linux/google_crashdump_uploader.h"
32
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <unistd.h>
36
37#include <iostream>
38
39#include "common/using_std_string.h"
40
41namespace google_breakpad {
42
43GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
44                                                 const string& version,
45                                                 const string& guid,
46                                                 const string& ptime,
47                                                 const string& ctime,
48                                                 const string& email,
49                                                 const string& comments,
50                                                 const string& minidump_pathname,
51                                                 const string& crash_server,
52                                                 const string& proxy_host,
53                                                 const string& proxy_userpassword) {
54  LibcurlWrapper* http_layer = new LibcurlWrapper();
55  Init(product,
56       version,
57       guid,
58       ptime,
59       ctime,
60       email,
61       comments,
62       minidump_pathname,
63       crash_server,
64       proxy_host,
65       proxy_userpassword,
66       http_layer);
67}
68
69GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
70                                                 const string& version,
71                                                 const string& guid,
72                                                 const string& ptime,
73                                                 const string& ctime,
74                                                 const string& email,
75                                                 const string& comments,
76                                                 const string& minidump_pathname,
77                                                 const string& crash_server,
78                                                 const string& proxy_host,
79                                                 const string& proxy_userpassword,
80                                                 LibcurlWrapper* http_layer) {
81  Init(product,
82       version,
83       guid,
84       ptime,
85       ctime,
86       email,
87       comments,
88       minidump_pathname,
89       crash_server,
90       proxy_host,
91       proxy_userpassword,
92       http_layer);
93}
94
95void GoogleCrashdumpUploader::Init(const string& product,
96                                   const string& version,
97                                   const string& guid,
98                                   const string& ptime,
99                                   const string& ctime,
100                                   const string& email,
101                                   const string& comments,
102                                   const string& minidump_pathname,
103                                   const string& crash_server,
104                                   const string& proxy_host,
105                                   const string& proxy_userpassword,
106                                   LibcurlWrapper* http_layer) {
107  product_ = product;
108  version_ = version;
109  guid_ = guid;
110  ptime_ = ptime;
111  ctime_ = ctime;
112  email_ = email;
113  comments_ = comments;
114  http_layer_.reset(http_layer);
115
116  crash_server_ = crash_server;
117  proxy_host_ = proxy_host;
118  proxy_userpassword_ = proxy_userpassword;
119  minidump_pathname_ = minidump_pathname;
120  std::cout << "Uploader initializing";
121  std::cout << "\tProduct: " << product_;
122  std::cout << "\tVersion: " << version_;
123  std::cout << "\tGUID: " << guid_;
124  if (!ptime_.empty()) {
125    std::cout << "\tProcess uptime: " << ptime_;
126  }
127  if (!ctime_.empty()) {
128    std::cout << "\tCumulative Process uptime: " << ctime_;
129  }
130  if (!email_.empty()) {
131    std::cout << "\tEmail: " << email_;
132  }
133  if (!comments_.empty()) {
134    std::cout << "\tComments: " << comments_;
135  }
136}
137
138bool GoogleCrashdumpUploader::CheckRequiredParametersArePresent() {
139  string error_text;
140  if (product_.empty()) {
141    error_text.append("\nProduct name must be specified.");
142  }
143
144  if (version_.empty()) {
145    error_text.append("\nProduct version must be specified.");
146  }
147
148  if (guid_.empty()) {
149    error_text.append("\nClient ID must be specified.");
150  }
151
152  if (minidump_pathname_.empty()) {
153    error_text.append("\nMinidump pathname must be specified.");
154  }
155
156  if (!error_text.empty()) {
157    std::cout << error_text;
158    return false;
159  }
160  return true;
161
162}
163
164bool GoogleCrashdumpUploader::Upload(int* http_status_code,
165                                     string* http_response_header,
166                                     string* http_response_body) {
167  bool ok = http_layer_->Init();
168  if (!ok) {
169    std::cout << "http layer init failed";
170    return ok;
171  }
172
173  if (!CheckRequiredParametersArePresent()) {
174    return false;
175  }
176
177  struct stat st;
178  int err = stat(minidump_pathname_.c_str(), &st);
179  if (err) {
180    std::cout << minidump_pathname_ << " could not be found";
181    return false;
182  }
183
184  parameters_["prod"] = product_;
185  parameters_["ver"] = version_;
186  parameters_["guid"] = guid_;
187  parameters_["ptime"] = ptime_;
188  parameters_["ctime"] = ctime_;
189  parameters_["email"] = email_;
190  parameters_["comments_"] = comments_;
191  if (!http_layer_->AddFile(minidump_pathname_,
192                            "upload_file_minidump")) {
193    return false;
194  }
195  std::cout << "Sending request to " << crash_server_;
196  return http_layer_->SendRequest(crash_server_,
197                                  parameters_,
198                                  http_status_code,
199                                  http_response_header,
200                                  http_response_body);
201}
202}
203