]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/userstat/datathread.cpp
Merge branch 'log-unauth-reasons' into full-month-stats
[stg.git] / projects / stargazer / plugins / other / userstat / datathread.cpp
1 #include "datathread.h"
2
3 DataThread::DataThread()
4         : tid(-1),
5           users(NULL),
6           store(NULL),
7           sock(-1),
8           done(true),
9           pvList(NULL),
10           data(NULL),
11           dataSize(0)
12 {
13 xmlParser = XML_ParserCreate(NULL);
14 if (!xmlParser)
15     {
16     printfd(__FILE__, "DataThread::DataThread() Failed to create parser\n");
17     return;
18     }
19 XML_SetElementHandler(xmlParser, DTXMLStart, DTXMLEnd);
20 }
21
22 DataThread::~DataThread()
23 {
24 XML_ParserFree(xmlParser);
25 }
26
27 bool DataThread::Handle(int s)
28 {
29 if (users == NULL)
30     {
31     printfd(__FILE__, "DataThread::Handle() Users not set\n");
32     return false;
33     }
34 if (store == NULL)
35     {
36     printfd(__FILE__, "DataThread::Handle() Storage not set\n");
37     return false;
38     }
39
40 sock = s;
41
42 if (pthread_create(&tid, NULL, Run, this))
43     {
44     printfd(__FILE__, "DataThread::Handle() Failed to create thread\n");
45     return false;
46     }
47 if (pthread_detach(tid))
48     {
49     printfd(__FILE__, "DataThread::Handle() Cannot detach the thread\n");
50     }
51 return true;
52 }
53
54 void * DataThread::Run(void * self)
55 {
56 DataThread * dt = reinterpret_cast<DataThread *>(self);
57
58 dt->done = false;
59
60 if (dt->ReadRequest())
61     {
62     if (dt->DecodeRequest())
63         {
64         if (dt->ParseRequest())
65             {
66             if (dt->MakeAnswer())
67                 {
68                 printfd(__FILE__, "DataThread::Run() All done\n");
69                 }
70             else
71                 {
72                 printfd(__FILE__, "DataThread::Run() Failed to answer the request\n");
73                 }
74             }
75         else
76             {
77             printfd(__FILE__, "DataThread::Run() Cannot parse the request\n");
78             }
79         }
80     else
81         {
82         printfd(__FILE__, "DataThread::Run() Cannot decode the request\n");
83         }
84     }
85 else
86     {
87     printfd(__FILE__, "DataThread::Run() Cannot read the request\n");
88     }
89
90 dt->Cleanup();
91
92 return NULL;
93 }
94
95 bool DataThread::ReadRequest()
96 {
97 int32_t size;
98 char * buf;
99
100 int res = read(sock, &size, sizeof(size));
101 if (res != sizeof(size))
102     {
103     printfd(__FILE__, "DataThread::ReadRequest() Reading login size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
104     done = true;
105     return false;
106     }
107
108 if (size < 0)
109     {
110     printfd(__FILE__, "DataThread::ReadRequest() Invalid login size.\n");
111     done = true;
112     return false;
113     }
114
115 buf = new char[size];
116
117 res = read(sock, buf, size);
118 if (res != size)
119     {
120     printfd(__FILE__, "DataThread::ReadRequest() Reading login failed! Wanted %d bytes, got %d bytes.\n", size, res);
121     delete[] buf;
122     done = true;
123     return false;
124     }
125
126 login.assign(buf, size);
127 delete[] buf;
128
129 res = read(sock, &size, sizeof(size));
130 if (res != sizeof(size))
131     {
132     printfd(__FILE__, "DataThread::ReadRequest() Reading request size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
133     done = true;
134     return false;
135     }
136
137 if (size < 0)
138     {
139     printfd(__FILE__, "DataThread::ReadRequest() Invalid request size.\n");
140     done = true;
141     return false;
142     }
143
144 data = new char[size + 1];
145 dataSize = size;
146
147 res = read(sock, data, size);
148 if (res != size)
149     {
150     printfd(__FILE__, "DataThread::ReadRequest() Reading request failed! Wanted %d bytes, got %d bytes.\n", size, res);
151     done = true;
152     return false;
153     }
154 data[res] = 0;
155
156 return true;
157 }
158
159 bool DataThread::DecodeRequest()
160 {
161 if (users->FindByName(login, &(uit)))
162     {
163     printfd(__FILE__, "DataThread::DecodeRequest() User '%s' not found.\n", login.c_str());
164     done = true;
165     return false;
166     }
167
168 std::string password = uit->property.password;
169
170 BLOWFISH_CTX ctx;
171 char * key = new char[password.length()];
172 strncpy(key, password.c_str(), password.length());
173
174 Blowfish_Init(&ctx,
175               reinterpret_cast<unsigned char *>(key),
176               password.length());
177
178 for (int i = 0; i < dataSize / 8; ++i)
179     {
180     uint32_t a;
181     uint32_t b;
182     a = n2l(reinterpret_cast<unsigned char *>(data + i * 8));
183     b = n2l(reinterpret_cast<unsigned char *>(data + i * 8 + 4));
184     Blowfish_Decrypt(&ctx,
185                      &a,
186                      &b);
187     l2n(a, reinterpret_cast<unsigned char *>(data + i * 8));
188     l2n(b, reinterpret_cast<unsigned char *>(data + i * 8 + 4));
189     }
190
191 delete[] key;
192
193 return true;
194 }
195
196 bool DataThread::ParseRequest()
197 {
198 if (XML_Parse(xmlParser, data, dataSize, 1) != XML_STATUS_OK)
199     {
200     printfd(__FILE__, "DataThread::ParseRequest() Failed to parse the request\n");
201     request.isBad = true;
202     return false;
203     }
204 return true;
205 }
206
207 bool DataThread::MakeAnswer()
208 {
209 if (MakeConf())
210     {
211     if (MakeStat())
212         {
213         if (SendAnswer())
214             {
215             // All is ok
216             }
217         else
218             {
219             printfd(__FILE__, "DataThread::MakeAnswer() Failed to send answer");
220             return false;
221             }
222         }
223     else
224         {
225         printfd(__FILE__, "DataThread::MakeAnswer() Failed to make stat answer\n");
226         return false;
227         }
228     }
229 else
230     {
231     printfd(__FILE__, "DataThread::MakeAnswer() Failed to make conf answer\n");
232     return false;
233     }
234
235 return true;
236 }
237
238 void DataThread::Cleanup()
239 {
240 delete[] data;
241 dataSize = 0;
242 login = "";
243 done = false;
244 data = NULL;
245 request.conf.erase(request.conf.begin(), request.conf.end());
246 request.stat.erase(request.stat.begin(), request.stat.end());
247 request.login = "";
248 request.isOk = true;
249 request.isBad = false;
250 }
251
252 void DataThread::ParseTag(const std::string & name, const char ** attr)
253 {
254 if (request.isBad)
255     return;
256 if (name == "request")
257     {
258     if (attr == NULL)
259         {
260         printfd(__FILE__, "DataThread::ParseTag() 'request' tag require an attribute\n");
261         request.isBad = true;
262         return;
263         }
264     else
265         {
266         std::string attrName(*attr++);
267         std::string attrValue(*attr++);
268         if (attr != NULL)
269             {
270             printfd(__FILE__, "DataThread::ParseTag() Extra attributes on tag 'request'\n");
271             }
272         if (attrName == "login")
273             {
274             if (attrValue != login)
275                 {
276                 printfd(__FILE__, "DataThread::ParseTag() Logins doesn't match\n");
277                 request.isBad = true;
278                 return;
279                 }
280             }
281         else
282             {
283             printfd(__FILE__, "DataThread::ParseTag() Unexpected attribute '%s'\n", attrName.c_str());
284             request.isBad = true;
285             return;
286             }
287         }
288     }
289 else if (name == "conf")
290     {
291     pvList = &(request.conf);
292     }
293 else if (name == "stat")
294     {
295     pvList = &(request.stat);
296     }
297 else
298     {
299     (*pvList)[name];
300     }
301 }
302
303 bool DataThread::MakeConf()
304 {
305 return false;
306 }
307
308 bool DataThread::MakeStat()
309 {
310 return false;
311 }
312
313 bool DataThread::SendAnswer()
314 {
315 return false;
316 }
317
318 void DTXMLStart(void * data, const char * name, const char ** attr)
319 {
320 DataThread * dt = reinterpret_cast<DataThread *>(data);
321 dt->ParseTag(name, attr);
322 }
323
324 void DTXMLEnd(void * data, const char * name)
325 {
326 //DataThread * dt = reinterpret_cast<DataThread *>(data);
327 }