Added a comma after each msgnum exported. The parser was globbing them all together...
[citadel.git] / ctdlphp / sessionproxy.php
1 #!/usr/bin/php -q
2
3 <?php
4 include "config_ctdlclient.php";
5 // $Id$
6 //
7 // This is the session proxy that binds a unix domain socket to a Citadel
8 // server connection.  We need one of these for each session because PHP does
9 // not have a way to bind a session to a persistent socket.
10 //
11 // Web designers: don't touch this module.  It's not included in your web pages
12 // and therefore you don't need to be here.
13 //
14 // Copyright (c) 2003 by Art Cancro <ajc@uncensored.citadel.org>
15 // This program is released under the terms of the GNU General Public License.
16
17 global $msgsock;
18
19 // sock_gets() -- reads one line of text from a socket
20 // 
21 if (CITADEL_DEBUG_PROXY)
22 {
23         define_syslog_variables();
24         openlog("sessionproxylog", LOG_PID | LOG_PERROR, LOG_LOCAL0);
25 }
26 function sock_gets($sock) {
27         global $msgsock;
28         socket_clear_error($msgsock);
29         $buf = socket_read($sock, 4096, PHP_NORMAL_READ);
30         if (CITADEL_DEBUG_PROXY)
31         {
32                 syslog(LOG_DEBUG, "gets Read: ".$buf);
33         }
34         if (socket_last_error($sock)) return false;
35
36         if (preg_match("'\n$'s", $buf)) {
37                 $buf = substr($buf, 0, strpos($buf, "\n"));
38         }
39
40         return $buf;
41 }
42
43
44
45
46 // *** Start of main program ***
47
48 error_reporting(E_ALL);
49
50 /* Allow the script to hang around waiting for connections. */
51 set_time_limit(0);
52
53 /* Turn on implicit output flushing so we see what we're getting
54  * as it comes in.
55  */
56 ob_implicit_flush();
57
58 if ($argc != 2) {
59         echo "usage: ", $argv[0], " sockname\n";
60         exit(1);
61 }
62
63 $sockname = $argv[1];
64
65 if ($sockname == "/tmp/") {
66         echo "Invalid socket name.\n";
67         exit(1);
68 }
69
70 // If there's a dead socket already there, remove it.
71 system("/bin/rm -f " . $sockname);
72
73 $sock = socket_create(AF_UNIX, SOCK_STREAM, 0);
74 if (!$sock) {
75         echo "socket_create() failed: ", socket_strerror($sock), "\n";
76         system("/bin/rm -f " . $sockname);
77         exit(2);
78 }
79
80 $ret = socket_bind($sock, $sockname);
81 if (!$ret) {
82         echo "socket_bind() failed: ", socket_strerror($ret), "\n";
83         system("/bin/rm -f " . $sockname);
84         exit(3);
85 }
86
87 $ret = socket_listen($sock, 5);
88 if (!$ret) {
89         echo "socket_listen() failed: ", socket_strerror($ret), "\n";
90         system("/bin/rm -f " . $sockname);
91         exit(4);
92 }
93
94 // Set the permissions so someone else doesn't jump into our connection.
95 chmod($sockname, 0600);
96
97 // We need to get a connection to the Citadel server going now.
98
99 $ctdlsock = fsockopen(CITADEL_HOSTNAME, CITADEL_TCP_PORTNO, $errno, $errstr, 30);
100 if (!$ctdlsock) {
101         socket_close ($sock);
102         system("/bin/rm -f " . $sockname);
103         exit(5);
104 }
105
106 // Read the greeting from the Citadel server.
107 if (!$buf = fgets($ctdlsock, 4096)) {
108         socket_close ($sock);
109         system("/bin/rm -f " . $sockname);
110         exit(6);
111 }
112
113 // Make sure the server is allowing logins.
114 if (substr($buf, 0, 1) != "2") {
115         socket_close ($sock);
116         system("/bin/rm -f " . $sockname);
117         exit(7);
118 }
119
120 do {
121         // Wait for connections, but time out after 15 minutes.
122         // socket_select() is completely b0rken in PHP 4.1, which is why
123         // this program requires PHP 4.3 or newer.
124         //
125         if (socket_select($readsock = array($sock),
126                         $writesock = NULL,
127                         $exceptsock = NULL,
128                         900, 0
129         ) == 0) {
130                 // Timing out.
131                 socket_close ($sock);
132                 system("/bin/rm -f " . $sockname);
133                 exit(8);
134         }
135
136         // Ok, there's a valid connection coming in.  Accept it.
137         $msgsock = socket_accept($sock);
138         if ($msgsock >= 0) do {
139                 $buf = sock_gets($msgsock);
140                 if ($buf !== false) {
141 //                      fwrite($logfd, ">>");
142 //                      fwride($logfd, $buf);
143                         if (!fwrite($ctdlsock, $buf . "\n")) {
144                                 fclose($ctdlsock);
145                                 socket_close($sock);
146                                 system("/bin/rm -f " . $sockname);
147                                 exit(9);
148                         }
149                         $talkback = fgets($ctdlsock, 4096);
150                         if (CITADEL_DEBUG_PROXY)
151                         {
152                                 syslog(LOG_DEBUG, "talkback: ".$talkback);
153                         }
154                         if (!$talkback) {
155                                 if (CITADEL_DEBUG_PROXY)
156                                 {
157                                         syslog(LOG_ERROR, "closing socket.");
158                                 }
159                                 fclose($ctdlsock);
160                                 socket_close($sock);
161                                 system("/bin/rm -f " . $sockname);
162                                 exit(10);
163                         }
164                         socket_write($msgsock, $talkback, strlen($talkback));
165
166                         // BINARY_FOLLOWS mode
167                         if (substr($talkback, 0, 1) == "6") {
168                                 $bytes = intval(substr($talkback, 4));
169                                 if (CITADEL_DEBUG_PROXY)
170                                 {
171                                         syslog(LOG_DEBUG, "reading ".$bytes." bytes from server");
172                                 }
173                                 $buf = fread($ctdlsock, $bytes);
174                                 if (CITADEL_DEBUG_PROXY)
175                                 {
176                                         syslog(LOG_DEBUG, "Read: ".$buf);
177                                 }
178                                 socket_write($msgsock, $buf, $bytes);
179                         }
180
181                         // LISTING_FOLLOWS mode
182                         if (substr($talkback, 0, 1) == "1") do {
183                                 $buf = fgets($ctdlsock, 4096);
184                                 if (!$buf) {
185                                         $buf = "000\n" ;
186                                 }
187                                 else {
188                                         socket_write($msgsock, $buf,
189                                                 strlen($buf));
190                                 }
191                         } while ($buf != "000\n");
192
193                         // SEND_LISTING mode
194                         if (substr($talkback, 0, 1) == "4") do {
195                                 socket_clear_error($msgsock);
196                                 $buf = sock_gets($msgsock);
197                                 if (socket_last_error($msgsock)) {
198                                         $buf = "000" ;
199                                 }
200                                 if (!fwrite($ctdlsock, $buf . "\n")) {
201                                         fclose($ctdlsock);
202                                         socket_close($sock);
203                                         system("/bin/rm -f " . $sockname);
204                                         exit(11);
205                                 }
206                         } while ($buf != "000");
207
208                 }
209         } while($buf !== false);
210
211         socket_close ($msgsock);
212
213 } while (true);
214
215 socket_close($sock);
216 fclose($ctdlsock);
217 system("/bin/rm -f " . $sockname);
218 exit(0);
219
220 ?>