Author: dylan
Date: 2004-07-26 16:34:30 -0400 (Mon, 26 Jul 2004)
New Revision: 329

Added:
   branches/protocol-v4/docs/manual/haver.bib
Modified:
   branches/protocol-v4/docs/manual/chap/concepts.tex
   branches/protocol-v4/docs/manual/chap/introduction.tex
   branches/protocol-v4/docs/manual/chap/protocol.tex
   branches/protocol-v4/docs/manual/haver.tex
   branches/protocol-v4/jarverd/lib/Jarver/Connection.pm
   branches/protocol-v4/main/server/lib/Haver/Server/Object.pm
   branches/protocol-v4/main/server/lib/Haver/Server/POE/Commands.pm
   branches/protocol-v4/main/server/lib/Haver/Server/POE/Connection.pm
Log:
Commiting various changes so I can work on it with my laptop.


Modified: branches/protocol-v4/docs/manual/chap/concepts.tex
===================================================================
--- branches/protocol-v4/docs/manual/chap/concepts.tex  2004-07-25 00:35:49 UTC 
(rev 328)
+++ branches/protocol-v4/docs/manual/chap/concepts.tex  2004-07-26 20:34:30 UTC 
(rev 329)
@@ -1,6 +1,18 @@
 
 \chapter{Concepts}
 
+WRITE SUMMARY HERE.
+
+
+\section{Object Data}
+
+Describe per-object data. e.g. channel topics,
+nicknames, away messages...
+
+\section{User IDs Are Not Nicks}
+
+UIDs are not nicknames...
+
 WRITE ME.
 
 

Modified: branches/protocol-v4/docs/manual/chap/introduction.tex
===================================================================
--- branches/protocol-v4/docs/manual/chap/introduction.tex      2004-07-25 
00:35:49 UTC (rev 328)
+++ branches/protocol-v4/docs/manual/chap/introduction.tex      2004-07-26 
20:34:30 UTC (rev 329)
@@ -20,16 +20,16 @@
 There are several different types of clients, and each may have access to 
special features
 of the server.
 
-Each client of a given type (which is its namespace) must have a unique id. 
That is to say,
-each type and id combination must be unique.
+Each client of a given type (which is its namespace) must have a unique ID. 
That is to say,
+each type and ID combination must be unique.
 
-The format of identifiers and namespaces is defined in 
Section~\ref{sec:format.id}.
+The format of identifiers and namespaces is defined in 
Section~\ref{protocol.format.id}.
 
 \subsection{Users}
 
 The vast majority of clients will be representations of users.
 Users are the chatters of the network.
-They may be real people, bots, or GreenReaper.
+They may be real people or bots.
 
 Users may or may not require authorization, depending
 on if the user is registered or not.
@@ -41,19 +41,16 @@
 Services add new protocol commands to the server,
 and will typically require some form of authorization.
 
-\subsubsection{Agents}
-
 Services may produce virtual user-like entities to interact with
-users. These are called agents, and are rather like privileged bots.
+the real users. These are called agents, and are rather like privileged bots.
 
 % cross-ref: Authoriztion.
 
-
 \section{Channels}
 
 Channels are collections of users, much like in IRC,
 except they must be created by a server admin or by some other controlled 
means.
-Channel ids (cids) follow the same rules as identifiers for client objects
-as defined in section~\ref{sec:format.id}.
+Channel IDs (cids) follow the same rules as identifiers for client objects
+as defined in section~\ref{protocol.format.id}.
 
 

Modified: branches/protocol-v4/docs/manual/chap/protocol.tex
===================================================================
--- branches/protocol-v4/docs/manual/chap/protocol.tex  2004-07-25 00:35:49 UTC 
(rev 328)
+++ branches/protocol-v4/docs/manual/chap/protocol.tex  2004-07-26 20:34:30 UTC 
(rev 329)
@@ -14,7 +14,7 @@
 have special meaning. CR (Carriage Return) followed by LF (Line Feed)
 terminates a line. Each line is subdivided into tokens separated by Tabs.
 Esc is used for encoding literal CR, LF, Tab, and Esc characters.
