r8112 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r8111‎ | r8112 | r8113 >
Date:12:08, 7 April 2005
Author:markbergsma
Status:old
Tags:
Comment:
Initial revision
Modified paths:
  • /trunk/udpmcast (added) (history)
  • /trunk/udpmcast/edit_counter (added) (history)
  • /trunk/udpmcast/edit_counter/count_edits.py (added) (history)
  • /trunk/udpmcast/nodesync (added) (history)
  • /trunk/udpmcast/nodesync/nodesync.pl (added) (history)
  • /trunk/udpmcast/rcdumper (added) (history)
  • /trunk/udpmcast/rcdumper/rcdumper.cc (added) (history)
  • /trunk/udpmcast/six_degrees (added) (history)
  • /trunk/udpmcast/six_degrees/linksc.cc (added) (history)
  • /trunk/udpmcast/six_degrees/linksd.cc (added) (history)
  • /trunk/udpmcast/six_degrees/six_degrees.py (added) (history)
  • /trunk/udpmcast/udpmcast (added) (history)
  • /trunk/udpmcast/udpmcast/udpmcast.py (added) (history)

Diff [purge]

Index: trunk/udpmcast/udpmcast/udpmcast.py
@@ -0,0 +1,95 @@
 2+#!/usr/bin/python
 3+#
 4+# udpcast.py
 5+# application level udp multicaster/multiplexer
 6+# Written on 2005/04/03 by Mark Bergsma <mark@nedworks.org>
 7+#
 8+# $Id$
 9+
 10+import socket, getopt, sys, os
 11+
 12+debugging = False
 13+
 14+def debug(msg):
 15+ global debugging
 16+ if debugging:
 17+ print msg;
 18+
 19+def multicast_diagrams(sock, addresses):
 20+ portnr = sock.getsockname()[1];
 21+
 22+ while 1:
 23+ diagram = sock.recv(1500)
 24+ if not diagram: break
 25+ for addr in addresses:
 26+ try:
 27+ sock.sendto(diagram, 0, (addr, portnr))
 28+ debug('Sent diagram to '+addr+' port '+portnr)
 29+ except socket.error:
 30+ debug('Error while sending diagram to '+addr)
 31+ pass
 32+
 33+def join_multicast_group(sock, multicast_group):
 34+ import struct
 35+
 36+ ip_mreq = struct.pack('!4sl', socket.inet_aton(multicast_group),
 37+ socket.INADDR_ANY)
 38+ sock.setsockopt(socket.IPPROTO_IP,
 39+ socket.IP_ADD_MEMBERSHIP,
 40+ ip_mreq)
 41+
 42+def print_help():
 43+ print 'Usage:\n\tudpmcast [ options ] { addresses }\n'
 44+ print 'Options:'
 45+ print '\t-d\tFork into the background (become a daemon)'
 46+ print '\t-p {portnr}\tUDP port number to listen on (default is 4827)'
 47+ print '\t-j {multicast address}\tMulticast group to join on startup'
 48+ print '\t-v\tBe more verbose'
 49+
 50+if __name__ == '__main__':
 51+ host = ''
 52+ portnr = 4827
 53+ multicast_group = None
 54+ daemon = False
 55+ opts = 'dhj:p:v'
 56+
 57+ # Parse options
 58+ options, arguments = getopt.getopt(sys.argv[1:], opts)
 59+ if len(arguments) == 0:
 60+ print_help()
 61+ sys.exit()
 62+ else:
 63+ for option, value in options:
 64+ if option == '-j':
 65+ multicast_group = value
 66+ elif option == '-p':
 67+ portnr = int(value)
 68+ elif option == '-h':
 69+ print_help()
 70+ sys.exit()
 71+ elif option == '-d':
 72+ daemon = True
 73+ elif option == '-v':
 74+ debugging = True
 75+
 76+ try:
 77+ # Open the UDP socket
 78+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 79+ sock.bind((host, portnr))
 80+
 81+ # Join a multicast group if requested
 82+ if multicast_group != None:
 83+ debug('Joining multicast group ' + multicast_group)
 84+ join_multicast_group(sock, multicast_group)
 85+
 86+ # Become a daemon
 87+ if daemon and os.fork():
 88+ sys.exit()
 89+
 90+ # Multiplex everything that comes in
 91+ multicast_diagrams(sock, arguments)
 92+ except socket.error, msg:
 93+ print msg[1];
 94+ except KeyboardInterrupt:
 95+ pass
 96+
