xref: /aosp_15_r20/external/google-breakpad/src/client/windows/sender/crash_report_sender.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2006 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 // Disable exception handler warnings.
30 #pragma warning( disable : 4530 )
31 
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>  // Must come first
34 #endif
35 
36 #include <errno.h>
37 
38 #include "client/windows/sender/crash_report_sender.h"
39 #include "common/windows/http_upload.h"
40 
41 #if _MSC_VER < 1400  // MSVC 2005/8
42 // Older MSVC doesn't have fscanf_s, but they are compatible as long as
43 // we don't use the string conversions (%s/%c/%S/%C).
44 #define fscanf_s fscanf
45 #endif
46 
47 namespace google_breakpad {
48 
49 static const char kCheckpointSignature[] = "GBP1\n";
50 
CrashReportSender(const wstring & checkpoint_file)51 CrashReportSender::CrashReportSender(const wstring& checkpoint_file)
52     : checkpoint_file_(checkpoint_file),
53       max_reports_per_day_(-1),
54       last_sent_date_(-1),
55       reports_sent_(0) {
56   FILE* fd;
57   if (OpenCheckpointFile(L"r", &fd) == 0) {
58     ReadCheckpoint(fd);
59     fclose(fd);
60   }
61 }
62 
SendCrashReport(const wstring & url,const map<wstring,wstring> & parameters,const map<wstring,wstring> & files,wstring * report_code)63 ReportResult CrashReportSender::SendCrashReport(
64     const wstring& url, const map<wstring, wstring>& parameters,
65     const map<wstring, wstring>& files, wstring* report_code) {
66   int today = GetCurrentDate();
67   if (today == last_sent_date_ &&
68       max_reports_per_day_ != -1 &&
69       reports_sent_ >= max_reports_per_day_) {
70     return RESULT_THROTTLED;
71   }
72 
73   int http_response = 0;
74   bool result = HTTPUpload::SendMultipartPostRequest(
75     url, parameters, files, NULL, report_code,
76     &http_response);
77 
78   if (result) {
79     ReportSent(today);
80     return RESULT_SUCCEEDED;
81   } else if (http_response >= 400 && http_response < 500) {
82     return RESULT_REJECTED;
83   } else {
84     return RESULT_FAILED;
85   }
86 }
87 
ReadCheckpoint(FILE * fd)88 void CrashReportSender::ReadCheckpoint(FILE* fd) {
89   char buf[128];
90   if (!fgets(buf, sizeof(buf), fd) ||
91       strcmp(buf, kCheckpointSignature) != 0) {
92     return;
93   }
94 
95   if (fscanf_s(fd, "%d\n", &last_sent_date_) != 1) {
96     last_sent_date_ = -1;
97     return;
98   }
99   if (fscanf_s(fd, "%d\n", &reports_sent_) != 1) {
100     reports_sent_ = 0;
101     return;
102   }
103 }
104 
ReportSent(int today)105 void CrashReportSender::ReportSent(int today) {
106   // Update the report stats
107   if (today != last_sent_date_) {
108     last_sent_date_ = today;
109     reports_sent_ = 0;
110   }
111   ++reports_sent_;
112 
113   // Update the checkpoint file
114   FILE* fd;
115   if (OpenCheckpointFile(L"w", &fd) == 0) {
116     fputs(kCheckpointSignature, fd);
117     fprintf(fd, "%d\n", last_sent_date_);
118     fprintf(fd, "%d\n", reports_sent_);
119     fclose(fd);
120   }
121 }
122 
GetCurrentDate() const123 int CrashReportSender::GetCurrentDate() const {
124   SYSTEMTIME system_time;
125   GetSystemTime(&system_time);
126   return (system_time.wYear * 10000) + (system_time.wMonth * 100) +
127       system_time.wDay;
128 }
129 
OpenCheckpointFile(const wchar_t * mode,FILE ** fd)130 int CrashReportSender::OpenCheckpointFile(const wchar_t* mode, FILE** fd) {
131   if (checkpoint_file_.empty()) {
132     return ENOENT;
133   }
134 #if _MSC_VER >= 1400  // MSVC 2005/8
135   return _wfopen_s(fd, checkpoint_file_.c_str(), mode);
136 #else
137   *fd = _wfopen(checkpoint_file_.c_str(), mode);
138   if (*fd == NULL) {
139     return errno;
140   }
141   return 0;
142 #endif
143 }
144 
145 }  // namespace google_breakpad
146