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
// named clones -lynx
object compile_object(string file) {
P3((">> compile_object(%O)\n", file))
string path, name;
object rob;
@ -383,36 +384,46 @@ object compile_object(string file) {
return rob;
}
# 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 != "") {
#ifdef SANDBOX
string t;
#endif
unless (name = SIMUL_EFUN_FILE->legal_name(name))
unless (name = SIMUL_EFUN_FILE->legal_name(name, 1))
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
if (file_size(t = USER_PATH + name + ".c") != -1) {
rob = t -> sName(name);
D2(if (rob) PP(("USER PLACE loaded: %O becomes %O\n", rob, file));)
} else {
#endif
#ifdef _flag_disable_places_arbitrary
P2(("WARN: cloned places disabled by #define %O\n", file))
return (object)0;
#else
#ifdef _path_archetype_place_default
rob = clone_object(_path_archetype_place_default);
rob = clone_object(_path_archetype_place_default);
#else
rob = clone_object(NET_PATH "place/default");
rob = clone_object(NET_PATH "place/default");
#endif
rob -> sName(name);
D2(if (rob) PP(("PLACE CLONED: %O becomes %O\n", rob, file));)
@ -422,6 +433,15 @@ object compile_object(string file) {
#endif
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 != "") {
rob = clone_object(NET_PATH "text");
rob -> sPath(path);

View File

@ -546,12 +546,13 @@ int boss(mixed guy) {
}
mixed find_place(mixed a) {
P3((">> find_place(%O)\n", a))
string path, err;
object o;
if (objectp(a)) return a;
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
o = find_object(path);
if (o) return o;

View File

@ -2,8 +2,9 @@
#include <net.h>
// legal nickname/placename test..
string legal_name(string n) {
varargs string legal_name(string name, int place) {
int i;
string n = name;
//PT(("legal_name(%O) in %O\n", n, ME))
if (shutdown_in_progress) {
@ -25,17 +26,24 @@ string legal_name(string n) {
P1(("not legal_name: %O has !=- as first char.\n", n))
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\
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",
n, i, n[i]))
return 0;
}
}
return n;
return name;
}
array(string) legal_password(string pw, string nick) {

View File

@ -291,8 +291,8 @@ msgView(source, mc, data, vars, showingLog) {
// t = regreplace(s, ": ", "\", \"", 1);
// if (s == t) return;
if (showingLog == "html")
// 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 = "(<i>%s</i>) <b>%s %s</b>: %s<br/>\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"
fmt = "\t%O, %O, %O, %O,\n";
@ -2614,5 +2614,3 @@ qAide(snicker, aidesonly) {
qOwner(snicker) { return member(v("owners"), lower_case(snicker)); }
#endif

View File

@ -35,11 +35,13 @@ volatile int last_modified;
volatile string webact;
create() {
P3((">> threads:create()\n"))
::create();
unless (pointerp(_thread)) _thread = ({ });
}
cmd(a, args, b, source, vars) {
P3((">> threads:cmd(%O, %O, %O, %O, %O)", a, args, b, source, vars))
// TODO: multiline-sachen irgendwie
mapping entry;
int i = 0;
@ -51,34 +53,73 @@ cmd(a, args, b, source, vars) {
// _thread[<5..]
foreach( entry : _thread[<num_entries..] ) {
sendmsg(source, "_list_thread_item",
// hier auch noch den text?
"([_number]) \"[_thread]\", [_author]",
"#[_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" : i++,
"_nick_place" : MYNICK ]) );
}
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":
unless (sizeof(args) > 2){ // num + thread
unless (sizeof(args) > 2){
sendmsg(source, "_warning_usage_thread",
"Usage: /thread <threadid> <title>", ([ ]));
return 1;
}
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 "submit":
case "addentry":
unless (qAide(SNICKER)) return;
unless (sizeof(args) >= 2) {
unless (sizeof(args) >= 1) {
sendmsg(source, "_warning_usage_submit",
"Usage: /submit <title> <text>", ([ ]));
"Usage: /submit <text>", ([ ]));
return 1;
}
return addEntry(ARGS(2), SNICKER, args[1]);
return addEntry(ARGS(1), SNICKER);
// TODO: append fuer multiline-sachen
#if 0
case "iterator":
@ -111,8 +152,8 @@ cmd(a, args, b, source, vars) {
return ::cmd(a, args, b, source, vars);
}
msg(source, mc, data, mapping vars){
P2(("blog.c's msg: mc %O, source %O\n", mc, source))
msg(source, mc, data, vars){
P3(("thread:msg(%O, %O, %O, %O)", source, mc, data, vars))
// TODO: die source muss hierbei uebereinstimmen mit dem autor
if (abbrev("_notice_authentication", mc)){
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[number] = 0;
save();
return 1;
@ -449,47 +491,61 @@ displayMain(last) {
}
#endif
displayMain(last) {
htMain(last) {
int i;
int len;
string t;
string ht = "";
len = sizeof(_thread);
if (last > len) last = len;
// reverse order
for (i = len-1; i >= len - last; i--) {
P3((">>> _thread[%O]: %O\n", i, _thread[i]))
t = htquote(_thread[i]["text"]);
t = replace(t, "\n", "<br>\n");
write("<table class='newsTable' width='560px'>\n"
"<tr>"
"<td class='newsAuthor' width='20%'>" + _thread[i]["author"] + "</td>"
"<td class='newsTime' nowrap width='20%'>" + _thread[i]["date"] + "</td>"
"<td class='newsSubject' width='60%'>" + htquote(_thread[i]["thread"]) + "</td>"
"</tr>\n"
"<tr>"
"<td colspan='3' class='newsText'>" + t + "</td>"
"</tr>\n"
"<tr>"
"<td colspan='3' class='newsLink'><a href='" + webact + "?comments"
"=" + i + "'>" + sizeof(_thread[i]["comments"]) + " comments</a></td>"
"</tr>\n"
"</table>\n");
t = replace(t, "<", "&lt;");
t = replace(t, ">", "&gt;");
ht += "<div class='entry'>\n"
"<div class='title'>\n"
"<span class='author'>" + _thread[i]["author"] + "</span>\n"
"<span class='subject'>" + htquote(_thread[i]["thread"]) + "</span>\n"
"</div>\n"
"<div class='text'>" + t + "</div>\n"
"<div class='footer'>\n"
"<span class='date'>" + _thread[i]["date"] + "</span>\n"
"<span class='comments'>"
"<a href='" + webact + "?comments=" + i + "'>" + sizeof(_thread[i]["comments"]) + " comments</a>"
"</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) {
mapping item;
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");
}
write(htComments(data));
}
nntpget(cmd, args) {
@ -539,7 +595,7 @@ default:
}
#ifndef STYLESHEET
# define STYLESHEET (v("_uniform_style") || "http://www.psyc.eu/blog.css")
# define STYLESHEET (v("_uniform_style") || "/static/examine.css")
#endif
// wir können zwei strategien fahren.. die technisch einfachere ist es
@ -553,28 +609,10 @@ default:
//
displayHeader() {
w("_HTML_head_threads",
"<link rel='stylesheet' type='text/css' href='"+
STYLESHEET +"'>\n"+
"<style type='text/css'>\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");
"<html><head><link rel='stylesheet' type='text/css' href='"+
STYLESHEET +"'></head>\n"+
"<body class='threads'>\n\n");
}
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
object find_psyc_object(array(mixed) u) {
P3((">> find_psyc_object(%O)\n", u))
string t, r, svc, user;
object o;
@ -131,7 +132,15 @@ object find_psyc_object(array(mixed) u) {
#endif
if (strlen(r)) switch(r[0]) {
case '^':
break;
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;
case '$':
// target wird auf serv/args gesetzt
@ -174,6 +183,7 @@ object find_psyc_object(array(mixed) u) {
o = summon_person(user); //, PSYC_PATH "user");
P2(("%O summoning %O: %O\n", ME, user, o))
}
P3((">>> found psyc object: %O\n", 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=lang value=\""+v("language")+"\">\n\
//
object u = find_place("~" + nick + "#updates");
string updates = objectp(u) ? u->htMain(10) : "";
return psyctext(page, vars + ([
"_FORM_start" : "\
<form class=\"Pef\" name=\"Pef\" action=\"\">\n\
@ -292,7 +296,8 @@ htDescription(anonymous, query, headers, qs, variant, vars) {
"_nick_me" : MYNICK,
"_FORM_end" : "</form>\n",
])
);
) + updates;
;
}
#endif

View File

@ -1,7 +1,8 @@
body.threads,
.Pe {
font-family: verdana,helvetica;
font-weight: bold;
font-size: 9;
/*font-weight: bold;*/
font-size: 12px;
padding: 44;
background: #333;
color: white;
@ -30,8 +31,12 @@
padding: 4;
margin-bottom: 23px;
}
.ldp {
font-size: 9;
}
.entry,
.ldp {
font-weight: normal;
border: 3px dashed #333;
background: #933;
@ -39,6 +44,7 @@
margin: 44;
width: 562;
}
.entry .title,
.ldpc {
background: #f33;
color: black;
@ -67,3 +73,32 @@
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;
}