]> git.stg.codes - stg.git/blob - projects/sgauth/web.cpp
Merge branch 'master' into full-month-stats
[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 "stg/common.h"
32 #include "stg/ia.h"
33 #include "web.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 memset(&ls, 0, sizeof(ls));
71 }
72 //---------------------------------------------------------------------------
73 void WEB::Start()
74 {
75 #ifdef WIN32
76 unsigned long pt;
77 CreateThread(
78     NULL,   // pointer to thread security attributes
79     16384,  // initial thread stack size, in bytes
80     RunWeb, // pointer to thread function
81     NULL,   // argument for new thread
82     0,      // CREATE_SUSPENDED, // creation flags
83     &pt     // pointer to returned thread identifier
84    );
85 #else
86 pthread_create(&thread, NULL, RunWeb, NULL);
87 #endif
88 }
89 //---------------------------------------------------------------------------
90 void WEB::PrepareNet()
91 {
92 listenSocket = socket(PF_INET, SOCK_STREAM, 0);
93
94 struct sockaddr_in listenAddr;
95 listenAddr.sin_family = AF_INET;
96 listenAddr.sin_port = htons(LISTEN_PORT);
97 listenAddr.sin_addr.s_addr = listenWebAddr;
98
99 #ifndef WIN32
100 int lng = 1;
101 if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
102     {
103     printf("Setsockopt Fail\n");
104     printf(">>> Error %s\n", strerror(errno));
105     }
106 #else
107 //??? TODO
108 #endif
109
110
111 res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
112
113 if (res == -1)
114     {
115     printf("Bind failed.\n");
116     exit(0);
117     }
118
119 res = listen(listenSocket, 0);
120 if (res == -1)
121     {
122     printf("Listen failed.\n");
123     exit(0);
124     }
125 }
126 //---------------------------------------------------------------------------
127 void WEB::SetRefreshPagePeriod(int p)
128 {
129 refreshPeriod = p;
130 if (refreshPeriod <= 0 || refreshPeriod > 24*3600)
131     refreshPeriod = 5;
132 }
133 //---------------------------------------------------------------------------
134 void WEB::SetListenAddr(uint32_t ip)
135 {
136 listenWebAddr = ip;
137 }
138 //---------------------------------------------------------------------------
139 void WEB::Run()
140 {
141 PrepareNet();
142 char recvBuffer[4096];
143 while (1)
144     {
145     struct sockaddr_in outerAddr;
146
147     #ifndef WIN32
148     socklen_t outerAddrLen = sizeof(outerAddr);
149     #else
150     int outerAddrLen = sizeof(outerAddr);
151     #endif
152
153     outerSocket = accept(listenSocket, (struct sockaddr*)&outerAddr, &outerAddrLen);
154     if (outerSocket == -1)
155         {
156         printf(">>> Error %s\n", strerror(errno));
157         continue;
158         }
159     recv(outerSocket, recvBuffer, sizeof(recvBuffer), 0);
160
161     if (strncmp(recvBuffer, "GET /sgauth.css", strlen("GET /sgauth.css")) == 0)
162         {
163         SendCSS();
164         //printf("(1) recvBuffer=%s\n", recvBuffer);
165         }
166     else if (strncmp(recvBuffer, "GET /disconnect", strlen("GET /disconnect")) == 0)
167         {
168         clnp->Disconnect();
169         Redirect("/");
170         //printf("(2) recvBuffer=%s\n", recvBuffer);
171         }
172     else if (strncmp(recvBuffer, "GET /connect", strlen("GET /connect")) == 0)
173         {
174         clnp->Connect();
175         Redirect("/");
176         //printf("(3) recvBuffer=%s\n", recvBuffer);
177         }
178     else if (strncmp(recvBuffer, "GET /exit", strlen("GET /exit")) == 0)
179         {
180         Redirect("/");
181         clnp->Disconnect();
182         #ifdef WIN32
183         Sleep(1000);
184         #else
185         usleep(1000000);
186         #endif
187         exit(0);
188         }
189     else
190        {
191        SendReply();
192        //printf("(4) recvBuffer=%s\n", recvBuffer);
193        }
194
195     #ifdef WIN32
196     closesocket(outerSocket);
197     #else
198     close(outerSocket);
199     #endif
200     }
201 }
202 //---------------------------------------------------------------------------
203 int WEB::Redirect(const char * url)
204 {
205 const char * redirect =
206     "HTTP/1.0 200 OK\n"
207     "Content-Type: text/html\n"
208     "Connection: close"
209     "\n\n"
210     "<html>\n"
211     "<head>\n"
212     "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;%s\">\n"
213     "</head>\n"
214     "<body>\n"
215     "</body></html>\n\n";
216
217 char buff[2000];
218 sprintf(buff, redirect, url);
219 send(outerSocket, buff, strlen(buff), 0);
220
221 return 0;
222 }
223 //---------------------------------------------------------------------------
224 int WEB::SendReply()
225 {
226 int j, rowNum;
227
228 const char * replyHeader =
229     "HTTP/1.0 200 OK\n"
230     "Content-Type: text/html\n"
231     "Connection: close"
232     "\n\n"
233     "<html>\n"
234     "<head>\n"
235     "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">\n"
236     "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n"
237     "<title>sgauth</title>\n"
238     "<link rel=\"Stylesheet\" href=\"sgauth.css\">"
239     "</head>\n"
240     "<body>\n"
241     "<H3>Stargazer</H3><p>\n";
242
243 const char * replyFooter = "</body></html>\n\n";
244
245 char replyHeaderBuffer[2000];
246 sprintf(replyHeaderBuffer, replyHeader, refreshPeriod);
247
248 send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0);
249
250 char str[512];
251
252 int st = clnp->GetAuthorized();
253
254 sprintf(str, "<a href=\"connect\">%s</a><p>\n", gettext("Connect"));
255 res = send(outerSocket, str, strlen(str), 0);
256
257 sprintf(str, "<a href=\"disconnect\">%s</a><p>\n", gettext("Disconnect"));
258 res = send(outerSocket, str, strlen(str), 0);
259
260 sprintf(str, "<a href=\"/\">%s</a><p>\n", gettext("Refresh"));
261 res = send(outerSocket, str, strlen(str), 0);
262
263 sprintf(str, "<a href=\"exit\">%s</a><p>\n", gettext("Exit"));
264 res = send(outerSocket, str, strlen(str), 0);
265
266 sprintf(str, "<div id=\"%s\">%s</div><p>\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline");
267 res = send(outerSocket, str, strlen(str), 0);
268
269 sprintf(str, "<div id=\"Cash\">%s: %.3f</div><p>\n" , gettext("Cash"), ls.cash / 1000.0);
270 res = send(outerSocket, str, strlen(str), 0);
271
272 sprintf(str, "<div id=\"Prepaid Traffic\">%s: %s</div><p>\n" ,
273         gettext("PrepaidTraffic"),
274         ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb);
275 res = send(outerSocket, str, strlen(str), 0);
276
277 sprintf(str, "<TABLE id=\"TraffTable\">\n");
278 res = send(outerSocket, str, strlen(str), 0);
279 sprintf(str, "    <TR id=\"TraffTableCaptionRow\">\n");
280 res = send(outerSocket, str, strlen(str), 0);
281 sprintf(str, "       <TD id=\"TraffTableCaptionCellC\">&nbsp;</TD>\n");
282 res = send(outerSocket, str, strlen(str), 0);
283
284 rowNum = 0;
285 for (j = 0; j < DIR_NUM; j++)
286     {
287     if (dirName[j][0] == 0)
288         continue;
289     string s;
290     KOIToWin(dirName[j], &s);// +++++++++ sigsegv ==========   TODO too long dir name crashes sgauth
291     sprintf(str, "       <TD id=\"TraffTableCaptionCell%d\">%s</TD>\n", rowNum++, s.c_str());
292     send(outerSocket, str, strlen(str), 0);
293     }
294
295 sprintf(str,"    </TR>\n");
296 send(outerSocket, str, strlen(str), 0);
297
298 sprintf(str,"    <TR id=\"TraffTableUMRow\">\n");
299 send(outerSocket, str, strlen(str), 0);
300
301 sprintf(str,"        <TD id=\"TraffTableUMCellC\">%s</TD>\n", gettext("Month Upload"));
302 send(outerSocket, str, strlen(str), 0);
303
304 rowNum = 0;
305 for (j = 0; j < DIR_NUM; j++)
306     {
307     if (dirName[j][0] == 0)
308         continue;
309     sprintf(str,"        <TD id=\"TraffTableUMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.mu[j], ST_F));
310     res = send(outerSocket, str, strlen(str), 0);
311     }
312
313 sprintf(str,"    </TR>\n");
314 res = send(outerSocket, str, strlen(str), 0);
315 sprintf(str,"    <TR id=\"TraffTableDMRow\">\n");
316 res = send(outerSocket, str, strlen(str), 0);
317 sprintf(str,"        <TD id=\"TraffTableDMCellC\">%s</TD>\n", gettext("Month Download"));
318 res = send(outerSocket, str, strlen(str), 0);
319
320 rowNum = 0;
321 for (j = 0; j < DIR_NUM; j++)
322     {
323     if (dirName[j][0] == 0)
324         continue;
325     sprintf(str,"        <TD id=\"TraffTableDMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.md[j], ST_F));
326     res = send(outerSocket, str, strlen(str), 0);
327     }
328 sprintf(str,"    </TR>\n");
329 res = send(outerSocket, str, strlen(str), 0);
330
331
332 sprintf(str,"    <TR id=\"TraffTableUSRow\">\n");
333 res = send(outerSocket, str, strlen(str), 0);
334 sprintf(str,"        <TD id=\"TraffTableUSCellC\">%s</TD>\n", gettext("Session Upload"));
335 res = send(outerSocket, str, strlen(str), 0);
336
337 rowNum = 0;
338 for (j = 0; j < DIR_NUM; j++)
339     {
340     if (dirName[j][0] == 0)
341         continue;
342     sprintf(str,"        <TD id=\"TraffTableUSCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.su[j], ST_F));
343     res = send(outerSocket, str, strlen(str), 0);
344     }
345
346 sprintf(str,"    </TR>\n");
347 res = send(outerSocket, str, strlen(str), 0);
348 sprintf(str,"    <TR id=\"TraffTableDSRow\">\n");
349 res = send(outerSocket, str, strlen(str), 0);
350 sprintf(str,"        <TD id=\"TraffTableDSCellC\">%s</TD>\n", gettext("Session Download"));
351 res = send(outerSocket, str, strlen(str), 0);
352
353 rowNum = 0;
354 for (j = 0; j < DIR_NUM; j++)
355     {
356     if (dirName[j][0] == 0)
357         continue;
358     sprintf(str,"        <TD id=\"TraffTableDSCell%d\">%s</TD>\n", j, IntToKMG(ls.sd[j], ST_F));
359     res = send(outerSocket, str, strlen(str), 0);
360     }
361
362 sprintf(str,"    </TR>\n");
363 res = send(outerSocket, str, strlen(str), 0);
364
365 sprintf(str,"</TABLE>\n");
366 res = send(outerSocket, str, strlen(str), 0);
367
368 rowNum = 0;
369 if (!messages.empty())
370     {
371     sprintf(str,"    <TABLE id=\"MessagesTable\">\n");
372     res = send(outerSocket, str, strlen(str), 0);
373
374     sprintf(str,"        <TR id=\"MessagesTableRowC\">\n");
375     send(outerSocket, str, strlen(str), 0);
376     sprintf(str,"            <TD>Date</TD>\n");
377     send(outerSocket, str, strlen(str), 0);
378     sprintf(str,"            <TD>Text</TD>\n");
379     send(outerSocket, str, strlen(str), 0);
380     sprintf(str,"        </TR>\n");
381     send(outerSocket, str, strlen(str), 0);
382
383     list<STG_MESSAGE>::reverse_iterator it;
384     it = messages.rbegin();
385     while (it != messages.rend())
386         {
387         sprintf(str,"        <TR id=\"MessagesTableRow%d\">\n", rowNum);
388         send(outerSocket, str, strlen(str), 0);
389         sprintf(str,"            <TD>%s</TD>\n", it->recvTime.c_str());
390         send(outerSocket, str, strlen(str), 0);
391         sprintf(str,"            <TD>%s</TD>\n", it->msg.c_str());
392         send(outerSocket, str, strlen(str), 0);
393         sprintf(str,"        </TR>\n");
394         send(outerSocket, str, strlen(str), 0);
395         ++it;
396         ++rowNum;
397         }
398
399     sprintf(str,"   </TABLE>\n");
400     res = send(outerSocket, str, strlen(str), 0);
401     }
402
403 time_t t = time(NULL);
404 sprintf(str,"Îáíîâëåíî: %s</b>" , ctime(&t));
405 res = send(outerSocket, str, strlen(str), 0);
406
407 send(outerSocket, replyFooter, strlen(replyFooter), 0);
408
409 return 0;
410 }
411 //---------------------------------------------------------------------------
412 int WEB::SendCSS()
413 {
414 const char * replyHeader =
415     "HTTP/1.0 200 OK\n"
416     "Content-Type: text/css\n"
417     "Connection: close\n\n";
418
419 const char * replyFooter= "\n\n";
420
421 send(outerSocket, replyHeader, strlen(replyHeader), 0);
422 send(outerSocket, css, strlen(css), 0);
423 send(outerSocket, replyFooter, strlen(replyFooter), 0);
424
425 return 0;
426 }
427 //---------------------------------------------------------------------------
428 void WEB::SetDirName(const string & dn, int n)
429 {
430 web->dirName[n] =  dn;
431 }
432 //---------------------------------------------------------------------------
433 void WEB::AddMessage(const string & message, int type)
434 {
435 time_t t = time(NULL);
436 STG_MESSAGE m;
437
438 m.msg = message;
439 m.type = type;
440 m.recvTime = ctime(&t);
441
442 messages.push_back(m);
443
444 if (messages.size() > MAX_MESSAGES)
445     messages.pop_front();
446
447 }
448 //---------------------------------------------------------------------------
449 void WEB::UpdateStat(const LOADSTAT & ls)
450 {
451 memcpy((void*)&(WEB::ls), &ls, sizeof(LOADSTAT));
452 }
453 //---------------------------------------------------------------------------
454