libStatGen Software
1
|
00001 /* 00002 * Copyright (C) 2013 Regents of the University of Michigan 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include "PhoneHome.h" 00019 #include "knetfile.h" 00020 00021 #include <time.h> 00022 #include <iostream> 00023 #include <string.h> 00024 00025 int PhoneHome::allThinning = 50; 00026 int PhoneHome::ourNumber = -1; 00027 00028 bool PhoneHome::ourEnableCompletionStatus = false; 00029 std::string PhoneHome::ourBaseURL = "http://csgph.sph.umich.edu/ph/"; 00030 std::string PhoneHome::ourURL = ourBaseURL; 00031 char PhoneHome::ourPrefixChar = '?'; 00032 String PhoneHome::ourReturnString = ""; 00033 String PhoneHome::ourToolName = ""; 00034 00035 void PhoneHome::enableCompletionStatus(const char* programName) 00036 { 00037 if(programName != NULL) 00038 { 00039 add("pgm", programName); 00040 } 00041 ourEnableCompletionStatus = true; 00042 } 00043 00044 00045 void PhoneHome::disableCompletionStatus() 00046 { 00047 ourEnableCompletionStatus = false; 00048 } 00049 00050 00051 bool PhoneHome::checkVersion(const char* programName, const char* version, 00052 const char* params) 00053 { 00054 enableCompletionStatus(); 00055 add("pgm", programName); 00056 add("vsn", version); 00057 add("args", params); 00058 00059 connect(); 00060 00061 // Look for this program in the returned string. 00062 int start = ourReturnString.Find(ourToolName+"\t"); 00063 if(start < 0) 00064 { 00065 // Parse the toolName, and check for the program name 00066 // just up to a ':' 00067 int colStart = ourToolName.FastFindChar(':'); 00068 if(colStart >= 0) 00069 { 00070 ourToolName.SetLength(colStart); 00071 start = ourReturnString.Find(ourToolName+"\t"); 00072 } 00073 } 00074 00075 if(start < 0) 00076 { 00077 // This program name was not found in the version file, 00078 // so it is a program for which version is not tracked, 00079 // just return true. 00080 return(true); 00081 } 00082 00083 // Found this program, so extract the version. 00084 start += ourToolName.Length(); 00085 while((start < ourReturnString.Length()) && 00086 isspace(ourReturnString[start])) 00087 { 00088 // Consume whitespace 00089 ++start; 00090 } 00091 00092 // Start now contains the position of the start of the version 00093 String thisVersion = version; 00094 String latestVersion; 00095 int end = start; 00096 while((end < ourReturnString.Length()) && 00097 !isspace(ourReturnString[end])) 00098 { 00099 latestVersion += ourReturnString[end]; 00100 ++end; 00101 } 00102 00103 // std::cerr << "latest version = " << latestVersion << "\nthis version = " << thisVersion.c_str() << "\n"; 00104 00105 if(latestVersion.FastCompare(thisVersion) > 0) 00106 { 00107 std::cerr << "\n**************************************************************************************\n" 00108 << "A new version, " << latestVersion 00109 << ", of " << ourToolName 00110 << " is available (currently running " 00111 << thisVersion.c_str() << ")" 00112 << "\n**************************************************************************************\n\n"; 00113 return(false); 00114 } 00115 return(true); 00116 } 00117 00118 void PhoneHome::completionStatus(const char* status, const char* programName) 00119 { 00120 if(programName != NULL) 00121 { 00122 add("pgm", programName); 00123 enableCompletionStatus(); 00124 } 00125 if(ourEnableCompletionStatus) 00126 { 00127 add("status", status); 00128 connect(); 00129 } 00130 } 00131 00132 00133 void PhoneHome::resetURL() 00134 { 00135 ourURL = ourBaseURL; 00136 ourPrefixChar = '?'; 00137 } 00138 00139 00140 void PhoneHome::add(const char* name, const char* val) 00141 { 00142 if((name != NULL) && (strlen(name) != 0) && 00143 (val != NULL) && (strlen(val) != 0)) 00144 { 00145 // Check if the value is already set. 00146 if(ourURL.find(name) != std::string::npos) 00147 { 00148 // value already set, so do not set it. 00149 return; 00150 } 00151 00152 // A value was passed in, so add it to the URL. 00153 ourURL += ourPrefixChar; 00154 ourURL += name; 00155 ourURL += '='; 00156 // If it is a tool name, trim anything before the last '/' 00157 if(strstr(name, "pgm") != NULL) 00158 { 00159 // toolname, so trim the val. 00160 const char* toolVal = strrchr(val, '/'); 00161 if(toolVal != NULL) 00162 { 00163 toolVal++; 00164 } 00165 else 00166 { 00167 toolVal = val; 00168 } 00169 ourURL.append(toolVal); 00170 ourToolName = toolVal; 00171 } 00172 else 00173 { 00174 ourURL += val; 00175 } 00176 ourPrefixChar = '&'; 00177 } 00178 } 00179 00180 00181 bool PhoneHome::connect() 00182 { 00183 if(ourNumber == -1) 00184 { 00185 srand (time(NULL)); 00186 ourNumber = rand(); 00187 String numString; 00188 numString = ourNumber; 00189 String thinningString; 00190 thinningString = allThinning; 00191 add("uniqNum", numString); 00192 add("thinning", thinningString); 00193 } 00194 if((ourNumber % 100) >= allThinning) 00195 { 00196 // Skip phoneHome. 00197 return(true); 00198 } 00199 00200 // std::cerr << "url = " << ourURL << std::endl; 00201 ourReturnString.Clear(); 00202 // return(true); 00203 #ifndef _NO_PHONEHOME 00204 knet_silent(1); 00205 knetFile *file = knet_open(ourURL.c_str(), "r"); 00206 if (file == 0) return(false); 00207 00208 const int BUF_SIZE = 100; 00209 char buf[BUF_SIZE]; 00210 00211 ssize_t readLen = BUF_SIZE-1; 00212 ssize_t numRead = readLen; 00213 while(numRead == readLen) 00214 { 00215 numRead = knet_read(file, buf, readLen); 00216 buf[numRead] = '\0'; 00217 ourReturnString += buf; 00218 } 00219 00220 knet_close(file); 00221 knet_silent(0); 00222 // std::cerr << "PhoneHome URL = " << ourReturnString.c_str() << std::endl; 00223 #endif 00224 return(true); 00225 }