* improved but still wrong
[citadel.git] / ctdlphp / ctdlprotocol.php
1 <?PHP
2
3 // $Id$
4 // 
5 // Implements various Citadel server commands.
6 //
7 // Copyright (c) 2003 by Art Cancro <ajc@uncensored.citadel.org>
8 // This program is released under the terms of the GNU General Public License.
9
10
11 //
12 // serv_gets() -- generic function to read one line of text from the server
13 //
14 function serv_gets() {
15         global $clientsocket;
16
17         $buf = fgets($clientsocket, 4096);              // Read line
18         $buf = substr($buf, 0, (strlen($buf)-1) );      // strip trailing LF
19         return $buf;
20 }
21
22
23 //
24 // serv_puts() -- generic function to write one line of text to the server
25 //
26 function serv_puts($buf) {
27         global $clientsocket;
28         
29         fwrite($clientsocket, $buf . "\n", (strlen($buf)+1) );
30         fflush($clientsocket);
31 }
32
33
34 // 
35 // text_to_server() -- sends a block of text to the server.  Assumes that
36 //                     the server just sent back a SEND_LISTING response code
37 //                     and is now expecting a 000-terminated series of lines.
38 //                     Set 'convert_to_html' to TRUE to convert the block of
39 //                     text to HTML along the way.
40 //
41 function text_to_server($thetext, $convert_to_html) {
42
43
44         $this_line = strtok($thetext, "\n");
45
46         while ($this_line) {
47                 $this_line = trim($this_line, "\n\r");
48                 if ($this_line == "000") $this_line = "-000" ;
49                 serv_puts($this_line);
50                 $this_line = strtok("\n");
51         }
52
53         serv_puts("000");
54         serv_puts("ECHO echo test.");           // FIXME
55         echo "Echo test: " . serv_gets() . "<BR>\n" ;
56
57 }
58
59
60
61 //
62 // Identify ourselves to the Citadel server (do this once after connection)
63 //
64 function ctdl_iden() {
65         global $clientsocket;
66
67         // Identify client and hostname
68         serv_puts("IDEN 0|8|001|PHP web client|" . $_SERVER['REMOTE_ADDR'] );
69         $buf = serv_gets();
70
71         // Also express our message format preferences
72         serv_puts("MSGP text/html|text/plain");
73         $buf = serv_gets();
74 }
75
76
77
78 //
79 // login_existing_user() -- attempt to login using a supplied username/password
80 // Returns an array with two variables:
81 // 0. TRUE or FALSE to determine success or failure
82 // 1. String error message (if relevant)
83 //
84 function login_existing_user($user, $pass) {
85         global $clientsocket;
86
87         serv_puts("USER " . $user);
88         $resp = serv_gets();
89         if (substr($resp, 0, 1) != "3") {
90                 return array(FALSE, substr($resp, 4));
91         }
92
93         serv_puts("PASS " . $pass);
94         $resp = serv_gets();
95         if (substr($resp, 0, 1) != "2") {
96                 return array(FALSE, substr($resp, 4));
97         }
98
99         $_SESSION["username"] = $user;
100         $_SESSION["password"] = $pass;
101         become_logged_in(substr($resp, 4));
102
103         return array(TRUE, "Login successful.  Have fun.");
104 }
105
106
107 //
108 // create_new_user() -- attempt to create a new user 
109 //                      using a supplied username/password
110 // Returns an array with two variables:
111 // 0. TRUE or FALSE to determine success or failure
112 // 1. String error message (if relevant)
113 //
114 function create_new_user($user, $pass) {
115         global $clientsocket;
116
117         serv_puts("NEWU " . $user);
118         $resp = serv_gets();
119         if (substr($resp, 0, 1) != "2") {
120                 return array(FALSE, substr($resp, 4));
121         }
122
123         serv_puts("SETP " . $pass);
124         $resp = serv_gets();
125         if (substr($resp, 0, 1) != "2") {
126                 return array(FALSE, substr($resp, 4));
127         }
128
129         $_SESSION["username"] = $user;
130         $_SESSION["password"] = $pass;
131         become_logged_in(substr($resp, 4));
132
133         return array(TRUE, "Login successful.  Have fun.");
134 }
135
136
137 //
138 // Code common to both existing-user and new-user logins
139 //
140 function become_logged_in($server_parms) {
141         $_SESSION["logged_in"] = 1;
142
143         $tok = strtok($server_parms, "|");
144         if ($tok) $thisline["username"] = $tok;
145
146         $tok = strtok("|");
147         if ($tok) $thisline["axlevel"] = $tok;
148                 
149         $tok = strtok("|");
150         if ($tok) $thisline["calls"] = $tok;
151                 
152         $tok = strtok("|");
153         if ($tok) $thisline["posts"] = $tok;
154                 
155         $tok = strtok("|");
156         if ($tok) $thisline["userflags"] = $tok;
157                 
158         $tok = strtok("|");
159         if ($tok) $thisline["usernum"] = $tok;
160                 
161         $tok = strtok("|");
162         if ($tok) $thisline["lastcall"] = $tok;
163                 
164         ctdl_goto("_BASEROOM_");
165 }
166
167
168
169 //
170 // Learn all sorts of interesting things about the Citadel server to
171 // which we are connected.
172 //
173 function ctdl_get_serv_info() {
174         serv_puts("INFO");
175         $buf = serv_gets();
176         if (substr($buf, 0, 1) == "1") {
177                 $i = 0;
178                 do {
179                         $buf = serv_gets();
180                         if ($i == 1) $_SESSION["serv_nodename"] = $buf;
181                         if ($i == 2) $_SESSION["serv_humannode"] = $buf;
182                         if ($i == 3) $_SESSION["serv_fqdn"] = $buf;
183                         if ($i == 4) $_SESSION["serv_software"] = $buf;
184                         if ($i == 6) $_SESSION["serv_city"] = $buf;
185                         if ($i == 7) $_SESSION["serv_sysadmin"] = $buf;
186                         $i = $i + 1;
187                 } while (strcasecmp($buf, "000"));
188         }
189
190 }
191
192
193 //
194 // Display a system banner.  (Returns completed HTML.)
195 // (This is probably temporary because it outputs more or less finalized
196 // markup.  For now it's just usable.)
197 //
198 function ctdl_mesg($msgname) {
199         global $clientsocket;
200
201         $msgtext = "<DIV ALIGN=CENTER>\n";
202
203         serv_puts("MESG " . $msgname);
204         $response = serv_gets();
205
206         if (substr($response, 0, 1) == "1") {
207                 while (strcmp($buf = serv_gets(), "000")) {
208                         $msgtext .= "<TT>" . htmlspecialchars($buf)
209                                 . "</TT><BR>\n" ;
210                 }
211         }
212         else {
213                 $msgtext .= "<B><I>" . substr($response, 4) . "</I></B><BR>\n";
214         }
215
216         $msgtext .= "</DIV>\n";
217         return($msgtext);
218 }
219
220
221 //
222 // Fetch the list of users currently logged in.
223 //
224 function ctdl_rwho() {
225         global $clientsocket;
226
227         serv_puts("RWHO");
228         $response = serv_gets();
229
230         if (substr($response, 0, 1) != "1") {
231                 return array(0, NULL);
232         }
233         
234         $all_lines = array();
235         $num_lines = 0;
236
237         while (strcmp($buf = serv_gets(), "000")) {
238
239                 $thisline = array();
240
241                 $tok = strtok($buf, "|");
242                 if ($tok) $thisline["session"] = $tok;
243
244                 $tok = strtok("|");
245                 if ($tok) $thisline["user"] = $tok;
246                 
247                 $tok = strtok("|");
248                 if ($tok) $thisline["room"] = $tok;
249                 
250                 $tok = strtok("|");
251                 if ($tok) $thisline["host"] = $tok;
252                 
253                 $tok = strtok("|");
254                 if ($tok) $thisline["client"] = $tok;
255
256                 // IGnore the rest of the fields for now.
257
258                 $num_lines = array_push($all_lines, $thisline);
259         }
260
261         return array($num_lines, $all_lines);
262
263 }
264
265
266 //
267 // Goto a room.
268 //
269 function ctdl_goto($to_where) {
270         
271         serv_puts("GOTO " . $to_where);
272         $response = serv_gets();
273
274         if (substr($response, 0, 1) == "2") {
275                 $_SESSION["room"] = strtok(substr($response, 4), "|");
276                 return array(TRUE, substr($response, 0, 3));
277         }
278
279         else {
280                 return array(FALSE, substr($response, 0, 3));
281         }
282
283 }
284
285
286
287 //
288 // Fetch the list of known rooms.
289 //
290 function ctdl_knrooms() {
291         global $clientsocket;
292
293         serv_puts("LKRA");
294         $response = serv_gets();
295
296         if (substr($response, 0, 1) != "1") {
297                 return array(0, NULL);
298         }
299         
300         $all_lines = array();
301         $num_lines = 0;
302
303         while (strcmp($buf = serv_gets(), "000")) {
304
305                 $thisline = array();
306
307                 $tok = strtok($buf, "|");
308                 if ($tok) $thisline["name"] = $tok;
309
310                 $tok = strtok("|");
311                 if ($tok) $thisline["flags"] = $tok;
312                 
313                 $tok = strtok("|");
314                 if ($tok) $thisline["floor"] = $tok;
315                 
316                 $tok = strtok("|");
317                 if ($tok) $thisline["order"] = $tok;
318                 
319                 $tok = strtok("|");
320                 if ($tok) $thisline["flags2"] = $tok;
321
322                 $tok = strtok("|");
323                 if ($tok) $thisline["access"] = $tok;
324
325                 if ($thisline["access"] & 8) {
326                         $thisline["hasnewmsgs"] = TRUE;
327                 }
328                 else {
329                         $thisline["hasnewmsgs"] = FALSE;
330                 }
331
332                 $num_lines = array_push($all_lines, $thisline);
333         }
334
335         return array($num_lines, $all_lines);
336
337 }
338
339
340 //
341 // Fetch the list of messages in this room.
342 // Returns: count, response, message array
343 //
344 function ctdl_msgs($mode, $count) {
345         global $clientsocket;
346
347         serv_puts("MSGS " . $mode . "|" . $count);
348         $response = serv_gets();
349
350         if (substr($response, 0, 1) != "1") {
351                 return array(0, substr($response, 4), NULL);
352         }
353         
354         $msgs = array();
355         $num_msgs = 0;
356
357         while (strcmp($buf = serv_gets(), "000")) {
358                 $num_msgs = array_push($msgs, $buf);
359         }
360
361         return array($num_msgs, substr($response, 4), $msgs);
362 }
363
364
365 // Load a message from the server.
366 function ctdl_fetch_message($msgnum) {
367         global $clientsocket;
368
369         serv_puts("MSG4 " . $msgnum);
370         $response = serv_gets();
371
372         if (substr($response, 0, 1) != "1") {
373                 return array(FALSE, substr($response, 4), NULL);
374         }
375
376         $fields = array();
377         while (strcmp($buf = serv_gets(), "000")) {
378                 if (substr($buf, 0, 4) == "text") {
379                         // We're in the text body.  New loop here.
380                         $fields["text"] = ctdl_msg4_from_server();
381                         return array(TRUE, substr($response, 4), $fields);
382                 }
383                 else {
384                         $fields[substr($buf, 0, 4)] = substr($buf, 5);
385                 }
386         }
387
388         // Message terminated prematurely (no text body)
389         return array(FALSE, substr($response, 4), $fields);
390 }
391
392 // Support function for ctdl_fetch_message().  This handles the text body
393 // portion of the message, converting various formats to HTML as
394 // appropriate.
395 function ctdl_msg4_from_server() {
396
397         $txt = "";
398         $msgformat = "text/plain";
399         $in_body = FALSE;
400
401         $previous_line = "";
402         while (strcmp($buf = serv_gets(), "000")) {
403                 if ($in_body == FALSE) {
404                         if (strlen($buf) == 0) {
405                                 $in_body = TRUE;
406                         }
407                         else {
408                                 if (!strncasecmp($buf, "content-type: ", 14)) {
409                                         $msgformat = substr($buf, 14);
410                                 }
411                         }
412                 }
413                 else {
414                         if (!strcasecmp($msgformat, "text/html")) {
415                                 $txt .= $buf;
416                         }
417                         else if (!strcasecmp($msgformat, "text/plain")) {
418                                 $txt .= "<TT>" . htmlspecialchars($buf) . "</TT><BR>\n" ;
419                         }
420                         else if (!strcasecmp($msgformat, "text/x-citadel-variformat")) {
421                                 if (substr($previous_line, 0, 1) == " ") {
422                                         $txt .= "<BR>\n" ;
423                                 }
424                                 $txt .= htmlspecialchars($buf);
425                         }
426                         else {
427                                 $txt .= htmlspecialchars($buf);
428                         }
429                         $previous_line = $buf;
430                 }
431         }
432
433         return($txt);
434 }
435
436
437 ?>