// Host Update // // Douglas Thrift // // $Id$ #include "HostUpdate.hpp" #include "Host.hpp" #ifdef _WIN32 #include #endif int main(int argc, char* argv[]) { HostUpdate update; return 0; } HostUpdate::HostUpdate() { 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 { 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() { host = false, name = false, address = false, platform = false, since = false; for (multimap::iterator itor = cgi.find("mode"); itor != cgi.upper_bound("mode"); 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.find(')', begin); 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++) { if (itor->second != "") { 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 = new time_t; time(now); strftime(since, 20, "%m/%d/%Y %H:%M:%S", gmtime(now)); delete now; cout << "since=" << since << " GMT\n"; } }