Property changes on: trunk/udpmcast/udpmcast/udpmcast.py
___________________________________________________________________
Added: svn:keywords
197 + Author Date Id Revision
Added: svn:eol-style
298 + native
Added: svn:executable
399 + *
Index: trunk/udpmcast/rcdumper/rcdumper.cc
@@ -0,0 +1,715 @@
 2+/*
 3+ * $Header$
 4+ *
 5+ * Realtime recent changes feed.
 6+ * This code is in the public domain.
 7+ */
 8+
 9+#include <sys/types.h>
 10+#include <sys/socket.h>
 11+
 12+#include <netinet/in.h>
 13+
 14+#include <arpa/inet.h>
 15+
 16+#include <map>
 17+#include <list>
 18+#include <set>
 19+#include <vector>
 20+#include <cstdio>
 21+#include <cstdlib>
 22+#include <cstring>
 23+#include <queue>
 24+#include <string>
 25+#include <iostream>
 26+#include <fstream>
 27+#include <sstream>
 28+#include <ctime>
 29+
 30+#include <unistd.h>
 31+
 32+#include <mysql.h>
 33+
 34+std::string messages_en[] = {
 35+ "Show bots",
 36+ "Hide bots",
 37+ "Show logged in users",
 38+ "Hide logged in users",
 39+ "Show minor edits",
 40+ "Hide minor edits",
 41+ "Feedback",
 42+ "Key: N = new; B = bot; m = minor; 0-9 = number of reverts last 24 hrs",
 43+ "diff",
 44+ "Talk",
 45+ "hist",
 46+ "contribs",
 47+ "moved to",
 48+ "N", "B", "m"
 49+};
 50+
 51+std::string messages_sv[] = {
 52+ "Visa robotredigeringar",
 53+ "Göm robotredigeringar",
 54+ "Visa inloggade användare",
 55+ "Göm inloggade användare",
 56+ "Visa mindre redigeringar",
 57+ "Göm mindre redigeringar",
 58+ "Respons",
 59+ "Key: N = ny; B = robot; m = mindre redigering; 0-9 = antal återställningar de senaste 24 timmarna",
 60+ "skillnad",
 61+ "Diskussion",
 62+ "historik",
 63+ "contribs",
 64+ "moved to",
 65+ "N", "B", "m"
 66+};
 67+
 68+std::string messages_fi[] = {
 69+ "Näytä botit",
 70+ "Piilota botit",
 71+ "Näytä kirjautuneiden käyttäjien muokkaukset",
 72+ "Piilota kirjautuneiden käyttäjien muokkaukset",
 73+ "Näytä pienet muokkaukset",
 74+ "Piilota pienet muokkaukset",
 75+ "Palaute",
 76+ "Tiedot: U = uusi, B = botti, p = pieni muutos, 0-9 = palautukset 24 tunnin sisällä.",
 77+ "ero",
 78+ "Keskustelu",
 79+ "historia",
 80+ "contribs",
 81+ "moved to",
 82+ "U", "B", "p"
 83+};
 84+std::string messages_nl[] = {
 85+ "Toon robots",
 86+ "Verberg robots",
 87+ "Toon aangemelde gebruikers",
 88+ "Verberg aangemelde gebruikers",
 89+ "Toon kleine wijzigingen",
 90+ "Verberg kleine wijzigingen",
 91+ "Reageer",
 92+ "Legende: N = nieuw, B = robot, K = kleine wijziging, 0-9 = aantal herstellingen in de laatste 24 uur.",
 93+ "wijz",
 94+ "Overleg",
 95+ "gesch",
 96+ "contribs",
 97+ "moved to",
 98+ "N", "B", "K"
 99+};
 100+
 101+std::string messages_fr[] = {
 102+ "montrer robots",
 103+ "cacher robots",
 104+ "montrer utilisateurs enregistrés",
 105+ "cacher utilisateurs enregistrés",
 106+ "montrer modifications mineures",
 107+ "cacher modifications mineures",
 108+ "Commentaires",
 109+ "Légende: N = nouveau, B = Bot, m = Modifications mineures, 0-9 = nombre de réversions dans les dernières 24 heures",
 110+ "diff",
 111+ "Discuter",
 112+ "hist",
 113+ "contribs",
 114+ "moved to",
 115+ "N", "B", "m"
 116+};
 117+std::string messages_it[] = {
 118+ "Mostra i bot",
 119+ "Nascondi i bot",
 120+ "Mostra gli utenti connessi",
 121+ "Nascondi gli utenti connessi",
 122+ "Mostra le modifiche minori",
 123+ "Nascondi le modifiche minori",
 124+ "Feedback",
 125+ "Key: N = nuovo; B = bot; m = modifica minore; 0-9 = numbero di rollback nelle 24 ore",
 126+ "diff",
 127+ "Discussioni",
 128+ "cron",
 129+ "contribs",
 130+ "moved to",
 131+ "N", "B", "m"
 132+};
 133+
 134+std::string messages_de[] = {
 135+ "Bots zeigen",
 136+ "Bots verstecken",
 137+ "Angemeldete Benutzer zeigen",
 138+ "Angemeldete Benutzer verstecken",
 139+ "Kleine Änderungen zeigen",
 140+ "Kleine Änderungen verstecken",
 141+ "Feedback",
 142+ "Legende: N = neu, B = Bot, K = kleine Änderung, 0-9 = Zahl der Reverts in den letzten 24 Std",
 143+ "Unterschiede",
 144+ "Diskussion",
 145+ "Versionen",
 146+ "Benutzerbeiträge",
 147+ "verschoben nach",
 148+ "N", "B", "K"
 149+};
 150+
 151+std::string messages_ja[] = {
 152+ "ボットを表示する",
 153+ "ボットを隠す",
 154+ "ログインユーザを表示する",
 155+ "ログインユーザを隠す",
 156+ "細部の編集を表示する",
 157+ "細部の編集を隠す",
 158+ "フィードバックを書く",
 159+ "記号: N = 新しい記事; B = ボット; m = 細部の編集; 0-9 最近24時間のリバート数",
 160+ "差分",
 161+ "ノート",
 162+ "履歴",
 163+ "投稿記録",
 164+ "moved to",
 165+ "N", "B", "m"
 166+};
 167+
 168+std::string *messages = messages_en;
 169+
 170+#define M_SHOW_BOTS 0
 171+#define M_HIDE_BOTS 1
 172+#define M_SHOW_LOGGED 2
 173+#define M_HIDE_LOGGED 3
 174+#define M_SHOW_MINOR 4
 175+#define M_HIDE_MINOR 5
 176+#define M_FEEDBACK 6
 177+#define M_KEY 7
 178+#define M_DIFF 8
 179+#define M_TALK 9
 180+#define M_HIST 10
 181+#define M_CONTRIBS 11
 182+#define M_MOVED_TO 12
 183+#define M_NEW 13
 184+#define M_BOT 14
 185+#define M_MINOR 15
 186+
 187+
 188+std::string db;
 189+MYSQL mysql;
 190+
 191+template<class to, class from>
 192+to lexical_cast(from const& f)
 193+{
 194+ std::stringstream ss;
 195+ to t;
 196+ ss << f;
 197+ ss >> t;
 198+ return t;
 199+}
 200+
 201+std::string spaces(std::string const& s) {
 202+ std::string res;
 203+ for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i)
 204+ switch(*i) {
 205+ case '_': res += " "; break;
 206+ default: res += *i; break;
 207+ }
 208+ return res;
 209+}
 210+
 211+std::string underscores(std::string const& s) {
 212+ std::string res;
 213+ for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i)
 214+ switch(*i) {
 215+ case ' ': res += "_"; break;
 216+ default: res += *i; break;
 217+ }
 218+ return res;
 219+}
 220+
 221+std::string sqlsafe(std::string const& s) {
 222+ std::string res;
 223+ for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i)
 224+ switch(*i) {
 225+ case '\\': res += "\\\\"; break;
 226+ case '\'': res += "\\'"; break;
 227+ case '"': res += "\\\""; break;
 228+ default: res += *i; break;
 229+ }
 230+ return res;
 231+}
 232+
 233+void
 234+mysql_query_ordie(MYSQL* mysql, std::string const& query)
 235+{
 236+ int i = mysql_query(mysql, query.c_str());
 237+ if (i) {
 238+ printf("mysql query failed: %s\n", mysql_error(mysql));
 239+ exit(8);
 240+ }
 241+}
 242+
 243+std::string namespaces[] = {
 244+ "",
 245+ "Talk:",
 246+ "User:",
 247+ "User_talk:",
 248+ "Wikipedia:",
 249+ "Wikipedia_talk:",
 250+ "Image:",
 251+ "Image_talk:",
 252+ "MediaWiki:",
 253+ "MediaWiki_talk:",
 254+ "Template:",
 255+ "Template_talk:",
 256+ "Help:",
 257+ "Help_talk:",
 258+ "Category:",
 259+ "Category_talk:"
 260+};
 261+
 262+std::string ns2name(int ns) {
 263+ if (ns < -2 || ns > 15) return "Unknown namespace:";
 264+ mysql_query_ordie(&mysql, "SELECT ns_name FROM katesdb.ns_name WHERE ns_num = " + lexical_cast<std::string>(ns)
 265+ + " AND ns_db = '" + sqlsafe(db) + "'");
 266+ MYSQL_RES *res = mysql_store_result(&mysql);
 267+ MYSQL_ROW arow;
 268+ if (arow = mysql_fetch_row(res))
 269+ return mysql_free_result(res), arow[0];
 270+ mysql_free_result(res);
 271+ if (ns < 0) {
 272+ if (ns == -1) return "Special:";
 273+ else if (ns == -2) return "Media:";
 274+ else return "[Unknown namespace]:";
 275+ }
 276+ return namespaces[ns];
 277+}
 278+
 279+int name2ns(std::string const& name) {
 280+ if (name == "") return 0;
 281+ mysql_query_ordie(&mysql, "SELECT ns_num FROM katesdb.ns_name WHERE ns_name = '" + sqlsafe(name)
 282+ + "' AND ns_db = '" + sqlsafe(db) + "'");
 283+ MYSQL_RES *res = mysql_store_result(&mysql);
 284+ MYSQL_ROW arow;
 285+ if (arow = mysql_fetch_row(res))
 286+ return mysql_free_result(res), lexical_cast<int>(arow[0]);
 287+ mysql_free_result(res);
 288+ for (unsigned int i = 0; i < sizeof namespaces / sizeof *namespaces; ++i)
 289+ if (name + ":" == namespaces[i]) return i;
 290+ return 0;
 291+}
 292+
 293+std::string fmtdate(std::string const& date) {
 294+ return date.substr(8, 2) + ":" + date.substr(10, 2) + ":" + date.substr(12, 2);
 295+}
 296+
 297+std::string htmlsafe(std::string const& s) {
 298+ std::string res;
 299+ for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) {
 300+ switch(*i) {
 301+ case '&': res += "&amp;"; break;
 302+ case '<': res += "&lt;"; break;
 303+ case '>': res += "&gt;"; break;
 304+ case '"': res += "&#34;"; break;
 305+ case '\'': res += "&#39;"; break;
 306+ case '?': res += "&#63;"; break;
 307+ default: res += *i; break;
 308+ }
 309+ }
 310+ return res;
 311+}
 312+
 313+std::string urlsafe(std::string const& s) {
 314+ std::string res;
 315+ for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) {
 316+ if ((*i >= 'a' && *i <= 'z') || (*i >= 'A' && *i <= 'Z') || (*i >= '0' && *i <= '9') || strchr("/:.", *i))
 317+ res += *i;
 318+ else {
 319+ res += '%';
 320+ char *s; asprintf(&s, "%2x", (unsigned int)(unsigned char)*i);
 321+ res += s;
 322+ std::free(s);
 323+ }
 324+ }
 325+ return res;
 326+}
 327+
 328+
 329+std::string
 330+getdbname()
 331+{
 332+ char *e;
 333+ if ((e = getenv("QUERY_STRING")) == NULL) return "enwiki";
 334+ std::string s = e;
 335+ std::string d = "enwiki", lang;
 336+ std::string thispar;
 337+ std::string *thisval;
 338+ /* foo=bar&baz=quux */
 339+ int doing = 0; /* 0 = name / 1 = par */
 340+ for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) {
 341+ switch (*i) {
 342+ case '=':
 343+ doing = 1;
 344+ if (thispar == "d") thisval = &d;
 345+ else thisval = &lang;
 346+ *thisval = "";
 347+ thispar = "";
 348+ break;
 349+ case '&':
 350+ doing = 0;
 351+ thispar = "";
 352+ break;
 353+ default:
 354+ if (doing == 0) {
 355+ if (thispar.size() > 255) {
 356+ std::cout << "Content-Type: text/plain\r\n\r\n...\r\n";
 357+ std::exit(0);
 358+ }
 359+ thispar += *i;
 360+ } else {
 361+ if (thisval->size() > 255) {
 362+ std::cout << "Content-Type: text/plain\r\n\r\n...\r\n";
 363+ std::exit(0);
 364+ }
 365+ *thisval += *i;
 366+ }
 367+ }
 368+ }
 369+ //if (s.substr(0, 2) == "d=")
 370+ // d = s.substr(2);
 371+ //else
 372+ // return "enwiki";
 373+ if (lang == "ja") messages = messages_ja;
 374+ else if (lang == "de") messages = messages_de;
 375+ else if (lang == "it") messages = messages_it;
 376+ else if (lang == "fi") messages = messages_fi;
 377+ else if (lang == "nl") messages = messages_nl;
 378+ else if (lang == "fr") messages = messages_fr;
 379+ else if (lang == "sv") messages = messages_sv;
 380+ std::ifstream f("/home/wikipedia/common/all.dblist");
 381+ while (std::getline(f, s))
 382+ if (s == d)
 383+ return d;
 384+ return "";
 385+}
 386+
 387+std::string latin1dbs[] = {
 388+ "enwiki", "dawiki", "svwiki", "nlwiki"
 389+};
 390+
 391+std::string
 392+getencoding(std::string const& db) {
 393+ for (int i = 0; i < 4; ++i)
 394+ if (db == latin1dbs[i])
 395+ return "ISO_8859-1";
 396+ return "UTF-8";
 397+}
 398+
 399+std::string
 400+maybeutf8(std::string const& s) {
 401+ if (getencoding(db) == "UTF-8")
 402+ return s;
 403+ char const *q = s.c_str(), *t = q;
 404+ size_t qs = s.size();
 405+ static bool init = false;
 406+ static iconv_t ic;
 407+ if (!init) {
 408+ ++init;
 409+ ic = iconv_open("UTF-8", getencoding(db).c_str());
 410+ }
 411+ size_t rs = s.size() * 3;
 412+ char *r = new char[rs + 1], *z = r;
 413+ size_t i = iconv(ic, const_cast<char**>(&t), &qs, &z, &rs);
 414+ std::string p(r, z);
 415+ delete[] r;
 416+ if (i == (size_t)-1) {
 417+ return "!Conversion error: " + std::string(strerror(errno));
 418+ }
 419+ return p;
 420+}
 421+
 422+char const* projects[][2] = {
 423+ {"wiki", "wikipedia.org"},
 424+ {"wiktionary", "wiktionary.org"},
 425+ {"wikibooks", "wikibooks.org"},
 426+ {"wikiquote", "wikiquote.org"},
 427+ {"wikinews", "wikinews.org"}
 428+};
 429+
 430+std::string
 431+gethost(std::string const& db)
 432+{
 433+ if (db == "commonswiki") return "commons.wikimedia.org";
 434+ for (unsigned int i = 0; i < sizeof projects / sizeof *projects; ++i)
 435+ if (db.substr(db.size() - strlen(projects[i][0])) == projects[i][0])
 436+ return db.substr(0, db.size() - strlen(projects[i][0])) + "." + projects[i][1];
 437+ return "unknown";
 438+}
 439+
 440+std::string sane(std::string const& article) {
 441+ return article[0] == ':' ? article.substr(1) : article;
 442+}
 443+
 444+bool articleexists(int ns, std::string article)
 445+{
 446+ if (ns < 0) return true;
 447+ mysql_query_ordie(&mysql, "SELECT 1 FROM cur WHERE cur_namespace="+lexical_cast<std::string>(ns)+
 448+ " AND cur_title='"+sqlsafe(underscores(sane(article)))+"'");
 449+ MYSQL_RES *res = mysql_store_result(&mysql);
 450+ if (mysql_fetch_row(res))
 451+ return mysql_free_result(res), true;
 452+ mysql_free_result(res);
 453+ return false;
 454+}
 455+
 456+std::string
 457+fmtart(int ns, std::string link, std::string desc)
 458+{
 459+ link = sane(link);
 460+ std::string clas = articleexists(ns, link) ? "article" : "new";
 461+ return "<a href='http://"+gethost(db)+"/wiki/"+urlsafe(ns2name(ns)+link)+"' class='"+clas+"'>"+
 462+ htmlsafe(desc.size()?desc:spaces(link))+"</a>";
 463+}
 464+
 465+std::string
 466+link2url(std::string link, bool safe=true)
 467+{
 468+ link = sane(link);
 469+ std::string art = link, desc;
 470+ std::string::size_type i = art.find('|');
 471+ if (i != art.npos) {
 472+ desc = spaces((i+1 == art.size() ? art : art.substr(i + 1)));
 473+ art = art.substr(0, i);
 474+ if (desc == "") desc = art;
 475+ } else desc = art;
 476+ std::string titlebit;
 477+ int ns = 0;
 478+ std::string q = sane(underscores(art));
 479+ i = q.find(':');
 480+ if (i != q.npos)
 481+ ns = name2ns((i+1 == q.size() ? q : q.substr(0, i)));
 482+ std::string clas = articleexists(ns, q.substr(i==q.npos?0:i+1)) ? "article" : "new";
 483+ return "<a href='http://"+gethost(db)+"/wiki/"+
 484+ (safe?urlsafe(q):q)+"' class='"+clas+"'>"+(safe?htmlsafe(desc):desc)+"</a>";
 485+}
 486+
 487+std::string
 488+parsesummary(std::string s)
 489+{
 490+ std::string::size_type i,j;
 491+ while ((i = s.find("[[")) != s.npos) {
 492+ if ((j = s.find("]]", i)) == s.npos) break;
 493+ s = s.substr(0, i) + link2url(s.substr(i + 2, j - i - 2), false) + s.substr(j + 2);
 494+ }
 495+ while (i = s.find("/* ") != s.npos) {
 496+ if ((j = s.find(" */", i)) == s.npos) break;
 497+ s = s.substr(0, i - 1) + "<span style='color: gray'>" + s.substr(i + 2, j - i - 2) + "</span>"
 498+ + s.substr(j + 3);
 499+ }
 500+ return s;
 501+}
 502+
 503+std::string
 504+whatwasthedateyesterday() {
 505+ std::time_t t = std::time(NULL);
 506+ t -= 86400;
 507+ struct tm *gt = gmtime(&t);
 508+ char b[256];
 509+ std::strftime(b, sizeof b, "%Y%m%d%H%M%S", gt);
 510+ return b;
 511+}
 512+
 513+template<typename it>
 514+it next(it i)
 515+{
 516+ return ++i;
 517+}
 518+
 519+std::string
 520+mkrvtxt(std::set<std::string> const& rvers)
 521+{
 522+ if (rvers.empty()) return "";
 523+ std::string s = " [";
 524+ for (std::set<std::string>::const_iterator it = rvers.begin(), end = rvers.end(); it != end; ++it) {
 525+ s += fmtart(2, *it, *it);
 526+ if (next(it) != end)
 527+ s += ", ";
 528+ }
 529+ return s + "]";
 530+}
 531+
 532+int
 533+main(int argc, char *argv[])
 534+{
 535+ db = getdbname();
 536+
 537+ if (db.empty()) {
 538+ std::cout << "Content-Type: text/plain\r\n\r\nincorrect dbname predicts future losses\n";
 539+ return 0;
 540+ }
 541+
 542+ mysql_init(&mysql);
 543+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "rcdumper");
 544+
 545+ std::string dbhost, dbuser, dbpass, s;
 546+ std::vector<std::string> v;
 547+ std::ifstream f("/home/kate/dbconfig");
 548+ while (std::getline(f, s)) {
 549+ v.push_back(s);
 550+ }
 551+ f.close();
 552+ if (v.size() < 3) {
 553+ std::cerr << "Content-Type: text/plain\r\n\r\nsorry, broken\r\n";
 554+ std::exit(0);
 555+ }
 556+ dbhost = v[0];
 557+ dbuser = v[1];
 558+ dbpass = v[2];
 559+
 560+ if (!mysql_real_connect(&mysql, dbhost.c_str(), dbuser.c_str(), dbpass.c_str(), db.c_str(), 0, NULL, 0)) {
 561+ printf("mysql connect error: %s\n", mysql_error(&mysql));
 562+ return 1;
 563+ }
 564+
 565+ //std::cout << "HTTP/1.0 200 OK\r\n" << std::flush;
 566+ std::cout << "Content-type: text/html; charset=UTF-8\r\n" << std::flush;
 567+ std::cout << "\r\n" << std::flush;
 568+ std::cout << "<html><head><title>live recent changes feed</title>"
 569+"<style type='text/css'>"
 570+"body { padding: 0em; margin: 0em; }"
 571+"a { text-decoration: none; }"
 572+"a.new { color: red; }"
 573+"</style>"
 574+"<script language='javascript'>"
 575+"var showbots = false;"
 576+"var showminor = true;"
 577+"var showlogin = true;"
 578+"function toggleminor() {"
 579+" showminor = !showminor;"
 580+" v = document.getElementById('minortog');"
 581+" if (showminor) v.innerHTML = '"+messages[M_HIDE_MINOR]+"';"
 582+" else v.innerHTML = '"+messages[M_SHOW_MINOR]+"';"
 583+"}"
 584+"function togglelogin() {"
 585+" showlogin = !showlogin;"
 586+" v = document.getElementById('logintog');"
 587+" if (showlogin) v.innerHTML = '"+messages[M_HIDE_LOGGED]+"';"
 588+" else v.innerHTML = '"+messages[M_SHOW_LOGGED]+"';"
 589+"}"
 590+"function togglebots() {"
 591+" showbots = !showbots;"
 592+" v = document.getElementById('bottog');"
 593+" if (showbots) v.innerHTML = '"+messages[M_HIDE_BOTS]+"';"
 594+" else v.innerHTML = '"+messages[M_SHOW_BOTS]+"';"
 595+"}"
 596+"</script>"
 597+"</head><body><ul>\n"
 598+"<div style='width: 90%; height: 8%; padding-left: 2em; padding-right: 2em; border-bottom: solid 1px black; text-align: center'>"
 599+"<a id='bottog' href='javascript:togglebots()'>"+messages[M_SHOW_BOTS]+"</a> "
 600+"| <a id='logintog' href='javascript:togglelogin()'>"+messages[M_HIDE_LOGGED]+"</a> "
 601+"| <a id='minortog' href='javascript:toggleminor()'>"+messages[M_HIDE_MINOR]+"</a>"
 602+"| <a id='feedback' href='http://meta.wikimedia.org/wiki/Realtime_recent_changes'>"+messages[M_FEEDBACK]+"</a>"
 603+"<br/>" +messages[M_KEY]+ "</div>"
 604+"<div style='padding-left: 2em; padding-right: 2em; height: 85%; overflow: scroll;' id='contentbit'>\n"
 605+ << std::flush;
 606+
 607+ mysql_query_ordie(&mysql, "SELECT MAX(rc_id) FROM recentchanges");
 608+ MYSQL_ROW arow;
 609+ MYSQL_RES *res;
 610+ res = mysql_store_result(&mysql);
 611+ arow = mysql_fetch_row(res);
 612+ std::string lastrcid = arow[0];
 613+ mysql_free_result(res);
 614+
 615+ while (true) {
 616+ mysql_query_ordie(&mysql, "SELECT rc_id, rc_timestamp, rc_user_text, rc_namespace, rc_title, "
 617+ "rc_comment, rc_bot, rc_minor, rc_new, rc_user, rc_this_oldid, rc_cur_id, rc_moved_to_ns, "
 618+ "rc_moved_to_title,cur_text "
 619+ "FROM recentchanges LEFT OUTER JOIN cur ON cur_id=rc_cur_id WHERE rc_id > " + lastrcid + " ORDER BY rc_id");
 620+ res = mysql_store_result(&mysql);
 621+ while (arow = mysql_fetch_row(res)) {
 622+ std::string rc_timestamp = arow[1],
 623+ rc_user_text = arow[2],
 624+ rc_comment = arow[5],
 625+ rc_cur_id = arow[11],
 626+ rc_moved_title = arow[13] ? arow[13] : "",
 627+ cur_text = arow[14] ? arow[14] : "",
 628+ rc_title = arow[4];
 629+ int rc_namespace = atoi(arow[3]),
 630+ rc_bot = atoi(arow[6]),
 631+ rc_new = atoi(arow[8]),
 632+ rc_user = atoi(arow[9]),
 633+ rc_oldid = atoi(arow[10]),
 634+ rc_minor_edit = atoi(arow[7]),
 635+ rc_moved_ns = arow[12] ? atoi(arow[12]) : 0;
 636+ mysql_query_ordie(&mysql, "SELECT COUNT(*) FROM hashs WHERE hs_nstitle=MD5(CONCAT('"
 637+ + lexical_cast<std::string>(rc_namespace) + "','+','"
 638+ + sqlsafe(rc_title) + "')) AND hs_hash=MD5('"
 639+ + sqlsafe(cur_text) + "') AND hs_timestamp > " + whatwasthedateyesterday());
 640+ MYSQL_RES *res2 = mysql_store_result(&mysql);
 641+ MYSQL_ROW brow = mysql_fetch_row(res2);
 642+ int rc_reverts = atoi(brow[0]);
 643+ if (rc_reverts > 9) rc_reverts = 9;
 644+ mysql_free_result(res2);
 645+ std::set<std::string> reverters;
 646+ mysql_query_ordie(&mysql, "SELECT DISTINCT hs_user_text FROM hashs WHERE hs_nstitle=MD5(CONCAT('"
 647+ + lexical_cast<std::string>(rc_namespace) + "','+','"
 648+ + sqlsafe(rc_title) + "')) AND hs_hash=MD5('"
 649+ + sqlsafe(cur_text) + "') AND hs_timestamp > " + whatwasthedateyesterday());
 650+ res2 = mysql_store_result(&mysql);
 651+ while (brow = mysql_fetch_row(res2)) {
 652+ if (reverters.find(brow[0]) == reverters.end())
 653+ reverters.insert(brow[0]);
 654+ }
 655+ std::string reverter_text = mkrvtxt(reverters);
 656+ mysql_free_result(res2);
 657+
 658+ lastrcid = arow[0];
 659+ if (rc_bot) std::cout <<
 660+ "<script language='javascript'>"
 661+ "if (showbots == false) document.write('<span style=\"display:none\">')</script>";
 662+ if (rc_minor_edit) std::cout <<
 663+ "<script language='javascript'>"
 664+ "if (showminor == false) document.write('<span style=\"display:none\">')</script>";
 665+ if (rc_user != 0) std::cout <<
 666+ "<script language='javascript'>"
 667+ "if (showlogin == false) document.write('<span style=\"display:none\">')</script>";
 668+ std::cout << fmtdate(rc_timestamp) + " "
 669+ "<tt>"
 670+ + std::string(rc_minor_edit ? messages[M_MINOR] : "&nbsp;")
 671+ + std::string(rc_bot ? messages[M_BOT] : "&nbsp;")
 672+ + std::string(rc_new ? messages[M_NEW] : "&nbsp;")
 673+ + std::string(rc_reverts ? lexical_cast<std::string>(rc_reverts) : "&nbsp;")
 674+ + "&nbsp;</tt>"
 675+ "<a href='http://"+gethost(db)+"/wiki/"
 676+ + urlsafe(ns2name(rc_namespace) + rc_title)
 677+ + "'>" + spaces(maybeutf8(ns2name(rc_namespace) + htmlsafe(rc_title))) + "</a>"
 678+ + std::string(" (")
 679+ + (rc_moved_title.size()
 680+ ? (messages[M_MOVED_TO] + " " +
 681+ fmtart(rc_moved_ns, rc_moved_title, maybeutf8(ns2name(rc_moved_ns) + rc_moved_title)))
 682+ : (!rc_new ?
 683+ ("<a href='http://"+gethost(db)+"/wiki/"
 684+ + urlsafe(ns2name(rc_namespace) + rc_title)
 685+ + "?curid="+rc_cur_id+"&amp;diff=0'>" + messages[M_DIFF] + "</a>")
 686+ :(messages[M_DIFF]))
 687+ )
 688+ + "; "
 689+ "<a href='http://"+gethost(db)+"/wiki/"
 690+ + urlsafe(ns2name(rc_namespace) + rc_title)
 691+ + "?action=history'>"+messages[M_HIST]+"</a>) . . "
 692+ + fmtart(2, rc_user_text, maybeutf8(rc_user_text))
 693+ + " (" + fmtart(3, rc_user_text, messages[M_TALK]) + " | "
 694+ + fmtart(-1, "Contributions/" + underscores(rc_user_text), messages[M_CONTRIBS]) + ")"
 695+ + ((rc_moved_title.empty() && !rc_comment.empty())
 696+ ? " (" + parsesummary(htmlsafe(rc_comment)) + ")"
 697+ : std::string()
 698+ )
 699+ + maybeutf8(reverter_text)
 700+ + "<br/>\n" << std::endl << std::flush;
 701+ if (rc_user != 0) std::cout <<
 702+ "<script language='javascript'>if (showlogin == false) document.write('</span>')</script>\n";
 703+ if (rc_minor_edit) std::cout <<
 704+ "<script language='javascript'>if (showminor == false) document.write('</span>')</script>\n";
 705+ if (rc_bot) std::cout <<
 706+ "<script language='javascript'>if (showbots == false) document.write('</span>')</script>\n";
 707+ std::cout <<
 708+"<script language='javascript'>"
 709+" var v = document.getElementById('contentbit');"
 710+" v.scrollTop = v.scrollTop + 100;"
 711+"</script>\n" << std::flush;
 712+ }
 713+ mysql_free_result(res);
 714+ usleep(250000);
 715+ }
 716+}