-See Section~\ref{sec:esc} for details on escaping.
+See Section~\ref{protocol.parse.esc} for details on escaping.
 
 \begin{table}
 \caption{Special Characters}
@@ -28,17 +28,17 @@
 \end{tabular}
 \end{table}
 
-\subsection{Lines}
+       \subsection{Lines}
 
-Lines are terminated by the sequence CR LF,
-which is a carriage return followed by a line feed.
-A carriage return not followed by a line feed is illegal,
-as is a line feed not preceded with a carriage return.
-The previous sentence may be ignored for simplicity.
+       Lines are terminated by the sequence CR LF,
+       which is a carriage return followed by a line feed.
+       A carriage return not followed by a line feed is illegal,
+       as is a line feed not preceded with a carriage return.
+       The previous sentence may be ignored for simplicity.
 
-Most programming languages have a fairly easy
-way of reading lines from sockets. In perl,
-the \function{readline} function should do.
+       Most programming languages have a fairly easy
+       way of reading lines from sockets. In perl,
+       the \function{readline} function should do.
 
        \subsection{Lists}
 
@@ -51,7 +51,7 @@
        \function{g\_strsplit} function, as well.
 
        \subsection{Escaping and Unescaping}
-       \label{sec:esc}
+       \label{protocol.parse.esc}
 
        Escape sequences are used to encode ``CR'', ``LF'', ``Tab'', and 
``Esc'' (as defined
        in Table~\ref{tab:chars}) as ``Esc r'', ``Esc n'', ``Esc t'', and ``Esc 
e''
@@ -82,6 +82,7 @@
        TODO. WRITE ME.
 
 \section{Formats}
+\label{protocol.format}
 
 This section describes formats used in the haver protocol,
 such as how dates, times, and time zones are formatted.
@@ -89,19 +90,22 @@
 
 \subsection{Dates and Times}
 
-Haver dates are
+Time stamps are written as either ``Date Time'' or ``Date Time Timezone'',
+where the format of Date, Time, and Timezone is as defined in 
Table~\ref{tab:format.time}.
 
+Further explaination is given in the following subsections.
+
 \begin{table}
 \caption{Timestamp formats}
 \label{tab:format.time}
-\begin{tabular}{|l|l|} \hline
-Symbolic Name & Perl Regex & Example\\
+\begin{tabular}{|l|l|l|} \hline
+Name & Perl Regex & Example \\
 \hline
-\emph{Date}  & \verb!/\d{4}-\d{2}-\d{2}/! & 1985-09-14 \\
+Date  & \verb!/\d{4}-\d{2}-\d{2}/! & 1985-09-14 \\
 \hline
-\emph{Time}  & \verb!/\d{2}:\d{2}:\d{2}(\.\d+)?/! & 01:18:14 \\
+Time  & \verb!/\d{2}:\d{2}:\d{2}(\.\d+)?/! & 01:18:14 \\
 \hline
-\emph{Timezone} & \verb!/[+-]\d{2}\d{2}/! & -0400 \\
+Timezone & \verb!/[+-]\d{2}\d{2}/! & -0400 \\
 \hline
 \end{tabular}
 \end{table}
@@ -110,8 +114,6 @@
 which is June 6th, 1944 at half past noon (and 41 seconds...) in the UTC + 1
 time zone.
 
-
-
 \subsubsection{Dates}
 Dates are expressed as YYYY-MM-DD, which MM and DD are zero-padded if 
necessary.
 For example would be 1985-09-14.
@@ -120,9 +122,9 @@
 \subsubsection{Times}
 Time is expressed as HH:MM:SS, where the hour ranges from 00 to 23,
 the minute and second range from 00 to 59.
-A period (``.'') me be appended to SS to express any fractional part of a 
second.
+A period (``.'') followed by up to six digits may be appended to SS to
+express any fractional part of a second.
 
-
 \subsubsection{Time Zones}
 
 All times are assumed to be in UTC unless a different time zone is specified.
@@ -130,35 +132,50 @@
 HH the hour offset and MM is the minute offset. For example, Eastern Daylight 
Time is
 -0400.
 
+\subsection{Identifiers, Namespaces and Commands}
+\label{protocol.format.id}
 
