2009-01-26 20:12:53 +00:00
|
|
|
|
// vim:foldmethod=marker:syntax=lpc:noexpandtab
|
|
|
|
|
// $Id: common.c,v 1.120 2008/12/16 11:58:52 lynx Exp $
|
2009-01-26 19:21:29 +00:00
|
|
|
|
//
|
|
|
|
|
// common functions for IRC servers and clients (gateways)
|
|
|
|
|
//
|
|
|
|
|
#define MYNICK qName() // common for both server and user
|
|
|
|
|
|
|
|
|
|
#define NO_INHERIT
|
|
|
|
|
#include "irc.h"
|
|
|
|
|
//#include "hack.i"
|
|
|
|
|
#undef NO_INHERIT
|
|
|
|
|
|
|
|
|
|
#include "reply.h"
|
|
|
|
|
#include <strings.h>
|
|
|
|
|
|
|
|
|
|
#include <text.h>
|
|
|
|
|
virtual inherit NET_PATH "output";
|
|
|
|
|
|
|
|
|
|
volatile string prefix;
|
|
|
|
|
|
|
|
|
|
parse(a) {
|
|
|
|
|
string t, from, cmd, args, text;
|
|
|
|
|
|
|
|
|
|
#ifdef _flag_log_sockets_IRC
|
2009-02-25 14:12:44 +00:00
|
|
|
|
log_file("RAW_IRC", "%d %O\t» %s\n", time(), ME, a);
|
2009-01-26 19:21:29 +00:00
|
|
|
|
#endif
|
|
|
|
|
IRCD( D("IRC< '"+a+"'\n"); )
|
|
|
|
|
|
|
|
|
|
// some clients like ircII like to send trailing spaces
|
|
|
|
|
// which may f**k up some parsing. also regular irc servers
|
|
|
|
|
// ignore leading spaces, so should we
|
|
|
|
|
#if __EFUN_DEFINED__(trim)
|
|
|
|
|
//if (a == "") return; // but first make sure there's something at all
|
|
|
|
|
//if (a[<1] == ' ' || a[0] == ' ')
|
|
|
|
|
a = trim(a, TRIM_BOTH);
|
|
|
|
|
// efun probably faster than doing all those checks anyway
|
2009-01-26 20:12:53 +00:00
|
|
|
|
#else //{{{
|
2009-01-26 19:21:29 +00:00
|
|
|
|
// not as efficient as it could be, but we have trim() anyway
|
2009-01-26 20:12:53 +00:00
|
|
|
|
// move this into a pike macro for trim() emulation?
|
2009-01-26 19:21:29 +00:00
|
|
|
|
if (a == "") return; // first make sure there's something at all
|
|
|
|
|
while (a[0] == ' ') a = a[1..];
|
|
|
|
|
while (a[<1] == ' ') a = a[0..<2];
|
2009-01-26 20:12:53 +00:00
|
|
|
|
#endif //}}}
|
2009-01-26 19:21:29 +00:00
|
|
|
|
if (a == "") return; // don't let " \n" execute "/s"
|
|
|
|
|
unless (sscanf(a, ":%s %s", from, t)) t = a;
|
|
|
|
|
sscanf(t, "%s :%s", t, text);
|
2009-03-20 10:47:20 +00:00
|
|
|
|
// when 'text' is not present, the last argument could be a single
|
|
|
|
|
// word text according to rfc. this has never seemed to hurt, but
|
|
|
|
|
// we are not exactly compliant in that sense. we could copy the
|
|
|
|
|
// last arg over into text, but that requires to change the api
|
|
|
|
|
// into explode()-based. WONTFIX
|
2009-01-26 19:21:29 +00:00
|
|
|
|
unless (sscanf(t, "%s %s", cmd, args)) cmd = t;
|
|
|
|
|
if (cmd) ircMsg(from, lower_case(cmd), args, text, a);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ircMsg(from, cmd, args, text, all) {
|
|
|
|
|
mixed t,t1;
|
|
|
|
|
switch(cmd) {
|
|
|
|
|
case "motd":
|
|
|
|
|
motd();
|
|
|
|
|
return 1;
|
2009-03-07 09:36:41 +00:00
|
|
|
|
#ifndef GAMMA
|
2009-01-26 19:21:29 +00:00
|
|
|
|
case "lusers":
|
|
|
|
|
lusers();
|
|
|
|
|
return 1;
|
2009-01-26 20:12:53 +00:00
|
|
|
|
#endif
|
2009-01-26 19:21:29 +00:00
|
|
|
|
case "time":
|
|
|
|
|
t = time();
|
|
|
|
|
t1 = ctime(t);
|
|
|
|
|
write(SERVER_SOURCE "391 " + MYNICK + " " SERVER_HOST " " +
|
|
|
|
|
t + "0 :" + isotime(t1, 0) + " -- " + hhmmss(t1) + "\n");
|
|
|
|
|
return 1;
|
|
|
|
|
case "ping":
|
|
|
|
|
// sieht doof aus scheint aber amtlich zu sein
|
|
|
|
|
// ne isses nich. man ponged, was der user gepinged hat.
|
|
|
|
|
// write(SERVER_SOURCE "PONG " SERVER_HOST " :"+ MYNICK +"\n");
|
|
|
|
|
// eine fantasievolle lösung:
|
|
|
|
|
write(SERVER_SOURCE "PONG " SERVER_HOST " :"
|
|
|
|
|
+( text || args || MYNICK )+"\n");
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
case "quit":
|
|
|
|
|
quit();
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
case "userhost":
|
|
|
|
|
// kleine clientverarsche
|
|
|
|
|
reply(RPL_USERHOST, ":"+args+"=+"+args+"@" SERVER_HOST);
|
|
|
|
|
return 1;
|
|
|
|
|
default:
|
|
|
|
|
// write("421 :Huh?\n");
|
|
|
|
|
// D(S("Unknown IRC: %s\n", all));
|
|
|
|
|
// log_file("IRCPROT", "[%s] %s\n", query_ip_number(), all);
|
|
|
|
|
// return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
motd() {
|
|
|
|
|
string buffer = "";
|
|
|
|
|
// sollte alles in der textdb sein statt den reply hack zu verwenden
|
|
|
|
|
// ist aber leider ein bisschen tragisch, da sich ne motd abprubt ändern
|
|
|
|
|
// können soll... :( - die textdb geht ja eher von statischen inhalten aus.
|
|
|
|
|
// was halt ihr sinn ist.
|
|
|
|
|
//
|
|
|
|
|
// ok, also nicht die statische textdb - aber es gibt ja auch dynamische
|
|
|
|
|
// textdb sachen.. und ausserdem, MOTD sollte doch mehrsprachig sein können!?
|
|
|
|
|
|
|
|
|
|
emit(sreply(RPL_MOTDSTART, ":- " SERVER_HOST " Message of the Day - "));
|
|
|
|
|
|
|
|
|
|
#ifdef MOTD_FILE
|
|
|
|
|
if (file_size(MOTD_FILE) > 0) {
|
|
|
|
|
string motd_file;
|
|
|
|
|
|
|
|
|
|
// wir machen demnäxt noch n anderes define, dann kommts aus der
|
|
|
|
|
// datenbank. hat dann nur immernoch den beieffekt, dass in der datenbank
|
|
|
|
|
// direkt das MOTD-prefix stehen muss, und das werden ungefähr 3 leute
|
|
|
|
|
// wenn überhaupt verwenden, und alle davon aus dem kreis der muve/psycdevs.
|
|
|
|
|
// dummerweise fiel hier im Zuge des neuen emit das '- ' flach - fippo
|
|
|
|
|
P3(("MOTD_FILE (%O) found\n", MOTD_FILE))
|
|
|
|
|
motd_file = read_file(MOTD_FILE);
|
2009-01-26 20:12:53 +00:00
|
|
|
|
P4(("MOTD = %O\n", motd_file))
|
2009-01-26 19:21:29 +00:00
|
|
|
|
emit(sreply(RPL_MOTD, ":" + motd_file));
|
|
|
|
|
} else
|
|
|
|
|
#endif
|
|
|
|
|
emit(sreply(RPL_MOTD, ":- [PSYC] will probably make you happier. http://about.psyc.eu/\n"
|
|
|
|
|
#if 0
|
|
|
|
|
"- We're in public beta testing stage.\n"
|
|
|
|
|
"- Usage manuals and legacy transition help on http://help.pages.de/\n"
|
|
|
|
|
"- \n"
|
|
|
|
|
"- You're the administrator of this server? Save your customized\n"
|
|
|
|
|
#ifdef MOTD_FILE
|
|
|
|
|
"- MOTD to " MOTD_FILE " in psyced's world/ directory."
|
|
|
|
|
#else
|
|
|
|
|
"- MOTD to psyced's world/ directory and add\n"
|
|
|
|
|
"- #define MOTD_FILE \"<filename>\" to your local/local.h"
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
));
|
|
|
|
|
emit(sreply(RPL_ENDOFMOTD, ":End of MOTD command"));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-07 09:36:41 +00:00
|
|
|
|
#ifndef GAMMA
|
2009-01-26 19:21:29 +00:00
|
|
|
|
lusers() {
|
2009-01-26 20:12:53 +00:00
|
|
|
|
# ifndef _flag_disable_query_server
|
2009-01-26 19:21:29 +00:00
|
|
|
|
reply(RPL_LUSERCLIENT, ":There are " + amount_people()
|
2009-01-26 20:12:53 +00:00
|
|
|
|
+ " users on this server");
|
|
|
|
|
# endif
|
2009-01-26 19:21:29 +00:00
|
|
|
|
}
|
2009-01-26 20:12:53 +00:00
|
|
|
|
#endif
|
2009-01-26 19:21:29 +00:00
|
|
|
|
|
|
|
|
|
qCharset() {}
|
|
|
|
|
|
|
|
|
|
render(string mc, string data, mapping vars, mixed source) {
|
|
|
|
|
string template, output;
|
|
|
|
|
mixed t;
|
|
|
|
|
|
2009-01-26 20:12:53 +00:00
|
|
|
|
P3(("common:render %O %O\n", ME, data));
|
2009-01-26 19:21:29 +00:00
|
|
|
|
template = T(mc, 0); // enable textdb inheritance
|
|
|
|
|
#ifndef _flag_disable_stamp_time_IRC
|
|
|
|
|
t = vars["_time_place"] || vars["_time_log"];
|
2009-01-26 20:12:53 +00:00
|
|
|
|
// this goes thru ->v()
|
2009-01-26 19:21:29 +00:00
|
|
|
|
if (t && v("timestamp") != "off" // && abbrev("_message", mc)
|
|
|
|
|
&& stringp(data)) {
|
|
|
|
|
if (v("timestamp") == "on") {
|
|
|
|
|
string msa = " ";
|
|
|
|
|
msa[0] = 0x01; // msa's CTCP character
|
|
|
|
|
// should use psyctime instead of unixtime
|
|
|
|
|
data = msa +"TS "+ (t - PSYC_EPOCH) +msa+ data;
|
|
|
|
|
} else
|
2009-01-26 20:12:53 +00:00
|
|
|
|
data = "["+ time_or_date(t) +"] "+ data; // use T() ?
|
2009-01-26 19:21:29 +00:00
|
|
|
|
P3(("%O data is %O\n", ME, data))
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
P3(("c:r pre ptext: %O %O %O %O\n", template, vars, data, source ));
|
|
|
|
|
output = psyctext( template, vars, data, source);
|
|
|
|
|
P3(("c:r 1st ptext: %O\n", output));
|
|
|
|
|
if (!output || output=="") return D2(D("irc/user: empty output\n"));
|
|
|
|
|
|
2009-01-26 20:12:53 +00:00
|
|
|
|
#ifdef NEW_LINE
|
|
|
|
|
output += "\n";
|
|
|
|
|
#else
|
2009-02-28 19:14:56 +00:00
|
|
|
|
if (template == "") output += "\n";
|
2009-01-26 20:12:53 +00:00
|
|
|
|
#endif
|
|
|
|
|
if (output[0] == '#') output = SERVER_SOURCE + output[1 ..];
|
2009-01-26 19:21:29 +00:00
|
|
|
|
else if (output[0] != ':') {
|
|
|
|
|
string t2;
|
|
|
|
|
|
|
|
|
|
if (prefix) { output = prefix+output; prefix=0; }
|
|
|
|
|
// ich wage es mal hier den raumnamen als ziel auszugeben.
|
|
|
|
|
// wenn das nicht für alle fälle gut ist, dann mit dem
|
|
|
|
|
// if auf _notice_action einschränken. else liegt auch
|
|
|
|
|
// schon bereit. alles klar --lynX
|
|
|
|
|
// if (abbrev("_notice_action", mc)) {
|
|
|
|
|
// output = psyc2irc(mc) +" "+(vars["_nick_place"] ?
|
|
|
|
|
// place2channel(vars["_nick_place"]) : MYNICK)
|
|
|
|
|
// +" :" + output;
|
|
|
|
|
// else
|
|
|
|
|
// output = psyc2irc(mc) +" "+MYNICK+" :" + output;
|
|
|
|
|
|
|
|
|
|
// TODO: in theory, going thru the textdb twice should
|
|
|
|
|
// not be necessary, but it is the most straightforward
|
|
|
|
|
// solution
|
|
|
|
|
t2 = T(mc, data);
|
|
|
|
|
if (template != t2) {
|
|
|
|
|
output = psyctext( t2, vars, data, source) + "\n";
|
|
|
|
|
P3(("c:r 2nd ptext: %O\n", output));
|
|
|
|
|
#if DEBUG > 0
|
|
|
|
|
} else {
|
|
|
|
|
P3(("c:r %O==%O so there is no 2nd ptext for %O.\n"
|
|
|
|
|
"see also render(%O,%O,%O,%O)\n",
|
|
|
|
|
template, t2, output,
|
|
|
|
|
mc, data, vars, source));
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
unless (trail("\n", output)) {
|
|
|
|
|
PT(("(harmless) no IRC template for %O\n", mc))
|
|
|
|
|
log_file("IRC_TEXTDB", "%O\n", mc);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// _silent: when casts from a conversation-filtered place
|
|
|
|
|
// arrive, which isnt known to the client as a channel, we
|
|
|
|
|
// revert to personal notices to not irritate it.
|
|
|
|
|
if (
|
2009-01-26 20:12:53 +00:00
|
|
|
|
#if 1
|
2009-01-26 19:21:29 +00:00
|
|
|
|
// would be nicer to check if source is a place but
|
|
|
|
|
// isn't trivial right here.. looks like joining remote
|
|
|
|
|
// xmpp: mucs is affected by this change - you may not
|
|
|
|
|
// be able to see history. fippo is looking into this.
|
|
|
|
|
// <fippo> i wanted this for the _notice_place_* use case
|
|
|
|
|
// i would propose keeping the old way and adding a
|
|
|
|
|
// condition with _nick_place && abbrev(_notice_place, mc)
|
|
|
|
|
(vars["_nick_place"] || vars["_context"]) &&
|
|
|
|
|
#else
|
|
|
|
|
vars["_context"] && vars["_nick_place"] &&
|
|
|
|
|
#endif
|
|
|
|
|
(vars["_INTERNAL_control"] != "_silent" ||
|
|
|
|
|
v("entersilent") == "off")) {
|
|
|
|
|
P2(("irc/user: psyc2irc channel notice (%O)\n", mc))
|
|
|
|
|
// psyc2irc is called without source||context here so
|
|
|
|
|
// this will be server notices - it is yet to be
|
|
|
|
|
// determined if this is appropriate
|
|
|
|
|
output = psyc2irc(mc, 0) +" "+ // MYNICK+" "+
|
|
|
|
|
place2channel(vars["_nick_place"]) +" :" + output;
|
|
|
|
|
} else {
|
|
|
|
|
//PT(("irc/user: psyc2irc personal notice (%O) with %O\n", mc, vars))
|
|
|
|
|
output = psyc2irc(mc, source) +" "+MYNICK+" :" + output;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#ifdef NO_SMART_MSA
|
|
|
|
|
else {
|
|
|
|
|
// klammern und indent gemacht aus style-gruenden
|
|
|
|
|
for (i=strstr(output, "%"); i>=0; i=strstr(output, "%", i)) {
|
|
|
|
|
output[i] = 0x01; // support for msa's CTCP char
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
// i would really love to do it using the textdb, but it is unflexible.
|
|
|
|
|
// probably i'll change that somewhen.
|
|
|
|
|
if (mc == "_status_place_members_amount") {
|
|
|
|
|
// since irc ALWAYS needs to have a namreply, we
|
|
|
|
|
// simply give it one that only contains ourselves
|
|
|
|
|
w(mc[..<8], 0, ([ "_nick_place" : vars["_nick_place"],
|
2009-03-05 10:42:45 +00:00
|
|
|
|
"_members" : vars["_INTERNAL_nick_me"] ]));
|
2009-01-26 19:21:29 +00:00
|
|
|
|
w(mc[..<8] + "_end", 0, vars);
|
|
|
|
|
}
|
2009-01-26 20:12:53 +00:00
|
|
|
|
P4(("calling emit(%O)\n", output));
|
2009-01-26 19:21:29 +00:00
|
|
|
|
emit(output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// server:w() doesnt call this anyway, so we dont need last_prefix
|
|
|
|
|
//volatile private string last_prefix;
|
|
|
|
|
emit(string output) {
|
2009-01-26 20:12:53 +00:00
|
|
|
|
string* outlines;
|
|
|
|
|
|
|
|
|
|
P3(("common:emit %O %O\n", ME, output));
|
2009-01-26 19:21:29 +00:00
|
|
|
|
// misteries of virtual inheritance.. why doesnt this get called
|
|
|
|
|
// from gatebot? we need to get this working for 512-split!!
|
|
|
|
|
#ifdef _flag_log_sockets_IRC
|
2009-02-25 14:12:44 +00:00
|
|
|
|
# define EMIT(OUT) (log_file("RAW_IRC", "%d %O\t« %s", time(), ME, OUT), ::emit(OUT))
|
2009-01-26 19:21:29 +00:00
|
|
|
|
# else
|
|
|
|
|
# define EMIT ::emit
|
|
|
|
|
#endif
|
|
|
|
|
#if __EFUN_DEFINED__(convert_charset)
|
|
|
|
|
string cs = qCharset();
|
|
|
|
|
if (cs && cs != SYSTEM_CHARSET) {
|
|
|
|
|
iconv(output, SYSTEM_CHARSET, cs);
|
|
|
|
|
P4(("output in %O = %O\n", cs, output))
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2009-01-26 20:12:53 +00:00
|
|
|
|
if (output[<1] != '\n') {
|
|
|
|
|
// this is used when prompting for password
|
|
|
|
|
P4(("irc:emit optimized for prefix on %O\n", output))
|
|
|
|
|
return EMIT(output);
|
|
|
|
|
}
|
|
|
|
|
outlines = explode(slice_from_end(output, 0, 2), "\n");
|
|
|
|
|
if (sizeof(outlines) == 1 && strlen(output) < MAX_IRC_BYTES) {
|
|
|
|
|
// optimized for single line
|
|
|
|
|
P4(("irc:emit single %O\n", outlines[0]))
|
|
|
|
|
return EMIT(outlines[0] + "\r\n");
|
|
|
|
|
} else {
|
2009-01-26 19:21:29 +00:00
|
|
|
|
string split_prefix, line;
|
|
|
|
|
int cut, t;
|
|
|
|
|
|
|
|
|
|
cut = strstr(output, " :");
|
2009-01-26 20:12:53 +00:00
|
|
|
|
P4(("IRC:emit splitting large line at %O\n%O\n", cut, outlines))
|
2009-01-26 19:21:29 +00:00
|
|
|
|
if (cut >= 0) {
|
2009-01-26 20:12:53 +00:00
|
|
|
|
split_prefix = outlines[0][.. ++cut];
|
|
|
|
|
#if 0 // annoying rendering bug we had here.. but is <2 always wrong?
|
|
|
|
|
outlines[0] = outlines[0][++cut .. <2];
|
|
|
|
|
#else
|
|
|
|
|
outlines[0] = outlines[0][++cut .. <1];
|
|
|
|
|
#endif
|
|
|
|
|
if (strlen(outlines[0])
|
|
|
|
|
&& outlines[0][0] == outlines[0][<1]
|
|
|
|
|
&& outlines[0][0] == 0x01) {
|
|
|
|
|
outlines[0] = chop(outlines[0]);
|
2009-01-26 19:21:29 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
split_prefix = ""; //last_prefix;
|
2009-01-26 20:12:53 +00:00
|
|
|
|
outlines[0] = chop(outlines[0]);
|
2009-01-26 19:21:29 +00:00
|
|
|
|
}
|
|
|
|
|
// because of additional \\\r\n we have to subtract 3
|
|
|
|
|
cut = MAX_IRC_BYTES-3 - strlen(split_prefix);
|
|
|
|
|
if (cut < 9) {
|
|
|
|
|
// happens when 005 messages grows too big
|
|
|
|
|
P1(("%O encountered data w/out a decently placed ':' "
|
|
|
|
|
"to be able to do 512 splitting\n%O\n", ME, line))
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-01-26 20:12:53 +00:00
|
|
|
|
foreach(line : outlines) if (strlen(line)) {
|
2009-01-26 19:21:29 +00:00
|
|
|
|
while (strlen(line) > cut) {
|
2011-06-10 06:34:40 +00:00
|
|
|
|
#if 0 //{{{
|
|
|
|
|
// this is supposed to be the more elegant
|
|
|
|
|
// message continuation strategy but it
|
|
|
|
|
// breaks OTR over IRC! thx alice
|
|
|
|
|
//
|
2009-01-26 19:21:29 +00:00
|
|
|
|
// we shall look for last whitespace instead
|
|
|
|
|
t = rindex(line, ' ', cut);
|
|
|
|
|
if (t > 9) {
|
|
|
|
|
// msa's CTCP character
|
|
|
|
|
if (line[0] == 0x01) { // can only be true in
|
|
|
|
|
// the very first cycle.
|
|
|
|
|
// any realistic ideas
|
|
|
|
|
// how to do do this
|
|
|
|
|
// just once?
|
2009-01-26 20:12:53 +00:00
|
|
|
|
P4(("splitting an msa line %O\n", line[.. t]))
|
2009-01-26 19:21:29 +00:00
|
|
|
|
EMIT(split_prefix + line[..t]
|
|
|
|
|
+ line[0..0] + "\r\n");
|
2009-01-26 20:12:53 +00:00
|
|
|
|
line = line[t+1 ..];
|
2009-01-26 19:21:29 +00:00
|
|
|
|
} else {
|
2009-01-26 20:12:53 +00:00
|
|
|
|
P4(("time for %O\n", line[.. t]))
|
|
|
|
|
EMIT(split_prefix + line[.. t]+ "\r\n");
|
|
|
|
|
line = line[t+1 ..];
|
2009-01-26 19:21:29 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
P1(("%O encountered data w/out ' ' to "
|
|
|
|
|
"allow for a decent IRC 512 split:"
|
|
|
|
|
"\n%O\n", ME, line))
|
|
|
|
|
// ignore this junk
|
|
|
|
|
return;
|
|
|
|
|
// we might aswell use the old
|
|
|
|
|
// backslash splitting code below here
|
|
|
|
|
}
|
2011-06-10 06:34:40 +00:00
|
|
|
|
#else //}}}
|
2009-01-26 19:21:29 +00:00
|
|
|
|
t = line[cut] == '\r' ? cut-1 : cut;
|
|
|
|
|
|
|
|
|
|
// msa's CTCP character
|
|
|
|
|
if (line[0] == 0x01) { // can only be true in
|
|
|
|
|
// the very first cycle.
|
|
|
|
|
// any realistic ideas
|
|
|
|
|
// how to do do this
|
|
|
|
|
// only once?
|
|
|
|
|
// inserting stargazer-style backslashes
|
|
|
|
|
EMIT(split_prefix + line[..t-1]
|
|
|
|
|
+ "\\" + line[0..0] + "\r\n");
|
|
|
|
|
line = line[cut..];
|
|
|
|
|
} else {
|
|
|
|
|
EMIT(split_prefix + line[..t]
|
|
|
|
|
+ "\\\r\n");
|
|
|
|
|
line = line[cut+1..];
|
|
|
|
|
}
|
2011-06-10 06:34:40 +00:00
|
|
|
|
#endif
|
2009-01-26 19:21:29 +00:00
|
|
|
|
}
|
2009-01-26 20:12:53 +00:00
|
|
|
|
P4(("irc:emit each %O\n", line))
|
2009-01-26 19:21:29 +00:00
|
|
|
|
EMIT(split_prefix + line +"\r\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internalError() {
|
|
|
|
|
#ifdef RELAY
|
|
|
|
|
// yay. we could "fix" it here by
|
|
|
|
|
next_input_to(#'parse);
|
|
|
|
|
PT(("crazy experimental autofix in internalError()\n"))
|
|
|
|
|
#else
|
|
|
|
|
emit("ERROR :Congratulations! you triggered a runtime error in psyced."
|
|
|
|
|
" This server will no longer accept input until you reconnect.\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|