added ~user#updates channel; place/threads improvements

This commit is contained in:
Gabor Adam Toth 2010-02-15 01:31:55 +01:00
parent 3b837b2f1f
commit ca4da0725b
9 changed files with 212 additions and 82 deletions

View File

@ -336,6 +336,7 @@ object connect(int uid, int port, string service) {
#ifdef DRIVER_HAS_RENAMED_CLONES #ifdef DRIVER_HAS_RENAMED_CLONES
// named clones -lynx // named clones -lynx
object compile_object(string file) { object compile_object(string file) {
P3((">> compile_object(%O)\n", file))
string path, name; string path, name;
object rob; object rob;
@ -383,36 +384,46 @@ object compile_object(string file) {
return rob; return rob;
} }
# endif # endif
if (sscanf(file, "%s#%s.c", path, name) && name != "") {
unless (name = SIMUL_EFUN_FILE->legal_name(name))
return (object)0;
rob = clone_object(path);
rob -> sName(name);
D2(if (rob) PP(("NAMED CLONE: %O becomes %s of %s\n",
rob, name, path));)
return rob;
}
if (sscanf(file, "place/%s.c", name) && name != "") { if (sscanf(file, "place/%s.c", name) && name != "") {
#ifdef SANDBOX #ifdef SANDBOX
string t; string t;
#endif #endif
unless (name = SIMUL_EFUN_FILE->legal_name(name)) unless (name = SIMUL_EFUN_FILE->legal_name(name, 1))
return (object)0; return (object)0;
string username;
if (sscanf(file, "place/~%s#updates", username)) {
object p;
unless ((p = SIMUL_EFUN_FILE->summon_person(username, NET_PATH "user")) && p->vQuery("password")) {
P3(("PLACE %O NOT CLONED: %O isn't a registered user\n", name, username));
return (object)0;
}
if (rob = clone_object(NET_PATH "place/userthreads")) {
PP(("PLACE CLONED: %O becomes %O\n", rob, file));
rob->sName(name);
return rob;
} else {
P3(("ERROR: could not clone place %O\n", name));
return (object)0;
}
}
#ifdef SANDBOX #ifdef SANDBOX
if (file_size(t = USER_PATH + name + ".c") != -1) { if (file_size(t = USER_PATH + name + ".c") != -1) {
rob = t -> sName(name); rob = t -> sName(name);
D2(if (rob) PP(("USER PLACE loaded: %O becomes %O\n", rob, file));) D2(if (rob) PP(("USER PLACE loaded: %O becomes %O\n", rob, file));)
} else { } else {
#endif #endif
#ifdef _flag_disable_places_arbitrary #ifdef _flag_disable_places_arbitrary
P2(("WARN: cloned places disabled by #define %O\n", file)) P2(("WARN: cloned places disabled by #define %O\n", file))
return (object)0; return (object)0;
#else #else
#ifdef _path_archetype_place_default #ifdef _path_archetype_place_default
rob = clone_object(_path_archetype_place_default); rob = clone_object(_path_archetype_place_default);
#else #else
rob = clone_object(NET_PATH "place/default"); rob = clone_object(NET_PATH "place/default");
#endif #endif
rob -> sName(name); rob -> sName(name);
D2(if (rob) PP(("PLACE CLONED: %O becomes %O\n", rob, file));) D2(if (rob) PP(("PLACE CLONED: %O becomes %O\n", rob, file));)
@ -422,6 +433,15 @@ object compile_object(string file) {
#endif #endif
return rob; return rob;
} }
if (sscanf(file, "%s#%s.c", path, name) && name != "") {
unless (name = SIMUL_EFUN_FILE->legal_name(name))
return (object)0;
rob = clone_object(path);
rob -> sName(name);
D2(if (rob) PP(("NAMED CLONE: %O becomes %s of %s\n",
rob, name, path));)
return rob;
}
if (sscanf(file, "%s/text.c", path) && path != "") { if (sscanf(file, "%s/text.c", path) && path != "") {
rob = clone_object(NET_PATH "text"); rob = clone_object(NET_PATH "text");
rob -> sPath(path); rob -> sPath(path);

View File

@ -546,12 +546,13 @@ int boss(mixed guy) {
} }
mixed find_place(mixed a) { mixed find_place(mixed a) {
P3((">> find_place(%O)\n", a))
string path, err; string path, err;
object o; object o;
if (objectp(a)) return a; if (objectp(a)) return a;
if (path = lower_uniform(a)) return path; if (path = lower_uniform(a)) return path;
unless (a = legal_name(a)) return 0; unless (a = legal_name(a, 1)) return 0;
path = PLACE_PATH + lower_case(a); // assumes amylaar path = PLACE_PATH + lower_case(a); // assumes amylaar
o = find_object(path); o = find_object(path);
if (o) return o; if (o) return o;

View File

@ -2,8 +2,9 @@
#include <net.h> #include <net.h>
// legal nickname/placename test.. // legal nickname/placename test..
string legal_name(string n) { varargs string legal_name(string name, int place) {
int i; int i;
string n = name;
//PT(("legal_name(%O) in %O\n", n, ME)) //PT(("legal_name(%O) in %O\n", n, ME))
if (shutdown_in_progress) { if (shutdown_in_progress) {
@ -25,17 +26,24 @@ string legal_name(string n) {
P1(("not legal_name: %O has !=- as first char.\n", n)) P1(("not legal_name: %O has !=- as first char.\n", n))
return 0; return 0;
} }
for (i=strlen(n)-1; i>=0; i--) {
if (index("\ string nick;
if (place && sscanf(name, "~%s#updates", nick))
n = nick;
string chars = "\
abcdefghijklmnopqrstuvwxyz\ abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ\ ABCDEFGHIJKLMNOPQRSTUVWXYZ\
0123456789_-=+", n[i]) == -1) { 0123456789_-=+";
for (i=strlen(n)-1; i>=0; i--) {
if (index(chars, n[i]) == -1) {
P1(("not legal_name: %O has ill char at %d (%O).\n", P1(("not legal_name: %O has ill char at %d (%O).\n",
n, i, n[i])) n, i, n[i]))
return 0; return 0;
} }
} }
return n; return name;
} }
array(string) legal_password(string pw, string nick) { array(string) legal_password(string pw, string nick) {

View File

@ -291,8 +291,8 @@ msgView(source, mc, data, vars, showingLog) {
// t = regreplace(s, ": ", "\", \"", 1); // t = regreplace(s, ": ", "\", \"", 1);
// if (s == t) return; // if (s == t) return;
if (showingLog == "html") if (showingLog == "html")
// fmt = "(<i>%s</i>) <b>%s %s</b>: %s<br>\n"; // fmt = "(<i>%s</i>) <b>%s %s</b>: %s<br/>\n";
fmt = stringp(t[2]) ? "<tr><td nowrap class=ts>%s</td><td nowrap class=sp><b>%s</b> %s</td><td class=tx>%s</td></tr>\n" : "<tr><td nowrap class=ts>%s</td><td colspan=2 nowrap class=sp><b>%s</b> %s</td></tr>\n"; fmt = stringp(t[2]) ? "<div class='msg'><span class='ts'>%s</span> <span class='sp'><b>%s</b> %s</span> <span class='tx'>%s</span></div>\n" : "<div class='msg'><span class='ts'>%s</span> <span class='sp'><b>%s</b> %s</span></div>\n";
else // showingLog == "ecmascript" else // showingLog == "ecmascript"
fmt = "\t%O, %O, %O, %O,\n"; fmt = "\t%O, %O, %O, %O,\n";
@ -2614,5 +2614,3 @@ qAide(snicker, aidesonly) {
qOwner(snicker) { return member(v("owners"), lower_case(snicker)); } qOwner(snicker) { return member(v("owners"), lower_case(snicker)); }
#endif #endif

View File

@ -35,11 +35,13 @@ volatile int last_modified;
volatile string webact; volatile string webact;
create() { create() {
P3((">> threads:create()\n"))
::create(); ::create();
unless (pointerp(_thread)) _thread = ({ }); unless (pointerp(_thread)) _thread = ({ });
} }
cmd(a, args, b, source, vars) { cmd(a, args, b, source, vars) {
P3((">> threads:cmd(%O, %O, %O, %O, %O)", a, args, b, source, vars))
// TODO: multiline-sachen irgendwie // TODO: multiline-sachen irgendwie
mapping entry; mapping entry;
int i = 0; int i = 0;
@ -51,34 +53,73 @@ cmd(a, args, b, source, vars) {
// _thread[<5..] // _thread[<5..]
foreach( entry : _thread[<num_entries..] ) { foreach( entry : _thread[<num_entries..] ) {
sendmsg(source, "_list_thread_item", sendmsg(source, "_list_thread_item",
// hier auch noch den text? "#[_number] - [_author][_sep][_thread]: [_text] ([_comments])",
"([_number]) \"[_thread]\", [_author]",
([ ([
"_sep" : strlen(entry["thread"]) ? " - " : "",
"_thread" : entry["thread"], "_thread" : entry["thread"],
"_text" : entry["text"], "_text" : entry["text"],
"_author" : entry["author"], "_author" : entry["author"],
"_date" : entry["date"], "_date" : entry["date"],
"_comments": sizeof(entry["comments"]),
"_number" : i++, "_number" : i++,
"_nick_place" : MYNICK ]) ); "_nick_place" : MYNICK ]) );
} }
return 1; return 1;
case "entry":
unless (sizeof(args) > 1){
sendmsg(source, "_warning_usage_entry",
"Usage: /entry <threadid>", ([ ]));
return 1;
}
int n = to_int(args[1]);
entry = _thread[n];
sendmsg(source, "_list_thread_item",
"#[_number] [_author][_sep][_thread]: [_text] ([_comments])",
([
"_sep" : strlen(entry["thread"]) ? " - " : "",
"_thread" : entry["thread"],
"_text" : entry["text"],
"_author" : entry["author"],
"_date" : entry["date"],
"_comments": sizeof(entry["comments"]),
"_number" : n,
"_nick_place" : MYNICK ]) );
if (entry["comments"]) {
foreach(mapping item : entry["comments"]) {
sendmsg(source, "_list_thread_comment",
"> [_nick]: [_text]",
([
"_nick" : item["nick"],
"_text" : item["text"],
"_nick_place" : MYNICK ]) );
}
}
return 1;
case "thread": case "thread":
unless (sizeof(args) > 2){ // num + thread unless (sizeof(args) > 2){
sendmsg(source, "_warning_usage_thread", sendmsg(source, "_warning_usage_thread",
"Usage: /thread <threadid> <title>", ([ ])); "Usage: /thread <threadid> <title>", ([ ]));
return 1; return 1;
} }
return setSubject(to_int(args[1]), ARGS(2)); return setSubject(to_int(args[1]), ARGS(2));
case "comment":
unless (sizeof(args) >= 2) {
sendmsg(source, "_warning_usage_reply",
"Usage: /comment <threadid> <text>", ([ ]));
return 1;
}
return addComment(ARGS(2), SNICKER, to_int(args[1]));
case "blog": case "blog":
case "submit": case "submit":
case "addentry": case "addentry":
unless (qAide(SNICKER)) return; unless (qAide(SNICKER)) return;
unless (sizeof(args) >= 2) { unless (sizeof(args) >= 1) {
sendmsg(source, "_warning_usage_submit", sendmsg(source, "_warning_usage_submit",
"Usage: /submit <title> <text>", ([ ])); "Usage: /submit <text>", ([ ]));
return 1; return 1;
} }
return addEntry(ARGS(2), SNICKER, args[1]); return addEntry(ARGS(1), SNICKER);
// TODO: append fuer multiline-sachen // TODO: append fuer multiline-sachen
#if 0 #if 0
case "iterator": case "iterator":
@ -111,8 +152,8 @@ cmd(a, args, b, source, vars) {
return ::cmd(a, args, b, source, vars); return ::cmd(a, args, b, source, vars);
} }
msg(source, mc, data, mapping vars){ msg(source, mc, data, vars){
P2(("blog.c's msg: mc %O, source %O\n", mc, source)) P3(("thread:msg(%O, %O, %O, %O)", source, mc, data, vars))
// TODO: die source muss hierbei uebereinstimmen mit dem autor // TODO: die source muss hierbei uebereinstimmen mit dem autor
if (abbrev("_notice_authentication", mc)){ if (abbrev("_notice_authentication", mc)){
sendmsg(source, "_notice_place_blog_authentication_success", "([_entry]) has been authenticated", sendmsg(source, "_notice_place_blog_authentication_success", "([_entry]) has been authenticated",
@ -252,6 +293,7 @@ delEntry(int number, source, vars) {
} }
_thread = entries[0..number-1] + entries[number+1..]; _thread = entries[0..number-1] + entries[number+1..];
//_thread[number] = 0;
save(); save();
return 1; return 1;
@ -449,47 +491,61 @@ displayMain(last) {
} }
#endif #endif
displayMain(last) { htMain(last) {
int i; int i;
int len; int len;
string t; string t;
string ht = "";
len = sizeof(_thread); len = sizeof(_thread);
if (last > len) last = len; if (last > len) last = len;
// reverse order // reverse order
for (i = len-1; i >= len - last; i--) { for (i = len-1; i >= len - last; i--) {
P3((">>> _thread[%O]: %O\n", i, _thread[i]))
t = htquote(_thread[i]["text"]); t = htquote(_thread[i]["text"]);
t = replace(t, "\n", "<br>\n"); t = replace(t, "\n", "<br>\n");
write("<table class='newsTable' width='560px'>\n" t = replace(t, "<", "&lt;");
"<tr>" t = replace(t, ">", "&gt;");
"<td class='newsAuthor' width='20%'>" + _thread[i]["author"] + "</td>"
"<td class='newsTime' nowrap width='20%'>" + _thread[i]["date"] + "</td>" ht += "<div class='entry'>\n"
"<td class='newsSubject' width='60%'>" + htquote(_thread[i]["thread"]) + "</td>" "<div class='title'>\n"
"</tr>\n" "<span class='author'>" + _thread[i]["author"] + "</span>\n"
"<tr>" "<span class='subject'>" + htquote(_thread[i]["thread"]) + "</span>\n"
"<td colspan='3' class='newsText'>" + t + "</td>" "</div>\n"
"</tr>\n" "<div class='text'>" + t + "</div>\n"
"<tr>" "<div class='footer'>\n"
"<td colspan='3' class='newsLink'><a href='" + webact + "?comments" "<span class='date'>" + _thread[i]["date"] + "</span>\n"
"=" + i + "'>" + sizeof(_thread[i]["comments"]) + " comments</a></td>" "<span class='comments'>"
"</tr>\n" "<a href='" + webact + "?comments=" + i + "'>" + sizeof(_thread[i]["comments"]) + " comments</a>"
"</table>\n"); "</span>\n"
"</div>\n"
"</div>\n";
} }
return "<div class='threads'>" + ht + "</div>";
}
htComments(data) {
mapping item;
string ht = "";
write("<b>" + data["author"] + "</b>: " + data["text"] + "<br><br>\n");
if (data["comments"]) {
foreach(item : data["comments"]) {
ht += "<b>" + item["nick"] + "</b>: " + item["text"] + "<br>\n";
}
} else {
ht += "no comments...<br>\n";
}
return ht;
}
displayMain(last) {
write(htMain(last));
} }
displayComments(data) { displayComments(data) {
mapping item; write(htComments(data));
write("Ursprüngliche Nachricht:<br>"
"<b>" + data["author"] + "</b>: " + data["text"] + "<br><br>\n");
if (data["comments"]) {
foreach(item : data["comments"]) {
write("<b>" + item["nick"] + "</b>: " + item["text"] + "<br>\n");
}
} else {
write("no comments...<br>\n");
}
} }
nntpget(cmd, args) { nntpget(cmd, args) {
@ -539,7 +595,7 @@ default:
} }
#ifndef STYLESHEET #ifndef STYLESHEET
# define STYLESHEET (v("_uniform_style") || "http://www.psyc.eu/blog.css") # define STYLESHEET (v("_uniform_style") || "/static/examine.css")
#endif #endif
// wir können zwei strategien fahren.. die technisch einfachere ist es // wir können zwei strategien fahren.. die technisch einfachere ist es
@ -553,28 +609,10 @@ default:
// //
displayHeader() { displayHeader() {
w("_HTML_head_threads", w("_HTML_head_threads",
"<link rel='stylesheet' type='text/css' href='"+ "<html><head><link rel='stylesheet' type='text/css' href='"+
STYLESHEET +"'>\n"+ STYLESHEET +"'></head>\n"+
"<style type='text/css'>\n" "<body class='threads'>\n\n");
"<!--\n"
"body { font-family: lucida,verdana,geneva; }\n"
"td { font-family: lucida,verdana,geneva; }\n"
"table.newsTable {border: 1px solid #6f6; padding:4px; margin:6px;}\n"
"table td.newsAuthor {color:#fff; font-weight:bold;"
" border: 1px solid #6f6;"
" background-color:#041;}\n"
"table td.newsTime {color:#ddd;border: 1px solid #6f6;"
" background-color:#030;}\n"
"table td.newsSubject {color:#ddd; border: 1px solid #6f6;"
" background-color:#030;}\n"
"table td.newsLink {background-color:#030;}\n"
"table td.newsText {}\n"
"//-->\n"
"</style>\n"
"<body bgcolor='#002200' text='#33ff33' link='#ffdf00'"
"vlink='#ffaf00' alink='#00ff00'>\n\n");
} }
displayFooter() { displayFooter() {
w("_HTML_tail_threads", "</body>"); w("_HTML_tail_threads", "</body></html>");
} }

View File

@ -0,0 +1,15 @@
#include <net.h>
#include <person.h>
#include <status.h>
inherit NET_PATH "place/threads";
load(name, keep) {
P3((">> userthreads:load(%O, %O)\n", name, keep))
string nick;
if (sscanf(name, "~%s#updates", nick))
vSet("owners", ([ nick: 0 ]));
return ::load(name, keep);
}

View File

@ -117,6 +117,7 @@ object psyc_object(string uniform) {
#ifndef FORK #ifndef FORK
object find_psyc_object(array(mixed) u) { object find_psyc_object(array(mixed) u) {
P3((">> find_psyc_object(%O)\n", u))
string t, r, svc, user; string t, r, svc, user;
object o; object o;
@ -131,7 +132,15 @@ object find_psyc_object(array(mixed) u) {
#endif #endif
if (strlen(r)) switch(r[0]) { if (strlen(r)) switch(r[0]) {
case '^': case '^':
break;
case '~': case '~':
if (u[UChannel]) {
t = lower_case(r + "#" + u[UChannel]);
r = PLACE_PATH + t;
if (o = find_object(r)) break;
unless (t = legal_name(t)) break;
catch(o = r -> load(t));
}
break; break;
case '$': case '$':
// target wird auf serv/args gesetzt // target wird auf serv/args gesetzt
@ -174,6 +183,7 @@ object find_psyc_object(array(mixed) u) {
o = summon_person(user); //, PSYC_PATH "user"); o = summon_person(user); //, PSYC_PATH "user");
P2(("%O summoning %O: %O\n", ME, user, o)) P2(("%O summoning %O: %O\n", ME, user, o))
} }
P3((">>> found psyc object: %O\n", o))
return o; return o;
} }

View File

@ -283,6 +283,10 @@ htDescription(anonymous, query, headers, qs, variant, vars) {
// <input type=hidden name=token value=\""+v("token")+"\">\n\ // <input type=hidden name=token value=\""+v("token")+"\">\n\
// <input type=hidden name=lang value=\""+v("language")+"\">\n\ // <input type=hidden name=lang value=\""+v("language")+"\">\n\
// //
object u = find_place("~" + nick + "#updates");
string updates = objectp(u) ? u->htMain(10) : "";
return psyctext(page, vars + ([ return psyctext(page, vars + ([
"_FORM_start" : "\ "_FORM_start" : "\
<form class=\"Pef\" name=\"Pef\" action=\"\">\n\ <form class=\"Pef\" name=\"Pef\" action=\"\">\n\
@ -292,7 +296,8 @@ htDescription(anonymous, query, headers, qs, variant, vars) {
"_nick_me" : MYNICK, "_nick_me" : MYNICK,
"_FORM_end" : "</form>\n", "_FORM_end" : "</form>\n",
]) ])
); ) + updates;
;
} }
#endif #endif

View File

@ -1,7 +1,8 @@
body.threads,
.Pe { .Pe {
font-family: verdana,helvetica; font-family: verdana,helvetica;
font-weight: bold; /*font-weight: bold;*/
font-size: 9; font-size: 12px;
padding: 44; padding: 44;
background: #333; background: #333;
color: white; color: white;
@ -30,8 +31,12 @@
padding: 4; padding: 4;
margin-bottom: 23px; margin-bottom: 23px;
} }
.ldp { .ldp {
font-size: 9; font-size: 9;
}
.entry,
.ldp {
font-weight: normal; font-weight: normal;
border: 3px dashed #333; border: 3px dashed #333;
background: #933; background: #933;
@ -39,6 +44,7 @@
margin: 44; margin: 44;
width: 562; width: 562;
} }
.entry .title,
.ldpc { .ldpc {
background: #f33; background: #f33;
color: black; color: black;
@ -67,3 +73,32 @@
width: 400; width: 400;
} }
.entry {
margin: 22px 44px;
}
.entry .text {
background: black;
padding: 5px;
}
.entry .title {
display: none;
}
.entry .title .author {}
.entry .title .subject {}
.entry .footer a,
.entry .footer a:visited {
color: white;
background: transparent;
}
.entry .footer a:hover,
.entry .footer a:visited:hover {
text-decoration: underline;
}
.entry .footer .comments {
float: right;
}