// Zoe AIM Away Message RSS Feed Generator // // Seth King and Douglas Thrift // // $Id$ #include "Matcher/Matcher.hpp" #include "Collector.hpp" #include "Publisher.hpp" #include #include #include #include #include #include extern "C" { #include #include #include } struct ZoeCommand : public app::Application { virtual int Run(const app::ArgumentList& args) { Zoe::program = api::GetExecutablePath().GetName(); _foreach (app::ArgumentList, arg, args) { Matcher matcher; if (*arg == matcher("^-config=(.*)$")) { Zoe::config = matcher[1]; } else if (*arg == "-collector") { if (!Zoe::collector) Zoe::collector = true; } else if (*arg == "-publisher") { if (!Zoe::publisher) Zoe::publisher = true; } else if (*arg == "-color") { if (!Zoe::color) Zoe::color = true; } else if (*arg == "-D") { if (!Zoe::debug) Zoe::debug = true; } else { Zoe::usage(); return 1; } } Zoe zoe; return 0; } } zoe; Zoe::Zoe() { if (!(collector || publisher)) { usage(); return; } configure(); Collector collector(login, password, buddies, database, Zoe::collector); Publisher publisher(buddies, database, Zoe::publisher); } bool Zoe::debug(false), Zoe::collector(false), Zoe::publisher(false), Zoe::color(false); ext::String Zoe::program, Zoe::config("zoe.xml"); void Zoe::usage() { api::Cerr << "Usage: " << Zoe::program << " [-config=config] [-collector] [-publisher] [-color] [-D]" << ios::NewLine; } ext::String Zoe::generator(Generator generator) { ext::String generator_(generator == all || generator == agent ? "Zoe" : ""); switch (generator) { case all: generator_.InsertAllLast("/0.9"); case agent: { ::utsname system; ::uname(&system); generator_.InsertAllLast(ios::String() << " (" << system.sysname); } if (generator == agent) { generator_.InsertAllLast(")"); break; } else generator_.InsertAllLast("; "); case url: generator_.InsertAllLast("http://computers.douglasthrift.net/zoe.xml"); if (generator == all) generator_.InsertAllLast(")"); break; case version: generator_ = "0.9"; } return generator_; } void Zoe::configure() { if (debug) api::Cerr << "config = " << config << ios::NewLine; ext::Handle document(xml::Parse(config)); ext::Handle zoe(*document/"zoe"); login = *zoe/"login"; password = *zoe/"password"; database.driver = *zoe/"database"/"driver"; database.host = *zoe/"database"/"host"; database.user = *zoe/"database"/"user"; if ((*zoe/"database"/"password").IsEmpty()) { ext::String prompt(database.user + (!database.host.IsEmpty() ? "@" : "") + database.host + (!database.user.IsEmpty() ? "'s " : "") + "Database Password: "); char* password(getpass(prompt.NullTerminate())); database.password = password; for (size_t index(std::strlen(password)); index > 0; --index) password[index - 1] = '\0'; } else database.password = *zoe/"database"/"password"; database.db = *zoe/"database"/"db"; if (debug) api::Cerr << "login = " << login << "\npassword = " << std::string(password.GetSize(), '*') << "\ndatabase = {\n" << " driver = " << database.driver << "\n host = " << database.host << "\n user = " << database.user << "\n" << " password = " << std::string(database.password.GetSize(), '*') << "\n db = " << database.db << "\n}\n"; ext::String link(*zoe/"link"); xml::NodeSet buddies(*zoe/"buddy"); for (xml::NodeSet::Iterator buddy(buddies.Begin()); buddy != buddies.End(); ++buddy) { Buddy buddy_(**buddy/"login", **buddy/"rss", **buddy/"atom", !(**buddy/"link").IsEmpty() ? **buddy/"link" : (link + ext::String(**buddy/"login") + ".html")); this->buddies.insert(buddy_); } initialize(); if (debug) { api::Cerr << "buddies = {\n"; for (std::set::const_iterator buddy(this->buddies.begin()); buddy != this->buddies.end(); ++buddy) { api::Cerr << " " << *buddy << " = {\n rss = " << buddy->getRss() << "\n atom = " << buddy->getAtom() << "\n link = " << buddy->getLink() << "\n id = " << buddy->getId() << "\n }\n"; } api::Cerr << "}\n"; } if (debug) api::Cerr << "collector = " << collector << "\npublisher = " << publisher << "\ncolor = " << color << "\n" << ios::Flush; } void Zoe::initialize() { ext::Handle driver(dbi::GetDriver(database.driver)); ext::Handle db(driver->Connect(database.host, database.user, database.password, database.db)); ext::Handle buddies(db->Execute("SELECT * FROM buddies")); std::set buddies_; while (buddies->MoveNext()) { if (this->buddies.find(buddies->GetString("buddy")) != this->buddies.end()) { Buddy buddy(*this->buddies.find(buddies->GetString("buddy"))); buddy.setId(lexical_cast(buddies->GetString("id"))); buddies_.insert(buddy); } } std::vector difference; set_difference(this->buddies.begin(), this->buddies.end(), buddies_.begin(), buddies_.end(), std::insert_iterator >(difference, difference.begin())); for (std::vector::iterator buddy(difference.begin()); buddy != difference.end(); ++buddy) { ext::Uuid id(api::Uuid::CreateSequential()); buddy->setId(id); db->Execute("INSERT INTO buddies (id, buddy) VALUES ('" + lexical_cast(id) + "', '" + ext::String(*buddy) + "')"); buddies_.insert(*buddy); } this->buddies = buddies_; }