1
0
Fork 0
mirror of git://git.psyced.org/git/psyced synced 2024-08-15 03:25:10 +00:00

let the past begone in cvs land. welcome to igit igit!

This commit is contained in:
PSYC 2009-01-26 20:21:29 +01:00
commit 4e601cf1c7
509 changed files with 77963 additions and 0 deletions

View file

@ -0,0 +1,4 @@
it: profiles.c
profiles.c: profiles.pl
perl $<

162
world/net/library/admin.c Normal file
View file

@ -0,0 +1,162 @@
// $Id: admin.c,v 1.26 2007/08/20 12:25:23 lynx Exp $ // vim:syntax=lpc
//
// admin functions and shutdown procedure
//
#include <net.h>
#include <proto.h>
#include <sandbox.h>
// amount of seconds per pass
#ifndef TIME_SHUTDOWN
# if DEBUG > 0
# define TIME_SHUTDOWN 2
# else
# define TIME_SHUTDOWN 4
# endif
#endif
// this used to be notify_shutdown() in master.c, but we need to do this
// before the backend actually terminates, and give it a little time to
// shutdown communications sanely. so now the shutdown is a 3 pass process.
//
// pass 0: shutdown all entities
// pass 1: shutdown all network circuits
// pass 2: make sure everything is done and terminate
//
// beware that an external "killall -1 psyced" inevitabely performs only
// the last pass, so we need to be able to clean up as best we can, so that
// psyced gets half a chance to exit in a psyc-friendly way. it is therefore
// not recommended to shutdown a psyc server by signal. please use /ciao or
// implement a _request_shutdown you can trigger from say perlpsyc's tell.
//
varargs int server_shutdown(string reason, int restart, int pass) {
object o;
int i, errors;
PROTECT("SERVER_SHUTDOWN")
shutdown_in_progress++;
if (master) master->notify_shutdown_first(shutdown_in_progress);
else debug_message("Warning: Master object destructed?\n");
if (!reason || reason == "") {
#ifdef DEFAULT_SHUTDOWN_REASON
reason = DEFAULT_SHUTDOWN_REASON;
#else
reason = CHATNAME " is performing a quick full twist double "
"salto backwards.";
#endif
}
unless (pass) { // first pass
P0(("Server %s requested by %O. Grace period: "+ TIME_SHUTDOWN * 2
+" secs.\n", restart? "RESTART": "SHUTDOWN", previous_object()))
// see "psyced" script (was: muvelauncher)
unless (restart) rm(DATA_PATH ".autorestart");
call_out(#'server_shutdown, TIME_SHUTDOWN, reason, restart, 1);
}
// we first quit all users.. then do the items
foreach (o : objects_people()) {
if (catch(o->reboot(reason, restart, pass))) errors++;
}
if (pass++) {
// this walks thru the complete list of objects of the driver
// and gives every stupid little object a chance to store its state.
// this may one day change into something more strategic, but since
// most PSYC objects do have something to save, this does a good job!
#if __EFUN_DEFINED__(debug_info)
for(i=0; o = debug_info(2,i); i++) {
// we skip the tcp links, as the other objects will need them
unless (interactive(o)) {
// will output error anyway, but not stop loop from running
P2(("%O->reboot(%O, %O, %O)\n", o, reason, restart, pass))
if (catch(o->reboot(reason, restart, pass))) errors++;
}
}
#endif
// we use this because remove_player() comes too late to properly
// terminate any protocols and send any notifications
// TODO: rewrite this with a foreach catch!
pass++;
P2(("%O->reboot(%O, %O, %O)\n", users(), reason, restart, pass))
#ifdef __LPC_ARRAY_CALLS__
// this is actually imperfect, as a bug in one user breaks the loop
if (catch(users()->reboot(reason, restart, pass))) errors++;
#else
# if __EFUN_DEFINED__(lambda) && __EFUN_DEFINED__(filter)
// same problem here
filter(users(), lambda(({'u}),
({ #'call_other, 'u, "reboot", reason, restart, pass }) //'
));
# else
# echo Warning: No neat shutdown function.
# endif
#endif
if (pass == 3) {
call_out(#'shutdown, TIME_SHUTDOWN);
save_object(DATA_PATH "library");
} else {
P0(("server_shutdown ended at pass %O\n", pass))
}
}
P2(("Errors during shutdown: %O\n", errors))
return errors;
}
varargs void shout(mixed who, string what, string text, mapping vars) {
PROTECT("SHOUT")
unless(mappingp(vars)) vars = ([]);
#if 0 //def __LPC_ARRAY_CALLS__
// we can't use this cuz we need to copy(vars) for each
objects_people() -> msg(who, what, text, vars);
#else
# if __EFUN_DEFINED__(lambda) && (__EFUN_DEFINED__(filter_array) || __EFUN_DEFINED__(filter))
# if __EFUN_DEFINED__(filter)
filter(objects_people(), lambda(({'u}), ({#'call_other,
'u, "msg", who, to_string(what), to_string(text),
({ #'copy, vars }) })
));
# else
filter_array(objects_people(), lambda(({'u}), ({#'call_other,
'u, "msg", who, to_string(what), to_string(text),
({ #'copy, vars }) })
));
# endif
// # else
// # echo shout() admin function disabled on this driver
# endif
#endif
}
#ifndef PRO_PATH
// boss commands belong into an appropriate commander daemon meguesses
// anyway, they get called by bossy user objects - but also by the httpd
//
int boss_command(string cmd, string args) {
object o;
PROTECT("BOSS_COMMAND")
switch(cmd) {
case "shutdown":
// "Server shutting down. Please don't cry."
// shout(0, "_notice_broadcast_shutdown",
// "Server shutdown: [_reason]", ([ "_reason": args ]));
server_shutdown(args, 0);
return 1;
case "ciao":
case "hasta":
case "reboot":
case "restart":
// "Server restarting. Fasten seat belts."
// shout(0, "_notice_broadcast_shutdown_restart",
// "Server restart: [_reason]", ([ "_reason": args ]));
server_shutdown(args, 1);
return 1;
}
return 0;
}
#endif

102
world/net/library/base64.c Normal file
View file

@ -0,0 +1,102 @@
// $Id: base64.c,v 1.7 2005/11/13 19:52:44 lynx Exp $ // vim:syntax=lpc
//
// base64 encoder/decoder
// 2004 - Dan@Gueldenland - df@erinye.com
//
#include <net.h>
volatile string * char64 = efun::explode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "");
volatile mapping deco64 = funcall( (:
mapping x = ([ ]);
int i;
for(i=0; i<64; ++i) {
x[char64[i][0]] = i+1;
}
x['='] = 1;
return x;
:) );
static int deco(int i) {
i = deco64[i];
if(!i) raise_error("Oh crap.\n");
return i-1;
}
string encode_base64(int * b) {
int bbb, i=0, s=sizeof(b);
string res = "";
while(i+3 <= s) {
bbb = (b[i++] & 0xff) << 16;
bbb |= (b[i++] & 0xff) << 8;
bbb |= b[i++] & 0xff;
res += char64[(bbb & 0xfc0000) >> 18] + char64[(bbb & 0x3f000) >> 12] + char64[(bbb & 0xfc0) >> 6] + char64[bbb & 0x3f];
}
if(s - i == 2) {
bbb = ((b[i++] & 0xff) << 16) | ((b[i++] & 0xff) << 8);
res += char64[(bbb & 0xfc0000) >> 18] + char64[(bbb & 0x3f000) >> 12] + char64[(bbb & 0xfc0) >> 6] + "=";
} else if(s - i == 1) {
bbb = ((b[i] & 0xff) << 16);
res += char64[(bbb & 0xfc0000) >> 18] + char64[(bbb & 0x3f000) >> 12] + "==";
}
return res;
}
// this doesn't really enforce base64, but if it finds = on positions they
// shouldn't be on, this'll get sullen.
int * decode_base64(string b) {
int * res = ({ });
int i=0, s, next;
b = replace(b, "\n", "");
b = replace(b, "\r", "");
s = strlen(b);
while(i+4 <= s) {
res += ({ (deco(b[i]) << 2) | (deco(b[i+1]) >> 4) });
next = ((deco(b[i+1]) << 4) & 0xff) | (deco(b[i+2]) >> 2);
unless (!next && b[i+2] == '=') {
res += ({ next });
} else {
return res;
}
next = ((deco(b[i+2]) << 6) & 0xc0) | deco(b[i+3]);
unless (!next && b[i+3] == '=') {
res += ({ next });
} else {
return res;
}
i += 4;
}
return res;
}
#if DEBUG > 1
void base64_self_test() {
int i, j, cool;
string x, y, z;
for(i=0; i<10; ++i) {
x = "";
j = random(100) + 5;
while(j>0) {
x += to_string(({ 32 + random(96) }));
--j;
}
y = encode_base64(to_array(x));
z = to_string(decode_base64(y));
if(z == x) ++cool;
else {
P2(("uncool:\n%O !=\n%O\n", x, z));
P3(("base: %O\n", y))
P3(("strlen: %O, %O, last: %O\n", strlen(x), strlen(z), z[<1]))
}
}
P2(("base64_self_test: %d out of 10 successful.\n", cool));
}
#endif

664
world/net/library/dns.c Normal file
View file

@ -0,0 +1,664 @@
// vim:syntax=lpc
// info: to unfold and view the complete file, hit zR in your vim command mode.
//
// $Id: dns.c,v 1.112 2008/03/29 20:05:32 lynx Exp $
//
// {{{ meta-bla about foldmethod=marker
// <lynX> hm.. find ich folding jetzt eher nützlich oder lästig? muss ich
// noch herausfinden. auf jeden fall sind die farben eher unpraktisch.
// steht sicher irgendwo in irgendwelchen files definiert.. juchei
// übertreiben sollte man's jedenfalls nicht, oder was soll das
// "whatis comment" anderes erreichen als dass der kommentar nicht
// gelesen wird obwohl er extra dafür geschrieben wurde?
// }}}
// und dann ist da noch myUNL, myLowerCaseHost.
// in der psyclib. letzteres gehört wohl eher hier her.
// {{{ includes
#include "net.h"
#include "proto.h"
#include "closures.h"
#include <dns.h>
#include <erq.h>
#include <sandbox.h>
// }}}
// {{{ queue-inherit
#ifdef NEW_QUEUE
inherit NET_PATH "queue2";
#else
inherit NET_PATH "queue";
#endif
// }}}
// {{{ variables
//
// this mapping has to be *volatile* or it will carry old hostnames
// that may no longer be valid, then cause wild illogical behaviour
volatile mapping localhosts = ([
"localhost": "127.0.0.1",
"127.0.0.1": "localhost",
// unusual but valid syntax for localhost
// then again usually any 127.* leads to localhost so it's
// pointless and after all it can even be good for testing
// the switch protocol on oneself.. ;)
"127.0.1": "localhost",
"127.1": "localhost",
// "0": ??
#ifdef __HOST_IP_NUMBER__
# if __HOST_IP_NUMBER__ != "127.0.0.1"
__HOST_IP_NUMBER__ : 1,
# endif
#endif
// the hostnames need to be in lowercase... lets do it later
// SERVER_HOST : 1,
#if defined(JABBER_HOST)
# if JABBER_HOST != SERVER_HOST
// JABBER_HOST : 1,
# endif
#endif
]);
volatile mapping host2canonical = ([ ]);
volatile object hostsd;
// }}}
// {{{ query_server_ip && myip && register_localhost
#ifndef __HOST_IP_NUMBER__
volatile string myIP;
#else
# define myIP __HOST_IP_NUMBER__
#endif
string query_server_ip() { return myIP; }
// take care to always pass a lowercased (virtual) hostname
varargs void register_localhost(string name) { //, string ip) {
//unless (ip) ip = myIP;
localhosts[name] = 1; //ip;
// either we have a static ip, then we already know it, or we
// have a public ip hidden by a firewall or nat, then we can
// find it out using #'set_my_ip - but what if by dsl relogin
// or something like that our public ip address changes? then
// we have an old ip number which by very unlikely circumstance
// could possibly turn into a security problem. but what's worse:
// we might get used having the public ip in here, and then it
// suddenly no longer is (because there is an old one instead)
// i have the impression we are well off if we only know all of
// our virtual host names - we don't need our ip numbers really
//localhosts[ip] = name;
}
// }}}
#ifndef SANDBOX
// {{{ function: del_queue
void del_queue(string queue) {
qDel(queue);
}
// }}}
#endif
// {{{ function: legal_host
int legal_host(string ip, int port, string scheme, int udpflag) { // proto.h!
P3(("legal_host %O %O %O %O\n", ip, port, scheme, udpflag))
// do not allow logins during shutdown
// if (shutdown_in_progress) return 0;
// we sincerely hope our kernel will drop udp packets that
// spoof they are coming from localhost.. would be ridiculous if not
// if (ip == "127.0.0.1" || ip == "127.1" || ip == "0") return 9;
#ifndef DONT_TRUST_LOCALHOST
if (localhosts[ip]) return 9;
if (ip == myIP || !ip) return 8;
#endif
unless (hostsd) hostsd = DAEMON_PATH "hosts" -> load();
P4(("legal_host asks %O\n", hostsd))
return hostsd -> legal_host(ip, port, scheme, udpflag);
}
// }}}
// {{{ function: legal_domain
int legal_domain(string host, int port, string scheme, int udpflag) {
// we sincerely hope our kernel will drop udp packets that
// spoof they are coming from localhost.. would be ridiculous if not
//
// TODO: use is_localhost here?
#ifndef DONT_TRUST_LOCALHOST
if (host == "localhost" || host == SERVER_HOST) return 9;
#endif
// if (host == myLowerCaseHost) return 8;
// if (lower_case(host) == myLowerCaseHost) return 7;
// unless (hostsd) hostsd = DAEMON_PATH "hosts" -> load();
// return hostsd -> legal_domain(host, port, scheme, udpflag);
return 5; // TODOOOOOO
}
// }}}
// {{{ function: chost
// {{{ whatis comment
/** provides us with the "canonical" name of a host as given by DNS PTR,
** not to be confused with the aliasing facility "CNAME" - not sure
** about this function name but don't know any better right now.
** this function does NOT do any DNS resolutions itself, it only consults
** a cache which is kept up to date by the dns_*resolve functions.
** it is therefore nice and fast.
*/
// }}}
string chost(string host) {
return host2canonical[host];
}
// }}}
// {{{ function: same_host
// {{{ whatis comment
/** figures out if two hostnames (aliases or its ip) are the same host.
** this is essentially chost(a) == chost(b) with one function call less.
*/
// }}}
// {{{ remarks
// we should probably lower_case() hosts, as there has been trouble w/
// hostnames once lower_cased() (extracted from unl, probably) and
// !lower_cased() when we were testing _identification w/ pypsycd.
// of course we'd then have to do host = lower_case(host) in register_host(),
// too. }}}
int same_host(string a, string b) {
//mixed c = host2canonical[lower_case(a)];
mixed c = host2canonical[a];
P2(("same_host %O -> %O ==? %O -> %O\n", a, c, b, host2canonical[b]))
//return stringp(c) && c == host2canonical[lower_case(b)];
return stringp(c) && c == host2canonical[b];
}
// }}}
// {{{ function: register_host
varargs void register_host(string host, mixed canonical) {
PROTECT("REGISTER_HOST")
P2(("register_host %O, %O.\n", host, canonical))
if (stringp(canonical)) {
if (host2canonical[host] != canonical && host2canonical[host]) {
// 0 was already mapped to "andrack.tobij.de", now points ...
// dunno why that happens, but here we catch it
unless (host) return;
// this probably only happens if the server has been running
// for several weeks.. the fx are probably mostly harmless
// just some dynamic ip which gets reused by someone else
canonical = lower_case(canonical);
if (host2canonical[host] != canonical) {
// with akamai sites this happens all the time and is harmless
#if 0
monitor_report("_warning_overridden_register_host",
S("%O was already mapped to %O, now points to %O.",
host, host2canonical[host], canonical));
#else
P1(("%O was already mapped to %O, now points to %O.\n",
host, host2canonical[host], canonical))
#endif
}
}
else canonical = lower_case(canonical);
host2canonical[host] = canonical;
P3(("%O mapped to %O.\n", host, canonical))
return;
}
else if (intp(canonical) && canonical < 0) {
if (stringp(host2canonical[host])) {
// we do get to see this message sometimes.. weird thang dns
P1(("%O no longer resolves, we keep it mapped to %O.\n",
host, host2canonical[host]))
// no this doesn't seem to be triggered by timed out dyndns
// as dyndns usually carries around the old ip number
return;
}
// host did not resolve, let's store this fact
host2canonical[host] = canonical;
return;
}
// we won't need the lambda-closure because of my ingenious varargs design
// in dns_resolve() and dns_rresolve()
#if 0
dns_resolve(host, #'dns_rresolve, lambda(({ 'canonical }),
({ #'=, ({ CL_INDEX, host2canonical, host }), 'canonical }) ) );
#else
dns_resolve(host, #'dns_rresolve,
(: if (stringp($1)) $2[$3] = $1;
return; :), host2canonical, host);
#endif
return;
}
// }}}
// {{{ function: dns_refresh
/** wild idea of tobi, needs an admin command to trigger it */
void dns_refresh() {
string host;
PROTECT("DNS_REFRESH")
foreach (host : m_indices(host2canonical)) { register_host(host); }
}
// }}}
// {{{ usage: dns_*resolve
// we do know that lambda() might be a quite unfamiliar concept to the usual
// coder, so we made dns_resolve() and dns_rresolve() a little more handy.
// you can use inline-closures at the caller side, even if you need some
// "variables" or arguments which cannot be accessed by an unsual inline
// closure (with 3-3 style inline closures that works, but we encourage you
// not to use them for backward compatibility).
//
// so here is an usage example:
// dns_resolve(hostname, (: sendmsg($2, "_some_mc", $3 + " has been resolved "
// "to " + $1); :), source, hostname);
// $1 will be the dns_resolve result, $2 will be source and $3 will be
// hostname. as you already guessed, $2 and further are just the arguments
// you appended to the dns_resolve() call after the closure, and $1 is, as said,
// the dns_resolve() result.
// this works for any number of extra arguments.
//
// this is also works for dns_rresolve()
// }}}
// {{{ function: dns_resolve
// {{{ whatis comment
/** sends a request to the erq to resolve a hostname, on reception of the
** reply does the callback where it passes either the ip-number as string
** or -1 for failure, followed by any extra arguments you gave it
*/ // }}}
void dns_resolve(string hostname, closure callback, varargs array(mixed) extra) {
closure c, c2; // proto.h
string queuename;
P4(("dns_resolve called with (%O, %O, %O).\n", hostname, callback, extra))
unless (stringp(hostname)) {
P1(("dns_resolve called with (%O, %O, %O). stopping.\n", hostname, callback, extra))
return;
}
#ifdef __IDNA__
if (catch(hostname = idna_to_ascii(TO_UTF8(hostname)); nolog)) {
P0(("catch: punycode %O in %O\n", hostname, ME))
return;
}
#endif
if (sizeof(extra)) {
c2 = lambda( ({ 'name }),
({ #'funcall, callback, 'name }) + extra );
} else {
c2 = callback;
}
// if unnecessary this can move into !__ERQ_MAX_SEND__
switch(hostname) {
// case myLowerCaseHost: // TODO!!
#if defined(SERVER_HOST) && SERVER_HOST != "localhost"
case SERVER_HOST:
# ifdef __HOST_IP_NUMBER__
funcall(c2, __HOST_IP_NUMBER__, callback);
# else
unless (myIP) break;
funcall(c2, myIP, callback);
# endif
P4(("self rresolution used\n"))
return;
#endif
case "localhost":
P3(("localhost rresolution used\n"))
funcall(c2, "127.0.0.1", callback);
return;
}
if (sscanf(hostname,"%~D.%~D.%~D.%~D") == 4) {
// hostname is an IP already. Just call the callback.
funcall(c2, hostname, callback);
return;
}
#ifdef __ERQ_MAX_SEND__
queuename = "f" + hostname;
if (qExists(queuename)) {
enqueue(queuename, c2);
return;
} else {
qInit(queuename, 1000, 10);
enqueue(queuename, c2);
}
c = lambda( ({ 'name }), ({
(#'switch), ({ #'sizeof, 'name }),
({ 4 }), // ERQ: name resolved!
({ (#',),
({ (#'=),'name,({ (#'map),'name,#'&,255 }) }),
({ (#'=),'name,
({
(#'sprintf),"%d.%d.%d.%d",
({ CL_INDEX, 'name, 0 }),
({ CL_INDEX, 'name, 1 }),
({ CL_INDEX, 'name, 2 }),
({ CL_INDEX, 'name, 3 })
})
}),
({ #'while, ({ #'qSize, queuename }), 42,
({ #'catch,
({ #'funcall, ({ #'shift, queuename }),
'name })
})
}),
({ #'qDel, queuename })
}),
(#'break),
# ifdef XERQ
({ 6 + strlen(hostname) }), // XERQ
({ (#',),
({ (#'=),'name,({ (#'map),'name,#'&,255 }) }),
({ (#'=),'name,
({
(#'sprintf),"%d.%d.%d.%d",
({ CL_INDEX, 'name, 1 }),
({ CL_INDEX, 'name, 2 }),
({ CL_INDEX, 'name, 3 }),
({ CL_INDEX, 'name, 4 })
})
}),
({ #'while, ({ #'qSize, queuename }), 42,
({ #'catch,
({ #'funcall, ({ #'shift, queuename }),
'name
})
})
}),
({ #'qDel, queuename })
}),
(#'break),
# endif
({ #'default }),
({
(#',),
# if DEBUG > 0
({ #'debug_message, "ERQ could not resolve \""+ hostname +"\".\n" }),
# endif
// host2canonical[hostname] = 0; <--
({ #'funcall, #'register_host, hostname, -1 }),
({ #'while, ({ #'qSize, queuename }), 42,
/* held sagt: also zuerst sagt er
:* ERQ could not resolve
:* und dann die while whiles sind die queues
:* also angestaute einträge in der queue
:* die er dann mit -1 aufruft
:* nach den while whiles wird die queue gelöscht
:* und der nächste dns_resolve-aufruf geht wieder an den erq
:* ziel der queues ist in diesem falle kein caching, sondern
:* nur lineares aufrufen der callbacks
:* also, fifo
:*/
// ({ #'debug_message, "while while "+ hostname + "\n"}),
({ #'catch, ({ #'funcall, ({ #'shift, queuename }),
-1 }) }) }),
({ #'qDel, queuename })
}),
(#'break)
}) );
// this efun was introduced shortly after erq was fixed.. btw what does it do?
# if __EFUN_DEFINED__(reverse)
// we are currently doing too many resolutions.. this is nice for
// dyndns but silly if we have a valid tcp connection to the host
// in question, thus it is proven that the ip hasn't changed.
P3(("resolving "+hostname+"\n"))
unless (send_erq(ERQ_LOOKUP, hostname, c))
# else
// appending the zero byte fixes a bug in erq. sick!
unless (send_erq(ERQ_LOOKUP, to_array(hostname) + ({ 0 }), c))
# endif
#else
// it's all pretty useless if __ERQ_MAX_SEND__ is defined
// even if ldmud was called with -N. what is this, a bug?
P1(("no erq: returning unresolved %O\n", hostname))
#endif
{
P1(("%O failed to ERQ_LOOKUP %O!\n", ME, hostname))
// if we cannot resolve using erq, we'll send back the hostname,
// so the driver can do a blocking resolve itself (needed for
// net_connect())
funcall(c2, hostname, callback);
#ifdef __ERQ_MAX_SEND__
qDel(queuename);
#endif
}
return;
}
// }}}
// {{{ function: dns_rresolve
// {{{ whatis comment
/** requests a reverse lookup of the given ip address from the erq process,
** on reply calls dns_resolve() to ensure the returned host name does indeed
** point to the ip address (protection against basic DNS spoofing), then
** does the callback, where it passes either the hostname of the ip as given
** by IN PTR, -1 for resolution failure, or -2 for a DNS spoofing attempt.
** extra arguments follow, if you provided any.
*/ // }}}
void dns_rresolve(string ip, closure callback, varargs array(mixed) extra) {
closure rresolve, resolve; // proto.h
int i1, i2, i3, i4;
string queuename;
P4(("dns_rresolve called with (%O, %O, %O).\n", ip, callback, extra))
unless (stringp(ip)) {
P1(("dns_rresolve called with (%O, %O, %O). stopping.\n", ip, callback, extra))
return;
}
extra = ({ #'funcall, callback, 'host }) + extra;
// if unnecessary this can move into !__ERQ_MAX_SEND__
switch(ip) {
#ifdef __HOST_IP_NUMBER__
# if __HOST_IP_NUMBER__ != "127.0.0.1"
case __HOST_IP_NUMBER__:
# else
# ifndef myIP
case myIP:
# else
case 0: // the hostname IS localhost, so this never happens
# endif
# endif
P4(("self resolution used\n"))
if (sizeof(extra)) funcall(lambda( ({ 'host }), extra), SERVER_HOST);
else funcall(callback, SERVER_HOST);
return;
#endif
case "127.0.0.1":
P3(("localhost resolution used\n"))
if (sizeof(extra)) funcall(lambda( ({ 'host }), extra), "localhost");
else funcall(callback, "localhost");
return;
}
#ifdef __ERQ_MAX_SEND__
unless (sscanf(ip, "%D.%D.%D.%D", i1, i2, i3, i4) == 4) {
// that is not an ip. what shall we do?
// we're just returning for now. suggestions -> changestodo
P1(("dns_rresolve called with (%O, %O, %O). stopping.\n", ip, callback, extra))
return;
}
queuename = "r" + ip;
resolve = lambda( ({ 'host, 'ip, 'rip }),
({ #'?,
({ #'==, 'ip, 'rip }),
({ (#',),
({ #'while, ({ #'qSize, queuename }),
42,
({ #'catch,
({ #'funcall, ({ #'shift, queuename }), 'host })
})
}),
({ #'qDel, queuename }),
}),
({ (#',),
({ #'=, 'host, -2 }), // useless line
({ #'while, ({ #'qSize, queuename }),
42,
({ #'catch,
({ #'funcall, ({ #'shift, queuename }), -2 })
}),
}),
({ #'qDel, queuename })
})
}) );
if (qExists(queuename)) {
enqueue(queuename, sizeof(extra)
? lambda(({ 'host }), extra)
: callback);
return;
} else {
qInit(queuename, 1000, 10);
enqueue(queuename, sizeof(extra)
? lambda(({ 'host }), extra)
: callback);
}
rresolve = lambda( ({ 'name }),
({ #'funcall, (:
$1 = to_string($1[4..<2]); // extract hostname from crazy
// erq return format
unless ($1 == "") {
dns_resolve($1, lambda( ({ 'name }),
({ #'funcall, $4, $1, $2, 'name, $3 }) ));
} else {
funcall($4, -1, 0, 0, $3);
}
return; :), 'name, ip, callback, resolve }) );
unless (send_erq(ERQ_RLOOKUP, ({ i1, i2, i3, i4 }), rresolve))
#else
P1(("no erq: returning unrresolved %O\n", ip))
#endif
{
P1(("%O failed to ERQ_RLOOKUP!\n", ME))
if (sizeof(extra)) {
funcall(lambda( ({ 'host }),
extra), ip);
} else {
funcall(callback, ip);
}
#ifdef __ERQ_MAX_SEND__
qDel(queuename);
#endif
}
return;
}
// }}}
// {{{ function: is_localhost
#if 1
// take care to always pass a lowercased (virtual) hostname
int is_localhost(string host) {
// async discovery of virtual hosts is not necessary
// we should know all of our hostnames in advance for
// security anyway
return member(localhosts, host);
}
#else
int is_localhost(string host, closure callback, varargs array(mixed) extra) {
if (member(localhosts, host)) {
funcall(callback, 1, extra);
return;
}
// this is maybe not enough... we should resolve myIP,.. too
if (sscanf(host, "%~D.%~D.%~D.%~D") == 4) {
// what needs to be done?? rresolve both host and __HOST_IP_NUMBER__ ?
dns_rresolve(host,
lambda(({ 'hostname }),
({ #'funcall, callback,
({ #'==, 'hostname, SERVER_HOST }) })
+ (sizeof(extra) ? extra : ({ }) )
));
} else {
# if !defined(__HOST_IP_NUMBER__) || __HOST_IP_NUMBER__ != "127.0.0.1"
dns_resolve(host,
lambda(({ 'hostname }),
({ #'funcall, callback,
# ifdef __HOST_IP_NUMBER__
({ #'==, 'hostname, __HOST_IP_NUMBER__ })
# else
({ #'==, 'hostname, myIP })
# endif
}) + (sizeof(extra) ? extra : ({ }) )
));
# else
funcall(callback, 0, extra);
# endif
}
}
# if 0
// call either true or false
void if_localhost(string host, closure true, closure false,
varargs array(mixed) extra) {
is_localhost(host, lambda(({ 'bol }),
({ #'funcall,
({ #'?, 'bol, true, false }),
}) + (sizeof(extra) ? extra : ({ }) ) ));
}
# endif
#endif // if 1
// }}}
#ifndef ERQ_WITHOUT_SRV
// {{{ function: dns_srv_resolve
void dns_srv_resolve(string hostname, string service, string proto, closure callback, varargs array(mixed) extra)
{
#ifdef __ERQ_MAX_SEND__
string req;
int rc;
// dumme bevormundung. wegen der musste ich jetzt ewig lang suchen:
//unless (proto == "tcp" || proto == "udp") return;
// da wir mit nem String arbeiten muessen
req = sprintf("_%s._%s.%s", service, proto, hostname);
rc = send_erq(ERQ_LOOKUP_SRV, req, lambda(({ 'wu }),
({ (#',),
({ #'?, ({ #'<, ({ #'sizeof, 'wu }), 3 }),
({ (#',),
# if DEBUG > 1
({ #'debug_message, "Could not srv_resolve _" +service+"._"+proto+"."+ hostname + "\n" }),
# endif
({ #'funcall, callback, -1 }) + extra,
({ #'return, 1 }),
}),
}),
({ #'=, 'i, 0 }),
({ #'=, 'resarr, quote(({ })) }),
({ #'=, 'wu, ({ #'explode, ({ #'to_string, ({ #'[..<], 'wu, 0, 3 }) }), "\n" }) }),
// wieso die if in der condition der while ???
({ #'while, ({ #'?, ({ #'<, 'i, ({ #'sizeof, 'wu }) }) }), 42,
({ (#',),
({ #'+=, 'resarr, ({ #'({, ({ #'({, ({ #'[, 'wu, 'i }), ({ #'to_int, ({ #'[, 'wu, ({ #'+, 'i, 1 }) }) }), ({ #'to_int, ({ #'[, 'wu, ({ #'+, 'i, 2 }) }) }), ({ #'to_int, ({ #'[, 'wu, ({ #'+, 'i, 3 }) }) }) }) }) }),
({ #'=, 'i, ({ #'+, 'i, 4 }) })
})
}),
// ({ #'funcall, callback, ({ #'sort_array, 'resarr, sortsrv }) }) + extra
({ #'funcall, callback, 'resarr }) + extra
})
));
unless (rc) {
P0(("%O failed to ERQ_LOOKUP_SRV!\n", ME))
funcall(callback, -1, extra);
}
// Rueckgabe vom erq bei Fehlschlag -> empty message wie bei ERQ_RLOOKUP
// callback sollte erwarten:
// ein Array von Arrays jeweils mit name, port, pref, weigth
// oder ein einzelnes Array und man betrachtet jeweils vier Dinger
// waer dufte wenn die lambda das splitten koennte... sonst muss es
// halt nen string sein der zurueckgegeben wird
return;
#else
P1(("no erq: aborting SRV check for %O\n", hostname))
funcall(callback, -1, extra);
#endif
}
// }}}
#endif

View file

@ -0,0 +1,20 @@
// $Id: htbasics.c,v 1.5 2007/06/28 20:17:50 lynx Exp $ // vim:syntax=lpc
#include <net.h>
#include <ht/http.h>
// html-escaping of generic strings -lynx
// to make sure they won't trigger
// html commands
//
string htquote(string s) {
ASSERT("htquote", stringp(s), s)
s = replace(s, "&", "&amp;");
// s = replace(s, "\"", "&quot;"); //"
s = replace(s, "<", "&lt;");
s = replace(s, ">", "&gt;");
return s;
}
#ifdef HTTP_PATH
# include HTTP_PATH "library.i"
#endif

79
world/net/library/json.c Normal file
View file

@ -0,0 +1,79 @@
#include <net.h>
#include <proto.h>
// pike code can be made to run in lpc and the other way round..
#include "jsonparser.pike"
// see http://about.psyc.eu/Serialisation on the merits of JSON
//
// this function is useful if we decide to use json for complex data
// (or rather cannot come up with something better)
//
string make_json(mixed d) {
if (stringp(d)) {
#if 1
string *x;
// this code runs on the presumption that the regexplode
// will hardly ever encounter anything. should these chars
// be commonplace, then the 7 regreplace approach would be
// more efficient.
x = regexplode(d, "(\"|\\\\|\n|\t|\b|\r|\f)");
if (sizeof(x) > 1) {
int i;
for (i=sizeof(x)-2; i >= 0; i-=2) {
switch(x[i]) {
case "\"": x[i] = "\\\""; break; // common stuff
case "\n": x[i] = "\\n"; break;
case "\t": x[i] = "\\t"; break;
case "\b": x[i] = "\\b"; break; // these chars should
case "\r": x[i] = "\\r"; break; // not appear in psyc
case "\f": x[i] = "\\f"; break; // strings anyway.. !?
case "\\": x[i] = "\\\\"; break;
default:
raise_error(S("encountered %O in %O\n", x[i], d));
}
P4((" .. encountered %O", x[i]));
}
P4((" .. result: %O\n", d))
}
return "\""+ implode(x, "") +"\"";
#else
// what i don't like about this thing is 7 calls of regreplace
// for every damn little string.
d = regreplace(d, "\n", "\\n", 1);
d = regreplace(d, "\t", "\\t", 1);
d = regreplace(d, "\b", "\\b", 1);
d = regreplace(d, "\r", "\\r", 1);
d = regreplace(d, "\f", "\\f", 1);
//d = regreplace(d, "\u", "\\u", 1); // unicode..???
d = regreplace(d, "\"", "\\\"", 1);
d = regreplace(d, "\\\\", "\\\\\\\\", 1);
return "\""+ d +"\"";
#endif
} else if (intp(d)) {
return to_string(d);
} else if (pointerp(d)) {
return "[ " + implode(map(d, #'make_json), ", ") + " ]";
} else if (mappingp(d)) {
#if 0
return "{ " + implode(map(d,
(: return $1 + " : " + make_json($2[0]); :)),
", ") + " }";
#else
// mixed x = map(d,
// (: return make_json($1) +" : "+ make_json($2); :));
// let's presume a key of type string doesnt contain evil chars
mixed x = map(d,
(: return (stringp($1) ? ("\""+ $1 +"\"") : make_json($1))
+":"+ make_json($2); :));
P3(("\nintermediate: %O\n", m_values(x)))
return "{"+ implode(m_values(x), ",") +"}";
#endif
}
}
// see also net/place/storic.c for a JSON generator limited and optimized
// to the output of HTML-quoted strings.

View file

@ -0,0 +1,620 @@
// vim:syntax=lpc
// $Id: jsonparser.pike,v 1.2 2006/10/25 17:50:11 lynx Exp $
//
// I really hate those comments.
//
// Copyright History:
// 1. Public Domain 2002 JSON.org
// 2. Ported to C# by Are Bjolseth, teleplan.no
// 3. Ported to pike by Bill Welliver
// "Last night, I downloaded the JSON-C# code, and converted it to pike
// (with relatively little effort, it was mostly a tedious reformatting
// job)."
// 4. Adopted by Tobias 'tobij' Josefowitz, now uses Pike datastructures,
// and can only be run in LDMud.
//
// As far as I am concerned, this still is Public Domain.
// I will probably once find out whether Are and Bill think the same wwy
// about it.
#ifdef __PIKE__
/// <summary>
/// <para>
/// A JSONTokener takes a source string and extracts characters and tokens from
/// it. It is used by the JSONObject and JSONArray constructors to parse
/// JSON source strings.
/// </para>
/// <para>
/// Public Domain 2002 JSON.org
/// @author JSON.org
/// @version 0.1
/// </para>
/// <para>Ported to C# by Are Bjolseth, teleplan.no</para>
/// <para>
/// <list type="bullet">
/// <item><description>Implement Custom exceptions</description></item>
/// <item><description>Add unit testing</description></item>
/// <item><description>Add log4net</description></item>
/// </list>
/// </para>
/// </summary>
/// <summary>The index of the next character.</summary>
int myIndex;
/// <summary>The source string being tokenized.</summary>
string mySource;
# define PROTECTED public
# define THROW(x) throw(Error.Generic(x))
# define SBGET(x) (x)->get()
# define int2char(x) String.int2char(x)
# define trim_whites(x) String.trim_whites(x)
program objectbuilder, arraybuilder;
#else
# define PROTECTED protected
PROTECTED int myIndex;
PROTECTED string mySource;
# define arrayp(x) pointerp(x)
# define THROW(x) raise_error(x)
# define UNDEFINED 0
# define SBGET(x) (x)
# define int2char(x) _int2char(x)
# define trim_whites(x) trim(x)
# define search strstr
PROTECTED mixed nextObject();
PROTECTED string _int2char(int c) {
string s = " ";
s[0] = c;
return s;
}
#endif
/// <summary>
/// Construct a JSONTokener from a string.
/// </summary>
/// <param name="s">A source string.</param>
#ifdef __PIKE__
void create(string s, program|void objectb, program|void arrayb)
#else
mixed parse_json(string s)
#endif
{
mySource = s;
myIndex = 0;
#ifdef __PIKE__
objectbuilder = objectb;
arraybuilder = arrayb;
#else
return nextObject();
#endif
}
/// <summary>
/// Back up one character. This provides a sort of lookahead capability,
/// so that you can test for a digit or letter before attempting to parse
/// the next number or identifier.
/// </summary>
PROTECTED void back() {
if (myIndex > 0)
myIndex -= 1;
}
/// <summary>
/// Get the hex value of a character (base16).
/// </summary>
/// <param name="c">
/// A character between '0' and '9' or between 'A' and 'F' or
/// between 'a' and 'f'.
/// </param>
/// <returns>An int between 0 and 15, or -1 if c was not a hex digit.</returns>
PROTECTED int dehexchar(int c) {
if (c >= '0' && c <= '9')
{
return c - '0';
}
if (c >= 'A' && c <= 'F')
{
return c + 10 - 'A';
}
if (c >= 'a' && c <= 'f')
{
return c + 10 - 'a';
}
return -1;
}
/// <summary>
/// Determine if the source string still contains characters that next() can consume.
/// </summary>
/// <returns>true if not yet at the end of the source.</returns>
PROTECTED int more() {
return myIndex < sizeof(mySource);
}
/// <summary>
/// Get the next character in the source string.
/// </summary>
/// <returns>The next character, or 0 if past the end of the source string.</returns>
#ifdef __PIKE__
PROTECTED int next(int|void x)
#else
varargs PROTECTED int next(int x)
#endif
{
if(x) {
int n = next();
if (n != x) {
THROW("Expected '" + x + "' and instead saw '" + n + "'.\n");
}
return n;
} else {
int c = more() ? mySource[myIndex] : 0;
myIndex += 1;
return c;
}
}
/// <summary>
/// Get the next n characters.
/// </summary>
/// <param name="n">The number of characters to take.</param>
/// <returns>A string of n characters.</returns>
PROTECTED string nextn(int n) {
int i = myIndex;
int j = i + n;
if (j >= sizeof(mySource)) {
THROW("Substring bounds error\n");
}
myIndex += n;
return mySource[i..j];
}
/// <summary>
/// Get the next char in the string, skipping whitespace
/// and comments (slashslash and slashstar).
/// </summary>
/// <returns>A character, or 0 if there are no more characters.</returns>
PROTECTED int nextClean() {
while (1) {
int c = next();
if (c == '/') {
switch (next()) {
case '/':
do {
c = next();
} while (c != '\n' && c != '\r' && c != 0);
break;
case '*':
while (1) {
c = next();
if (c == 0) {
THROW("Unclosed comment.\n");
}
if (c == '*') {
if (next() == '/') {
break;
}
back();
}
}
break;
default:
back();
return '/';
}
}
else if (c == 0 || c > ' ') {
return c;
}
}
#ifndef __PIKE__
return 0; // will never be reached, stupid LDMud!
#endif
}
/// <summary>
/// Return the characters up to the next close quote character.
/// Backslash processing is done. The formal JSON format does not
/// allow strings in single quotes, but an implementation is allowed to
/// accept them.
/// </summary>
/// <param name="quote">The quoting character, either " or '</param>
/// <returns>A String.</returns>
PROTECTED string nextString(int quote) {
int c;
#ifdef __PIKE__
String.Buffer sb = String.Buffer();
#else
string sb = "";
#endif
while (1) {
c = next();
if ((c == 0x00) || (c == 0x0A) || (c == 0x0D)) {
THROW("Unterminated string.\n");
}
// CTRL chars
if (c == '\\') {
c = next();
switch (c) {
case 'b': //Backspace
sb+="\b";
break;
case 't': //Horizontal tab
sb+="\t";
break;
case 'n': //newline
sb+="\n";
break;
case 'f': //Form feed
sb+="\f";
break;
case 'r': // Carriage return
sb+="\r";
break;
case 'u':
#ifdef __PIKE__
int iascii;
sscanf(nextn(4), "%4x", iascii);
sb+=int2char(iascii);
#else
sb+=int2char(hex2int(nextn(2)));
sb+=int2char(hex2int(nextn(2)));
#endif
break;
default:
sb+=int2char(c);
break;
}
} else {
if (c == quote) {
#ifdef __PIKE__
return SBGET(sb);
#else
return sb;
#endif
}
sb+=int2char(c);
}
}//END-while
#ifndef __PIKE__
return ""; // will never be reached. stupid LDMud
#endif
}
/// <summary>
/// Unescape the source text. Convert %hh sequences to single characters,
/// and convert plus to space. There are Web transport systems that insist on
/// doing unnecessary URL encoding. This provides a way to undo it.
/// </summary>
/// <summary>
/// Convert %hh sequences to single characters, and convert plus to space.
/// </summary>
/// <param name="s">A string that may contain plus and %hh sequences.</param>
/// <returns>The unescaped string.</returns>
#ifdef __PIKE__
PROTECTED string unescape(string|void s)
#else
PROTECTED varargs string unescape(string s)
#endif
{
if(!s) s = mySource;
int len = sizeof(s);
#ifdef __PIKE__
String.Buffer sb = String.Buffer();
#else
string sb = "";
#endif
for (int i=0; i < len; i++) {
int c = s[i];
if (c == '+') {
c = ' ';
} else if (c == '%' && (i + 2 < len)) {
int d = dehexchar(s[i+1]);
int e = dehexchar(s[i+2]);
if (d >= 0 && e >= 0) {
c = (d*16 + e);
i += 2;
}
}
sb+=int2char(c);
}
return SBGET(sb);
}
#ifdef __PIKE__
mapping|object jsonObject()
#else
mapping jsonObject()
#endif
{
#ifdef __PIKE__
mixed addTo = objectbuilder ? objectbuilder() : ([ ]);
#else
mapping addTo = ([ ]);
#endif
if (next() == '%') {
unescape();
}
back();
if (nextClean() != '{') {
THROW("A JSONObject must begin with '{'.\n");
}
while (1) {
int c;
string key;
mixed obj;
c = nextClean();
switch (c) {
case 0:
THROW("A JSONObject must end "
"with '}'.\n");
case '}':
#ifdef __PIKE__
return mappingp(addTo)
? addTo
: ([object]addTo)->finish();
#else
return addTo;
#endif
case '"':
back();
// TODO:: error on != " || '
key = nextObject();
break;
default:
THROW("Non-String as "
"JSONObject-key. That "
"is invalid!\n");
}
if (nextClean() != ':') {
THROW("Expected a ':' after a key.\n");
}
obj = nextObject();
#ifdef __PIKE__
if (mappingp(addTo)) {
([mapping]addTo)[key] = obj;
} else {
([object]addTo)->add(key, obj);
}
#else
addTo[key] = obj;
#endif
switch (nextClean()) {
case ',':
if (nextClean() == '}') {
#ifdef __PIKE__
return mappingp(addTo) ? addTo : ([object]addTo)->finish();
#else
return addTo;
#endif
}
back();
break;
case '}':
#ifdef __PIKE__
return mappingp(addTo) ? addTo : ([object]addTo)->finish();
#else
return addTo;
#endif
default:
THROW("Expected a ',' or '}'");
}
}
#ifdef __PIKE__
return mappingp(addTo) ? addTo : ([object]addTo)->finish();
#else
return addTo;
#endif
}
#ifdef __PIKE__
array|object jsonArray()
#else
mixed *jsonArray()
#endif
{
#ifdef __PIKE__
mixed addTo = objectbuilder ? objectbuilder() : ({ });
#else
mixed *addTo = ({ });
#endif
if (nextClean() != '[') {
THROW("A JSONArray must start with '['.\n");
}
if (nextClean() == ']') {
#ifdef __PIKE__
return arrayp(addTo) ? addTo : ([object]addTo)->finish();
#else
return addTo;
#endif
}
back();
while (1) {
if (arrayp(addTo)) {
addTo += ({ nextObject() });
} else {
addTo->add(nextObject());
}
switch (nextClean())
{
case ',':
if (nextClean() == ']') {
#ifdef __PIKE__
return arrayp(addTo)
? addTo
: ([object]addTo)->finish();
#else
return addTo;
#endif
}
back();
break;
case ']':
#ifdef __PIKE__
return arrayp(addTo)
? addTo
: ([object]addTo)->finish();
#else
return addTo;
#endif
default:
THROW("Expected a ',' or ']'.\n");
}
}
#ifdef __PIKE__
return arrayp(addTo) ? addTo : ([object]addTo)->finish();
#else
return addTo;
#endif
}
/// <summary>
/// Get the next value as object. The value can be a Boolean, Double, Integer,
/// JSONArray, JSONObject, or String, or the JSONObject.NULL object.
/// </summary>
/// <returns>An object.</returns>
PROTECTED mixed nextObject() {
int c = nextClean();
string s;
if (c == '"' || c == '\'') {
return nextString(c);
}
// Object
if (c == '{') {
back();
return jsonObject();
}
// JSON Array
if (c == '[') {
back();
return jsonArray();
}
#ifdef __PIKE__
String.Buffer sb = String.Buffer();
#else
string sb = "";
#endif
int b = c;
while (c >= ' ' && c != ':' && c != ',' && c != ']' && c != '}' && c != '/') {
sb+=int2char(c);
c = next();
}
back();
s = trim_whites(SBGET(sb));
if (s == "true")
return 1;
if (s == "false")
return 0;
if (s == "null")
return UNDEFINED;
if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') {
int a; float b_; string c_;
sscanf(s, "%d%s", a, c_);
if(c_ && sizeof(c_)) {
#ifdef __PIKE__
sscanf(s, "%f", b_);
#else
b_ = to_float(s);
#endif
return b_;
}
else return a;
}
if (s == "") {
THROW("Missing value.\n");
}
return s;
}
/// <summary>
/// Skip characters until the next character is the requested character.
/// If the requested character is not found, no characters are skipped.
/// </summary>
/// <param name="to">A character to skip to.</param>
/// <returns>
/// The requested character, or zero if the requested character is not found.
/// </returns>
PROTECTED int skipTo(int to) {
int c;
int i = myIndex;
do {
c = next();
if (c == 0) {
myIndex = i;
return c;
}
}while (c != to);
back();
return c;
}
/// <summary>
/// Skip characters until past the requested string.
/// If it is not found, we are left at the end of the source.
/// </summary>
/// <param name="to">A string to skip past.</param>
PROTECTED void skipPast(string to) {
myIndex = search(mySource, to, myIndex);
if (myIndex < 0) {
myIndex = sizeof(mySource);
} else {
myIndex += sizeof(to);
}
}
// TODO implement exception SyntaxError
/// <summary>
/// Make a printable string of this JSONTokener.
/// </summary>
/// <returns>" at character [myIndex] of [mySource]"</returns>
PROTECTED string ToString() {
return " at character " + myIndex + " of " + mySource;
}

88
world/net/library/legal.c Normal file
View file

@ -0,0 +1,88 @@
// $Id: legal.c,v 1.16 2008/02/10 14:27:17 lynx Exp $ // vim:syntax=lpc
#include <net.h>
// legal nickname/placename test..
string legal_name(string n) {
int i;
//PT(("legal_name(%O) in %O\n", n, ME))
if (shutdown_in_progress) {
P1(("not legal_name for %O: shutdown in progress\n", n))
return 0;
}
if (!n || n == "") {
P1(("not legal_name: %O is empty\n", n))
return 0; // "somebody";
}
#ifdef MAX_NAME_LEN
if (strlen(n) > MAX_NAME_LEN) {
P1(("not legal_name: %O exceeds MAX_NAME_LEN\n", n))
return 0;
}
#endif
// this saves applet/user from malfunction!
if (index("!=-", n[0]) != -1) {
P1(("not legal_name: %O has !=- as first char.\n", n))
return 0;
}
for (i=strlen(n)-1; i>=0; i--) {
if (index("\
abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
0123456789_-=+", n[i]) == -1) {
P1(("not legal_name: %O has ill char at %d (%O).\n",
n, i, n[i]))
return 0;
}
}
return n;
}
array(string) legal_password(string pw, string nick) {
int i;
if (shutdown_in_progress)
return ({ "_failure_server_shutdown",
"Sorry, server is being shut down.\n" });
if (!stringp(pw) || strlen(pw) < 3)
return ({ "_error_illegal_password_size",
"That password is too short.\n" });
if (index(pw, '<') != -1 || index(pw, '>') != -1)
return ({ "_error_illegal_password_characters",
"Password contains illegal characters.\n" });
if (nick && strstr(lower_case(pw), lower_case(nick), 0) != -1)
return ({ "_error_illegal_password_username",
"That password contains your nickname.\n" });
return 0;
}
/* check for legal PSYC keyword (var or mc names), see specs */
#ifndef legal_keyword // inline variant is better of course
int legal_keyword(string n) {
# if __EFUN_DEFINED__(regreplace)
# include <regexp.h>
string t = regmatch(n, "[^_0-9A-Za-z]");
P1(("legal_keyword(%O) says %O\n", n, t))
return !t;
# else
int i;
for (i=strlen(n)-1; i>=0; i--) {
if (index("_\
abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
0123456789", n[i]) == -1) {
P1(("not legal_keyword: %O has ill char at %d (%O).\n",
n, i, n[i]))
return 0;
}
}
return 1;
# endif
}
#endif

View file

@ -0,0 +1,21 @@
// vim:noexpandtab:syntax=lpc
// $Id: library2.i,v 1.19 2007/10/08 11:00:31 lynx Exp $
#include <sandbox.h>
// one day this could be merged with PSYC_SYNCHRONIZE into
// channels of the same context
static object monitor;
void monitor_report(string mc, string text) {
#if DEBUG < 2
debug_message("MONITOR: "+ text +"\n");
#endif
log_file("MONITOR", mc +"\t"+ text +"\n");
#ifndef __PIKE__ // TPD
unless (monitor) monitor = load_object(PLACE_PATH "monitor");
if (monitor) monitor->msg(previous_object() || query_server_unl(),
mc, text, ([]));
#endif
}

View file

@ -0,0 +1,121 @@
#include <net.h>
#include <xml.h>
#include "profiles.i"
// convert a setting name from source format to target format, null == psyc
varargs string convert_setting(string name, string sf, string tf) {
switch (sf) {
case "set":
name = set2psyc[name];
break;
case "jCard":
name = jCard2psyc[name];
break;
case "vCard":
name = vCard2psyc[name];
break;
case "LDAP":
name = ldap2psyc[name];
break;
case 0:
break;
default:
return 0;
}
unless (name) return 0;
switch (tf) {
case "set":
name = psyc2set[name];
break;
case "jProf":
name = psyc2jProf[name];
break;
case "jCard":
name = psyc2jCard[name];
break;
case "vCard":
name = psyc2vCard[name];
break;
case "LDAP":
name = psyc2ldap[name];
break;
case 0:
break;
default:
return 0;
}
return name;
}
// convert a profile from source format to target format, null == psyc
varargs mixed convert_profile(mixed p, string sf, string tf) {
string k, vc, t, t2;
XMLNode n, n2;
mixed val;
mapping vars = ([ ]);
// could also create arrays, but not sure if that's useful to anyone
#define append(v, nu) if (stringp(nu)) v = stringp(v) ? (v +" "+ nu) : nu;
// first convert source format to psyc vars
switch (sf) {
case "jCard":
P3(("debug jCard2psyc with p = %O\n", p))
foreach( k,vc : jCard2psyc) {
if (sscanf(k, "%s/%s", t, t2) && (n = p["/" + t])
&& !nodelistp(n) && (n2 = n["/" + t2])) {
append(vars[vc], n2[Cdata]);
} else if ((n = p["/" + k]) && !nodelistp(n)) {
append(vars[vc], n[Cdata]);
}
}
break;
case "set":
foreach( k,val : p ) {
t = set2psyc[k];
if (t) vars[t] = val;
else D(k +" can't be set2psyc? never mind.\n");
}
break;
default: // no source format, p contains the vars
vars = p;
break;
}
// then convert psyc vars to target format
switch (tf) {
case "jCard":
// am i allowed to add newlines?
t = "<vCard xmlns='vcard-temp'>";
foreach( vc,k : psyc2jCard) {
// should be able to render ints too meguess
if (stringp(vars[vc])) t += sprintf(k, vars[vc]);
}
return t + "</vCard>";
case "jProf":
// see discussion in wiki:
// http://about.psyc.eu/Jabber#JEP_0154
t = "<field var='FORM_TYPE' type='hidden'>"
"<value>http://jabber.org/protocol/profile</value>"
"</field>";
foreach( vc,k : psyc2jProf) t += "<field var='"+ k +"'><value>"
+ vars[vc] +"</value></field>";
return t; // no wrapper?
case "set":
p = ([]);
foreach( k,val : vars ) {
t = psyc2set[k];
if (t) p[t] = val;
else D(k +" can't be psyc2set? never mind.\n");
}
return p;
default: // no target format, return the psyc vars
return vars;
}
// other cases not supported yet
raise_error("cannot convert from "+sf+" to "+tf+" (yet)\n");
return 0;
}

View file

@ -0,0 +1,130 @@
<style> td { background-color: #ccc } </style>
<title>PROFILING FIELD NAMES COMPARISON CHART</title>
<body bgcolor="#ff9900" text=black link=red vlink=black>
<h1>PROFILING FIELD NAMES COMPARISON CHART</h1>
<table cellspacing=2>
<tr align=left><th>PSYC</th><th>/set</th><th>jProf</th><th>vCard</th><th>jCard</th><th>LDAP</th><th>FOAF</th></tr>
<tr><td>_INTERNAL_image_photo</td><td></td><td>photo_data</td><td>PHOTO</td><td>PHOTO/BINVAL</td><td>jpegPhoto</td><td></td></tr>
<tr><td>_INTERNAL_type_image_photo</td><td></td><td></td><td></td><td>PHOTO/TYPE</td><td></td><td></td></tr>
<tr><td>_action_ask</td><td>askaction</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_action_motto</td><td>mottoaction</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_action_speak</td><td>speakaction</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_address_area</td><td>area</td><td>area</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_address_box_postal</td><td>postalbox</td><td>postalbox</td><td>POBOX</td><td>ADR/POBOX</td><td>postOfficeBox</td><td></td></tr>
<tr><td>_address_building</td><td>building</td><td>building</td><td>EXTADD</td><td>ADR/EXTADD</td><td></td><td></td></tr>
<tr><td>_address_code_postal</td><td>postalcode</td><td>postalcode</td><td>PCODE</td><td>ADR/PCODE</td><td>postalCode</td><td></td></tr>
<tr><td>_address_country</td><td>country</td><td>country</td><td>COUNTRY</td><td>ADR/CTRY</td><td>c</td><td></td></tr>
<tr><td>_address_floor</td><td>floor</td><td>floor</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_address_latitude</td><td>latitude</td><td>lat</td><td>LAT</td><td>GEO/LAT</td><td></td><td></td></tr>
<tr><td>_address_locality</td><td>locality</td><td>locality</td><td>LOCALITY</td><td>ADR/LOCALITY</td><td>l</td><td></td></tr>
<tr><td>_address_longitude</td><td>longitude</td><td>lon</td><td>LON</td><td>GEO/LON</td><td></td><td></td></tr>
<tr><td>_address_past</td><td>past</td><td>places_lived</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_address_region</td><td>region</td><td>region</td><td>REGION</td><td>ADR/REGION</td><td>st</td><td></td></tr>
<tr><td>_address_room</td><td>room</td><td>room</td><td></td><td></td><td>roomNumber</td><td></td></tr>
<tr><td>_address_street</td><td>street</td><td>street</td><td>STREET</td><td>ADR/STREET</td><td>street</td><td></td></tr>
<tr><td>_address_zone_time</td><td>timezone</td><td></td><td>TZ</td><td>TZ</td><td></td><td></td></tr>
<tr><td>_affiliation</td><td>affiliation</td><td>org_name</td><td>ORGNAME</td><td>ORG/ORGNAME</td><td>o</td><td></td></tr>
<tr><td>_character_action</td><td>actioncharacter</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_character_command</td><td>commandcharacter</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_color</td><td>color</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_contact_telephone</td><td>phone</td><td>landline</td><td></td><td>TEL/NUMBER</td><td>telephoneNumber</td><td>phone</td></tr>
<tr><td>_contact_telephone_fax</td><td>fax</td><td>fax</td><td>TEL;FAX</td><td></td><td>facsimileTelephoneNumber</td><td></td></tr>
<tr><td>_contact_telephone_pager</td><td>pager</td><td>pager</td><td>TEL;PAGER</td><td></td><td>pager</td><td></td></tr>
<tr><td>_contact_telephone_voice_home</td><td>homephone</td><td></td><td>TEL;VOICE;HOME</td><td></td><td></td><td></td></tr>
<tr><td>_contact_telephone_voice_mobile</td><td>mobilephone</td><td>mobile</td><td>TEL;CELL</td><td></td><td>mobile</td><td>phone</td></tr>
<tr><td>_contact_telephone_voice_work</td><td>workphone</td><td></td><td>TEL;VOICE;WORK</td><td></td><td></td><td></td></tr>
<tr><td>_date_birth</td><td>birthday</td><td>birth</td><td>BDAY</td><td>BDAY</td><td></td><td></td></tr>
<tr><td>_date_name</td><td>nameday</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_date_wedding</td><td>weddingday</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_description_expertise</td><td>expertisetext</td><td>expertise</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_description_hobby</td><td>hobbytext</td><td>hobby</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_description_motto</td><td>mottotext</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_description_preferences</td><td>likestext</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_description_preferences_not</td><td>dislikestext</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_description_presence</td><td>presencetext</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_description_private</td><td>privatetext</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_description_public</td><td>publictext</td><td>description</td><td></td><td>DESC</td><td>description</td><td></td></tr>
<tr><td>_description_quotes</td><td>quotestext</td><td>fav_quotes</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_encoding_characters</td><td>charset</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_animal</td><td>animalfave</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_athletes</td><td>athletesfave</td><td>fav_athletes</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_drinks</td><td>drinksfave</td><td>fav_drinks</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_foods</td><td>foodsfave</td><td>fav_foods</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_games</td><td>gamesfave</td><td>fav_games</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_literature</td><td>literaturefave</td><td>fav_authors</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_movies</td><td>moviesfave</td><td>fav_movies</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_music</td><td>musicfave</td><td>fav_music</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_popstar</td><td>popstarfave</td><td>fav_stars</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_teams</td><td>teamsfave</td><td>fav_teams</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_favorite_television</td><td>televisionfave</td><td>fav_tv</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_action_speak_visible</td><td>visiblespeakaction</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_colors_ignore</td><td>ignorecolors</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_echo</td><td>echo</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_expose_friends</td><td>friendsexpose</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_expose_groups</td><td>groupsexpose</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_filter_strangers</td><td>filter</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_greeting</td><td>greeting</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_places_multiple</td><td>multipleplaces</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_presence_ctcp</td><td>ctcppresence</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_screen_clear</td><td>clearscreen</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_stamp_time</td><td>timestamp</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_uniform_verbatim</td><td>verbatimuniform</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_flag_visibility</td><td>visibility</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_gender</td><td>sex</td><td>gender</td><td></td><td></td><td></td><td>gender</td></tr>
<tr><td>_identification</td><td>id</td><td>psyc_id</td><td></td><td>PSYCID</td><td></td><td>psycID</td></tr>
<tr><td>_identification_other</td><td>otherid</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_identification_scheme_AIM</td><td>aimid</td><td>aim_id</td><td></td><td></td><td></td><td>aimChatID</td></tr>
<tr><td>_identification_scheme_ICQ</td><td>icqid</td><td>icq_id</td><td></td><td></td><td></td><td>icqChatID</td></tr>
<tr><td>_identification_scheme_MSN</td><td>msnid</td><td>msn_id</td><td></td><td></td><td></td><td>msnChatID</td></tr>
<tr><td>_identification_scheme_SIP</td><td>sipid</td><td>sip_address</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_identification_scheme_Skype</td><td>skypeid</td><td>skype_address</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_identification_scheme_XMPP</td><td>xmppid</td><td>jid</td><td></td><td>JABBERID</td><td></td><td>jabberID</td></tr>
<tr><td>_identification_scheme_Yahoo</td><td>yahooid</td><td>yahoo_id</td><td></td><td></td><td></td><td>yahooChatID</td></tr>
<tr><td>_identification_scheme_mailto</td><td>email</td><td>email</td><td>EMAIL</td><td>EMAIL/USERID</td><td>mail</td><td></td></tr>
<tr><td>_identification_videophone</td><td>videophoneid</td><td>video_phone</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_image_character</td><td>characterimage</td><td>avatar_data</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_language</td><td>language</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_language_alternate</td><td>alternatelanguage</td><td>languages_well</td><td></td><td></td><td>preferredLanguage</td><td></td></tr>
<tr><td>_language_optional</td><td>optionallanguage</td><td>languages_lesswell</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_location_work</td><td>worklocation</td><td>workstation</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_login_work</td><td>worklogin</td><td>system_username</td><td></td><td></td><td>userid</td><td></td></tr>
<tr><td>_name_family</td><td>familyname</td><td>family_name</td><td>FAMILY</td><td>N/FAMILY</td><td>sn</td><td>surname</td></tr>
<tr><td>_name_given</td><td>givenname</td><td>given_name</td><td>GIVEN</td><td>N/GIVEN</td><td>givenName</td><td>givenname</td></tr>
<tr><td>_name_middle</td><td>middlename</td><td>middle_name</td><td>MIDDLE</td><td>N/MIDDLE</td><td></td><td></td></tr>
<tr><td>_name_patronymic</td><td>patronymicname</td><td>patronymic</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_name_prefix</td><td>prefixname</td><td>name_prefix</td><td>PREFIX</td><td>N/PREFIX</td><td></td><td>title</td></tr>
<tr><td>_name_public</td><td>publicname</td><td>display_name</td><td>FN</td><td>FN</td><td>displayName</td><td>name</td></tr>
<tr><td>_name_suffix</td><td>suffixname</td><td>name_suffix</td><td>SUFFIX</td><td>N/SUFFIX</td><td></td><td></td></tr>
<tr><td>_nick_alternate</td><td>alternatenick</td><td>familiar_name</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_nick_profile</td><td>name</td><td>nickname</td><td>NICKNAME</td><td>NICKNAME</td><td>nickname</td><td>nick</td></tr>
<tr><td>_nick_spaced</td><td>longname</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_page_biography</td><td>biographypage</td><td>bio</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_page_diary</td><td>diarypage</td><td>weblog</td><td></td><td></td><td></td><td>weblog</td></tr>
<tr><td>_page_links</td><td>linkspage</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_page_photo</td><td>photopage</td><td></td><td></td><td></td><td></td><td>img</td></tr>
<tr><td>_page_private</td><td>privatepage</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_page_public</td><td>publicpage</td><td>homepage</td><td>URL</td><td>URL</td><td>labelledURI</td><td>homepage</td></tr>
<tr><td>_page_publications</td><td>publicationspage</td><td>publications</td><td></td><td></td><td></td><td>publications</td></tr>
<tr><td>_page_resume</td><td>resumepage</td><td>resume</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_page_start</td><td>startpage</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_page_status</td><td>statuspage</td><td>status_url</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_page_work</td><td>workpage</td><td>org_url</td><td></td><td></td><td></td><td>workplaceHomepage</td></tr>
<tr><td>_password</td><td>password</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_person_assistant_work</td><td>workassistant</td><td>assistant</td><td></td><td></td><td>secretary</td><td></td></tr>
<tr><td>_person_manager_work</td><td>workmanager</td><td>manager</td><td></td><td></td><td>manager</td><td></td></tr>
<tr><td>_place_home</td><td>home</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_profession</td><td>profession</td><td>profession</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_role_work</td><td>workrole</td><td>org_role</td><td>ROLE</td><td>ROLE</td><td></td><td></td></tr>
<tr><td>_select_filter_presence</td><td>presencefilter</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_title_work</td><td>worktitle</td><td>job_title</td><td>TITLE</td><td>TITLE</td><td>title</td><td>title</td></tr>
<tr><td>_uniform_FOAF_private</td><td>privatefoaffile</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_uniform_FOAF_public</td><td>publicfoaffile</td><td>foaf_url</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_uniform_character</td><td>characterfile</td><td>avatar_url</td><td></td><td></td><td></td><td></td></tr>
<tr><td>_uniform_key_public</td><td>keyfile</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_uniform_photo</td><td>photofile</td><td>photo_url</td><td>PHOTO</td><td></td><td></td><td>depiction</td></tr>
<tr><td>_uniform_photo_small</td><td>miniphotofile</td><td></td><td></td><td></td><td></td><td>thumbnail</td></tr>
<tr><td>_uniform_style</td><td>stylefile</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>_unit_work</td><td>workunit</td><td>org_unit</td><td>ORGUNIT</td><td>ORG/ORGUNIT</td><td>ou</td><td></td></tr>
</table>
<h3>This document was generated by <a href="http://www.psyced.org/dist/world/net/library/profiles.pl">profiles.pl</a> of <a href="http://www.psyced.org/">psyced</a>. See <a href="http://about.psyc.eu/Profile">http://about.psyc.eu/Profile</a> for explanations.</h3>

View file

@ -0,0 +1,521 @@
// profiles.i generated out of profiles.gen. do not edit.
volatile mapping psyc2jProf = ([
"_INTERNAL_image_photo" : "photo_data",
"_address_area" : "area",
"_address_box_postal" : "postalbox",
"_address_building" : "building",
"_address_code_postal" : "postalcode",
"_address_country" : "country",
"_address_floor" : "floor",
"_address_latitude" : "lat",
"_address_locality" : "locality",
"_address_longitude" : "lon",
"_address_past" : "places_lived",
"_address_region" : "region",
"_address_room" : "room",
"_address_street" : "street",
"_affiliation" : "org_name",
"_contact_telephone" : "landline",
"_contact_telephone_fax" : "fax",
"_contact_telephone_pager" : "pager",
"_contact_telephone_voice_mobile" : "mobile",
"_date_birth" : "birth",
"_description_expertise" : "expertise",
"_description_hobby" : "hobby",
"_description_public" : "description",
"_description_quotes" : "fav_quotes",
"_favorite_athletes" : "fav_athletes",
"_favorite_drinks" : "fav_drinks",
"_favorite_foods" : "fav_foods",
"_favorite_games" : "fav_games",
"_favorite_literature" : "fav_authors",
"_favorite_movies" : "fav_movies",
"_favorite_music" : "fav_music",
"_favorite_popstar" : "fav_stars",
"_favorite_teams" : "fav_teams",
"_favorite_television" : "fav_tv",
"_gender" : "gender",
"_identification" : "psyc_id",
"_identification_scheme_AIM" : "aim_id",
"_identification_scheme_ICQ" : "icq_id",
"_identification_scheme_MSN" : "msn_id",
"_identification_scheme_SIP" : "sip_address",
"_identification_scheme_Skype" : "skype_address",
"_identification_scheme_XMPP" : "jid",
"_identification_scheme_Yahoo" : "yahoo_id",
"_identification_scheme_mailto" : "email",
"_identification_videophone" : "video_phone",
"_image_character" : "avatar_data",
"_language_alternate" : "languages_well",
"_language_optional" : "languages_lesswell",
"_location_work" : "workstation",
"_login_work" : "system_username",
"_name_family" : "family_name",
"_name_given" : "given_name",
"_name_middle" : "middle_name",
"_name_patronymic" : "patronymic",
"_name_prefix" : "name_prefix",
"_name_public" : "display_name",
"_name_suffix" : "name_suffix",
"_nick_alternate" : "familiar_name",
"_nick_profile" : "nickname",
"_page_biography" : "bio",
"_page_diary" : "weblog",
"_page_public" : "homepage",
"_page_publications" : "publications",
"_page_resume" : "resume",
"_page_status" : "status_url",
"_page_work" : "org_url",
"_person_assistant_work" : "assistant",
"_person_manager_work" : "manager",
"_profession" : "profession",
"_role_work" : "org_role",
"_title_work" : "job_title",
"_uniform_FOAF_public" : "foaf_url",
"_uniform_character" : "avatar_url",
"_uniform_photo" : "photo_url",
"_unit_work" : "org_unit",
]);
volatile mapping psyc2jCard = ([
"_INTERNAL_image_photo" : "<PHOTO><BINVAL>%s</BINVAL></PHOTO>",
"_INTERNAL_type_image_photo" : "<PHOTO><TYPE>%s</TYPE></PHOTO>",
"_address_box_postal" : "<ADR><POBOX>%s</POBOX></ADR>",
"_address_building" : "<ADR><EXTADD>%s</EXTADD></ADR>",
"_address_code_postal" : "<ADR><PCODE>%s</PCODE></ADR>",
"_address_country" : "<ADR><CTRY>%s</CTRY></ADR>",
"_address_latitude" : "<GEO><LAT>%s</LAT></GEO>",
"_address_locality" : "<ADR><LOCALITY>%s</LOCALITY></ADR>",
"_address_longitude" : "<GEO><LON>%s</LON></GEO>",
"_address_region" : "<ADR><REGION>%s</REGION></ADR>",
"_address_street" : "<ADR><STREET>%s</STREET></ADR>",
"_address_zone_time" : "<TZ>%s</TZ>",
"_affiliation" : "<ORG><ORGNAME>%s</ORGNAME></ORG>",
"_date_birth" : "<BDAY>%s</BDAY>",
"_description_public" : "<DESC>%s</DESC>",
"_identification" : "<PSYCID>%s</PSYCID>",
"_identification_scheme_XMPP" : "<JABBERID>%s</JABBERID>",
"_identification_scheme_mailto" : "<EMAIL><USERID>%s</USERID></EMAIL>",
"_name_family" : "<N><FAMILY>%s</FAMILY></N>",
"_name_given" : "<N><GIVEN>%s</GIVEN></N>",
"_name_middle" : "<N><MIDDLE>%s</MIDDLE></N>",
"_name_prefix" : "<N><PREFIX>%s</PREFIX></N>",
"_name_public" : "<FN>%s</FN>",
"_name_suffix" : "<N><SUFFIX>%s</SUFFIX></N>",
"_nick_profile" : "<NICKNAME>%s</NICKNAME>",
"_page_public" : "<URL>%s</URL>",
"_role_work" : "<ROLE>%s</ROLE>",
"_title_work" : "<TITLE>%s</TITLE>",
"_unit_work" : "<ORG><ORGUNIT>%s</ORGUNIT></ORG>",
"_contact_telephone" : "<TEL><NUMBER>%s</NUMBER></TEL>",
"_contact_telephone_fax" : "<TEL><FAX/><NUMBER>%s</NUMBER></TEL>",
"_contact_telephone_pager" : "<TEL><PAGER/><NUMBER>%s</NUMBER></TEL>",
"_contact_telephone_voice_home" : "<TEL><VOICE/><HOME/><NUMBER>%s</NUMBER></TEL>",
"_contact_telephone_voice_mobile" : "<TEL><VOICE/><CELL/><NUMBER>%s</NUMBER></TEL>",
"_contact_telephone_voice_work" : "<TEL><VOICE/><WORK/><NUMBER>%s</NUMBER></TEL>",
]);
volatile mapping jCard2psyc = ([
"PHOTO/BINVAL" : "_INTERNAL_image_photo",
"PHOTO/TYPE" : "_INTERNAL_type_image_photo",
"ADR/POBOX" : "_address_box_postal",
"ADR/EXTADD" : "_address_building",
"ADR/PCODE" : "_address_code_postal",
"ADR/CTRY" : "_address_country",
"GEO/LAT" : "_address_latitude",
"ADR/LOCALITY" : "_address_locality",
"GEO/LON" : "_address_longitude",
"ADR/REGION" : "_address_region",
"ADR/STREET" : "_address_street",
"TZ" : "_address_zone_time",
"ORG/ORGNAME" : "_affiliation",
"TEL/NUMBER" : "_contact_telephone",
"BDAY" : "_date_birth",
"DESC" : "_description_public",
"PSYCID" : "_identification",
"JABBERID" : "_identification_scheme_XMPP",
"EMAIL/USERID" : "_identification_scheme_mailto",
"N/FAMILY" : "_name_family",
"N/GIVEN" : "_name_given",
"N/MIDDLE" : "_name_middle",
"N/PREFIX" : "_name_prefix",
"FN" : "_name_public",
"N/SUFFIX" : "_name_suffix",
"NICKNAME" : "_nick_profile",
"URL" : "_page_public",
"ROLE" : "_role_work",
"TITLE" : "_title_work",
"ORG/ORGUNIT" : "_unit_work",
]);
volatile mapping psyc2set = ([
"_action_ask" : "askaction",
"_action_motto" : "mottoaction",
"_action_speak" : "speakaction",
"_address_area" : "area",
"_address_box_postal" : "postalbox",
"_address_building" : "building",
"_address_code_postal" : "postalcode",
"_address_country" : "country",
"_address_floor" : "floor",
"_address_latitude" : "latitude",
"_address_locality" : "locality",
"_address_longitude" : "longitude",
"_address_past" : "past",
"_address_region" : "region",
"_address_room" : "room",
"_address_street" : "street",
"_address_zone_time" : "timezone",
"_affiliation" : "affiliation",
"_character_action" : "actioncharacter",
"_character_command" : "commandcharacter",
"_color" : "color",
"_contact_telephone" : "phone",
"_contact_telephone_fax" : "fax",
"_contact_telephone_pager" : "pager",
"_contact_telephone_voice_home" : "homephone",
"_contact_telephone_voice_mobile" : "mobilephone",
"_contact_telephone_voice_work" : "workphone",
"_date_birth" : "birthday",
"_date_name" : "nameday",
"_date_wedding" : "weddingday",
"_description_expertise" : "expertisetext",
"_description_hobby" : "hobbytext",
"_description_motto" : "mottotext",
"_description_preferences" : "likestext",
"_description_preferences_not" : "dislikestext",
"_description_presence" : "presencetext",
"_description_private" : "privatetext",
"_description_public" : "publictext",
"_description_quotes" : "quotestext",
"_encoding_characters" : "charset",
"_favorite_animal" : "animalfave",
"_favorite_athletes" : "athletesfave",
"_favorite_drinks" : "drinksfave",
"_favorite_foods" : "foodsfave",
"_favorite_games" : "gamesfave",
"_favorite_literature" : "literaturefave",
"_favorite_movies" : "moviesfave",
"_favorite_music" : "musicfave",
"_favorite_popstar" : "popstarfave",
"_favorite_teams" : "teamsfave",
"_favorite_television" : "televisionfave",
"_flag_action_speak_visible" : "visiblespeakaction",
"_flag_colors_ignore" : "ignorecolors",
"_flag_echo" : "echo",
"_flag_expose_friends" : "friendsexpose",
"_flag_expose_groups" : "groupsexpose",
"_flag_filter_strangers" : "filter",
"_flag_greeting" : "greeting",
"_flag_places_multiple" : "multipleplaces",
"_flag_presence_ctcp" : "ctcppresence",
"_flag_screen_clear" : "clearscreen",
"_flag_stamp_time" : "timestamp",
"_flag_uniform_verbatim" : "verbatimuniform",
"_flag_visibility" : "visibility",
"_gender" : "sex",
"_identification" : "id",
"_identification_other" : "otherid",
"_identification_scheme_AIM" : "aimid",
"_identification_scheme_ICQ" : "icqid",
"_identification_scheme_MSN" : "msnid",
"_identification_scheme_SIP" : "sipid",
"_identification_scheme_Skype" : "skypeid",
"_identification_scheme_XMPP" : "xmppid",
"_identification_scheme_Yahoo" : "yahooid",
"_identification_scheme_mailto" : "email",
"_identification_videophone" : "videophoneid",
"_image_character" : "characterimage",
"_language" : "language",
"_language_alternate" : "alternatelanguage",
"_language_optional" : "optionallanguage",
"_location_work" : "worklocation",
"_login_work" : "worklogin",
"_name_family" : "familyname",
"_name_given" : "givenname",
"_name_middle" : "middlename",
"_name_patronymic" : "patronymicname",
"_name_prefix" : "prefixname",
"_name_public" : "publicname",
"_name_suffix" : "suffixname",
"_nick_alternate" : "alternatenick",
"_nick_profile" : "name",
"_nick_spaced" : "longname",
"_page_biography" : "biographypage",
"_page_diary" : "diarypage",
"_page_links" : "linkspage",
"_page_photo" : "photopage",
"_page_private" : "privatepage",
"_page_public" : "publicpage",
"_page_publications" : "publicationspage",
"_page_resume" : "resumepage",
"_page_start" : "startpage",
"_page_status" : "statuspage",
"_page_work" : "workpage",
"_password" : "password",
"_person_assistant_work" : "workassistant",
"_person_manager_work" : "workmanager",
"_place_home" : "home",
"_profession" : "profession",
"_role_work" : "workrole",
"_select_filter_presence" : "presencefilter",
"_title_work" : "worktitle",
"_uniform_FOAF_private" : "privatefoaffile",
"_uniform_FOAF_public" : "publicfoaffile",
"_uniform_character" : "characterfile",
"_uniform_key_public" : "keyfile",
"_uniform_photo" : "photofile",
"_uniform_photo_small" : "miniphotofile",
"_uniform_style" : "stylefile",
"_unit_work" : "workunit",
]);
volatile mapping set2psyc = ([
"askaction" : "_action_ask",
"mottoaction" : "_action_motto",
"speakaction" : "_action_speak",
"area" : "_address_area",
"postalbox" : "_address_box_postal",
"building" : "_address_building",
"postalcode" : "_address_code_postal",
"country" : "_address_country",
"floor" : "_address_floor",
"latitude" : "_address_latitude",
"locality" : "_address_locality",
"longitude" : "_address_longitude",
"past" : "_address_past",
"region" : "_address_region",
"room" : "_address_room",
"street" : "_address_street",
"timezone" : "_address_zone_time",
"affiliation" : "_affiliation",
"actioncharacter" : "_character_action",
"commandcharacter" : "_character_command",
"color" : "_color",
"phone" : "_contact_telephone",
"fax" : "_contact_telephone_fax",
"pager" : "_contact_telephone_pager",
"homephone" : "_contact_telephone_voice_home",
"mobilephone" : "_contact_telephone_voice_mobile",
"workphone" : "_contact_telephone_voice_work",
"birthday" : "_date_birth",
"nameday" : "_date_name",
"weddingday" : "_date_wedding",
"expertisetext" : "_description_expertise",
"hobbytext" : "_description_hobby",
"mottotext" : "_description_motto",
"likestext" : "_description_preferences",
"dislikestext" : "_description_preferences_not",
"presencetext" : "_description_presence",
"privatetext" : "_description_private",
"publictext" : "_description_public",
"quotestext" : "_description_quotes",
"charset" : "_encoding_characters",
"animalfave" : "_favorite_animal",
"athletesfave" : "_favorite_athletes",
"drinksfave" : "_favorite_drinks",
"foodsfave" : "_favorite_foods",
"gamesfave" : "_favorite_games",
"literaturefave" : "_favorite_literature",
"moviesfave" : "_favorite_movies",
"musicfave" : "_favorite_music",
"popstarfave" : "_favorite_popstar",
"teamsfave" : "_favorite_teams",
"televisionfave" : "_favorite_television",
"visiblespeakaction" : "_flag_action_speak_visible",
"ignorecolors" : "_flag_colors_ignore",
"echo" : "_flag_echo",
"friendsexpose" : "_flag_expose_friends",
"groupsexpose" : "_flag_expose_groups",
"filter" : "_flag_filter_strangers",
"greeting" : "_flag_greeting",
"multipleplaces" : "_flag_places_multiple",
"ctcppresence" : "_flag_presence_ctcp",
"clearscreen" : "_flag_screen_clear",
"timestamp" : "_flag_stamp_time",
"verbatimuniform" : "_flag_uniform_verbatim",
"visibility" : "_flag_visibility",
"sex" : "_gender",
"id" : "_identification",
"otherid" : "_identification_other",
"aimid" : "_identification_scheme_AIM",
"icqid" : "_identification_scheme_ICQ",
"msnid" : "_identification_scheme_MSN",
"sipid" : "_identification_scheme_SIP",
"skypeid" : "_identification_scheme_Skype",
"xmppid" : "_identification_scheme_XMPP",
"yahooid" : "_identification_scheme_Yahoo",
"email" : "_identification_scheme_mailto",
"videophoneid" : "_identification_videophone",
"characterimage" : "_image_character",
"language" : "_language",
"alternatelanguage" : "_language_alternate",
"optionallanguage" : "_language_optional",
"worklocation" : "_location_work",
"worklogin" : "_login_work",
"familyname" : "_name_family",
"givenname" : "_name_given",
"middlename" : "_name_middle",
"patronymicname" : "_name_patronymic",
"prefixname" : "_name_prefix",
"publicname" : "_name_public",
"suffixname" : "_name_suffix",
"alternatenick" : "_nick_alternate",
"name" : "_nick_profile",
"longname" : "_nick_spaced",
"biographypage" : "_page_biography",
"diarypage" : "_page_diary",
"linkspage" : "_page_links",
"photopage" : "_page_photo",
"privatepage" : "_page_private",
"publicpage" : "_page_public",
"publicationspage" : "_page_publications",
"resumepage" : "_page_resume",
"startpage" : "_page_start",
"statuspage" : "_page_status",
"workpage" : "_page_work",
"password" : "_password",
"workassistant" : "_person_assistant_work",
"workmanager" : "_person_manager_work",
"home" : "_place_home",
"profession" : "_profession",
"workrole" : "_role_work",
"presencefilter" : "_select_filter_presence",
"worktitle" : "_title_work",
"privatefoaffile" : "_uniform_FOAF_private",
"publicfoaffile" : "_uniform_FOAF_public",
"characterfile" : "_uniform_character",
"keyfile" : "_uniform_key_public",
"photofile" : "_uniform_photo",
"miniphotofile" : "_uniform_photo_small",
"stylefile" : "_uniform_style",
"workunit" : "_unit_work",
]);
volatile mapping psyc2ldap = ([
"_INTERNAL_image_photo" : "jpegPhoto",
"_address_box_postal" : "postOfficeBox",
"_address_code_postal" : "postalCode",
"_address_country" : "c",
"_address_locality" : "l",
"_address_region" : "st",
"_address_room" : "roomNumber",
"_address_street" : "street",
"_affiliation" : "o",
"_contact_telephone" : "telephoneNumber",
"_contact_telephone_fax" : "facsimileTelephoneNumber",
"_contact_telephone_pager" : "pager",
"_contact_telephone_voice_mobile" : "mobile",
"_description_public" : "description",
"_identification_scheme_mailto" : "mail",
"_language_alternate" : "preferredLanguage",
"_login_work" : "userid",
"_name_family" : "sn",
"_name_given" : "givenName",
"_name_public" : "displayName",
"_nick_profile" : "nickname",
"_page_public" : "labelledURI",
"_person_assistant_work" : "secretary",
"_person_manager_work" : "manager",
"_title_work" : "title",
"_unit_work" : "ou",
]);
volatile mapping ldap2psyc = ([
"jpegPhoto" : "_INTERNAL_image_photo",
"postOfficeBox" : "_address_box_postal",
"postalCode" : "_address_code_postal",
"c" : "_address_country",
"l" : "_address_locality",
"st" : "_address_region",
"roomNumber" : "_address_room",
"street" : "_address_street",
"o" : "_affiliation",
"telephoneNumber" : "_contact_telephone",
"facsimileTelephoneNumber" : "_contact_telephone_fax",
"pager" : "_contact_telephone_pager",
"mobile" : "_contact_telephone_voice_mobile",
"description" : "_description_public",
"mail" : "_identification_scheme_mailto",
"preferredLanguage" : "_language_alternate",
"userid" : "_login_work",
"sn" : "_name_family",
"givenName" : "_name_given",
"displayName" : "_name_public",
"nickname" : "_nick_profile",
"labelledURI" : "_page_public",
"secretary" : "_person_assistant_work",
"manager" : "_person_manager_work",
"title" : "_title_work",
"ou" : "_unit_work",
]);
volatile mapping psyc2vCard = ([
"_INTERNAL_image_photo" : "PHOTO",
"_address_box_postal" : "POBOX",
"_address_building" : "EXTADD",
"_address_code_postal" : "PCODE",
"_address_country" : "COUNTRY",
"_address_latitude" : "LAT",
"_address_locality" : "LOCALITY",
"_address_longitude" : "LON",
"_address_region" : "REGION",
"_address_street" : "STREET",
"_address_zone_time" : "TZ",
"_affiliation" : "ORGNAME",
"_contact_telephone_fax" : "TEL;FAX",
"_contact_telephone_pager" : "TEL;PAGER",
"_contact_telephone_voice_home" : "TEL;VOICE;HOME",
"_contact_telephone_voice_mobile" : "TEL;CELL",
"_contact_telephone_voice_work" : "TEL;VOICE;WORK",
"_date_birth" : "BDAY",
"_identification_scheme_mailto" : "EMAIL",
"_name_family" : "FAMILY",
"_name_given" : "GIVEN",
"_name_middle" : "MIDDLE",
"_name_prefix" : "PREFIX",
"_name_public" : "FN",
"_name_suffix" : "SUFFIX",
"_nick_profile" : "NICKNAME",
"_page_public" : "URL",
"_role_work" : "ROLE",
"_title_work" : "TITLE",
"_uniform_photo" : "PHOTO",
"_unit_work" : "ORGUNIT",
]);
volatile mapping vCard2psyc = ([
"PHOTO" : "_INTERNAL_image_photo",
"POBOX" : "_address_box_postal",
"EXTADD" : "_address_building",
"PCODE" : "_address_code_postal",
"COUNTRY" : "_address_country",
"LAT" : "_address_latitude",
"LOCALITY" : "_address_locality",
"LON" : "_address_longitude",
"REGION" : "_address_region",
"STREET" : "_address_street",
"TZ" : "_address_zone_time",
"ORGNAME" : "_affiliation",
"TEL;FAX" : "_contact_telephone_fax",
"TEL;PAGER" : "_contact_telephone_pager",
"TEL;VOICE;HOME" : "_contact_telephone_voice_home",
"TEL;CELL" : "_contact_telephone_voice_mobile",
"TEL;VOICE;WORK" : "_contact_telephone_voice_work",
"BDAY" : "_date_birth",
"EMAIL" : "_identification_scheme_mailto",
"FAMILY" : "_name_family",
"GIVEN" : "_name_given",
"MIDDLE" : "_name_middle",
"PREFIX" : "_name_prefix",
"FN" : "_name_public",
"SUFFIX" : "_name_suffix",
"NICKNAME" : "_nick_profile",
"URL" : "_page_public",
"ROLE" : "_role_work",
"TITLE" : "_title_work",
"PHOTO" : "_uniform_photo",
"ORGUNIT" : "_unit_work",
]);

View file

@ -0,0 +1,694 @@
#!/usr/bin/perl
# $Id: profiles.pl,v 1.54 2008/04/11 10:37:25 lynx Exp $
#
# generator of mappings between several profile file formats -lynX 2005
# part of the psyced project. see documentation for copyrights and licenses.
#
# see below __DATA__ for the actual mapping data
# this is just the perl program to make use of the data
while (<main::DATA>) {
next if /^\s*$/;
next if /^#/;
if ( /^PSYC\t(\w+)$/ ) {
$_ = $psyc = $1;
$psyc{$psyc} = 1;
next if /^_INTERNAL/;
s/_(address|contact|voice|scheme|source|flag|person|select)//g;
s/_date/_day/g;
s/_description/_text/g;
s/_favorite/_fave/g;
s/_identification/_ID/g;
s/_uniform/_file/g;
s/_telephone/_phone/g;
$set{$psyc} = lc( join('', reverse split('_', $_)) );
next;
}
if ( /^(\S+)\t(\S+)$/ ) {
${$1}{$psyc} = $2;
next;
}
warn "couldn't parse $_";
}
# generate some documentation for your enjoyment
open O, ">profiles.html" or die $!;
print O <<X;
<style> td { background-color: #ccc } </style>
<title>PROFILING FIELD NAMES COMPARISON CHART</title>
<body bgcolor="#ff9900" text=black link=red vlink=black>
<h1>PROFILING FIELD NAMES COMPARISON CHART</h1>
<table cellspacing=2>
X
print O "<tr align=left><th>PSYC</th><th>/set</th><th>jProf</th><th>vCard</th><th>jCard</th><th>LDAP</th><th>FOAF</th></tr>\n";
foreach $k ( sort keys %psyc ) {
print O "<tr><td>$k</td><td>$set{$k}</td><td>$jProf{$k}</td><td>$vCard{$k}</td><td>$jCard{$k}</td><td>$LDAP{$k}</td><td>$FOAF{$k}</td></tr>\n";
}
print O <<X;
</table>
<h3>This document was generated by <a href="http://www.psyced.org/dist/world/net/library/profiles.pl">profiles.pl</a> of <a href="http://www.psyced.org/">psyced</a>. See <a href="http://about.psyc.eu/Profile">http://about.psyc.eu/Profile</a> for explanations.</h3>
X
close O;
# and now let's get to the real work
open O, ">profiles.i" or die $!;
print O "// profiles.i generated out of profiles.gen. do not edit.\n\n";
print O "volatile mapping psyc2jProf = ([\n";
foreach $k ( sort keys %jProf ) {
printf O " %37s : \"%s\",\n", "\"$k\"", $jProf{$k};
}
print O "]);\n\nvolatile mapping psyc2jCard = ([\n";
foreach $k ( sort keys %jCard ) {
unless ($OjCard{$k}) { $j = $jCard{$k};
$j = $j =~ m#^(\w+)/(\w+)$# ? "<$1><$2>%s</$2></$1>" : "<$j>%s</$j>";
printf O " %25s : \"%s\",\n", "\"$k\"", $j;
}
}
foreach $k ( sort keys %OjCard ) {
printf O " %25s : \"%s\",\n", "\"$k\"", $OjCard{$k};
}
print O "]);\n\nvolatile mapping jCard2psyc = ([\n";
foreach $k ( sort keys %jCard ) {
printf O " %15s : \"%s\",\n", "\"$jCard{$k}\"", $k;
}
print O "]);\n\nvolatile mapping psyc2set = ([\n";
foreach $k ( sort keys %set ) {
printf O " %37s : \"%s\",\n", "\"$k\"", $set{$k};
}
print O "]);\n\nvolatile mapping set2psyc = ([\n";
foreach $k ( sort keys %set ) {
printf O " %20s : \"%s\",\n", "\"$set{$k}\"", $k;
}
print O "]);\n\nvolatile mapping psyc2ldap = ([\n";
foreach $k ( sort keys %LDAP ) {
printf O " %37s : \"%s\",\n", "\"$k\"", $LDAP{$k};
}
print O "]);\n\nvolatile mapping ldap2psyc = ([\n";
foreach $k ( sort keys %LDAP ) {
printf O " %27s : \"%s\",\n", "\"$LDAP{$k}\"", $k;
}
print O "]);\n\nvolatile mapping psyc2vCard = ([\n";
foreach $k ( sort keys %vCard ) {
printf O " %37s : \"%s\",\n", "\"$k\"", $vCard{$k};
}
print O "]);\n\nvolatile mapping vCard2psyc = ([\n";
foreach $k ( sort keys %vCard ) {
printf O " %20s : \"%s\",\n", "\"$vCard{$k}\"", $k;
}
print O "]);\n\n";
close O;
my $skip = <<ENDSKIP;
# let's generate a file that will make PsycZilla overkill .. then again, no
open O, ">profiles.xul" or die $!;
print O <<X if 0;
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<prefwindow id="psycProfile"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
type="profwindow"
title="PSYC profile" onload="prefWinLoad()"
maxwidth='550' windowtype='preferences'>
<groupbox>
X
foreach ( sort keys %psyc ) {
next if /^_INTERNAL/ or /^_degree/;
# http://developer.mozilla.org/en/docs/XUL:textbox
print O <<X;
<hbox><label value='$set{$_}'/><textbox id='$_' preference='profile_$set{$_}'/></hbox>
X
}
print O <<X if 0;
</groupbox>
</prefwindow>
X
close O;
ENDSKIP
# this file was generated from JEP-0154, then edited.. a lot.
#
# apparently psyc is the only format which keeps hierarchy in the variable
# names using families. most newer formats use complex xml paths or even
# unusable xml paths.
#
# there are huge amounts of profile options in here, but please - don't
# confront users with endless questionnaires and don't hand this information
# out to people who make money out of it. the intention behind such elaborate
# profiles is to empower the private trust network of friends to maximize
# their use of psyc however they may seem fit, not 3rd parties or the general
# public. do not fill in fields until they are actually useful for something.
#
#PSYC variable name
#set user-friendly variable name for /set command
#jProf JEP-0154 field var. JEP-0154 is the new profile data representation
# for jabber. it is mostly unused everywhere.
# http://www.jabber.org/jeps/jep-0154.html
#vCard either RFC 2426 or JEP-0054, probably needs to be split into...
#jCard JEP-0054 field names should be tagged jCard rather than vCard.
# JEP-0054 is a not so brilliant adaption of vCard to jabber,
# it is superceded but in use everywhere.
# http://www.jabber.org/jeps/jep-0054.html
#OjCard OUTGOING format strings for jCard
# many cases just cannot be treated the same way as incoming JEP-0054
#LDAP actually useful ISO standard. good to have it here for future use.
#xNAL http://xml.coverpages.org/xnal.html by OASIS. we don't use it.
#FOAF the profiles-without-privacy format. unused, but no need to delete it.
__DATA__
PSYC _name_public
jProf display_name
vCard FN
jCard FN
LDAP displayName
FOAF name
PSYC _name_family
jProf family_name
vCard FAMILY
jCard N/FAMILY
LDAP sn
xNAL LastName
#FOAF family_name
FOAF surname
PSYC _nick_alternate
jProf familiar_name
PSYC _name_given
jProf given_name
vCard GIVEN
jCard N/GIVEN
LDAP givenName
xNAL FirstName
#FOAF first_name
FOAF givenname
PSYC _name_middle
jProf middle_name
vCard MIDDLE
jCard N/MIDDLE
xNAL MiddleName
PSYC _name_prefix
jProf name_prefix
vCard PREFIX
jCard N/PREFIX
xNAL Title
FOAF title
PSYC _name_suffix
jProf name_suffix
vCard SUFFIX
jCard N/SUFFIX
xNAL GeneralSuffix
PSYC _nick_profile
set name
jProf nickname
LDAP nickname
vCard NICKNAME
jCard NICKNAME
xNAL Alias
FOAF nick
PSYC _name_patronymic
jProf patronymic
PSYC _address_country
jProf country
vCard COUNTRY
jCard ADR/CTRY
LDAP c
xNAL CountryName
JEP0112 country
PSYC _address_region
jProf region
vCard REGION
jCard ADR/REGION
LDAP st
xNAL AdministrativeAreaName
JEP0112 region
# optionally postfixed by _home _work etc.
PSYC _address_locality
jProf locality
# optionally supplemented with the "HOME" or "WORK" type
vCard LOCALITY
jCard ADR/LOCALITY
LDAP l
xNAL LocalityName
JEP0112 locality
PSYC _address_area
jProf area
xNAL DependentLocalityName
JEP0112 area
PSYC _address_street
jProf street
vCard STREET
jCard ADR/STREET
LDAP street
xNAL ThoroughfareNumber+ThoroughfareName
JEP0112 street
PSYC _address_building
jProf building
vCard EXTADD
jCard ADR/EXTADD
xNAL BuildingName
JEP0112 building
PSYC _address_floor
jProf floor
xNAL SubPremiseNumber
JEP0112 floor
PSYC _address_room
jProf room
LDAP roomNumber
xNAL SubPremiseNumber
JEP0112 room
PSYC _address_box_postal
jProf postalbox
vCard POBOX
jCard ADR/POBOX
LDAP postOfficeBox
PSYC _address_code_postal
jProf postalcode
vCard PCODE
jCard ADR/PCODE
LDAP postalCode
xNAL PostalCodeNumber
JEP0112 postalcode
PSYC _address_latitude
jProf lat
vCard LAT
jCard GEO/LAT
JEP0080 lat
PSYC _address_longitude
jProf lon
vCard LON
jCard GEO/LON
JEP0080 lon
PSYC _address_zone_time
vCard TZ
jCard TZ
PSYC _contact_telephone
jProf landline
# both vCard and jCard have no hierarchy for telephone number types
# which makes them very cumbersome to use.
# so we just ignore it and merge all phone numbers into one _telephone field.
jCard TEL/NUMBER
OjCard <TEL><NUMBER>%s</NUMBER></TEL>
LDAP telephoneNumber
FOAF phone
PSYC _contact_telephone_voice_home
vCard TEL;VOICE;HOME
OjCard <TEL><VOICE/><HOME/><NUMBER>%s</NUMBER></TEL>
PSYC _contact_telephone_voice_work
vCard TEL;VOICE;WORK
OjCard <TEL><VOICE/><WORK/><NUMBER>%s</NUMBER></TEL>
PSYC _contact_telephone_voice_mobile
jProf mobile
vCard TEL;CELL
OjCard <TEL><VOICE/><CELL/><NUMBER>%s</NUMBER></TEL>
LDAP mobile
FOAF phone
PSYC _contact_telephone_pager
jProf pager
set pager
vCard TEL;PAGER
OjCard <TEL><PAGER/><NUMBER>%s</NUMBER></TEL>
LDAP pager
PSYC _contact_telephone_fax
set fax
jProf fax
vCard TEL;FAX
OjCard <TEL><FAX/><NUMBER>%s</NUMBER></TEL>
LDAP facsimileTelephoneNumber
PSYC _identification_scheme_SIP
jProf sip_address
PSYC _identification_scheme_Skype
jProf skype_address
PSYC _identification_videophone
jProf video_phone
PSYC _identification_scheme_AIM
jProf aim_id
FOAF aimChatID
PSYC _identification_scheme_mailto
set email
jProf email
vCard EMAIL
jCard EMAIL/USERID
LDAP mail
PSYC _identification_scheme_ICQ
jProf icq_id
FOAF icqChatID
PSYC _identification
jProf psyc_id
jCard PSYCID
FOAF psycID
PSYC _identification_other
PSYC _identification_scheme_XMPP
jProf jid
jCard JABBERID
FOAF jabberID
PSYC _identification_scheme_MSN
jProf msn_id
FOAF msnChatID
PSYC _identification_scheme_Yahoo
jProf yahoo_id
FOAF yahooChatID
PSYC _uniform_character
jProf avatar_url
PSYC _page_biography
jProf bio
PSYC _uniform_FOAF_public
jProf foaf_url
# why i define this? because with profiles.gen we could easily
# generate a _real_ foaf file, and with psycish friendsnetting
# or at least psyc auth we can make it useful to those we want
# to have it. but probably whatever foaf software exists, it is
# probably web-based and doesn't have the faintest clue about
# privacy.. so better do this all in psyc anyway.
PSYC _uniform_FOAF_private
PSYC _uniform_photo_small
set miniphotofile
FOAF thumbnail
PSYC _uniform_photo
jProf photo_url
vCard PHOTO
FOAF depiction
PSYC _page_photo
FOAF img
# _page_public is a substring of _page_publications
# could become a problem for simple inheritance detection
PSYC _page_public
vCard URL
jCard URL
jProf homepage
LDAP labelledURI
FOAF homepage
PSYC _page_publications
jProf publications
FOAF publications
PSYC _page_resume
jProf resume
PSYC _page_status
jProf status_url
PSYC _page_work
jProf org_url
FOAF workplaceHomepage
PSYC _page_diary
jProf weblog
FOAF weblog
# bookmarks, favorites, del.icio.us stuff or just your friends homepages
PSYC _page_links
PSYC _person_assistant_work
jProf assistant
LDAP secretary
PSYC _title_work
jProf job_title
vCard TITLE
jCard TITLE
LDAP title
FOAF title
PSYC _person_manager_work
jProf manager
LDAP manager
# was: _organisation_work. _affiliation is more generic but since the
# other profile things only have the stricter field, we merge them here
PSYC _affiliation
jProf org_name
vCard ORGNAME
jCard ORG/ORGNAME
LDAP o
PSYC _role_work
jProf org_role
vCard ROLE
jCard ROLE
PSYC _unit_work
jProf org_unit
vCard ORGUNIT
jCard ORG/ORGUNIT
LDAP ou
PSYC _login_work
jProf system_username
LDAP uid
LDAP userid
PSYC _location_work
jProf workstation
PSYC _date_birth
jProf birth
vCard BDAY
jCard BDAY
## "onomastico" - catholics like to party on the saint's day by the same name
## maybe something similar exists in other cultures too?
PSYC _date_name
## hahahaha
PSYC _date_wedding
## only we have a distinction of public and private text.. sigh
## not talking of mottos and slogans ;)
PSYC _description_public
jProf description
jCard DESC
LDAP description
#jProf eye_color
PSYC _gender
set sex
jProf gender
FOAF gender
#jProf hair_color
#jProf height
#jProf weight
PSYC _description_expertise
jProf expertise
PSYC _image_character
jProf avatar_data
#jProf dietary_preferences
PSYC _description_hobby
jProf hobby
#jProf interest
# the current language setting - needs to be iso-conformant etc.
PSYC _language
set language
PSYC _language_optional
jProf languages_lesswell
PSYC _language_alternate
jProf languages_well
LDAP preferredLanguage
#jProf marital_status
#jProf mbti
#FOAF myersBriggs
# we don't want to send base64 encoded photos in psyc
# but we can handle them internally
PSYC _INTERNAL_image_photo
jProf photo_data
vCard PHOTO
jCard PHOTO/BINVAL
LDAP jpegPhoto
PSYC _INTERNAL_type_image_photo
jCard PHOTO/TYPE
PSYC _profession
jProf profession
#jProf religion
#jProf sexual_orientation
#jProf smoker
#jProf wishlist
#jProf zodiac_chinese
#jProf zodiac_western
# for children
PSYC _favorite_animal
PSYC _favorite_literature
jProf fav_authors
PSYC _favorite_athletes
jProf fav_athletes
#jProf fav_charities
PSYC _favorite_drinks
jProf fav_drinks
PSYC _favorite_foods
jProf fav_foods
PSYC _favorite_games
jProf fav_games
PSYC _favorite_movies
jProf fav_movies
PSYC _favorite_music
jProf fav_music
# for teenagers
PSYC _favorite_popstar
jProf fav_stars
PSYC _description_quotes
jProf fav_quotes
PSYC _favorite_teams
jProf fav_teams
PSYC _favorite_television
jProf fav_tv
PSYC _address_past
jProf places_lived
#jProf schools
# PSYC things that other formats do not propose
# listed here to get the set2psyc and psyc2set mappings of it
PSYC _place_home
set home
PSYC _flag_filter_strangers
set filter
PSYC _uniform_key_public
set keyfile
# stylesheet for showing psyc profile
PSYC _uniform_style
set stylefile
# superceded, but we keep it for those who want to use the code by psyced tuning
PSYC _flag_uniform_verbatim
set verbatimuniform
PSYC _description_preferences
set likestext
PSYC _description_preferences_not
set dislikestext
# this one typically requires special care, here it is anyhow..
PSYC _password
# just a version of _nick where spaces are allowed
PSYC _nick_spaced
set longname
PSYC _encoding_characters
set charset
PSYC _action_ask
PSYC _action_speak
# nice alternative name for motto: slogan
PSYC _action_motto
# hmm.. looks like jProf has no place for slogans and mottos
# not even if we introduce a motto variant which is not /me-like.
PSYC _description_motto
# this one gets used by the so-called IRCNAME since hardly anyone
# really puts his real name in there.
PSYC _character_action
PSYC _character_command
PSYC _color
# these aren't /set'tings as of now - too volatile
#PSYC _degree_availability
#PSYC _degree_mood
PSYC _description_private
PSYC _description_presence
PSYC _select_filter_presence
PSYC _flag_action_speak_visible
PSYC _flag_colors_ignore
# does this strictly qualify as a flag, if it has three values, not two?
PSYC _flag_echo
PSYC _flag_expose_friends
PSYC _flag_expose_groups
PSYC _flag_greeting
PSYC _flag_places_multiple
PSYC _flag_presence_ctcp
PSYC _flag_screen_clear
# does this strictly qualify as a flag, if it has three values, not two?
PSYC _flag_stamp_time
PSYC _flag_visibility
PSYC _page_private
PSYC _page_start

View file

@ -0,0 +1,116 @@
<hbox><label value='askaction'/><textbox id='_action_ask' preference='profile_askaction'/></hbox>
<hbox><label value='mottoaction'/><textbox id='_action_motto' preference='profile_mottoaction'/></hbox>
<hbox><label value='speakaction'/><textbox id='_action_speak' preference='profile_speakaction'/></hbox>
<hbox><label value='area'/><textbox id='_address_area' preference='profile_area'/></hbox>
<hbox><label value='postalbox'/><textbox id='_address_box_postal' preference='profile_postalbox'/></hbox>
<hbox><label value='building'/><textbox id='_address_building' preference='profile_building'/></hbox>
<hbox><label value='postalcode'/><textbox id='_address_code_postal' preference='profile_postalcode'/></hbox>
<hbox><label value='country'/><textbox id='_address_country' preference='profile_country'/></hbox>
<hbox><label value='floor'/><textbox id='_address_floor' preference='profile_floor'/></hbox>
<hbox><label value='latitude'/><textbox id='_address_latitude' preference='profile_latitude'/></hbox>
<hbox><label value='locality'/><textbox id='_address_locality' preference='profile_locality'/></hbox>
<hbox><label value='longitude'/><textbox id='_address_longitude' preference='profile_longitude'/></hbox>
<hbox><label value='past'/><textbox id='_address_past' preference='profile_past'/></hbox>
<hbox><label value='region'/><textbox id='_address_region' preference='profile_region'/></hbox>
<hbox><label value='room'/><textbox id='_address_room' preference='profile_room'/></hbox>
<hbox><label value='street'/><textbox id='_address_street' preference='profile_street'/></hbox>
<hbox><label value='timezone'/><textbox id='_address_zone_time' preference='profile_timezone'/></hbox>
<hbox><label value='affiliation'/><textbox id='_affiliation' preference='profile_affiliation'/></hbox>
<hbox><label value='actioncharacter'/><textbox id='_character_action' preference='profile_actioncharacter'/></hbox>
<hbox><label value='commandcharacter'/><textbox id='_character_command' preference='profile_commandcharacter'/></hbox>
<hbox><label value='color'/><textbox id='_color' preference='profile_color'/></hbox>
<hbox><label value='phone'/><textbox id='_contact_telephone' preference='profile_phone'/></hbox>
<hbox><label value='fax'/><textbox id='_contact_telephone_fax' preference='profile_fax'/></hbox>
<hbox><label value='pager'/><textbox id='_contact_telephone_pager' preference='profile_pager'/></hbox>
<hbox><label value='homephone'/><textbox id='_contact_telephone_voice_home' preference='profile_homephone'/></hbox>
<hbox><label value='mobilephone'/><textbox id='_contact_telephone_voice_mobile' preference='profile_mobilephone'/></hbox>
<hbox><label value='workphone'/><textbox id='_contact_telephone_voice_work' preference='profile_workphone'/></hbox>
<hbox><label value='birthday'/><textbox id='_date_birth' preference='profile_birthday'/></hbox>
<hbox><label value='nameday'/><textbox id='_date_name' preference='profile_nameday'/></hbox>
<hbox><label value='weddingday'/><textbox id='_date_wedding' preference='profile_weddingday'/></hbox>
<hbox><label value='expertisetext'/><textbox id='_description_expertise' preference='profile_expertisetext'/></hbox>
<hbox><label value='hobbytext'/><textbox id='_description_hobby' preference='profile_hobbytext'/></hbox>
<hbox><label value='likestext'/><textbox id='_description_preferences' preference='profile_likestext'/></hbox>
<hbox><label value='dislikestext'/><textbox id='_description_preferences_not' preference='profile_dislikestext'/></hbox>
<hbox><label value='presencetext'/><textbox id='_description_presence' preference='profile_presencetext'/></hbox>
<hbox><label value='privatetext'/><textbox id='_description_private' preference='profile_privatetext'/></hbox>
<hbox><label value='publictext'/><textbox id='_description_public' preference='profile_publictext'/></hbox>
<hbox><label value='quotestext'/><textbox id='_description_quotes' preference='profile_quotestext'/></hbox>
<hbox><label value='charset'/><textbox id='_encoding_characters' preference='profile_charset'/></hbox>
<hbox><label value='animalfave'/><textbox id='_favorite_animal' preference='profile_animalfave'/></hbox>
<hbox><label value='athletesfave'/><textbox id='_favorite_athletes' preference='profile_athletesfave'/></hbox>
<hbox><label value='drinksfave'/><textbox id='_favorite_drinks' preference='profile_drinksfave'/></hbox>
<hbox><label value='foodsfave'/><textbox id='_favorite_foods' preference='profile_foodsfave'/></hbox>
<hbox><label value='gamesfave'/><textbox id='_favorite_games' preference='profile_gamesfave'/></hbox>
<hbox><label value='literaturefave'/><textbox id='_favorite_literature' preference='profile_literaturefave'/></hbox>
<hbox><label value='moviesfave'/><textbox id='_favorite_movies' preference='profile_moviesfave'/></hbox>
<hbox><label value='musicfave'/><textbox id='_favorite_music' preference='profile_musicfave'/></hbox>
<hbox><label value='popstarfave'/><textbox id='_favorite_popstar' preference='profile_popstarfave'/></hbox>
<hbox><label value='teamsfave'/><textbox id='_favorite_teams' preference='profile_teamsfave'/></hbox>
<hbox><label value='televisionfave'/><textbox id='_favorite_television' preference='profile_televisionfave'/></hbox>
<hbox><label value='visiblespeakaction'/><textbox id='_flag_action_speak_visible' preference='profile_visiblespeakaction'/></hbox>
<hbox><label value='ignorecolors'/><textbox id='_flag_colors_ignore' preference='profile_ignorecolors'/></hbox>
<hbox><label value='echo'/><textbox id='_flag_echo' preference='profile_echo'/></hbox>
<hbox><label value='filter'/><textbox id='_flag_filter_strangers' preference='profile_filter'/></hbox>
<hbox><label value='exposefriends'/><textbox id='_flag_friends_expose' preference='profile_exposefriends'/></hbox>
<hbox><label value='greeting'/><textbox id='_flag_greeting' preference='profile_greeting'/></hbox>
<hbox><label value='multipleplaces'/><textbox id='_flag_places_multiple' preference='profile_multipleplaces'/></hbox>
<hbox><label value='ctcppresence'/><textbox id='_flag_presence_ctcp' preference='profile_ctcppresence'/></hbox>
<hbox><label value='clearscreen'/><textbox id='_flag_screen_clear' preference='profile_clearscreen'/></hbox>
<hbox><label value='verbatimuniform'/><textbox id='_flag_uniform_verbatim' preference='profile_verbatimuniform'/></hbox>
<hbox><label value='visibility'/><textbox id='_flag_visibility' preference='profile_visibility'/></hbox>
<hbox><label value='sex'/><textbox id='_gender' preference='profile_sex'/></hbox>
<hbox><label value='id'/><textbox id='_identification' preference='profile_id'/></hbox>
<hbox><label value='otherid'/><textbox id='_identification_other' preference='profile_otherid'/></hbox>
<hbox><label value='aimid'/><textbox id='_identification_scheme_AIM' preference='profile_aimid'/></hbox>
<hbox><label value='icqid'/><textbox id='_identification_scheme_ICQ' preference='profile_icqid'/></hbox>
<hbox><label value='msnid'/><textbox id='_identification_scheme_MSN' preference='profile_msnid'/></hbox>
<hbox><label value='sipid'/><textbox id='_identification_scheme_SIP' preference='profile_sipid'/></hbox>
<hbox><label value='skypeid'/><textbox id='_identification_scheme_Skype' preference='profile_skypeid'/></hbox>
<hbox><label value='xmppid'/><textbox id='_identification_scheme_XMPP' preference='profile_xmppid'/></hbox>
<hbox><label value='yahooid'/><textbox id='_identification_scheme_Yahoo' preference='profile_yahooid'/></hbox>
<hbox><label value='email'/><textbox id='_identification_scheme_mailto' preference='profile_email'/></hbox>
<hbox><label value='videophoneid'/><textbox id='_identification_videophone' preference='profile_videophoneid'/></hbox>
<hbox><label value='characterimage'/><textbox id='_image_character' preference='profile_characterimage'/></hbox>
<hbox><label value='language'/><textbox id='_language' preference='profile_language'/></hbox>
<hbox><label value='alternatelanguage'/><textbox id='_language_alternate' preference='profile_alternatelanguage'/></hbox>
<hbox><label value='optionallanguage'/><textbox id='_language_optional' preference='profile_optionallanguage'/></hbox>
<hbox><label value='worklocation'/><textbox id='_location_work' preference='profile_worklocation'/></hbox>
<hbox><label value='worklogin'/><textbox id='_login_work' preference='profile_worklogin'/></hbox>
<hbox><label value='familyname'/><textbox id='_name_family' preference='profile_familyname'/></hbox>
<hbox><label value='givenname'/><textbox id='_name_given' preference='profile_givenname'/></hbox>
<hbox><label value='middlename'/><textbox id='_name_middle' preference='profile_middlename'/></hbox>
<hbox><label value='patronymicname'/><textbox id='_name_patronymic' preference='profile_patronymicname'/></hbox>
<hbox><label value='prefixname'/><textbox id='_name_prefix' preference='profile_prefixname'/></hbox>
<hbox><label value='publicname'/><textbox id='_name_public' preference='profile_publicname'/></hbox>
<hbox><label value='suffixname'/><textbox id='_name_suffix' preference='profile_suffixname'/></hbox>
<hbox><label value='alternatenick'/><textbox id='_nick_alternate' preference='profile_alternatenick'/></hbox>
<hbox><label value='name'/><textbox id='_nick_profile' preference='profile_name'/></hbox>
<hbox><label value='longname'/><textbox id='_nick_spaced' preference='profile_longname'/></hbox>
<hbox><label value='biographypage'/><textbox id='_page_biography' preference='profile_biographypage'/></hbox>
<hbox><label value='diarypage'/><textbox id='_page_diary' preference='profile_diarypage'/></hbox>
<hbox><label value='linkspage'/><textbox id='_page_links' preference='profile_linkspage'/></hbox>
<hbox><label value='photopage'/><textbox id='_page_photo' preference='profile_photopage'/></hbox>
<hbox><label value='privatepage'/><textbox id='_page_private' preference='profile_privatepage'/></hbox>
<hbox><label value='publicpage'/><textbox id='_page_public' preference='profile_publicpage'/></hbox>
<hbox><label value='publicationspage'/><textbox id='_page_publications' preference='profile_publicationspage'/></hbox>
<hbox><label value='resumepage'/><textbox id='_page_resume' preference='profile_resumepage'/></hbox>
<hbox><label value='startpage'/><textbox id='_page_start' preference='profile_startpage'/></hbox>
<hbox><label value='statuspage'/><textbox id='_page_status' preference='profile_statuspage'/></hbox>
<hbox><label value='workpage'/><textbox id='_page_work' preference='profile_workpage'/></hbox>
<hbox><label value='password'/><textbox id='_password' preference='profile_password'/></hbox>
<hbox><label value='workassistant'/><textbox id='_person_assistant_work' preference='profile_workassistant'/></hbox>
<hbox><label value='workmanager'/><textbox id='_person_manager_work' preference='profile_workmanager'/></hbox>
<hbox><label value='home'/><textbox id='_place_home' preference='profile_home'/></hbox>
<hbox><label value='profession'/><textbox id='_profession' preference='profile_profession'/></hbox>
<hbox><label value='workrole'/><textbox id='_role_work' preference='profile_workrole'/></hbox>
<hbox><label value='presencefilter'/><textbox id='_select_filter_presence' preference='profile_presencefilter'/></hbox>
<hbox><label value='worktitle'/><textbox id='_title_work' preference='profile_worktitle'/></hbox>
<hbox><label value='privatefoaffile'/><textbox id='_uniform_FOAF_private' preference='profile_privatefoaffile'/></hbox>
<hbox><label value='publicfoaffile'/><textbox id='_uniform_FOAF_public' preference='profile_publicfoaffile'/></hbox>
<hbox><label value='characterfile'/><textbox id='_uniform_character' preference='profile_characterfile'/></hbox>
<hbox><label value='keyfile'/><textbox id='_uniform_key_public' preference='profile_keyfile'/></hbox>
<hbox><label value='photofile'/><textbox id='_uniform_photo' preference='profile_photofile'/></hbox>
<hbox><label value='miniphotofile'/><textbox id='_uniform_photo_small' preference='profile_miniphotofile'/></hbox>
<hbox><label value='stylefile'/><textbox id='_uniform_style' preference='profile_stylefile'/></hbox>
<hbox><label value='workunit'/><textbox id='_unit_work' preference='profile_workunit'/></hbox>

330
world/net/library/sandbox.c Normal file
View file

@ -0,0 +1,330 @@
// vim:foldmethod=marker:syntax=lpc:noexpandtab
// $Id: sandbox.c,v 1.16 2008/02/06 12:16:16 lynx Exp $
#include <net.h>
#include <sandbox.h>
#if __EFUN_DEFINED__(shutdown)
MASK(shutdown, "SHUTDOWN")
#endif
#if __EFUN_DEFINED__(add_action)
MASK(add_action, "ADD_ACTION")
#endif
#if __EFUN_DEFINED__(break_point)
MASK(break_point, "BREAK_POINT")
#endif
#if __EFUN_DEFINED__(call_direct)
MASK(call_direct, "CALL_DIRECT")
#endif
#if __EFUN_DEFINED__(call_direct_resolved)
MASK(call_direct_resolved, "CALL_DIRECT_RESOLVED")
#endif
#if __EFUN_DEFINED__(call_resolved)
MASK(call_resolved, "CALL_RESOLVED")
#endif
#if __EFUN_DEFINED__(swap)
MASK(swap, "SWAP")
#endif
#if __EFUN_DEFINED__(debug_info)
MASK(debug_info, "DEBUG_INFO")
#endif
#if __EFUN_DEFINED__(command)
MASK(command, "COMMAND")
#endif
#if __EFUN_DEFINED__(command_stack)
MASK(command_stack, "COMMAND_STACK")
#endif
#if __EFUN_DEFINED__(command_stack_depth)
MASK(command_stack_depth, "COMMAND_STACK_DEPTH")
#endif
#if __EFUN_DEFINED__(convert_charset)
MASK(convert_charset, "CONVERT_CHARSET")
#endif
#if __EFUN_DEFINED__(debug_message) && DEBUG < 1
MASK(debug_message, "DEBUG_MESSAGE")
#endif
#if __EFUN_DEFINED__(disable_commands)
MASK(disable_commands, "DISABLE_COMMANDS")
#endif
#if __EFUN_DEFINED__(enable_commands)
MASK(enable_commands, "ENABLE_COMMANDS")
#endif
#if __EFUN_DEFINED__(function_exists)
MASK(function_exists, "FUNCTION_EXISTS")
#endif
#if __EFUN_DEFINED__(functionlist)
MASK(functionlist, "FUNCTIONLIST")
#endif
#if __EFUN_DEFINED__(garbage_collection)
MASK(garbage_collection, "GARBAGECOLLECTION")
#endif
#if __EFUN_DEFINED__(get_dir) // caught by valid_read?
MASK(get_dir, "GETDIR")
#endif
#if __EFUN_DEFINED__(include_list)
MASK(include_list, "INCLUDE_LIST")
#endif
#if __EFUN_DEFINED__(inherit_list)
MASK(inherit_list, "INHERIT_LIST")
#endif
#if __EFUN_DEFINED__(input_to_info)
MASK(input_to_info, "INPUT_TO_INFO")
#endif
#if __EFUN_DEFINED__(last_instructions)
MASK(last_instructions, "LAST_INSTRUCTIONS")
#endif
#if __EFUN_DEFINED__(load_object)
MASK(load_object, "LOAD_OBJECT")
#endif
#if __EFUN_DEFINED__(mkdir) // caught by valid_write?
MASK(mkdir, "MKDIR")
#endif
#if __EFUN_DEFINED__(move_object)
MASK(move_object, "MOVE_OBJECT")
#endif
#if __EFUN_DEFINED__(object_info)
MASK(object_info, "OBJECT_INFO")
#endif
#if __EFUN_DEFINED__(process_string)
MASK(process_string, "PROCESS_STRING")
#endif
#if __EFUN_DEFINED__(query_ip_name)
MASK(query_ip_name, "QUERY_IP_NAME")
#endif
#if __EFUN_DEFINED__(query_ip_number)
MASK(query_ip_number, "QUERY_IP_NUMBER")
#endif
#if __EFUN_DEFINED__(query_load_average)
MASK(query_load_average, "QUERY_LOAD_AVERAGE")
#endif
#if __EFUN_DEFINED__(query_shadowing)
MASK(query_shadowing, "QUERY_SHADOWING")
#endif
#if __EFUN_DEFINED__(remove_action)
MASK(remove_action, "REMOVE_ACTION")
#endif
#if __EFUN_DEFINED__(remove_input_to)
MASK(remove_input_to, "REMOVE_INPUT_TO")
#endif
#if __EFUN_DEFINED__(remove_interactive)
MASK(remove_interactive, "REMOVE_INTERACTIVE")
#endif
#if __EFUN_DEFINED__(rename) // seems to be caught by valid_(read|write), but
// i have to check that
MASK(rename, "RENAME")
#endif
#if __EFUN_DEFINED__(rm) // caught by valid_write?
MASK(rm, "RM")
#endif
#if __EFUN_DEFINED__(rmdir) // caught by valid_write?
MASK(rmdir, "RMDIR")
#endif
#if __EFUN_DEFINED__(rusage)
MASK(rusage, "RUSAGE")
#endif
#if __EFUN_DEFINED__(say)
MASK(say, "SAY")
#endif
#if __EFUN_DEFINED__(set_environment)
MASK(set_environment, "SET_ENVIRONMENT")
#endif
#if __EFUN_DEFINED__(set_is_wizard)
MASK(set_is_wizard, "SET_IS_WIZARD")
#endif
#if __EFUN_DEFINED__(set_modify_command)
MASK(set_modify_command, "SET_MODIFY_COMMAND")
#endif
#if __EFUN_DEFINED__(set_prompt)
MASK(set_prompt, "SET_PROMPT")
#endif
#if __EFUN_DEFINED__(swap)
MASK(swap, "SWAP")
#endif
#if __EFUN_DEFINED__(tell_object)
MASK(tell_object, "TELL_OBJECT")
#endif
#if __EFUN_DEFINED__(tell_room)
MASK(tell_room, "TELL_ROOM")
#endif
#if __EFUN_DEFINED__(tls_deinit_connection)
MASK(tls_deinit_connection, "TLS_DEINIT_CONNECTION")
#endif
#if __EFUN_DEFINED__(tls_init_connection)
MASK(tls_init_connection, "TLS_INIT_CONNECTION")
#endif
#if __EFUN_DEFINED__(tls_query_connection_info)
MASK(tls_query_connection_info, "TLS_QUERY_CONNECTION_INFO")
#endif
#if __EFUN_DEFINED__(tls_query_connection_state)
MASK(tls_query_connection_state, "TLS_QUERY_CONNECTION_STATE")
#endif
#if __EFUN_DEFINED__(transfer)
//MASK(transfer, "TRANSFER")
// avoid deprecation warning, and as nobody uses it:
nomask void transfer() {}
#endif
#if __EFUN_DEFINED__(unshadow)
MASK(unshadow, "UNSHADOW")
#endif
#if __EFUN_DEFINED__(users)
MASK(users, "USERS")
#endif
#if __EFUN_DEFINED__(variable_list)
MASK(variable_list, "VARIABLE_LIST")
#endif
#if __EFUN_DEFINED__(wizlist_info)
MASK(wizlist_info, "WIZLIST_INFO")
#endif
nomask mixed call_other(mixed obj, string func, varargs mixed * b) {
P4(("call_other(%O, %O, %O)\n", obj, func, b));
if (extern_call()) {
mixed euid = geteuid(previous_object());
if (stringp(euid) && euid[0] != '/') {
string s;
object o;
s = stringp(obj) ? obj : object_name(obj);
o = objectp(obj) ? obj : find_object(obj);
#ifndef __COMPAT_MODE__
if (s[0] == '/') s = s[1..];
#endif
if (euid[0] == '@') { // yes, this check is overdone, but only for
// now. i think we can use exactly this
// structure for allowed call_others into
// daemons. says tobij.
// <lynX> yes, checking the identity of daemons is much
// easier. some of them we already have stored in library
// vars, others have static object names, so they can be put
// into a switch or mapping. it's only doing so for "any"
// user object, which gets too messy. it is architecturally
// much cleaner to let sendmsg() decide which msg is legal
// (which it has to do anyway) so we don't need yet another
// security scheme in here with this wild guessing for user
// objects. in fact two redundant security approaches also
// unnecessarily raise the chances of being flawed. so let's
// allow as few -> operations as possible for sandbox mode.
//
// great idea. library_object()->sendmsg() _is_
// a -> operation, in case you forgot we're doing that (in
// entity.c).
//
// if we rename the library-sendmsg to something reachable
// without a call_other, anyways, sendmsg() will be an extra
// function call if it just redirects the msg to
// target->msg().
// in fact, it might be same complexity as calling target->msg
// directly, as call_other is overloaded and an lfun doing
// ... virtually the same thing for the discussed type of
// call.
//
// the if here isn't even more complex than in sendmsg, it'll
// be of equal or less complexity, plus, normal objects
// (and, if we want to allow ->qName for everybody anywhere,
// normal call_others (well, qName)
// don't run deep into this check.
//
// so, after all, the only argument is "evil! code!
// 'duplication'!", which i prefer over (for users who do
// their own rooms etc) incomprehensible
// #ifndef SADNBOX
// target->msg
// #else
// sendmsg(target, ...)
// #endif
// mess in files.
//
// additionally, my sandbox-philosophy is to keep things
// maximum equal in usage with and without SANDBOX,
// so i'll do it this way.
unless (o == previous_object() || o == ME) {
int i;
if ((i = index(s, '#')) == -1) i = strlen(s) - 1;
unless (func == "qName"
#ifdef FORK
|| func == "qOrigin"
#endif
) switch (s[..i]) {
case "net/person#":
case "net/user#":
//if (func == "qName" || func == "msg") break;
if (func == "msg") break;
default:
if (sscanf(s[..i], "net/%~s/user#")
&& func == "msg") break;
raise_error(sprintf("INVALID %O "
"call_other(%O, %O, %O)\n",
euid, obj, func, b));
}
}
} else {
raise_error(sprintf("INVALID %O call_other(%O, %O, %O)\n",
euid, obj, func, b));
}
} else unless (euid) {
raise_error(sprintf("INVALID euid-0 (%O) call_other(%O, %O, %O)\n",
previous_object(), obj, func, b));
}
set_this_object(previous_object());
}
return efun::call_other(obj, func, b...);
}

119
world/net/library/sasl.c Normal file
View file

@ -0,0 +1,119 @@
// $Id: sasl.c,v 1.17 2006/10/18 17:52:15 fippo Exp $ // vim:syntax=lpc
#include <net.h>
mapping sasl_parse(string t) {
string vname, vvalue;
mapping data = ([ ]);
while (sscanf(t, "%s=%s,%.0t%s", vname, vvalue, t) >= 2) {
sscanf(vvalue, "\"%s\"", vvalue);
data[vname] = vvalue;
}
sscanf(t, "%s=%s", vname, vvalue);
sscanf(vvalue, "\"%s\"", vvalue);
data[vname] = vvalue;
return data;
}
varargs string sasl_calculate_digestMD5(mapping data, string secret, int calcresponse, string prehash) {
/*
* calculate the digest-md5 response or rspauth value for data + secret
* set calcresponse to 1 if you want to calculate the rspauth,
* 0 if you want to calculate the expected response
* this function assumes that you have checked the necessary data
* and will only complain about missing data with DEBUG > 3
*/
string HA1, HA2;
string t, t2;
#if DEBUG > 2
// data checks
unless(mappingp(data) && data["username"] && data["realm"] && data["nonce"]
&& data["cnonce"] && data["digest-uri"] && data["nc"]
&& data["qop"] && data["qop"] == "auth" // unimplemented otherwise
) {
raise_error("sasl_calculate_digestMD5 called with invalid data\n"
+ sprintf("data is %O\n\n", data));
}
#endif
if (prehash) {
/* according to RFC 2831, 3.9 Storing passwords this may also
* come directly from a database / storage
*/
t = prehash;
} else {
t = md5(data["username"] + ":" + data["realm"] + ":" + secret);
}
t2 = "";
// we need octet form
// only works with ldmud after 3.3.611
for (int i = 0; i < 32; i += 2)
t2 += sprintf("%c", to_int("0x" + t[i..i+1]));
HA1 = md5(t2 + ":" + data["nonce"] + ":" + data["cnonce"]);
if (calcresponse)
t = ":";
else
t = "AUTHENTICATE:";
t += data["digest-uri"];
// TODO: qop == "auth-int"
HA2 = md5(t);
P2(("sasl: t is %O, t2 is %O\n", t, t2))
P2(("sasl: HA1 is %O, HA2 is %O\n", HA1, HA2))
// watch out, int(nc) should always be one as we dont have
// subsequent auth (see rfc 2831)
t = sprintf("%s:%s:%s:%s:%s:%s",
HA1, data["nonce"], data["nc"],
data["cnonce"], data["qop"], HA2);
P2(("sasl: response will be md5(%O)\n", t))
return md5(t);
}
/* this is testing the behaviour with the example data from RFC 2831
* run this whenever you change the code above
*/
#ifdef TESTSUITE
int sasl_test(void) {
string t = "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\","
"qop=\"auth\",algorithm=md5-sess,charset=utf-8";
string rsp;
mapping data;
// check parsing
data = sasl_parse(t);
unless (data["realm"] == "elwood.innosoft.com"
&& data["algorithm"] == "md5-sess"
&& data["charset"] == "utf-8"
&& data["nonce"] == "OA6MG9tEQGm2hh"
&& data["qop"] == "auth"
&& sizeof(data) == 5) {
P0(("SASL TEST: parsing failed!! got %O\n", data))
return -1;
}
// now add the necessary values from rfc 2831
data["username"] = "chris";
data["cnonce"] = "OA6MHXh6VqTrRk";
data["nc"] = "00000001";
data["digest-uri"] = "imap/elwood.innosoft.com";
// and calculate the response
rsp = sasl_calculate_digestMD5(data, "secret", 0);
unless (rsp == "d388dad90d4bbd760a152321f2143af7") {
P0(("SASL TEST: calc0 failed!! got response %O\n", rsp))
return -2;
}
rsp = sasl_calculate_digestMD5(data, "secret", 1);
unless (rsp == "ea40f60335c427b5527b84dbabcdfffd") {
P0(("SASL TEST: calc1 failed!! got rspauth %O\n", rsp))
return -3;
}
P2(("SASL TEST successful.\n"))
return 1;
}
#endif

211
world/net/library/share.c Normal file
View file

@ -0,0 +1,211 @@
// $Id: share.c,v 1.20 2008/02/10 11:31:10 lynx Exp $ // vim:syntax=lpc
//
// verrry simple way to keep single sets of data for all kinds of purposes.
//
// the trick is: if you put these mappings here, they only exist once in
// the entire system, whereas if defined in your application they will be
// recreated for each instance of your app.
//
// net/d/share was essentially a similar idea, but this works better in library.
// use something like this to access the mappings:
//
// volatile mapping mood2jabber;
// mood2jabber = shared_memory("mood2jabber");
#include <net.h>
#include <presence.h>
#include <peers.h>
#include <proto.h>
#include <psyc.h>
// share already contains "preset" data sets
volatile mapping share = ([
// 'mmp vars' belongs into here aswell.. TODO
#ifdef JABBER_PATH
"jabber2avail": ([
0 : AVAILABILITY_HERE,
"chat" : AVAILABILITY_TALKATIVE,
"dnd" : AVAILABILITY_BUSY,
"away" : AVAILABILITY_DO_NOT_DISTURB,
"xa" : AVAILABILITY_AWAY
]),
// map to http://www.jabber.org/jeps/jep-0107.html although that
// is more like good ole mud feelings
"mood2jabber": ([
0 : "neutral", // unspecified mood
// any suggestions on these?
1 : "depressed", // not dead
2 : "angry",
3 : "sad",
4 : "moody",
5 : "neutral", // not okay
6 : "interested", // nothing like 'good'
7 : "happy",
8 : "excited", // not bright
9 : "invincible", // not nirvana
]),
"disco_identity" : ([
"administrator" : "admin",
"newbie" : "anonymous",
"person" : "registered",
"place" : "irc",
"news" : "rss",
"chatserver" : "im",
]),
"disco_features" : ([
"vCard" : "vcard-temp",
"list_feature" : "http://jabber.org/protocol/disco#info",
"list_item" : "http://jabber.org/protocol/disco#items",
"ignore" : "http://jabber.org/protocol/blocking",
"jabber-gc-1.0" : "gc-1.0",
"jabber-muc" : "http://jabber.org/protocol/muc",
"commands" : "http://jabber.org/protocol/commands",
"membersonly" : "muc_membersonly",
"nonanonymous" : "muc_nonanonymous",
"moderated" : "muc_moderated",
"unmoderated" : "muc_unmoderated",
"public" : "muc_public",
"private" : "muc_hidden",
"persistent" : "muc_persistent",
"temporary" : "muc_temporary",
"registration" : "jabber:iq:register",
"offlinestorage" : "msgoffline",
"version" : "jabber:iq:version",
"lasttime" : "jabber:iq:last",
"time" : "jabber:iq:time",
]),
#endif
// even if _degree_availability says it all, we still need
// a string to feed to the textdb - even if it were only internal
"avail2mc": ([
AVAILABILITY_EXPIRED : "_absent", // not true, but..
AVAILABILITY_OFFLINE : "_absent",
AVAILABILITY_VACATION : "_absent_vacation",
AVAILABILITY_AWAY : "_away",
AVAILABILITY_DO_NOT_DISTURB : "_here_busy",
AVAILABILITY_NEARBY : "_here_busy",
AVAILABILITY_BUSY : "_here_busy",
AVAILABILITY_HERE : "_here",
AVAILABILITY_TALKATIVE : "_here_talkative"
]),
// these mc mappings are only for the internal textdb
"mood2mc": ([
0 : "", // unspecified mood
// any suggestions on these?
1 : "_dead",
2 : "_angry",
3 : "_sad",
4 : "_moody",
5 : "_okay",
6 : "_good",
7 : "_happy",
8 : "_bright",
9 : "_nirvana",
]),
// see peers.h for these
"ppl2psyc": ([
PPL_DISPLAY : "_display",
PPL_NOTIFY : "_notification",
PPL_EXPOSE : "_expose",
PPL_TRUST : "_trust",
]),
"_display": ([
PPL_DISPLAY_NONE : "_none",
PPL_DISPLAY_SMALL : "_reduced",
PPL_DISPLAY_REGULAR : "_normal",
PPL_DISPLAY_BIG : "_highlighted",
]),
"_notification": ([
PPL_NOTIFY_IMMEDIATE : "_immediate",
PPL_NOTIFY_DELAYED : "_delayed",
PPL_NOTIFY_DELAYED_MORE : "_delayed_more",
PPL_NOTIFY_MUTE : "_mute",
PPL_NOTIFY_PENDING : "_pending",
PPL_NOTIFY_OFFERED : "_offered",
PPL_NOTIFY_NONE : "_none",
]),
// this table defines variable names to go into the routing layer
// of PSYC. default is to handle them locally in the routing layer
// PSYC_ROUTING_MERGE means to merge them into end-to-end vars at
// parsing time. PSYC_ROUTING_RENDER to accept and render them from
// application provided vars.
"routing": ([
"_amount_fragments" : PSYC_ROUTING,
"_context" : PSYC_ROUTING + PSYC_ROUTING_MERGE,
"_count" : PSYC_ROUTING + PSYC_ROUTING_MERGE,
"_fragment" : PSYC_ROUTING,
"_length" : PSYC_ROUTING,
"_source" : PSYC_ROUTING + PSYC_ROUTING_MERGE,
"_source_identification" :
PSYC_ROUTING + PSYC_ROUTING_MERGE + PSYC_ROUTING_RENDER,
"_source_relay" : PSYC_ROUTING + PSYC_ROUTING_MERGE,
// until you have a better idea.. is this really in use?
"_source_relay_relay" :
PSYC_ROUTING + PSYC_ROUTING_MERGE + PSYC_ROUTING_RENDER,
#ifdef NEW_RENDER
"_tag" :
PSYC_ROUTING + PSYC_ROUTING_MERGE + PSYC_ROUTING_RENDER,
"_tag_relay" :
PSYC_ROUTING + PSYC_ROUTING_MERGE + PSYC_ROUTING_RENDER,
// should be obsolete, but.. TODO
"_tag_reply" :
PSYC_ROUTING + PSYC_ROUTING_MERGE + PSYC_ROUTING_RENDER,
#endif
"_target" : PSYC_ROUTING + PSYC_ROUTING_MERGE,
"_target_relay" : PSYC_ROUTING + PSYC_ROUTING_MERGE,
"_understand_modules" : PSYC_ROUTING,
"_using_modules" : PSYC_ROUTING,
]),
]);
varargs mixed shared_memory(mixed datensatz, mixed value) {
if (value) {
share[datensatz] = value;
// we don't need a function to delete a data set, do we?
// anyway, this could be it:
//unless (datensatz) return m_delete(share, value);
// usage: shared_memory(0, datensatz);
}
if (datensatz) return share[datensatz];
else return share;
}
#ifdef PSYC_SYNCHRONIZE
// one day this could be merged with monitor_report() into
// channels of the same context
static object sync;
int synchro_report(string mc, string text, mapping vars) {
PT(("SYNCHROCAST %O from %O\n", mc, previous_object()))
unless (sync) sync = load_object(PLACE_PATH "sync");
if (sync) {
sync->msg(previous_object(), mc, text, vars);
return 1;
}
// if you really get here, you will have to parse this
// file and resync from there
log_file("SYNC_PANIC", "\n\n"+ time() +"\n"+ make_json( ({
psyc_name(previous_object()), mc, text, vars
}) ));
// hey! a new family.. call it _emergency? naah.. long live unix
monitor_report("_panic_unavailable_synchronization",
"Could not synchronize a "+mc);
return 0;
}
int synchronize_contact(string mynick, string contact, int pplix, mixed value) {
string s = share["ppl2psyc"][pplix];
unless (s) return 0;
if (share[s]) value = share[s][value];
else value = PPLDEC(value);
synchro_report("_notice_synchronize_contact",
"[_nick] has changed [_setting] for \"[_contact]\".", ([
"_nick": mynick, "_contact": contact,
"_setting": s, "_value": value,
]));
return 1;
}
#endif

View file

@ -0,0 +1,129 @@
// $Id: signature.c,v 1.17 2008/03/11 13:42:26 lynx Exp $ // vim:syntax=lpc
//
// generic implementation of http://about.psyc.eu/Signature
//
// maps an anonymous ordered value list to a named parametric var mapping
// according to the signature of a method. probably should
// also be able to do it in the other direction.
//
// needed both for converting slash commands into _request commands
// and to implement a protocol level optimization where variable names
// can be left out as long as the values are in the proper order.
//
// currently we only do the first of the two applications (actually the
// second being an extension of the first). to achieve that we hold a hash
// of command methods which point to their respective signatures.
#include <net.h>
#include <signature.h>
/* we still don't use structs because they make the driver a lot fatter
* we'll get by using arrays and a couple of macros from signature.h
*
struct Signature {
closure handler;
mixed extra;
array(string) vars;
};
*
* also, we don't use closures as closures stick to the blueprint instead
* of operating on the working object. apparently bind_lambda() can rebind
* a CLOSURE_LFUN, but i didn't find out how to create that type of closure
* and having something like
* if (blueprintp(ME)) return
* previous_object()->myself(myargs);
* in *each* handler is a very ugly enterprise. I finally decided that the
* little performance trade off in looking up an object's function in its
* function table is well worth the simplicity we get by keeping all
* signatures in a central place, being here. first I tried to make a custom
* signature hash for each blueprint of a place, but that is just too messy
* to go for.
*/
// these could be generated by an external tool
private volatile mapping _sigs = ([
// "OFFICIAL" METHODS as seen on [[Command]].
// ahem... _do? consistency please!
"_request_do_show_log": ({ "_request_history", 0, "_parameter" }),
// can either be _amount or _match or _parameter
"_request_history": ({ "_request_history", 0, "_parameter" }),
"_request_kick": ({ "_request_kick", 0, "_person" }),
"_request_nickname": ({ "_request_nick_local", 0, "_nick_local", "_INTERNAL_stuss" }),
// the real thing, maybe? method inheritance could even lead to here
// for all of the _request_set_something methods. good? bad?
"_request_set": ({ "_request_set", 0, "_key", "_value" }),
// when called by _request_set(), value might be in _value
"_request_set_masquerade": ({ "_request_masquerade", 0, "_flag_masquerade" }),
"_request_set_owners": ({ "_request_owners", 0, "_list_owners" }), // _tab
"_request_set_public": ({ "_request_public", 0, "_flag_public" }),
"_request_set_style": ({ "_request_set_style", 0, "_uniform_style" }),
// "INTERNAL" METHODS
// all of the following "fake" _request methods are just the psyced
// way to handle command name variations and shortcuts. never use this
// in your clients. always use the official versions listed on
// [[Command]]. when sending arbitrary commands, use _request_execute,
// don't make up _request_something like psyced does internally.
"_request_hist": ({ "_request_history", 0, "_parameter" }),
"_request_style": ({ "_request_set_style", 0, "_uniform_style" }),
"_request_owners": ({ "_request_owners", 0, "_list_owners" }), // _tab
"_request_elrid": ({ "_request_kick", 0, "_person" }),
"_request_masquerade": ({ "_request_masquerade", 0, "_flag_masquerade" }),
"_request_masq": ({ "_request_masquerade", 0, "_flag_masquerade" }),
"_request_nick": ({ "_request_nick_local", 0, "_nick_local", "_INTERNAL_stuss" }),
"_request_ni": ({ "_request_nick_local", 0, "_nick_local", "_INTERNAL_stuss" }),
"_request_public": ({ "_request_public", 0, "_flag_public" }),
"_request_pub": ({ "_request_public", 0, "_flag_public" }),
#ifdef EXPERIMENTAL
// stuff to play around with
"_request_pset": ({ "_request_set", 0, "_key", "_value" }),
"_request_cset": ({ "_request_set", 0, "_key_set", "_value" }),
"_request_tt": ({ "_request_set", ([ "_key": "_topic" ]), "_value" }),
#endif
]);
varargs int call_signature(string source, string mc, mixed data,
mapping origvars, varargs array(mixed) more) {
Signature s = _sigs[mc];
mapping vars;
string last;
int i, j;
unless (s) return 0;
// ASSERT("call_signature:closurep", closurep(s[SHandler]), s)
// vars = ([ "_INTERNAL_method_signature": mc ]);
vars = ([]);
if (mappingp(origvars) && sizeof(origvars))
vars += origvars;
if (mappingp(s[SPreset])) vars += s[SPreset];
/* else if (s[SPreset])
vars["_INTERNAL_preset"] = s[SPreset]; */
if (pointerp(data) && sizeof(data)) {
vars["_INTERNAL_command"] = data[0];
for (i=1, j=SKeys; i<sizeof(data); i++, j++) {
if (j < sizeof(s))
// check var type here.. TODO
vars[ last = s[j] ] = data[i];
else
vars[ last ] += " "+ data[i];
}
data = 0;
}
P2(("call_signature: created %O as vars\n", vars))
// this is how i tried to do it with closures..
//bind_lambda(s[SHandler]);
//return apply(s[SHandler], vars, more);
return call_direct(previous_object(), s[SHandler],
source, mc, data, vars, more...);
}
#ifdef _flag_extend_backend
mapping register_signature(mapping newsigs) {
if (newsigs) {
_sigs = newsigs;
ASSERT("register_signature",
mappingp(_sigs) && sizeof(_sigs), _sigs)
}
return _sigs;
}
#endif

97
world/net/library/text.c Normal file
View file

@ -0,0 +1,97 @@
// $Id: text.c,v 1.17 2008/04/11 10:37:25 lynx Exp $ // vim:syntax=lpc
//
// the marvellous psyctext() function, fundamental of any PSYC implementation.
//
// this function does PSYC variable replacement for error messages
// and informational notices as described in the internet drafts
//
// this code performs okay, but i would rather have it written in C and
// linked to the driver. see also CHANGESTODO for thoughts on how to do a
// generic template replacement C function in a way that it does psyctext()
// effectively, but can also be used for other syntaxes.
//
#include <net.h>
#include <proto.h>
varargs string psyctext(string s, mapping m, vastring data,
vamixed source, vastring nick) {
string r, p, q, v;
P3(("psyctext(%O)\n", s))
unless(s) return "";
if (s == "") {
if (data) s = data;
else return 0;
}
#if 0
ASSERT("psyctext-mapping for "+ to_string(s),
mappingp(m) && widthof(m) == 1, m)
#else
// easy on missing mapping
unless (mappingp(m)) return s;
#endif
r="";
while (sscanf(s, "%s[%s]%s", p, v, s) && v) {
if (v == "_nick") r += p + (nick || m["_nick"]);
else if (v == "_data") r += p + (data || "");
else unless (member(m, v)) {
if (v == "_source") r += p + to_string(source);
else {
PT(("psyctext: ignoring [%s]\n", v))
r += p + "["+v+"]"; // pretend we havent seen it
}
}
else if (stringp(m[v])) r += p + m[v];
else if (pointerp(m[v])) { // used by showMembers
r += p + implode(m[v], ", ");
}
// if (member(m,v) && m[v]) r += p + m[v];
else if (intp(m[v])) { // used by /lu and /edit
if (v == "_time_idle") r += p + timedelta(m[v]);
else if (abbrev("_time", v)) {
// verrry similar code in net/user.c
if (time() - m[v] > 24*60*60)
r += p + isotime( m[v], 0 );
else
r += p + hhmmss(ctime( m[v] ));
// r += p + hhmm(ctime(m[v]));
} else
r += p + to_string(m[v]);
}
else if (mappingp(m[v])) { // made by psyc/parse
r += p + implode(m_indices(m[v]), ", ");
}
// used in rare cases where _identification is output
else if (objectp(m[v])) r += p + psyc_name(m[v]);
else {
// in theory at this point we could perform
// an inheritance search, but that's overkill.
// instead we just bail out. for the psyc standard
// on psyctext we will have to decide which option
// is right: simplicity vs inheritance power. ouch.
D1( if (v[0] == '_')
D(S("psyctext warning: invalid %s=%O for %O\n",
v, m[v], previous_object() || ME)); )
r += p + "["+v+"]"; // pretend we havent seen it
}
}
if (s != "") r += s;
return r;
}
#if 0
// this doesn't help detect a problem.. this MAKES the problem!
// when the library offers a function of the same name as a method
// defined in an inheriting class, then the inherited class will
// execute the library function instead of finding the method in
// the inheriting class. so when you #if 1 this, you will see that
// person.c:w() resolves here instead of going into user.c:w().
// evil!! -lynX
//
varargs void w(string mc, string data, mixed vars) {
// oh my god seit wann gibt's denn das!?
raise_error(sprintf("%O ended up in library/text:w(%s) for %O\n",
previous_object(), mc, this_interactive()));
}
#endif

55
world/net/library/time.c Normal file
View file

@ -0,0 +1,55 @@
// $Id: time.c,v 1.3 2007/09/18 08:37:58 lynx Exp $ // vim:syntax=lpc
#include <net.h>
volatile mapping cmonth;
// produces a date/time according to ISO 8601
varargs string isotime(mixed ctim, int long) {
array(string) t;
string res;
unless (ctim) ctim = ctime();
else if (intp(ctim)) ctim = ctime(ctim);
if (ctim[8] == ' ') ctim[8] = '0';
t = explode(ctim, " ");
unless (cmonth) cmonth = ([
"Jan" : "01", "Feb" : "02", "Mar" : "03", "Apr" : "04",
"May" : "05", "Jun" : "06", "Jul" : "07", "Aug" : "08",
"Sep" : "09", "Oct" : "10", "Nov" : "11", "Dec" : "12"
]);
res = t[4] +"-"+ cmonth[t[1]] +"-"+ t[2];
// official would be to have "T" instead of " " there,
// but all the world prefers readable ISO timestamps.
return long ? res+" "+t[3] : res;
}
string timedelta(int secs) {
string t = "";
int y, d, h, m;
if (secs < 60) return "--:--";
if (y = secs/86400/365) {
t += y + "y ";
secs = secs % (86400*365);
}
// if (d = secs/86400/30) {
// t += d + "M ";
// secs = secs % (86400*30);
// }
if (d = secs/86400) {
if (y) return t + d +"d";
t += d + "d ";
secs = secs % 86400;
}
if (h = secs/3600) secs = secs % 3600;
if (d) return t+ to_string(h) +"h";
// if (m = secs/60) secs = secs % 60;
// t += sprintf("%02d:%02d:%02d", h, m, secs);
m = secs/60;
t += sprintf("%02d:%02d", h, m);
// t += hhmm(ctime(secs - 60*60));
return t;
}

90
world/net/library/tls.c Normal file
View file

@ -0,0 +1,90 @@
#include <net.h> // vim syntax=lpc
mapping tls_certificate(object who, int longnames) {
mixed *extra, extensions;
mapping cert;
int i, j;
cert = ([ ]);
#if __EFUN_DEFINED__(tls_check_certificate)
# ifdef WANT_S2S_SASL
/*
* some platforms (notably cygwin) still have a problem executing the following
* #if ... even psyclpc bails out with an "illegal unary operator in #if"
* which is nonsense. i simplify this by ifdeffing for psyclpc.
*/
//# if (__VERSION_MAJOR__ == 3 && __VERSION_MICRO__ > 712) || __VERSION_MAJOR__ > 3
# ifdef __psyclpc__
# if __EFUN_DEFINED__(enable_binary) // happens to be committed at the same time
extra = tls_check_certificate(who, 2);
# else
extra = tls_check_certificate(who, 1);
# endif
# else
extra = tls_check_certificate(who);
# endif
unless (extra && sizeof(extra) > 2) return 0;
cert[0] = extra[0];
if (sizeof(extra) >= 4)
cert[1] = extra[3];
extensions = extra[2];
extra = extra[1];
for (i = 0; i < sizeof(extra); i += 3) {
mixed t;
t = cert[extra[i]];
// THIS IS ALWAYS TRUE FOR DRIVER >= 3.3.712
// OTHERWISE YOU SHOULD NOT ENABLE S2S SASL. PERIOD.
if (sizeof(extra) > i+2) {
unless (t) {
cert[extra[i]] = extra[i+2];
} else if (stringp(t)) {
cert[extra[i]] = ({ t, extra[i+2] });
} else if (pointerp(t)) {
cert[extra[i]] += ({ extra[i+2] });
} else {
PT(("fippo says this should not happen but you know it always does! %O\n", ME))
}
} else {
PT(("fippo says this should not happen(2) but you know it always does! %O\n", ME))
}
}
if (longnames) {
// set up short/long names
for (i = 0; i < sizeof(extra); i +=3) {
cert[extra[i+1]] = cert[extra[i]];
}
}
for (i = 0; i < sizeof(extensions); i += 3) {
string key, mkey;
mixed *val;
unless(extensions[i]) continue;
key = extensions[i];
val = extensions[i+2];
for (j = 0; j < sizeof(val); j += 3) {
mixed t;
mkey = key + ":" + val[j];
t = cert[mkey];
unless (t) {
cert[mkey] = val[j+2];
} else if (stringp(t)) {
cert[mkey] = ({ t, val[j+2] });
} else if (pointerp(t)) {
cert[mkey] += ({ val[j+2] });
} else {
// should not happen
}
}
}
# else
# echo No WANT_S2S_SASL ? You even have the right driver for it!
# endif
#else
# echo No tls_check_certificate available with this driver.
#endif
P2(("cert is %O\n", cert))
return cert;
}

138
world/net/library/url.c Normal file
View file

@ -0,0 +1,138 @@
// $Id: url.c,v 1.43 2008/03/29 20:36:43 lynx Exp $ // vim:syntax=lpc
//
// URLs.. URIs.. UNLs.. UNIs.. maybe even URNs..
// the fact they wear a uniform is the only thing these items have in common
// after all.. they are not always resources, not always locators,
// not always identificators.. but one thing is for sure, they have a
// common format.. the uniform :)
//
// TODO: first move everything called _uniform or url somewhere into here
// then rename everything into uniform, also url.c and url.h..
#include <net.h>
#include <url.h>
string legal_url(string url, string scheme) {
if (scheme &&! abbrev(scheme+":", url)) return 0;
if (index(url, '"') >= 0) return 0;
if (index(url, ' ') >= 0) return 0; // just
if (index(url, '\t') >= 0) return 0; // paranoid
return url;
}
/** pass it a URL string and it will find out if that string
** is a uniform, and if so return an array as defined in url.h
**
** <fippo> what about using
** http://www.gbiv.com/protocols/uri/rfc/rfc3986.html#regexp ?
** <lynX> sweet, i really like that. can we do that?
** only we have to change that regexp a lot. like we don't
** need $1, $6 and $8, we need USlashes instead of $3, but
** what's tough is, we need UQuery to support ; or ? and
** we need UUser, UPass, UPort, UTransport, and UHostPort.
** all of that isn't in that regexp yet...
*/
varargs array(mixed) parse_uniform(string url, vaint tolerant) {
array(string) u = allocate(USize);
string t;
string s;
u[UString] = url;
if (sscanf(url, "%s:%s", u[UScheme], t) != 2) {
if (tolerant) t = url;
else return 0;
}
ASSERT("parse_uniform w/out scheme", u[UScheme] || tolerant, url)
P3(("parse_uniform %s of %O (tolerant: %O)\n",
url, u[UScheme], tolerant))
if (abbrev("//", t)) {
t = t[2..];
u[USlashes] = "//";
} else u[USlashes] = "";
switch(u[UScheme]) {
case "sip":
sscanf(t, "%s;%s", t, u[UQuery]);
break;
case "telnet":
break;
case "psyc":
sscanf(t, "%s#%s", t, u[UChannel]);
break;
#if 0 //def MUCSUC
case "xmpp":
sscanf(t, "%s#%s", t, u[UChannel]);
break;
#endif
//case "mailto":
default:
sscanf(t, "%s?%s", t, u[UQuery]);
}
u[UBody] = t;
sscanf(t, "%s/%s", t, u[UResource]);
#if 0
// int n;
if (-1 != (n = member(u[UResource], '#'))) {
u[UChannel] = u[UResource][n+1..]; // strlen checken??
}
#endif
u[UUserAtHost] = t;
if (sscanf(t, "%s@%s", s, t)) {
unless (sscanf(s, "%s:%s", u[UUser], u[UPass]))
u[UUser] = s;
}
u[UHostPort] = t;
// if (complete) u[UCircuit] = u[UScheme]+":"+u[UHostPort];
u[URoot] = u[UScheme]+":"+u[USlashes]+u[UHostPort];
if (sscanf(t, "%s:%s", t, s)) {
unless (sscanf(s, "%d%s", u[UPort], u[UTransport]))
u[UTransport] = s;
unless (strlen(u[UTransport])) u[UTransport] = 0;
}
u[UHost] = t;
P4(("parse_uniform %s = %O (tolerant: %O)\n", url, u, tolerant))
return u;
}
string render_uniform(array(mixed) u) {
string s, t;
// wird aufgerufen wenn dieser string nicht mehr gültig ist:
// if (u[UString]) return u[UString];
unless (s = u[UHost]) return 0;
if (u[UUser]) s = u[UPass] ? (u[UUser]+":"+u[UPass]+"@"+s)
: (u[UUser]+"@"+s);
if (u[UScheme]) s = u[UScheme]+"://"+s;
t = u[UPort] ? to_string(u[UPort]) : "";
if (u[UTransport]) t += u[UTransport];
if (t != "") s += ":"+t+"/";
if (u[UResource]) s += u[UResource];
if (u[UChannel]) s += "#"+ u[UChannel];
if (u[UQuery]) s += "?"+ u[UQuery];
D2( if (u[UString] == s) D("render_uniform: das war umsonst..\n"); )
P3(("render_uniform %O = %s\n", u, s))
return u[UString] = s;
}
// convert GENERIC psyc url stringp()s to objects (if local)
#if 0
mixed urlobject(string url) {
array(mixed) u;
object o;
// we avoid errors! we rule!
u = parse_uniform(url);
unless (query_udp_port() == (u[UPort] || PSYC_PORT))
return url;
unless (u[UHost] == __HOST_IP_NUMBER__
|| lower_case(u[UHost]) == lower_case(SERVER_HOST))
return url;
if (u[UResource][0] == '~')
o = find_person(u[UResource][1..]);
else if (u[UUser]) o = find_person(u[UUser]);
else o = find_object(u[UResource]);
unless(objectp(o)) return url;
return o;
}
#endif