-\subsection{Identifiers and Namespaces}
-\label{sec:format.id}
-
 This section describes the various naming convention for
 objects such as channels, users, and services within a haver server.
 
-\subsubsection{Identifiers}
+The form of identifiers, namespaces and commands is defined
+in Table~\ref{tab:id}, and explained in greater detail in the following 
subsections.
 
-Identifiers may begin with an optional ampersand or dollar sign,
-and must then be followed (or start with in the first place) a lower-case 
letter,
-and then must be followed by at least one lower case letter, number,
-underscore, single quote, hyphen or at symbol.
+\begin{table}
+\caption{IDs, Namespaces and Commands}
+\label{tab:id}
+\begin{tabular}{|l|l|} \hline
+Name      & Perl Regex \\
+\hline
+IDs       & \verb!/&?[A-Za-z][A-Za-z0-9_.'@-]+/! \\
+\hline
+Namespace & \verb!/[a-z]+/! \\
+\hline
+Command  & \verb!/[A-Z][A-Z:_-]+/! \\
+\hline
+\end{tabular}
+\end{table}
 
-All identifiers that begin with either an ampersand or dollar sign,
-or that contain the at symbol, are reserved for the server and for services
-with appropriate authority.
 
 
-\verb!/[&$]?[a-z][a-z0-9_'@-]+/!
+\subsubsection{Identifiers}
 
-A user client will not be allowed to login with user ids that fail to match 
\verb!/[a-z][a-z0-9_'-]+/!,
-nor create channel ids fail to match the same.
+Each channel, user, and service is identified with a unique string
+characters, and this is called the identifier, or ID.
+Identifiers (henceforth refered to as IDs) may be prefixed with an ampersand,
+must begin with a letter, and must be followed by one or more of: letters;
+numbers; periods; hyphens; underscores; single quotes; or the ``at'' symbol.
+All other characters constitute an illegal ID.
 
+
 \subsubsection{Namespaces}
 
-Namespaces are used to separate the identifiers for different types of things,
-so that, for example, there may be a channel named joe and a user named joe.
-Namespaces are composed of only lower case letters.
+Name spaces must contain one or more lower-case letters,
+and may contain no other character.
 
+\subsubsection{Commands}
 
-\verb!/[a-z]+/!
+The commands to and from the server must begin with an upper case
+letter and may be followed by one or more of upper case letters, the 
underscore, hyphens, or the colon.
+Commands containing any other characters will be considered illegal.
+

Added: branches/protocol-v4/docs/manual/haver.bib
===================================================================
--- branches/protocol-v4/docs/manual/haver.bib  2004-07-25 00:35:49 UTC (rev 
328)
+++ branches/protocol-v4/docs/manual/haver.bib  2004-07-26 20:34:30 UTC (rev 
329)
@@ -0,0 +1,18 @@
+
[EMAIL PROTECTED](rfc:1459,
+       TITLE = {RFC 1459},
+       HOWPUBLISHED = {\url{http://www.irchelp.org/irchelp/text/rfc1459.txt}},
+       AUTHOR = { Unknown },
+)
+
[EMAIL PROTECTED](silc,
+       TITLE = {SILC net},
+       HOWPUBLISHED = {\url{http://silcnet.org/}},
+       AUTHOR = { Unknown },
+)
+
[EMAIL PROTECTED](jabber,
+       TITLE = {Extensible Messaging and Presence Protocol},
+       HOWPUBLISHED = 
{\url{http://www.ietf.org/html.charters/xmpp-charter.html}},
+       AUTHOR = { Unknown },
+)              

Modified: branches/protocol-v4/docs/manual/haver.tex
===================================================================
--- branches/protocol-v4/docs/manual/haver.tex  2004-07-25 00:35:49 UTC (rev 
328)
+++ branches/protocol-v4/docs/manual/haver.tex  2004-07-26 20:34:30 UTC (rev 
329)
@@ -29,7 +29,7 @@
 
 \include{chap/introduction}
 \include{chap/protocol}
-\include{chap/concepts}
+\include{chap/commands}
 
 \bibliographystyle{plain}
 \bibliography{haver}

Modified: branches/protocol-v4/jarverd/lib/Jarver/Connection.pm
===================================================================
--- branches/protocol-v4/jarverd/lib/Jarver/Connection.pm       2004-07-25 
00:35:49 UTC (rev 328)
+++ branches/protocol-v4/jarverd/lib/Jarver/Connection.pm       2004-07-26 
20:34:30 UTC (rev 329)
@@ -62,8 +62,6 @@
                                haver_error
                                cmd_WANT
                                cmd_ACCEPT
-                               cmd_IN
-                               cmd_OF
                                cmd_JOIN
                                cmd_MSG
                                cmd_USERS
@@ -72,6 +70,9 @@
                                cmd_PART
                                cmd_MARK
                                cmd_INFO
+                               cmd_LINFO
+                               cmd_PMSG
+                               cmd_FAIL
                        )],
                ],
                heap => {
@@ -132,11 +133,11 @@
                $heap->{channel} = $1;
                $heap->{haver}->put(['JOIN', $1]);
        } elsif (/^Hc$/ or /^Hc\t(.+)$/) {
-               $heap->{haver}->put(['IN', $1 || $heap->{channel}, 'USERS']);
+               $heap->{haver}->put(['USERS', $1 || $heap->{channel}]);
        } elsif (/^Hb$/) {
                $heap->{haver}->put(['CHANS']);
        } elsif (/^Ha$/) {
-               $heap->{haver}->put(['USERS']);
+               $heap->{haver}->put(['USERS', '*']);
        } elsif (/^E(.+)$/) {
                my $msg = $1;
                my $kind;
@@ -145,24 +146,30 @@
                } else {
                        $kind = '"';
                }
-               $heap->{haver}->put(['IN', $heap->{channel}, 'MSG', $kind, 
$msg]);
+               $heap->{haver}->put(['MSG', $heap->{channel}, $kind, $msg]);
        } elsif (/^F([^\t]+)\t(.+)$/) {
                my $to = $1;
                my $msg = $2;
+               my $omsg = $msg;
                my $kind;
                if ($msg =~ s/^\.me //) {
                        $kind = ':';
                } else {
                        $kind = '"';
                }
-               $heap->{haver}->put(['TO', $to, 'MSG', $kind, $msg]);
-               $heap->{jrc}->put(join("\t", "F$heap->{name}", $to, $msg.'F'));
+               $heap->{haver}->put(['PMSG', $to, $kind, $msg]);
+               $heap->{jrc}->put(join("\t", "F$heap->{name}", $to, $omsg.'F'));
        } elsif (/^\^(.+)\t(.+)$/) {
-               my ($type, $data) = ($1, $2);
+               my ($mark, $data) = ($1, $2);
                if ($data =~ /^Ic$/) {
-                       $heap->{haver}->put(['MARK', $type, 'TO', '*', 'IN', 
$heap->{channel}, 'INFO']);
+                       $heap->{haver}->put(
+                               [
+                                       'MARK', $mark, 
+                                       'LINFO', $heap->{channel}, '*'
+                               ]
+                       );
                } elsif ($data =~ /^Ia\t?(.+)$/) {
-                       $heap->{haver}->put(['MARK', $type, 'TO', $1, 'IN', 
$heap->{channel}, 'INFO']);
+                       $heap->{haver}->put(['MARK', $mark, 'INFO', 'user', 
$1]);
                } else {
                        $kernel->post('Logger', 'error', "Unknown whois: 
$data");
                }
@@ -186,7 +193,8 @@
                "Socket generated $operation error ${errnum}: $errstr");
 
        $heap->{jrc} = undef;
-       $kernel->yield('cleanup', 'DISCON');
+       $kernel->yield('shutdown', 'DISCON');
+       eval { $heap->{haver}->put(['BYE']) };
 }
 
 
@@ -227,7 +235,7 @@
        # Connecting Internet domain socket.
        my $wheel = POE::Wheel::SocketFactory->new(
                RemoteAddress  => "localhost",       # Sets the connect() addre
-               RemotePort     => "7071",          # Sets the connect() port
+               RemotePort     => "7070",          # Sets the connect() port
                SuccessEvent   => 'haver_connect',      # Event to emit on 
connection
                FailureEvent   => 'haver_fail',      # Event to emit on error
        );
@@ -258,6 +266,7 @@
                ErrorEvent   => 'haver_error',
        );
 
+       $wheel->put(['HAVER', $heap->{version}]);
        $heap->{haver} = $wheel;
 }
 
@@ -283,52 +292,29 @@
        my ($kernel, $heap, $operation, $errnum, $errstr) = @_[KERNEL, HEAP, 
ARG0..ARG3];
 
        $kernel->post('Logger', 'error', 
-               "Socket generated $operation error ${errnum}: $errstr");
+               "Haver socket generated $operation error ${errnum}: $errstr");
 
        $heap->{haver} = undef;
-       $kernel->yield('cleanup', 'DISCON');
+       $kernel->yield('shutdown', 'DISCON');
+       eval { $heap->{jrc}->put('wCLost haver connectionw') };
 }
 
-sub cmd_IN {
-       my ($kernel, $heap, $args) = @_[KERNEL,HEAP,ARG0];
-       my ($in, $event, @rest) = @$args;
-       my $cmd   = "cmd_$event";
-
-
-       print "Calling $cmd...\n";
-       $heap->{in} = $in;
-       $kernel->call($_[SESSION], $cmd, [EMAIL PROTECTED]);
-       $heap->{in} = undef;
-}
-
 sub cmd_MARK {
        my ($kernel, $heap, $args) = @_[KERNEL,HEAP,ARG0];
        my ($mark, $event, @rest) = @$args;
        my $cmd   = "cmd_$event";
 
 
-       print "Calling $cmd...\n";
        $heap->{mark} = $mark;
        $kernel->call($_[SESSION], $cmd, [EMAIL PROTECTED]);
        $heap->{mark} = undef;
 }
 
-sub cmd_OF {
-       my ($kernel, $heap, $args) = @_[KERNEL,HEAP,ARG0];
-       my ($of, $event, @rest) = @$args;
-       my $cmd   = "cmd_$event";
-
-
-       print "Calling $cmd...\n";
-       $heap->{of} = $of;
-       $kernel->call($_[SESSION], $cmd, [EMAIL PROTECTED]);
-       $heap->{of} = undef;
-}
-
 sub cmd_JOIN {
        my ($kernel, $heap, $args) = @_[KERNEL,HEAP,ARG0];
+       my ($cid, $uid) = @$args;
 
-       eval { $heap->{jrc}->put('D'.$heap->{of}."\t".$heap->{in}.'D') };
+       eval { $heap->{jrc}->put('D'.$uid."\t".$cid.'D') };
 }
 
 sub cmd_WANT {
@@ -336,7 +322,7 @@
        my $want = shift @$args;
 
        if ($want eq 'IDENT') {
-               $heap->{haver}->put(['IDENT', $heap->{name}, 'user', "Jarver + 
$heap->{version}"]);
+               $heap->{haver}->put(['IDENT', $heap->{name}]);
        } else {
                $heap->{haver}->put(['CANT', $want]);
        }
@@ -351,7 +337,7 @@
 
 sub cmd_MSG {
        my ($kernel, $heap, $args) = @_[KERNEL,HEAP,ARG0];
-       my ($type, $msg) = @$args;
+       my ($cid, $uid, $type, $msg) = @$args;
 
        if ($type eq ':') {
                $msg = ".me $msg";
@@ -361,18 +347,30 @@
                return;
        }
 
-       if ($heap->{in}) {
-               $heap->{jrc}->put('E'.$heap->{of}."\t".$msg.'E');
-       } else {
-               $heap->{jrc}->put('F'.$heap->{of}."\t".$msg.'F');
+       $heap->{jrc}->put('E'.$uid."\t".$msg.'E');
+}
+
+sub cmd_PMSG {
+       my ($kernel, $heap, $args) = @_[KERNEL,HEAP,ARG0];
+       my ($uid, $type, $msg) = @$args;
+
+       if ($type eq ':') {
+               $msg = ".me $msg";
        }
+
+       if ($type ne '"' && $type ne ':') {
+               return;
+       }
+
+       $heap->{jrc}->put('F'.$uid."\t".$msg.'F');
 }
 
 sub cmd_USERS {
        my ($kernel, $heap, $args) = @_[KERNEL,HEAP,ARG0];
+       my $cid = shift @$args;
 
-       if ($heap->{in}) {
-               $heap->{jrc}->put('H'.$heap->{name}."\tc$heap->{in}\t" . 
join("\t", @$args) . 'H');
+       if ($cid ne '*') {
+               $heap->{jrc}->put('H'.$heap->{name}."\tc$cid\t" . join("\t", 
@$args) . 'H');
        } else {
                $heap->{jrc}->put('H'.$heap->{name}."\ta".join("\t", @$args) . 
'H');
        }
@@ -385,17 +383,20 @@
 
 sub cmd_QUIT {
        my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
-       $heap->{jrc}->put('C'.$heap->{of}."\t".$heap->{channel}.'C');
+       my $uid = shift @$args;
+       $heap->{jrc}->put('C'.$uid."\t".$heap->{channel}.'C');
 }
 
 sub cmd_PART {
        my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
-       $heap->{jrc}->put('C'.$heap->{of}."\t".$heap->{in}.'C');
+       my ($cid, $uid) = $args;
+       $heap->{jrc}->put('C'.$uid."\t".$cid.'C');
 }
 
 sub cmd_INFO {
        my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
-       my $msg = "^$heap->{name}\t$heap->{mark}\tIa$heap->{of}\t";
+       my ($type, $id) = splice(@$args, 0, 2);
+       my $msg = "^$heap->{name}\t$heap->{mark}\tIa$id\t";
        my %hash = @$args;
        $hash{Access} = delete($hash{Role}) . "\t" . delete($hash{Rank});
        
@@ -407,6 +408,46 @@
        $heap->{jrc}->put($msg);
 }
 
+sub cmd_LINFO {
+       my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
+       my ($cid, $uid) = splice(@$args, 0, 2);
+       my $msg = "^$heap->{name}\t$heap->{mark}\tIa$uid\t";
+       my %hash = @$args;
+       $hash{Access} = delete($hash{Role}) . "\t" . delete($hash{Rank});
+       
+       foreach my $key (keys %hash) {
+               $msg .= "$key\cB$hash{$key}\cC";
+       }
+       $msg .= "\cD^";
 
+       $heap->{jrc}->put($msg);
+}
+
+sub cmd_FAIL {
+       my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
+       my ($cmd, $err, @args) = @$args;
+
+       if ($cmd eq 'IDENT') {
+               if ($err eq 'used' or $err eq 'reserved') {
+                       $heap->{jrc}->put("xAName in usex");
+               } elsif ($err eq 'syntax') {
+                       $heap->{jrc}->put("xASyntax errorx");
+               }
+               $heap->{jrc}->put('wCw');
+               $heap->{haver}->put(['BYE']);
+               $kernel->yield('shutdown');
+       } elsif ($cmd eq 'PMSG') {
+               if ($err eq 'notfound.uid' or $err eq 'syntax.uid') {
+                       $heap->{jrc}->put("xya$args[0]x");
+               }
+       } elsif ($cmd eq 'JOIN') {
+               if ($err eq 'notfound.cid') {
+                       $heap->{jrc}->put("xyb$args[0]x");
+               } elsif ($err eq 'syntax.cid') {
+                       $heap->{jrc}->put("xzb$args[0]x");
+               }
+       }
+}
+
 1;
 

Modified: branches/protocol-v4/main/server/lib/Haver/Server/Object.pm
===================================================================
--- branches/protocol-v4/main/server/lib/Haver/Server/Object.pm 2004-07-25 
00:35:49 UTC (rev 328)
+++ branches/protocol-v4/main/server/lib/Haver/Server/Object.pm 2004-07-26 
20:34:30 UTC (rev 329)
@@ -85,6 +85,7 @@
        $me->SUPER::initialize();
 
        $me->{_fields}  = {};
+       $me->{_loc}     = {};
        $me->{id}       ||= $ID++;
 
        my @ns = @{ (delete $me->{namespaces}) || [] };
@@ -135,6 +136,14 @@
        }
 }
 
+sub lset {
+       my ($me, $loc, @set) = @_;
+       
+       while (my ($k,$v) = splice(@set, 0, 2)) {
+               $me->{_loc}{$loc}{$k} = $v;
+       }
+}
+
 sub get {
        my ($me, @keys) = @_;
 
@@ -150,6 +159,20 @@
        return wantarray ? @values : [EMAIL PROTECTED] ;
 }
 
+sub lget {
+       my ($me, $loc, @keys) = @_;
+
+       if (@keys <= 1) {
+               return _val($me->{_loc}{$loc}{$keys[0]}, $me);
+       }
+       my @values;
+       
+       foreach my $key (@keys) {
+               push(@values, _val($me->{_loc}{$loc}{$key}, $me));
+       }
+
+       return wantarray ? @values : [EMAIL PROTECTED] ;
+}
 sub _val {
        return $_[0] if not ref $_[0];
        
@@ -263,7 +286,6 @@
 
 
 
-
 sub has_namespace {
        my ($me, $ns) = @_;
        return exists $me->{".$ns"};
@@ -273,7 +295,11 @@
        my ($this, $uid) = @_;
 
        if (defined $uid && $uid =~ /^$IdPattern$/) {
-               return 1;
+               if (length($uid) > 2 and length($uid) < 20) {
+                       return 1;
+               } else {
+                       return 0;
+               }
        } else {
                return 0;
        }

Modified: branches/protocol-v4/main/server/lib/Haver/Server/POE/Commands.pm
===================================================================
--- branches/protocol-v4/main/server/lib/Haver/Server/POE/Commands.pm   
2004-07-25 00:35:49 UTC (rev 328)
+++ branches/protocol-v4/main/server/lib/Haver/Server/POE/Commands.pm   
2004-07-26 20:34:30 UTC (rev 329)
@@ -42,8 +42,10 @@
        JOIN PART BYE
        HAVER
        INFO
+       LINFO
        MARK
-       FOREACH
+       USERS
+       CHANS
 );
 
 
@@ -213,8 +215,8 @@
 #> C: MSG $cid $type @args
 #> S: MSG $cid $uid $type @args
 #> Errors:
-#>     * syntax   -- the cid %1 is invalid.
-#>     * notfound -- the cid %1 was not found.
+#>     * syntax.cid   -- the cid %1 is invalid.
+#>     * notfound.cid -- the cid %1 was not found.
 sub cmd_MSG {
        my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
        my ($cid, $type) = (shift @$args, shift @$args);
@@ -231,8 +233,8 @@
 #> C: PMSG $uid $type @args
 #> S: PMSG $uid $type @args
 #> Errors:
-#>     * syntax   -- the uid %1 is invalid.
-#>     * notfound -- the uid %1 was not found.
+#>     * syntax.uid   -- the uid %1 is invalid.
+#>     * notfound.uid -- the uid %1 was not found.
 sub cmd_PMSG {
        my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
        my $uid = shift @$args;
@@ -247,8 +249,8 @@
 #> C: JOIN $cid
 #> S: JOIN $cid $uid
 #> Errors:
-#>     * notfound -- the cid %1 was not found.
-#>     * syntax   -- the cid %1 is invalid.
+#>     * notfound.cid -- the cid %1 was not found.
+#>     * syntax.cid   -- the cid %1 is invalid.
 #>     * joined   -- tried to join %1 while already in it.
 sub cmd_JOIN {
        my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
@@ -271,8 +273,8 @@
 #> C: PART $cid
 #> S: PART $cid $uid
 #> Errors:
-#>     * notfound -- the cid %1 was not found.
-#>     * syntax   -- the cid %1 is invalid.
+#>     * notfound.cid -- the cid %1 was not found.
+#>     * syntax.cid   -- the cid %1 is invalid.
 #>     * timetravel -- you tried to part %1 before you joined it...
 sub cmd_PART {
        my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
@@ -302,7 +304,7 @@
 }
 
 #> [INFO]
-#> C: INFO $type $id
+#> C: INFO $id
 #> S: INFO $type $id (list of key value pairs)
 #> Errors:
 #>     * notfound -- the id %1 of type %2 was not found.
@@ -317,41 +319,50 @@
        $heap->{socket}->put([EMAIL PROTECTED]);
 }
 
-
-#> [FOREACH]
-#> C: FOREACH type cid @subcmd
-#> S: ...
-sub cmd_FOREACH {
+#> [LINFO]
+#> C: LINFO $cid $uid
+#> S: LINFO $cid $uid (key-value pairs)
+#> Errors:
+#>     * notfound.cid -- the cid %1 was not found.
+#>     * notfound.uid -- the uid %1 was not found.
+#>     * syntax.cid   -- the cid %1 is invalid.
+#>     * syntax.uid   -- the uid %1 is invalid.
+sub cmd_LINFO {
        my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
-       my ($type, $cid, $cmd) = splice(@$args, 0, 3);
-       my $chan = check_cid($cid, 'FOREACH');
+       my ($cid, $uid) = @$args;
+       my $chan = check_cid($cid, 'LINFO') or return;
+       my @m = $heap->{scope}{mark} ? ('MARK', $heap->{scope}{mark}) : ();
+       if ($uid ne '*') {
+               my $user = check_uid($uid, 'LINFO') or return;
+               my @keys = @{ $user->get('_info') };
+               my @out = (@m, 'LINFO', $cid, $uid, map { ($_ => 
$user->get($_)) } @keys);
 
-       if ($cmd ne 'INFO') {
-               $kernel->yield('fail', 'FOREACH', 'forbidden', $cmd);
-               return;
+               $heap->{socket}->put([EMAIL PROTECTED]);
+       } else {
+               foreach my $user ($chan->contents('user')) {
+                       my @keys = @{ $user->get('_info') };
+                       my @out = (@m, 'LINFO', $cid, $user->id, map { ($_ => 
$user->get($_)) } @keys);
+                       $heap->{socket}->put([EMAIL PROTECTED]);
+               }
        }
-       foreach my $obj ($chan->contents($type)) {
-               my @args = map {
-                       if ($_ eq '%id%') {
-                               $obj->id;
-                       } else {
-                               $_;
-                       }
-               } @$args;
-               $kernel->post($_[SESSION], "cmd_$cmd", [EMAIL PROTECTED]);
-       }
 }
+       
 
+sub err {
+       my ($s, $d) = @_;
+       
+       return $d ? "$s.$d" : $s;
+}
 
 sub check_id {
-       my ($type, $id, $cmd) = @_;
+       my ($type, $id, $cmd, $d) = @_;
        
        unless (Haver::Server::Object->is_valid_id($id)) {
-               $poe_kernel->yield('fail', $cmd, 'syntax', [$id]);
+               $poe_kernel->yield('fail', $cmd, err('syntax', $d), [$id]);
                return undef;
        }
        unless ($Registry->contains($type, $id)) {
-               $poe_kernel->yield('fail', $cmd, 'notfound', [$id]);
+               $poe_kernel->yield('fail', $cmd, err('notfound', $d), [$id]);
                return undef;
        }
 
@@ -361,13 +372,13 @@
 sub check_cid {
        my ($id, $cmd) = @_;
 
-       check_id('channel', $id, $cmd);
+       check_id('channel', $id, $cmd, 'cid');
 }
 
 sub check_uid {
        my ($id, $cmd) = @_;
 
-       check_id('user', $id, $cmd);
+       check_id('user', $id, $cmd, 'uid');
 }
 
 1;

Modified: branches/protocol-v4/main/server/lib/Haver/Server/POE/Connection.pm
===================================================================
--- branches/protocol-v4/main/server/lib/Haver/Server/POE/Connection.pm 
2004-07-25 00:35:49 UTC (rev 328)
+++ branches/protocol-v4/main/server/lib/Haver/Server/POE/Connection.pm 
2004-07-26 20:34:30 UTC (rev 329)
@@ -211,7 +211,7 @@
        my ($kernel, $heap, $session, @args) = @_[KERNEL, HEAP, SESSION, ARG0 
.. $#_];
        return if $heap->{shutdown};
 
-       $heap->{socket}->put(['BYE', @args]);
+       eval { $heap->{socket}->put(['BYE', @args]) };
        $heap->{shutdown} = 1;
        $kernel->yield('cleanup', @args);
 }


Reply via email to