Property changes on: trunk/udpmcast/rcdumper/rcdumper.cc
___________________________________________________________________
Added: svn:keywords
1717 + Author Date Id Revision
Added: svn:eol-style
2718 + native
Index: trunk/udpmcast/six_degrees/linksc.cc
@@ -0,0 +1,61 @@
 2+/*
 3+ * $Header$
 4+ *
 5+ * Links path finder client.
 6+ * This source code is in the public domain.
 7+ *
 8+ */
 9+
 10+#include <sys/types.h>
 11+#include <sys/socket.h>
 12+
 13+#include <netinet/in.h>
 14+
 15+#include <arpa/inet.h>
 16+
 17+#include <iostream>
 18+#include <cstdio>
 19+#include <cstdlib>
 20+#include <cstring>
 21+#include <string>
 22+
 23+#include <unistd.h>
 24+
 25+#define PORT 7584
 26+
 27+int
 28+main(int argc, char *argv[])
 29+{
 30+ std::string src, dst;
 31+ std::getline(std::cin, src);
 32+ std::getline(std::cin, dst);
 33+ int s;
 34+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 35+ printf("ERROR\nNO_CONNECT\n");
 36+ exit(8);
 37+ }
 38+ struct sockaddr_in addr;
 39+ memset(&addr, 0, sizeof(addr));
 40+ addr.sin_family = AF_INET;
 41+ addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 42+ addr.sin_port = htons(PORT);
 43+ if (connect(s, (sockaddr *) &addr, sizeof(addr)) < 0) {
 44+ printf("ERROR\nNO_CONNECT\n");
 45+ exit(8);
 46+ }
 47+ uint32_t i;
 48+ i = src.size();
 49+ write(s, &i, sizeof(i));
 50+ write(s, src.data(), src.size());
 51+ i = dst.size();
 52+ write(s, &i, sizeof(i));
 53+ write(s, dst.data(), dst.size());
 54+ char buf[512];
 55+ int j;
 56+ while ((j = read(s, buf, sizeof(buf))) > 0) {
 57+ for (char *s = buf; s < buf + j; ++s)
 58+ if (*s != 0) /* work around old linksd bug */
 59+ write(STDOUT_FILENO, s, 1);
 60+ }
 61+}
 62+
