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