]> git.stg.codes - stg.git/blob - projects/sgauth/web.cpp
Fix group for file database
[stg.git] / projects / sgauth / web.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  */
20
21  /*
22  $Revision: 1.7 $
23  $Date: 2010/03/15 12:58:17 $
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <time.h>
29 #include <libintl.h>
30
31 #include "web.h"
32 #include "common.h"
33 #include "ia_auth_c.h"
34
35 extern WEB * web;
36 extern IA_CLIENT_PROT * clnp;
37
38 #define LISTEN_PORT (5580)
39
40 #include "css.h"
41
42 //---------------------------------------------------------------------------
43 #ifndef WIN32
44 void * RunWeb(void *)
45 #else
46 unsigned long WINAPI RunWeb(void *)
47 #endif
48 {
49 while (1)
50     web->Run();
51 return NULL;
52 }
53 //---------------------------------------------------------------------------
54 WEB::WEB()
55     : res(0),
56       listenSocket(0),
57       outerSocket(0),
58       refreshPeriod(0),
59       listenWebAddr(0)
60 {
61 #ifdef WIN32
62 res = WSAStartup(MAKEWORD(2,0), &wsaData);
63 #endif
64
65 for (int i = 0; i < DIR_NUM; i++)
66     dirName[i] = "-";
67
68 refreshPeriod = 5;
69 }
70 //---------------------------------------------------------------------------
71 void WEB::Start()
72 {
73 #ifdef WIN32
74 unsigned long pt;
75 CreateThread(
76     NULL,   // pointer to thread security attributes
77     16384,  // initial thread stack size, in bytes
78     RunWeb, // pointer to thread function
79     NULL,   // argument for new thread
80     0,      // CREATE_SUSPENDED, // creation flags
81     &pt     // pointer to returned thread identifier
82    );
83 #else
84 pthread_create(&thread, NULL, RunWeb, NULL);
85 #endif
86 }
87 //---------------------------------------------------------------------------
88 void WEB::PrepareNet()
89 {
90 listenSocket = socket(PF_INET, SOCK_STREAM, 0);
91
92 struct sockaddr_in listenAddr;
93 listenAddr.sin_family = AF_INET;
94 listenAddr.sin_port = htons(LISTEN_PORT);
95 listenAddr.sin_addr.s_addr = listenWebAddr;
96
97 #ifndef WIN32
98 int lng = 1;
99 if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
100     {
101     printf("Setsockopt Fail\n");
102     printf(">>> Error %s\n", strerror(errno));
103     }
104 #else
105 //??? TODO
106 #endif
107
108
109 res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
110
111 if (res == -1)
112     {
113     printf("Bind failed.\n");
114     exit(0);
115     }
116
117 res = listen(listenSocket, 0);
118 if (res == -1)
119     {
120     printf("Listen failed.\n");
121     exit(0);
122     }
123 }
124 //---------------------------------------------------------------------------
125 void WEB::SetRefreshPagePeriod(int p)
126 {
127 refreshPeriod = p;
128 if (refreshPeriod <= 0 || refreshPeriod > 24*3600)
129     refreshPeriod = 5;
130 }
131 //---------------------------------------------------------------------------
132 void WEB::SetListenAddr(uint32_t ip)
133 {
134 listenWebAddr = ip;
135 }
136 //---------------------------------------------------------------------------
137 void WEB::Run()
138 {
139 PrepareNet();
140 char recvBuffer[4096];
141 while (1)
142     {
143     struct sockaddr_in outerAddr;
144
145     #ifndef WIN32
146     socklen_t outerAddrLen = sizeof(outerAddr);
147     #else
148     int outerAddrLen = sizeof(outerAddr);
149     #endif
150
151     outerSocket = accept(listenSocket, (struct sockaddr*)&outerAddr, &outerAddrLen);
152     if (outerSocket == -1)
153         {
154         printf(">>> Error %s\n", strerror(errno));
155         continue;
156         }
157     recv(outerSocket, recvBuffer, sizeof(recvBuffer), 0);
158
159     if (strncmp(recvBuffer, "GET /sgauth.css", strlen("GET /sgauth.css")) == 0)
160         {
161         SendCSS();
162         //printf("(1) recvBuffer=%s\n", recvBuffer);
163         }
164     else if (strncmp(recvBuffer, "GET /disconnect", strlen("GET /disconnect")) == 0)
165         {
166         clnp->Disconnect();
167         Redirect("/");
168         //printf("(2) recvBuffer=%s\n", recvBuffer);
169         }
170     else if (strncmp(recvBuffer, "GET /connect", strlen("GET /connect")) == 0)
171         {
172         clnp->Connect();
173         Redirect("/");
174         //printf("(3) recvBuffer=%s\n", recvBuffer);
175         }
176     else if (strncmp(recvBuffer, "GET /exit", strlen("GET /exit")) == 0)
177         {
178         Redirect("/");
179         clnp->Disconnect();
180         #ifdef WIN32
181         Sleep(1000);
182         #else
183         usleep(1000000);
184         #endif
185         exit(0);
186         }
187     else
188        {
189        SendReply();
190        //printf("(4) recvBuffer=%s\n", recvBuffer);
191        }
192
193     #ifdef WIN32
194     closesocket(outerSocket);
195     #else
196     close(outerSocket);
197     #endif
198     }
199 }
200 //---------------------------------------------------------------------------
201 int WEB::Redirect(const char * url)
202 {
203 const char * redirect =
204     "HTTP/1.0 200 OK\n"
205     "Content-Type: text/html\n"
206     "Connection: close"
207     "\n\n"
208     "<html>\n"
209     "<head>\n"
210     "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;%s\">\n"
211     "</head>\n"
212     "<body>\n"
213     "</body></html>\n\n";
214
215 char buff[2000];
216 sprintf(buff, redirect, url);
217 send(outerSocket, buff, strlen(buff), 0);
218
219 return 0;
220 }
221 //---------------------------------------------------------------------------
222 int WEB::SendReply()
223 {
224 int j, rowNum;
225
226 const char * replyHeader =
227     "HTTP/1.0 200 OK\n"
228     "Content-Type: text/html\n"
229     "Connection: close"
230     "\n\n"
231     "<html>\n"
232     "<head>\n"
233     "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">\n"
234     "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n"
235     "<title>sgauth</title>\n"
236     "<link rel=\"Stylesheet\" href=\"sgauth.css\">"
237     "</head>\n"
238     "<body>\n"
239     "<H3>Stargazer</H3><p>\n";
240
241 const char * replyFooter = "</body></html>\n\n";
242
243 char replyHeaderBuffer[2000];
244 sprintf(replyHeaderBuffer, replyHeader, refreshPeriod);
245
246 send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0);
247
248 char str[512];
249
250 int st = clnp->GetAuthorized();
251
252 sprintf(str, "<a href=\"connect\">%s</a><p>\n", gettext("Connect"));
253 res = send(outerSocket, str, strlen(str), 0);
254
255 sprintf(str, "<a href=\"disconnect\">%s</a><p>\n", gettext("Disconnect"));
256 res = send(outerSocket, str, strlen(str), 0);
257
258 sprintf(str, "<a href=\"/\">%s</a><p>\n", gettext("Refresh"));
259 res = send(outerSocket, str, strlen(str), 0);
260
261 sprintf(str, "<a href=\"exit\">%s</a><p>\n", gettext("Exit"));
262 res = send(outerSocket, str, strlen(str), 0);
263
264 sprintf(str, "<div id=\"%s\">%s</div><p>\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline");
265 res = send(outerSocket, str, strlen(str), 0);
266
267 sprintf(str, "<div id=\"Cash\">%s: %.3f</div><p>\n" , gettext("Cash"), ls.cash / 1000.0);
268 res = send(outerSocket, str, strlen(str), 0);
269
270 sprintf(str, "<div id=\"Prepaid Traffic\">%s: %s</div><p>\n" ,
271         gettext("PrepaidTraffic"),
272         ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb);
273 res = send(outerSocket, str, strlen(str), 0);
274
275 sprintf(str, "<TABLE id=\"TraffTable\">\n");
276 res = send(outerSocket, str, strlen(str), 0);
277 sprintf(str, "    <TR id=\"TraffTableCaptionRow\">\n");
278 res = send(outerSocket, str, strlen(str), 0);
279 sprintf(str, "       <TD id=\"TraffTableCaptionCellC\">&nbsp;</TD>\n");
280 res = send(outerSocket, str, strlen(str), 0);
281
282 rowNum = 0;
283 for (j = 0; j < DIR_NUM; j++)
284     {
285     if (dirName[j][0] == 0)
286         continue;
287     string s;
288     KOIToWin(dirName[j], &s);// +++++++++ sigsegv ==========   TODO too long dir name crashes sgauth
289     sprintf(str, "       <TD id=\"TraffTableCaptionCell%d\">%s</TD>\n", rowNum++, s.c_str());
290     send(outerSocket, str, strlen(str), 0);
291     }
292
293 sprintf(str,"    </TR>\n");
294 send(outerSocket, str, strlen(str), 0);
295
296 sprintf(str,"    <TR id=\"TraffTableUMRow\">\n");
297 send(outerSocket, str, strlen(str), 0);
298
299 sprintf(str,"        <TD id=\"TraffTableUMCellC\">%s</TD>\n", gettext("Month Upload"));
300 send(outerSocket, str, strlen(str), 0);
301
302 rowNum = 0;
303 for (j = 0; j < DIR_NUM; j++)
304     {
305     if (dirName[j][0] == 0)
306         continue;
307     sprintf(str,"        <TD id=\"TraffTableUMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.mu[j], ST_F));
308     res = send(outerSocket, str, strlen(str), 0);
309     }
310
311 sprintf(str,"    </TR>\n");
312 res = send(outerSocket, str, strlen(str), 0);
313 sprintf(str,"    <TR id=\"TraffTableDMRow\">\n");
314 res = send(outerSocket, str, strlen(str), 0);
315 sprintf(str,"        <TD id=\"TraffTableDMCellC\">%s</TD>\n", gettext("Month Download"));
316 res = send(outerSocket, str, strlen(str), 0);
317
318 rowNum = 0;
319 for (j = 0; j < DIR_NUM; j++)
320     {
321     if (dirName[j][0] == 0)
322         continue;
323     sprintf(str,"        <TD id=\"TraffTableDMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.md[j], ST_F));
324     res = send(outerSocket, str, strlen(str), 0);
325     }
326 sprintf(str,"    </TR>\n");
327 res = send(outerSocket, str, strlen(str), 0);
328
329
330 sprintf(str,"    <TR id=\"TraffTableUSRow\">\n");
331 res = send(outerSocket, str, strlen(str), 0);
332 sprintf(str,"        <TD id=\"TraffTableUSCellC\">%s</TD>\n", gettext("Session Upload"));
333 res = send(outerSocket, str, strlen(str), 0);
334
335 rowNum = 0;
336 for (j = 0; j < DIR_NUM; j++)
337     {
338     if (dirName[j][0] == 0)
339         continue;
340     sprintf(str,"        <TD id=\"TraffTableUSCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.su[j], ST_F));
341     res = send(outerSocket, str, strlen(str), 0);
342     }
343
344 sprintf(str,"    </TR>\n");
345 res = send(outerSocket, str, strlen(str), 0);
346 sprintf(str,"    <TR id=\"TraffTableDSRow\">\n");
347 res = send(outerSocket, str, strlen(str), 0);
348 sprintf(str,"        <TD id=\"TraffTableDSCellC\">%s</TD>\n", gettext("Session Download"));
349 res = send(outerSocket, str, strlen(str), 0);
350
351 rowNum = 0;
352 for (j = 0; j < DIR_NUM; j++)
353     {
354     if (dirName[j][0] == 0)
355         continue;
356     sprintf(str,"        <TD id=\"TraffTableDSCell%d\">%s</TD>\n", j, IntToKMG(ls.sd[j], ST_F));
357     res = send(outerSocket, str, strlen(str), 0);
358     }
359
360 sprintf(str,"    </TR>\n");
361 res = send(outerSocket, str, strlen(str), 0);
362
363 sprintf(str,"</TABLE>\n");
364 res = send(outerSocket, str, strlen(str), 0);
365
366 rowNum = 0;
367 if (!messages.empty())
368     {
369     sprintf(str,"    <TABLE id=\"MessagesTable\">\n");
370     res = send(outerSocket, str, strlen(str), 0);
371
372     sprintf(str,"        <TR id=\"MessagesTableRowC\">\n");
373     send(outerSocket, str, strlen(str), 0);
374     sprintf(str,"            <TD>Date</TD>\n");
375     send(outerSocket, str, strlen(str), 0);
376     sprintf(str,"            <TD>Text</TD>\n");
377     send(outerSocket, str, strlen(str), 0);
378     sprintf(str,"        </TR>\n");
379     send(outerSocket, str, strlen(str), 0);
380
381     list<STG_MESSAGE>::reverse_iterator it;
382     it = messages.rbegin();
383     while (it != messages.rend())
384         {
385         sprintf(str,"        <TR id=\"MessagesTableRow%d\">\n", rowNum);
386         send(outerSocket, str, strlen(str), 0);
387         sprintf(str,"            <TD>%s</TD>\n", it->recvTime.c_str());
388         send(outerSocket, str, strlen(str), 0);
389         sprintf(str,"            <TD>%s</TD>\n", it->msg.c_str());
390         send(outerSocket, str, strlen(str), 0);
391         sprintf(str,"        </TR>\n");
392         send(outerSocket, str, strlen(str), 0);
393         ++it;
394         ++rowNum;
395         }
396
397     sprintf(str,"   </TABLE>\n");
398     res = send(outerSocket, str, strlen(str), 0);
399     }
400
401 time_t t = time(NULL);
402 sprintf(str,"Îáíîâëåíî: %s</b>" , ctime(&t));
403 res = send(outerSocket, str, strlen(str), 0);
404
405 send(outerSocket, replyFooter, strlen(replyFooter), 0);
406
407 return 0;
408 }
409 //---------------------------------------------------------------------------
410 int WEB::SendCSS()
411 {
412 const char * replyHeader =
413     "HTTP/1.0 200 OK\n"
414     "Content-Type: text/css\n"
415     "Connection: close\n\n";
416
417 const char * replyFooter= "\n\n";
418
419 send(outerSocket, replyHeader, strlen(replyHeader), 0);
420 send(outerSocket, css, strlen(css), 0);
421 send(outerSocket, replyFooter, strlen(replyFooter), 0);
422
423 return 0;
424 }
425 //---------------------------------------------------------------------------
426 void WEB::SetDirName(const string & dn, int n)
427 {
428 web->dirName[n] =  dn;
429 }
430 //---------------------------------------------------------------------------
431 void WEB::AddMessage(const string & message, int type)
432 {
433 time_t t = time(NULL);
434 STG_MESSAGE m;
435
436 m.msg = message;
437 m.type = type;
438 m.recvTime = ctime(&t);
439
440 messages.push_back(m);
441
442 if (messages.size() > MAX_MESSAGES)
443     messages.pop_front();
444
445 }
446 //---------------------------------------------------------------------------
447 void WEB::UpdateStat(const LOADSTAT & ls)
448 {
449 memcpy((void*)&(WEB::ls), &ls, sizeof(LOADSTAT));
450 }
451 //---------------------------------------------------------------------------
452