Property changes on: trunk/udpmcast/six_degrees/linksc.cc
___________________________________________________________________
Added: svn:keywords
163 + Author Date Id Revision
Added: svn:eol-style
264 + native
Index: trunk/udpmcast/six_degrees/linksd.cc
@@ -0,0 +1,233 @@
 2+/*
 3+ * $Header$
 4+ *
 5+ * Links path finder daemon.
 6+ * This source code is in the public domain.
 7+ *
 8+ */
 9+
 10+#include <sys/types.h>
 11+#include <sys/socket.h>
 12+
 13+#include <netinet/in.h>
 14+
 15+#include <arpa/inet.h>
 16+
 17+#include <map>
 18+#include <list>
 19+#include <set>
 20+#include <vector>
 21+#include <cstdio>
 22+#include <cstdlib>
 23+#include <cstring>
 24+#include <cassert>
 25+#include <queue>
 26+#include <string>
 27+
 28+#include <unistd.h>
 29+
 30+#include <mysql.h>
 31+
 32+#define PORT 7584 /* KT :-) */
 33+
 34+#define dbhost "whatever"
 35+#define dbuser "whatever"
 36+#define dbpass "whatever"
 37+
 38+std::vector<std::string> names;
 39+std::map<std::string, int> ids;
 40+
 41+std::vector< std::vector< int > > adjacency;
 42+std::vector< int > back;
 43+std::deque< int > next;
 44+
 45+/* dijkstra implementation by zorbathutt@efnet #c++, not copyrighted */
 46+std::vector< int > findPath( int src, int dst ) {
 47+ back.clear();
 48+ back.resize( adjacency.size(), -1 );
 49+ next.clear();
 50+ back[ src ] = -2;
 51+ next.push_back( src );
 52+ while( next.size() ) {
 53+ int ts = next[ 0 ];
 54+ next.pop_front();
 55+ if( ts == dst ) {
 56+ std::vector< int > path;
 57+ path.push_back( dst );
 58+ int lastlink = back[ dst ];
 59+ while( lastlink != -2 ) {
 60+ assert( lastlink != -1 );
 61+ path.push_back( lastlink );
 62+ lastlink = back[ lastlink ];
 63+ }
 64+ reverse( path.begin(), path.end() );
 65+ return path;
 66+ }
 67+ for( int i = 0; i < adjacency[ ts ].size(); i++ ) {
 68+ if( back[ adjacency[ ts ][ i ] ] == -1 ) {
 69+ back[ adjacency[ ts ][ i ] ] = ts;
 70+ next.push_back( adjacency[ ts ][ i ] );
 71+ }
 72+ }
 73+ }
 74+ return std::vector< int >();
 75+}
 76+
 77+void
 78+ioloop(void)
 79+{
 80+ int sfd;
 81+ struct sockaddr_in servaddr, cliaddr;
 82+ if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 83+ perror("socket");
 84+ exit(8);
 85+ }
 86+ memset(&servaddr, 0, sizeof(servaddr));
 87+ servaddr.sin_family = AF_INET;
 88+ servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 89+ servaddr.sin_port = htons(PORT);
 90+ int one = 1;
 91+ setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
 92+ if (bind(sfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
 93+ perror("bind");
 94+ exit(8);
 95+ }
 96+ if (listen(sfd, 5) < 0) {
 97+ perror("listen");
 98+ exit(8);
 99+ }
 100+ int cfd;
 101+ socklen_t clilen = sizeof(cliaddr);
 102+ while ((cfd = accept(sfd, (sockaddr *) &cliaddr, &clilen)) > 0) {
 103+ std::string from, to;
 104+ uint32_t len;
 105+ if (read(cfd, &len, sizeof(len)) < 0) {
 106+ perror("read");
 107+ close(cfd);
 108+ continue;
 109+ }
 110+#define nofrom "ERROR\nNO_FROM\n"
 111+#define noto "ERROR\nNO_TO\n"
 112+ if (len > 255) {
 113+ write(cfd, nofrom, sizeof(nofrom));
 114+ close(cfd);
 115+ continue;
 116+ }
 117+ std::vector<u_char> b(len);
 118+ if (read(cfd, &b[0], len) < 0) {
 119+ perror("read");
 120+ close(cfd);
 121+ continue;
 122+ }
 123+ from.assign(b.begin(), b.end());
 124+ if (read(cfd, &len, sizeof(len)) < 0) {
 125+ perror("read");
 126+ close(cfd);
 127+ continue;
 128+ }
 129+ if (len > 255) {
 130+ write(cfd, noto, sizeof(noto));
 131+ close(cfd);
 132+ continue;
 133+ }
 134+ b.resize(len);
 135+ if (read(cfd, &b[0], len) < 0) {
 136+ perror("read");
 137+ close(cfd);
 138+ continue;
 139+ }
 140+ to.assign(b.begin(), b.end());
 141+ int fromid, toid;
 142+ if (ids.find(from) == ids.end()) {
 143+ write(cfd, nofrom, sizeof(nofrom));
 144+ close(cfd);
 145+ continue;
 146+ }
 147+ fromid = ids[from];
 148+ if (ids.find(to) == ids.end()) {
 149+ write(cfd, noto, sizeof(noto));
 150+ close(cfd);
 151+ continue;
 152+ }
 153+ toid = ids[to];
 154+ std::vector<int> links = findPath(fromid, toid);
 155+#define ok "OK\n"
 156+ write(cfd, ok, sizeof(ok));
 157+ for (std::vector<int>::const_iterator it = links.begin(), end = links.end(); it != end; ++it)
 158+ {
 159+ std::string s = names[*it] + '\n';
 160+ b.assign(s.begin(), s.end());
 161+ write(cfd, &b[0], b.size());
 162+ }
 163+ close(cfd);
 164+ }
 165+ exit(0);
 166+}
 167+
 168+
 169+void
 170+mysql_query_ordie(MYSQL* mysql, char const *query)
 171+{
 172+ int i = mysql_query(mysql, query);
 173+ if (i) {
 174+ printf("mysql query failed: %s\n", mysql_error(mysql));
 175+ exit(8);
 176+ }
 177+}
 178+int
 179+main(int argc, char *argv[])
 180+{
 181+ MYSQL mysql;
 182+ mysql_init(&mysql);
 183+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "linksd");
 184+
 185+ if (!mysql_real_connect(&mysql, dbhost, dbuser, dbpass, argv[1], 0, NULL, 0)) {
 186+ printf("mysql connect error: %s\n", mysql_error(&mysql));
 187+ return 1;
 188+ }
 189+
 190+ printf("retrieving links table...\n");
 191+ mysql_query_ordie(&mysql, "SELECT l_to, l_from FROM links");
 192+ MYSQL_RES *res = mysql_use_result(&mysql);
 193+
 194+ MYSQL_ROW arow;
 195+ while (arow = mysql_fetch_row(res)) {
 196+ int l_from = atoi(arow[1]);
 197+ int l_to = atoi(arow[0]);
 198+ if (l_from >= adjacency.size())
 199+ adjacency.resize(l_from + 1);
 200+ std::vector<int>& l = adjacency[l_from];
 201+ l.insert(l.end(), l_to);
 202+ }
 203+ mysql_free_result(res);
 204+
 205+ printf("ok\n");
 206+ printf("retrieving titles...\n");
 207+ mysql_query_ordie(&mysql, "SELECT cur_title,cur_id FROM cur WHERE cur_namespace=0");
 208+ res = mysql_use_result(&mysql);
 209+ while (arow = mysql_fetch_row(res)) {
 210+ std::string title = arow[0];
 211+ int id = atoi(arow[1]);
 212+ if (id >= names.size())
 213+ names.resize(id + 1);
 214+ names[id] = title;
 215+ ids[title] = id;
 216+ }
 217+ printf("ok, %d links, %d titles\n", adjacency.size(), names.size());
 218+ mysql_free_result(res);
 219+ printf("filtering links...\n");
 220+ for (int i = 1; i < adjacency.size(); ++i) {
 221+ if (i >= names.size() || names[i].empty()) {
 222+ adjacency[i].clear();
 223+ continue;
 224+ }
 225+ for (std::vector<int>::iterator it = adjacency[i].begin(); it != adjacency[i].end();)
 226+ if (*it >= names.size() || names[*it].empty())
 227+ it = adjacency[i].erase(it);
 228+ else ++it;
 229+ }
 230+ printf("ok\n");
 231+
 232+ mysql_close(&mysql);
 233+ ioloop();
 234+}
