/***************************************************************************
* *
* Copyright (C) 2001 Grub, Inc. *
* File: ServerSettings.cpp *
* Author: Kord Campbell *
* *
* Description: *
* Server settings are obtained using cURL and contacting the server *
* with the correct client id and password. This function is fairly *
* easy to add to, just fix the server to pass additional settings, *
* and then change the calls below. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA *
* *
***************************************************************************/
#include "ServerSettings.h"
#ifndef GRUB_UNIX
#include "platform.h"
#define snprintf _snprintf
#endif
using namespace std;
struct MemoryStruct {
char *memory;
size_t size;
};
size_t SettingsWriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
register int realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory)
{
memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
return realsize;
}
int readServerSettings()
{
// set up our cURL session
CURL *curl_handle;
CURLcode curlerror;
CURLcode curlcode;
long httpcode = 0;
// set up memory space
struct MemoryStruct chunk;
// define some variables
char urlbuf[BUFLEN];
bool goodresults = true;
// integer stuff needs to be converted, so we define extra
// variables for holding their values till we do
char tempClientID[BUFLEN];
char tempAltClientID[BUFLEN];
char tempThreadsPerHost[BUFLEN];
char tempMaxAmountOfBandwidth[BUFLEN];
char tempNumOfCrawlersToRun[BUFLEN];
char tempPortNumber[BUFLEN];
char tempNewVersionFlag[BUFLEN];
char tempHistoricURLs[BUFLEN];
char tempTodaysURLs[BUFLEN];
char tempOverallURLRank[BUFLEN];
char tempDailyURLRank[BUFLEN];
// set the url to fetch our info
snprintf(urlbuf, sizeof(urlbuf), SERVERURL, PACKAGE, VERSION, Config_File_Info.ClientID, Config_File_Info.ClientPassword);
urlbuf[sizeof(urlbuf)-1] = '\0';
// log the URL that we used
CLog(GCLOG_INFO, "Server setting fetch url is: %s", urlbuf);
// clear our our chunk memory
chunk.memory=NULL;
chunk.size = 0;
// initiate the cURL stuff
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, urlbuf);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, SettingsWriteMemoryCallback);
curl_easy_setopt(curl_handle, CURLOPT_FILE, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, CURL_TIMEOUT);
// if proxy information was specified in our config file, we use it here
if ( strcmp(Config_File_Info.Proxy, "") )
{
if (!(Config_File_Info.ProxyPort == 0))
{
curl_easy_setopt(curl_handle, CURLOPT_PROXYPORT, Config_File_Info.ProxyPort);
curl_easy_setopt(curl_handle, CURLOPT_PROXY, Config_File_Info.Proxy);
if (Config_File_Info.ProxyUserName != NULL && *Config_File_Info.ProxyUserName != '\0' &&
Config_File_Info.ProxyPassword != NULL && *Config_File_Info.ProxyPassword != '\0' )
{
static char buff[1000];
sprintf(buff,"%s:%s", Config_File_Info.ProxyUserName, Config_File_Info.ProxyPassword);
curl_easy_setopt(curl_handle, CURLOPT_PROXYUSERPWD, buff);
}
}
}
// perform the cURL fetch
curlerror = curl_easy_perform(curl_handle);
if (curlerror)
{
CLog(GCLOG_ERR, "Error contacting remote settings server.");
#ifdef GRUB_UNIX
free (chunk.memory);
#endif
return(1);
}
curlcode = curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CODE, &httpcode);
if (httpcode == 404) // page not found, we don't parse
{
CLog(GCLOG_ERR, "Error contacting server - page not found (404).");
#ifdef GRUB_UNIX
free (chunk.memory);
#endif
return(1);
}
// start parsing
if (chunk.size)
{
char *contents = chunk.memory;
CLog(GCLOG_INFO, "(readServerSettings) Result from server is: %s", contents);
if(parsethecontents(1, contents, tempClientID)) goodresults = false;
if(parsethecontents(2, contents, tempAltClientID)) goodresults = false;
if(parsethecontents(3, contents, tempThreadsPerHost)) goodresults = false;
if(parsethecontents(4, contents, tempMaxAmountOfBandwidth)) goodresults = false;
if(parsethecontents(5, contents, tempNumOfCrawlersToRun)) goodresults = false;
if(parsethecontents(6, contents, tempPortNumber)) goodresults = false;
if(parsethecontents(7, contents, tempNewVersionFlag)) goodresults = false;
if(parsethecontents(8, contents, tempHistoricURLs)) goodresults = false;
if(parsethecontents(9, contents, tempTodaysURLs)) goodresults = false;
if(parsethecontents(10, contents, tempOverallURLRank)) goodresults = false;
if(parsethecontents(11, contents, tempDailyURLRank)) goodresults = false;
}
if (!goodresults)
{
CLog(GCLOG_ERR, "(readServerSettings) Error parsing results - contact support@grub.org");
#ifdef GRUB_UNIX
free (chunk.memory);
#endif
return(1);
}
else
{
// check client id is the same, just in case
if (atoi(tempClientID) == Config_File_Info.ClientID)
{
// override the AltID with the one pulled from the server
sscanf(tempAltClientID, "%u", &(Config_File_Info.AltClientID));
// override the number of crawlers to run if larger than what the server says
if (Config_File_Info.NumOfCrawlersToRun > atoi(tempNumOfCrawlersToRun))
{
Config_File_Info.NumOfCrawlersToRun = atoi(tempNumOfCrawlersToRun);
}
// override the server port number regardless of what the config file says
if (Config_File_Info.PortNumber > atoi(tempPortNumber))
{
Config_File_Info.PortNumber = atoi(tempPortNumber);
}
// override the threads per host if larger than what the server says
if (Config_File_Info.ThreadsPerHost > atoi(tempThreadsPerHost))
{
Config_File_Info.ThreadsPerHost = atoi(tempThreadsPerHost);
}
// override the maximum amount of useable bandwidth if larger than what the
// server says. this could be used by grub to slow the entire crawling
// process down if there was a problem.
if(Config_File_Info.MaxAmountOfBandwidth > atoi(tempMaxAmountOfBandwidth))
{
Config_File_Info.MaxAmountOfBandwidth = atoi(tempMaxAmountOfBandwidth);
}
// override the maximum number of crawlers to run if larger than what the
// server says. this could be used to slow the crawling process as well.
if(Config_File_Info.NumOfCrawlersToRun > atoi(tempNumOfCrawlersToRun))
{
Config_File_Info.NumOfCrawlersToRun = atoi(tempNumOfCrawlersToRun);
}
// log upgrade recommendation or requirement if version flag was set
if (atoi(tempNewVersionFlag) == 1)
{
CLog(GCLOG_ERR, "(readServerSettings) Newer version available - please upgrade your client soon.");
}
else if (atoi(tempNewVersionFlag) ==2)
{
CLog(GCLOG_ERR, "(readServerSettings) Newer version available - upgrading your client is required.");
}
// set the flag in the global struct
Crawler_Status_Info.NewVersionFlag = atoi(tempNewVersionFlag);
// set the number crawled and ranking information
Crawler_Status_Info.HistoricURLs = atoi(tempHistoricURLs);
Crawler_Status_Info.TodaysURLs = atoi(tempTodaysURLs);
Crawler_Status_Info.OverallURLRank = atoi(tempOverallURLRank);
Crawler_Status_Info.DailyURLRank = atoi(tempDailyURLRank);
}
else
{
CLog(GCLOG_ERR, "(readServerSettings) Authentication error - check your password and clientid.");
#ifdef GRUB_UNIX
free (chunk.memory);
#endif
return(1);
}
}
#ifdef GRUB_UNIX
free (chunk.memory);
#endif
return(0);
}
int parsethecontents(int set_num, char *contents, char *setting)
{
// pointers for parsing
char *head, *body, *tail;
body = contents;
// find the set_num occurence of a ':'
for(int x = 0; x < set_num; x++)
{
// set to begining
head = body;
// seek to next colon
tail = strchr(head, ':');
// return if out of colons
if (tail == NULL)
{
CLog(GCLOG_ERR, "(readServerSettings) Tried to read past last available field!");
return(1);
}
// seek to next character
body = tail + 1;
}
// copy first entry to temp
strncpy(setting, head, tail-head);
// set end of string
setting[tail-head] = '\0';
// good to go
return(0);
}