// Host Update // // Douglas Thrift // // $Id$ #include "HostUpdate.hpp" #include "Host.hpp" #ifndef _WIN32 extern "C" { #include } #else #include #endif int main(int argc, char* argv[]) { #ifndef _WIN32 res_init(); for (short index(0); index < MAXNS; ++index) { if (index + 1 < MAXNS) { memcpy(&_res.nsaddr_list[index].sin_addr, &_res.nsaddr_list[index + 1].sin_addr, sizeof(in_addr_t)); } else { memset(&_res.nsaddr_list[index].sin_addr, 0, sizeof(in_addr_t)); } } #endif HostUpdate update; return 0; } HostUpdate::HostUpdate() : host(false), name(false), address(false), platform(false), since(false) { struct stat* hosts = new struct stat; if (stat("hosts", hosts) != 0) { mkdir("hosts"); } delete [] hosts; string agent = sgetenv("HTTP_USER_AGENT"); string method = sgetenv("REQUEST_METHOD"); parse(method); mode(); if (agent.find("Host Update/") == 0 && method == "POST" && agent.find(" (") != string::npos && agent.find(") libwww-perl/") != string::npos) { update(agent); } else if (agent.find("Host Update Sharp/") == 0 && method == "POST" && agent.find(" (") != string::npos && agent.find(')') != string::npos) { update(agent); } else { display(); } } void HostUpdate::parse(const string& method) { string query; if (method == "POST") { getline(cin, query); } else { query = sgetenv("QUERY_STRING"); } if (query == "") return; istringstream input(query); do { string name, value; getline(input, name, '='); getline(input, value, '&'); cgi.insert(pair(name, value)); } while (input.good()); } void HostUpdate::mode() { for (multimap::iterator itor(cgi.find("mode")); itor != cgi.upper_bound("mode") && itor != cgi.end(); itor++) { string mode(itor->second); for (string::iterator itor(mode.begin()); itor != mode.end(); itor++) { char mode(*itor); switch (mode) { case 'h': if (!host) host = true; break; case 'n': if (!name) name = true; break; case 'a': if (!address) address = true; break; case 'p': if (!platform) platform = true; break; case 's': if (!since) since = true; break; default: break; } } } if (!host && !name && !address && !platform && !since) host = true, name = true, address = true, platform = true, since = true; } void HostUpdate::update(const string& agent) { cout << "Content-Type: text/plain\n\n"; multimap::iterator itor = cgi.find("host"); if (itor == cgi.end()) return; if (itor->second == "") return; string host(itor->second), name(sgetenv("REMOTE_HOST")), address(sgetenv("REMOTE_ADDR")); string::size_type begin(agent.find('(') + 1), end(agent.rfind(')')); if (begin >= end) return; string platform(agent.substr(begin, end - begin)); Host client(host, name, address, platform), saved(host); if (client != ++saved) client--; display(client); } void HostUpdate::display() { cout << "Content-Type: text/plain\n\n"; { bool request(false); for (multimap::iterator itor(cgi.find("host")); itor != cgi.upper_bound("host") && itor != cgi.end(); itor++) { if (!itor->second.empty()) { Host host(itor->second); display(++host); if (!request) request = true; } } if (request) return; } set hosts; #ifndef _WIN32 DIR* dir(opendir("hosts")); struct dirent* ent; while ((ent = readdir(dir)) != NULL) { string file(ent->d_name); if (file == "." || file == "..") continue; Host host(file); hosts.insert(++host); } closedir(dir); #else WIN32_FIND_DATA found; HANDLE find(FindFirstFile("hosts\\*", &found)); do { string file(found.cFileName); if (file == "." || file == "..") continue; Host host(file); hosts.insert(++host); } while (FindNextFile(find, &found) != 0); FindClose(find); #endif for (set::iterator itor(hosts.begin()); itor != hosts.end(); itor++) { display(*itor); } } void HostUpdate::display(const Host& host) { if (this->host) cout << "host=" << host.getHost() << '\n'; if (name) cout << "name=" << host.getName() << '\n'; if (address) cout << "address=" << host.getAddress() << '\n'; if (platform) cout << "platform=" << host.getPlatform() << '\n'; string name(string("hosts") + slash + host.getHost()); struct stat file; if (since && stat(name.c_str(), &file) == 0) { char since[20]; strftime(since, 20, "%m/%d/%Y %H:%M:%S", gmtime(&file.st_mtime)); cout << "since=" << since << " GMT\n"; } else if (since) { char since[20]; time_t now(time(NULL)); strftime(since, 20, "%m/%d/%Y %H:%M:%S", gmtime(&now)); cout << "since=" << since << " GMT\n"; } }