Property changes on: trunk/udpmcast/six_degrees/linksd.cc
___________________________________________________________________
Added: svn:keywords
1235 + Author Date Id Revision
Added: svn:eol-style
2236 + native
Index: trunk/udpmcast/six_degrees/six_degrees.py
@@ -0,0 +1,225 @@
 2+#! /usr/bin/python
 3+#
 4+# $Header$
 5+#
 6+# Links path finder CGI client.
 7+# This source is in the public domain.
 8+
 9+import sys
 10+import cgi
 11+import os
 12+
 13+print "Content-Type: text/html; charset=iso-8859-1"
 14+print
 15+
 16+form = cgi.FieldStorage()
 17+
 18+fromval = ''
 19+toval = ''
 20+
 21+def safe(s):
 22+ return cgi.escape(s).replace('"', "&dquot;").replace("'", "&quot;")
 23+
 24+if form.has_key('from'):
 25+ fromval = safe(form['from'].value)
 26+if form.has_key('to'):
 27+ toval = safe(form['to'].value)
 28+
 29+print """
 30+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 31+<html>
 32+<head>
 33+<title>six degrees of wikipedia</title>
 34+<style type="text/css">
 35+body {
 36+ background-color: white;
 37+ padding-right: 0px;
 38+ margin-right: 0px;
 39+}
 40+input { border: solid 1px blue; background: white; color: black; }
 41+div.error {
 42+ display: inline;
 43+ border: solid 1px #ff8888;
 44+}
 45+span.error {
 46+ padding-left: 1em;
 47+ padding-right: 1em;
 48+ background-color: #ffdcdc;
 49+ font-weight: bold;
 50+ border-right: solid 1px #ff8888;
 51+}
 52+span.errtext {
 53+ padding-left: 1em;
 54+ padding-right: 1em;
 55+}
 56+div.result {
 57+ border: solid 1px #0000ff;
 58+ width: 50%;
 59+ margin-left: auto; margin-right: auto;
 60+ text-align: center;
 61+}
 62+div.answer {
 63+ width: 100%;
 64+ text-align: center;
 65+ border-bottom: solid 1px #0000ff;
 66+ background-color: #ddddff;
 67+}
 68+span.art {
 69+}
 70+a {
 71+ color: #0000C0;
 72+}
 73+a:hover {
 74+ text-decoration: underline;
 75+}
 76+</style>
 77+</head>
 78+<body>
 79+<div style="text-align: right; padding: 0px; margin: 0px"><img src="/~kate/6deg.png" alt="" /><br/></div>
 80+<div style="text-align: center">
 81+<i>
 82+<a href="http://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search">iterative deepening</a>
 83+<a href="http://en.wikipedia.org/Depth-first_search">depth first search</a>
 84+<a href="http://en.wikipedia.org/Shortest_path_problem">shortest path</a>
 85+query tool for <a href="http://en.wikipedia.org/wiki/Main_Page">Wikipedia</a>...</i><br/>
 86+<i>six degrees</i> finds the shortest path between any two Wikipedia articles in the
 87+main namespace using wiki links
 88+</div>
 89+<div style="padding-top: 35px;">
 90+<form method="post" action="six_degrees">
 91+<center>
 92+<strong>find path...</strong>
 93+from: <input type="text" name="from" value=\"""" + fromval + """\"/>
 94+to: <input type="text" name="to" value=\"""" + toval + """\" />
 95+<input type="submit" value="go" />
 96+</center>
 97+</form>
 98+"""
 99+
 100+def mklink(art):
 101+ a2 = art.replace('_', ' ')
 102+ return "<a href=\"http://en.wikipedia.org/wiki/" + safe(art) + "\">" + safe(a2) + "</a>"
 103+
 104+def chop(s):
 105+ if s[-1:] == '\n':
 106+ return s[:-1]
 107+ else:
 108+ return s
 109+
 110+def getrecent():
 111+ try:
 112+ f = file("/home/kate/rcq", "r")
 113+ except IOError:
 114+ return ''
 115+ i = []
 116+ while True:
 117+ s,t,d = f.readline(), f.readline(), f.readline()
 118+ s = safe(chop(s))
 119+ t = safe(chop(t))
 120+
 121+ if '' in [s,t,d]:
 122+ break
 123+ i = i + [[s,t,d]]
 124+ i.reverse()
 125+ s = ''
 126+ for t in i[:10]:
 127+ s = s + '<li>' + mklink(t[0]) + ' -> ' + mklink(t[1]) + ' (' + t[2] + ' hops)'
 128+ return s
 129+
 130+footer = """
 131+<div style="width: 50%; margin-left: auto; margin-right: auto; border-top: solid 1px black; margin-top: 3em">
 132+<div style="text-align: center">
 133+<strong>hints:</strong>
 134+</div>
 135+<ul>
 136+<li>redirects are searched as well as articles</li>
 137+<li>using a redirect as the target will generally produce an inferior result</li>
 138+<li>article names are case sensitive except for the first letter, which is always capital</li>
 139+</ul>
 140+</div>
 141+</div>
 142+"""
 143+
 144+rc = getrecent()
 145+if rc != '':
 146+ footer = footer + """
 147+<div style="width: 50%; margin-left: auto; margin-right: auto; border-top: solid 1px black; margin-top: 3em">
 148+<div style="text-align: center">
 149+<strong>recent queries:</strong>
 150+<ul>"""
 151+ footer = footer + rc
 152+ footer = footer + "</ul></div>"
 153+
 154+footer = footer + """
 155+<hr/>
 156+kate's tools:
 157+ <a href="count_edits">user edit counter</a>
 158+| <strong>six degrees of wikipedia</strong>
 159+| <a href="mailto:keturner@livejournal.com">send feedback...</a>
 160+</div></body></html>"""
 161+
 162+def error(text):
 163+ print "<center><div class='error'><span class='error'>error:</span><span class='errtext'>%s</span></div></center>" % cgi.escape(text)
 164+ print footer
 165+ sys.exit()
 166+
 167+if not (form.has_key('from') and form.has_key('to')):
 168+ print footer
 169+ sys.exit()
 170+
 171+def cfirst(s):
 172+ return s[0].upper() + s[1:]
 173+srcname,targname = cfirst(form['from'].value.replace(' ', '_')), cfirst(form['to'].value.replace(' ', '_'))
 174+
 175+if len(srcname) > 255:
 176+ error("source article %s does not exist" % srcname)
 177+if len(targname) > 255:
 178+ error("target article %s does not exist" % targname)
 179+def findlink(src, dst):
 180+ (sin, sout) = os.popen2("/home/kate/linksc")
 181+ sin.write(src + '\n')
 182+ sin.write(dst + '\n')
 183+ sin.flush()
 184+ i = sout.readline()
 185+ if i == "ERROR\n":
 186+ err = sout.readline()
 187+ if err == "NO_FROM\n":
 188+ error("source article %s does not exist" % src)
 189+ elif err == "NO_TO\n":
 190+ error("target article %s does not exist" % dst)
 191+ elif err == "NO_CONNECT\n":
 192+ error("could not contact links server")
 193+ else:
 194+ error("unknown error")
 195+ i = []
 196+ while True:
 197+ nid = sout.readline()
 198+ if nid == '':
 199+ return i
 200+ i = i + [nid]
 201+
 202+def mklink(art):
 203+ a2 = art.replace('_', ' ')
 204+ return "<a href=\"http://en.wikipedia.org/wiki/" + safe(art) + "\">" + cgi.escape(a2) + "</a>"
 205+
 206+def writelog(src, targ, degs):
 207+ try:
 208+ f = file("/home/kate/rcq", "a")
 209+ f.write(src + '\n' + targ + '\n' + str(degs) + '\n')
 210+ except IOError:
 211+ return
 212+ f.close()
 213+
 214+answer = findlink(srcname, targname)
 215+if answer != []:
 216+ writelog(srcname, targname, len(answer))
 217+ print "<div class='result'>"
 218+ print "<div class='answer'>%d degrees of separation</div>" % len(answer)
 219+ print "<span class='art'>%s</span><br/>" % mklink(answer[0]),
 220+ for i in answer[1:]:
 221+ print "<span class='art'>%s</span><br/>" % mklink(i),
 222+ #print "<span class='art'>%s</span>" % mklink(targname)
 223+ print "</div>"
 224+ print footer
 225+ sys.exit()
 226+error("no route found after %d degrees..." % 10)
