libStatGen Software 1
Loading...
Searching...
No Matches
PhoneHome.cpp
1/*
2 * Copyright (C) 2013 Regents of the University of Michigan
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "PhoneHome.h"
19#include "knetfile.h"
20
21#include <time.h>
22#include <iostream>
23#include <string.h>
24
25int PhoneHome::allThinning = 50;
26int PhoneHome::ourNumber = -1;
27
28bool PhoneHome::ourEnableCompletionStatus = false;
29std::string PhoneHome::ourBaseURL = "http://csgph.sph.umich.edu/ph/";
30std::string PhoneHome::ourURL = ourBaseURL;
31char PhoneHome::ourPrefixChar = '?';
32String PhoneHome::ourReturnString = "";
33String PhoneHome::ourToolName = "";
34
35void PhoneHome::enableCompletionStatus(const char* programName)
36{
37 if(programName != NULL)
38 {
39 add("pgm", programName);
40 }
41 ourEnableCompletionStatus = true;
42}
43
44
45void PhoneHome::disableCompletionStatus()
46{
47 ourEnableCompletionStatus = false;
48}
49
50
51bool PhoneHome::checkVersion(const char* programName, const char* version,
52 const char* params)
53{
54 enableCompletionStatus();
55 add("pgm", programName);
56 add("vsn", version);
57 add("args", params);
58
59 connect();
60
61 // Look for this program in the returned string.
62 int start = ourReturnString.Find(ourToolName+"\t");
63 if(start < 0)
64 {
65 // Parse the toolName, and check for the program name
66 // just up to a ':'
67 int colStart = ourToolName.FastFindChar(':');
68 if(colStart >= 0)
69 {
70 ourToolName.SetLength(colStart);
71 start = ourReturnString.Find(ourToolName+"\t");
72 }
73 }
74
75 if(start < 0)
76 {
77 // This program name was not found in the version file,
78 // so it is a program for which version is not tracked,
79 // just return true.
80 return(true);
81 }
82
83 // Found this program, so extract the version.
84 start += ourToolName.Length();
85 while((start < ourReturnString.Length()) &&
86 isspace(ourReturnString[start]))
87 {
88 // Consume whitespace
89 ++start;
90 }
91
92 // Start now contains the position of the start of the version
93 String thisVersion = version;
94 String latestVersion;
95 int end = start;
96 while((end < ourReturnString.Length()) &&
97 !isspace(ourReturnString[end]))
98 {
99 latestVersion += ourReturnString[end];
100 ++end;
101 }
102
103 // std::cerr << "latest version = " << latestVersion << "\nthis version = " << thisVersion.c_str() << "\n";
104
105 if(latestVersion.FastCompare(thisVersion) > 0)
106 {
107 std::cerr << "\n**************************************************************************************\n"
108 << "A new version, " << latestVersion
109 << ", of " << ourToolName
110 << " is available (currently running "
111 << thisVersion.c_str() << ")"
112 << "\n**************************************************************************************\n\n";
113 return(false);
114 }
115 return(true);
116}
117
118void PhoneHome::completionStatus(const char* status, const char* programName)
119{
120 if(programName != NULL)
121 {
122 add("pgm", programName);
123 enableCompletionStatus();
124 }
125 if(ourEnableCompletionStatus)
126 {
127 add("status", status);
128 connect();
129 }
130}
131
132
133void PhoneHome::resetURL()
134{
135 ourURL = ourBaseURL;
136 ourPrefixChar = '?';
137}
138
139
140void PhoneHome::add(const char* name, const char* val)
141{
142 if((name != NULL) && (strlen(name) != 0) &&
143 (val != NULL) && (strlen(val) != 0))
144 {
145 // Check if the value is already set.
146 if(ourURL.find(name) != std::string::npos)
147 {
148 // value already set, so do not set it.
149 return;
150 }
151
152 // A value was passed in, so add it to the URL.
153 ourURL += ourPrefixChar;
154 ourURL += name;
155 ourURL += '=';
156 // If it is a tool name, trim anything before the last '/'
157 if(strstr(name, "pgm") != NULL)
158 {
159 // toolname, so trim the val.
160 const char* toolVal = strrchr(val, '/');
161 if(toolVal != NULL)
162 {
163 toolVal++;
164 }
165 else
166 {
167 toolVal = val;
168 }
169 ourURL.append(toolVal);
170 ourToolName = toolVal;
171 }
172 else
173 {
174 ourURL += val;
175 }
176 ourPrefixChar = '&';
177 }
178}
179
180
181bool PhoneHome::connect()
182{
183 if(ourNumber == -1)
184 {
185 srand (time(NULL));
186 ourNumber = rand();
187 String numString;
188 numString = ourNumber;
189 String thinningString;
190 thinningString = allThinning;
191 add("uniqNum", numString);
192 add("thinning", thinningString);
193 }
194 if((ourNumber % 100) >= allThinning)
195 {
196 // Skip phoneHome.
197 return(true);
198 }
199
200 // std::cerr << "url = " << ourURL << std::endl;
201 ourReturnString.Clear();
202 // return(true);
203#ifndef _NO_PHONEHOME
204 knet_silent(1);
205 knetFile *file = knet_open(ourURL.c_str(), "r");
206 if (file == 0) return(false);
207
208 const int BUF_SIZE = 100;
209 char buf[BUF_SIZE];
210
211 ssize_t readLen = BUF_SIZE-1;
212 ssize_t numRead = readLen;
213 while(numRead == readLen)
214 {
215 numRead = knet_read(file, buf, readLen);
216 buf[numRead] = '\0';
217 ourReturnString += buf;
218 }
219
220 knet_close(file);
221 knet_silent(0);
222 // std::cerr << "PhoneHome URL = " << ourReturnString.c_str() << std::endl;
223#endif
224 return(true);
225}