Property changes on: trunk/udpmcast/six_degrees/six_degrees.py
___________________________________________________________________
Added: svn:keywords
1227 + Author Date Id Revision
Added: svn:eol-style
2228 + native
Added: svn:executable
3229 + *
Index: trunk/udpmcast/nodesync/nodesync.pl
@@ -0,0 +1,23 @@
 2+#! /usr/bin/perl -w
 3+#
 4+# $Header$
 5+# Create dsh node_groups from nodes.list file.
 6+#
 7+# Permission is granted for anyone to use, modify and distribute this
 8+# source code for any purpose whatsoever, provided you balance a live
 9+# salmon on your head whilst doing so.
 10+
 11+use strict;
 12+
 13+unlink or die for glob "node_groups/*";
 14+
 15+open LIST, "<nodes.list" or die;
 16+sub {
 17+ my @nodes = split / /, shift;
 18+ my $server = shift @nodes;
 19+ sub {
 20+ open my $h, ">>node_groups/". shift or die;
 21+ print $h "$server\n";
 22+ }->($_) for @nodes;
 23+}->($_) for <LIST>;
 24+
Property changes on: trunk/udpmcast/nodesync/nodesync.pl
___________________________________________________________________
Added: svn:keywords
125 + Author Date Id Revision
Added: svn:eol-style
226 + native
Added: svn:executable
327 + *
Index: trunk/udpmcast/edit_counter/count_edits.py
@@ -0,0 +1,141 @@
 2+#! /usr/bin/env python
 3+#
 4+# $Header$
 5+#
 6+# MediaWiki user edit counter.
 7+# This code is in the public domain.
 8+
 9+execfile("/home/kate/degree.cf", globals());
 10+
 11+import sys
 12+import MySQLdb
 13+
 14+import cgi
 15+f = cgi.FieldStorage()
 16+
 17+def getdblist():
 18+ try:
 19+ f = file("/home/wikipedia/common/all.dblist", "r")
 20+ i = []
 21+ while True:
 22+ s = f.readline()
 23+ if s == '':
 24+ return i
 25+ s = s[:-1]
 26+ i.append(s)
 27+ return i
 28+ except:
 29+ return []
 30+ return []
 31+
 32+if f.has_key('dbname') and f['dbname'].value in getdblist():
 33+ dbname = f['dbname'].value
 34+
 35+print "Content-Type: text/html; charset=iso-8859-1"
 36+print
 37+print """
 38+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 39+<html>
 40+<head><title>editcount</title>
 41+</head>
 42+<body>"""
 43+
 44+namespaces = {
 45+ 0: 'Articles',
 46+ 1: 'Talk',
 47+ 2: 'User',
 48+ 3: 'User talk',
 49+ 4: 'Wikipedia',
 50+ 5: 'Wikipedia talk',
 51+ 6: 'Image',
 52+ 7: 'Image talk',
 53+ 8: 'MediaWiki',
 54+ 9: 'MediaWiki talk',
 55+ 10: 'Template',
 56+ 11: 'Template talk',
 57+ 12: 'Help',
 58+ 13: 'Help talk',
 59+ 14: 'Category',
 60+ 15: 'Category talk'
 61+}
 62+
 63+def ns2name(ns):
 64+ return namespaces[ns]
 65+
 66+def editcount(user, nsb):
 67+ ns = dict()
 68+ total = 0
 69+ db = MySQLdb.connect(db=dbname, host=dbserver, user=dbuser, passwd=dbpassword)
 70+ c = db.cursor()
 71+ c.execute("SELECT user_id FROM user WHERE user_name=%s", user)
 72+ t = c.fetchone()
 73+ if t == None:
 74+ print "<strong>user '" + cgi.escape(user) + "' does not exist</strong><br/>"
 75+ return
 76+ uid = t[0]
 77+ if nsb:
 78+ for i in range(0, 16):
 79+ c.execute("SELECT COUNT(*) FROM cur WHERE cur_user=%s AND cur_namespace=%s", (uid, i))
 80+ t = c.fetchone()
 81+ ns[i] = t[0]
 82+ c.execute("SELECT COUNT(*) FROM old WHERE old_user=%s AND old_namespace=%s", (uid, i))
 83+ t = c.fetchone()
 84+ ns[i] += t[0]
 85+ print """
 86+<table cellspacing="0">
 87+<tr><th style="border-bottom: solid 1px black; border-right: solid 1px black">namespace</th><th style="border-bottom: solid 1px black">edits</th></tr>
 88+"""
 89+ for nsn in ns.keys():
 90+ print "<tr><td style='border-right: solid 1px black'>%s</td><td style='text-align: right'>%d</td></tr>" % (ns2name(nsn), ns[nsn])
 91+ total += ns[nsn]
 92+ print "</table>"
 93+ else:
 94+ c.execute("SELECT COUNT(*) FROM cur WHERE cur_user=%s", uid)
 95+ t = c.fetchone()
 96+ total = int(t[0])
 97+ c.execute("SELECT COUNT(*) FROM old WHERE old_user=%s", uid)
 98+ t = c.fetchone()
 99+ total += t[0]
 100+ print cgi.escape(user) + " has a total of %d edits<br/>" % total
 101+ return
 102+
 103+if f.has_key('user'):
 104+ print "<div>"
 105+ print "<br/>"
 106+ nsb = False
 107+ # too slow
 108+ #if f.has_key('nsb'):
 109+ # nsb = True
 110+ editcount(f['user'].value, nsb)
 111+ print "</div>"
 112+
 113+print """
 114+<hr/>
 115+<form action="count_edits" method="get">
 116+user name: <input type="text" name="user"/>
 117+<select name="dbname">
 118+"""
 119+
 120+dblist = getdblist()
 121+dblist.sort()
 122+for db in dblist:
 123+ selected = ''
 124+ if db == dbname:
 125+ selected=' selected="selected"'
 126+ print '<option value="%s"%s>%s</option>' % (db, selected,db)
 127+print """
 128+</select>
 129+<input type="submit" value="go" />
 130+<!--<input type="checkbox" name="nsb"/>breakdown by namespace (slow)-->
 131+<br/>
 132+<p>
 133+<strong>warning:</strong> <em>editcountitis can be fatal</em>
 134+</p>
 135+<hr/>
 136+kate's tools:
 137+<strong>user edit counter</strong>
 138+| <a href="six_degrees">six degrees of wikipedia</a>
 139+</form>
 140+</body>
 141+</html>
 142+"""
Property changes on: trunk/udpmcast/edit_counter/count_edits.py
___________________________________________________________________
Added: svn:keywords
1143 + Author Date Id Revision
Added: svn:eol-style
2144 + native
Added: svn:executable
3145 + *

Status & tagging log