1 //-< CLIDB.CPP >-----------------------------------------------------*--------*
2 // FastDB Version 1.0 (c) 1999 GARRET * ? *
3 // (Main Memory Database Management System) * /\| *
4 // * / \ *
5 // Created: 7-Nov-99 K.A. Knizhnik * / [] \ *
6 // Last update: 7-Nov-99 K.A. Knizhnik * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Example of Web database publishing: Clients Database
9 //-------------------------------------------------------------------*--------*
10
11 #include "clidb.h"
12
13 dbDatabase db;
14
15 //- Client ------------------------------------------------
16
print(WWWconnection & con) const17 void Client::print(WWWconnection& con) const
18 {
19 con << TAG << "<OPTION VALUE=" << clientId << ">" << organization
20 << "</OPTION>";
21 }
22
23 REGISTER(Client);
24
25
26 //- Manager ------------------------------------------------
27
28 bool Manager::loginFromAnyHost;
29
print(WWWconnection & con) const30 void Manager::print(WWWconnection& con) const
31 {
32 con << TAG << "<OPTION VALUE=\"" << name << "\">" << name
33 << "</OPTION>";
34 }
35
36 REGISTER(Manager);
37
38 //- Segment ------------------------------------------------
39
print(WWWconnection & con) const40 void Segment::print(WWWconnection& con) const
41 {
42 con << TAG << "<OPTION VALUE=\"" << name << "\">" << name
43 << "</OPTION>";
44 }
45
46 REGISTER(Segment);
47
48 //- History ------------------------------------------------
49
print(WWWconnection & con) const50 void History::print(WWWconnection& con) const
51 {
52 ThreadContext& the = ThreadContext::of(con);
53 char buf[64];
54
55 con << TAG << "<OPTION VALUE=" << messageId << ">"
56 << date.asString(buf, sizeof buf)
57 << " " << (the.managerForm
58 ? the.clients.at(client)->organization
59 : manager != null ? the.managers.at(manager)->name : "")
60 << "</OPTION>";
61 }
62
63 REGISTER(History);
64
65 //---- ClientSequencer -------------------------------------
66
67 REGISTER(Sequencer);
68
69
70 template<class T>
print(WWWconnection & con,dbCursor<T> & cursor)71 void print(WWWconnection& con, dbCursor<T>& cursor) {
72 do {
73 cursor->print(con);
74 } while(cursor.next());
75 }
76
77 template<class T>
print(WWWconnection & con,dbArray<dbReference<T>> const & arr)78 void print(WWWconnection& con, dbArray<dbReference<T> > const& arr) {
79 dbCursor<T> cursor;
80 for (int i = 0, n = (int)arr.length(); i < n; i++) {
81 cursor.at(arr[i])->print(con);
82 }
83 }
84
85 //---- Thread Context --------------------------------------------------
86
of(WWWconnection & con)87 ThreadContext& ThreadContext::of(WWWconnection& con)
88 {
89 if (con.userData == NULL) {
90 con.userData = new ThreadContext;
91 }
92 return *(ThreadContext*)con.userData;
93 }
94
ThreadContext()95 ThreadContext::ThreadContext()
96 {
97 qClient = "clientId=",clientId;
98 qManager = "name=",&name;
99 qClients = "start from",clientsArray,"order by organization";
100 qManagers = "start from",managersArray,"order by name";
101 qSegment = "name=",&name;
102 qMessage = "messageId=",messageId;
103 qMessages = "start from",messagesArray,
104 "order by",dbDateTime::descent("date");
105 }
106
107 //--- HTML specific part -------------------------------------------
108
109 #define HTML_HEAD "Content-type: text/html\r\n\r\n\
110 <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\"><HTML><HEAD>"
111
112 #define BODY "<BODY BGCOLOR=\"#c0c0c0\">"
113
114 #define EMPTY_LIST "<OPTION> </OPTION></SELECT><BR>"
115
mainMenuReference(WWWconnection & con)116 void mainMenuReference(WWWconnection& con)
117 {
118 char* manager = con.get("manager");
119 if (manager != NULL) {
120 con << TAG
121 << "<P><HR><CENTER><A HREF=\"" << con.getStub() << "?socket="
122 << con.getAddress() << "&page=managerForm&manager="
123 << URL << manager << "\">Back to main menu</A></CENTER>";
124 }
125 con << TAG << "</BODY></HTML>";
126 }
127
error(WWWconnection & con,char const * msg)128 bool error(WWWconnection& con, char const* msg)
129 {
130 con << TAG <<
131 HTML_HEAD "<TITLE>ClientDB error</TITLE></HEAD><BODY>"
132 "<H1><FONT COLOR=\"#FF0000\">"
133 << msg << "</FONT></H1></BODY></HTML>";
134 mainMenuReference(con);
135 return true;
136 }
137
138
139
addManagerForm(WWWconnection & con)140 bool addManagerForm(WWWconnection& con)
141 {
142 con << TAG <<
143 HTML_HEAD "<TITLE>Add new manager</TITLE></HEAD>"
144 BODY
145 "<H2>Add manager</H2>"
146 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
147 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
148 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"addManager\">"
149 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << con.get("manager") <<
150 "\">"
151 "<INPUT TYPE=hidden NAME=\"segment\" VALUE=\"" << con.get("segment") <<
152 "\"><TABLE>"
153 "<TR><TH ALIGN=LEFT>Manager name</TH>"
154 "<TD><INPUT TYPE=text NAME=\"name\" SIZE=30></TD></TR>"
155 "<TR><TH ALIGN=LEFT>Host IP address</TH>"
156 "<TD><INPUT TYPE=text NAME=\"ipaddr\" SIZE=16 VALUE=\"*\"></TD></TR>"
157 "<TR><TH ALIGN=LEFT>Administrator rights</TH>"
158 "<TD><INPUT TYPE=CHECKBOX NAME=\"miniadmin\" VALUE=\"on\"></TD></TR>"
159 "</TABLE>"
160 "<INPUT TYPE=submit VALUE=\"Add\"> "
161 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
162 mainMenuReference(con);
163 return true;
164 }
165
addClientForm(WWWconnection & con)166 bool addClientForm(WWWconnection& con)
167 {
168 con << TAG <<
169 HTML_HEAD "<TITLE>Add new client</TITLE></HEAD>"
170 BODY
171 "<H2>Add client</H2>"
172 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
173 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
174 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"addClient\">"
175 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << con.get("manager") <<
176 "\">"
177 "<INPUT TYPE=hidden NAME=\"segment\" VALUE=\"" << con.get("segment") <<
178 "\"><TABLE>"
179 "<TR><TH ALIGN=LEFT>Organization</TH>"
180 "<TD><INPUT TYPE=text NAME=\"organization\" SIZE=40></TD></TR>"
181 "<TR><TH ALIGN=LEFT>Phone</TH>"
182 "<TD><INPUT TYPE=text NAME=\"phone\" SIZE=20></TD></TR>"
183 "<TR><TH ALIGN=LEFT>Phone2</TH>"
184 "<TD><INPUT TYPE=text NAME=\"phone2\" SIZE=20></TD></TR>"
185 "<TR><TH ALIGN=LEFT>Fax</TH>"
186 "<TD><INPUT TYPE=text NAME=\"fax\" SIZE=20></TD></TR>"
187 "<TR><TH ALIGN=LEFT>E-Mail</TH>"
188 "<TD><INPUT TYPE=text NAME=\"email\" SIZE=30></TD></TR>"
189 "<TR><TH ALIGN=LEFT>WWW address</TH>"
190 "<TD><INPUT TYPE=text NAME=\"www\" SIZE=30></TD></TR>"
191 "<TR><TH ALIGN=LEFT>Person</TH>"
192 "<TD><INPUT TYPE=text NAME=\"person\" SIZE=40></TD></TR>"
193 "<TR><TH ALIGN=LEFT>Person2</TH>"
194 "<TD><INPUT TYPE=text NAME=\"person2\" SIZE=40></TD></TR>"
195 "<TR><TH ALIGN=LEFT>CEO</TH>"
196 "<TD><INPUT TYPE=text NAME=\"lpr\" SIZE=40></TD></TR>"
197 "<TR><TH ALIGN=LEFT>Address</TH>"
198 "<TD><INPUT TYPE=text NAME=\"addr\" SIZE=40></TD></TR>"
199 "<TR><TH ALIGN=LEFT>Information</TH>"
200 "<TD><INPUT TYPE=text NAME=\"info\" SIZE=40></TD></TR>"
201 "<TR><TH ALIGN=LEFT>Status</TH>"
202 "<TD><INPUT TYPE=text NAME=\"status\" SIZE=40></TD></TR>"
203 "</TABLE><INPUT TYPE=submit VALUE=\"Add\"> "
204 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
205 mainMenuReference(con);
206 return true;
207 }
208
209
addSegmentForm(WWWconnection & con)210 bool addSegmentForm(WWWconnection& con)
211 {
212 con << TAG <<
213 HTML_HEAD "<TITLE>Add new segment</TITLE></HEAD>"
214 BODY
215 "<H2>Add segment</H2>"
216 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
217 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
218 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"addSegment\">"
219 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << con.get("manager") <<
220 "\"><TABLE>"
221 "<TR><TH ALIGN=LEFT>Segment name </TH>"
222 "<TD><INPUT TYPE=text NAME=\"name\" SIZE=30></TD></TR>"
223 "</TD></TR></TABLE><P>"
224 "<INPUT TYPE=submit VALUE=\"Add\"> "
225 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
226 mainMenuReference(con);
227 return true;
228 }
229
addHistoryForm(WWWconnection & con)230 bool addHistoryForm(WWWconnection& con)
231 {
232 con << TAG <<
233 HTML_HEAD "<TITLE>Add message</TITLE></HEAD>"
234 BODY
235 "<H2>Add message</H2>"
236 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
237 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
238 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"addHistory\">"
239 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << con.get("manager") <<
240 "\"><INPUT TYPE=hidden NAME=\"client\" VALUE=" << con.get("client") <<
241 "\"><TEXTAREA NAME=\"message\" ROWS=10 COLS=60></TEXTAREA><P>"
242 "<INPUT TYPE=submit VALUE=\"Add\"> "
243 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
244 mainMenuReference(con);
245 return true;
246 }
247
248
editManagerForm(WWWconnection & con)249 bool editManagerForm(WWWconnection& con)
250 {
251 if (con.get("new")) {
252 return addManagerForm(con);
253 }
254 ThreadContext& the = ThreadContext::of(con);
255 the.name = con.get("name");
256 if (the.name == NULL) {
257 return error(con, "No manager was selected");
258 }
259 if (the.managers.select(the.qManager) == 0) {
260 return error(con, "No such manager");
261 }
262
263 con << TAG <<
264 HTML_HEAD "<TITLE>Edit manager form</TITLE></HEAD>"
265 BODY
266 "<H2>Update manager</H2>"
267 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
268 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
269 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editManager\">"
270 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << con.get("manager") <<
271 "\"><INPUT TYPE=hidden NAME=\"oldName\" VALUE=\"" << the.name << "\">"
272 "<TABLE><TR><TH ALIGN=LEFT>Manager name</TH>"
273 "<TD><INPUT TYPE=text NAME=\"name\" SIZE=30 VALUE=\""
274 << the.managers->name << "\"></TD></TR>"
275 "<TR><TH ALIGN=LEFT>Host IP address</TH>"
276 "<TD><INPUT TYPE=text NAME=\"ipaddr\" SIZE=16 VALUE=\""
277 << the.managers->IPaddr << "\"</TD></TR>"
278 "<TR><TH ALIGN=LEFT>Administrator rights</TH>"
279 "<TD><INPUT TYPE=CHECKBOX NAME=\"miniadmin\" VALUE=\"on\""
280 << ((the.managers->flags & Manager::isMinAdmin)
281 ? "CHECKED" : "") << "></TD></TR></TABLE>"
282 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Update\"> "
283 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\"></FORM><P>"
284 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
285 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
286 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editHistoryForm\">"
287 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << con.get("manager") <<
288 "\"><SELECT NAME=\"messageId\" SIZE=15>";
289 the.managerForm = true;
290 if (the.managers->messages.length() != 0) {
291 print(con, the.managers->messages);
292 con << TAG <<
293 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\"></FORM>";
294 } else {
295 con << TAG << EMPTY_LIST "</FORM>";
296 }
297 mainMenuReference(con);
298 return true;
299 }
300
editClientForm(WWWconnection & con)301 bool editClientForm(WWWconnection& con)
302 {
303 if (con.get("new")) {
304 return addClientForm(con);
305 }
306 ThreadContext& the = ThreadContext::of(con);
307 char* client = con.get("client");
308 if (client == NULL) {
309 return error(con, "No client was selected");
310 }
311 the.clientId = atoi(client);
312 if (the.clients.select(the.qClient) == 0) {
313 return error(con, "No such client");
314 }
315 the.name = con.get("manager");
316 if (the.managers.select(the.qManager) == 0) {
317 return error(con, "No such manager");
318 }
319 con << TAG <<
320 HTML_HEAD "<TITLE>Edit client form</TITLE></HEAD>"
321 BODY
322 "<H2>Update client</H2>"
323 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
324 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
325 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editClient\">"
326 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << the.name << "\">"
327 "<INPUT TYPE=hidden NAME=\"client\" VALUE=" << client << "\">"
328 "<TABLE>"
329 "<TR><TH ALIGN=LEFT>Organization</TH>"
330 "<TD><INPUT TYPE=text NAME=\"organization\" SIZE=40 VALUE=\""
331 << the.clients->organization << "\"></TD></TR>"
332 "<TR><TH ALIGN=LEFT>Phone</TH>"
333 "<TD><INPUT TYPE=text NAME=\"phone\" SIZE=20 VALUE=\""
334 << the.clients->phone << "\"></TD></TR>"
335 "<TR><TH ALIGN=LEFT>Phone2</TH>"
336 "<TD><INPUT TYPE=text NAME=\"phone2\" SIZE=20 VALUE=\""
337 << the.clients->phone2 << "\"></TD></TR>"
338 "<TR><TH ALIGN=LEFT>Fax</TH>"
339 "<TD><INPUT TYPE=text NAME=\"fax\" SIZE=20 VALUE=\""
340 << the.clients->fax << "\"></TD></TR>"
341 "<TR><TH ALIGN=LEFT>E-Mail</TH>"
342 "<TD><INPUT TYPE=text NAME=\"email\" SIZE=30 VALUE=\""
343 << the.clients->email << "\"></TD></TR>"
344 "<TR><TH ALIGN=LEFT>WWW address</TH>"
345 "<TD><INPUT TYPE=text NAME=\"www\" SIZE=30 VALUE=\""
346 << the.clients->www << "\"></TD></TR>"
347 "<TR><TH ALIGN=LEFT>Person</TH>"
348 "<TD><INPUT TYPE=text NAME=\"person\" SIZE=40 VALUE=\""
349 << the.clients->person << "\"></TD></TR>"
350 "<TR><TH ALIGN=LEFT>Person2</TH>"
351 "<TD><INPUT TYPE=text NAME=\"person2\" SIZE=40 VALUE=\""
352 << the.clients->person2 << "\"></TD></TR>"
353 "<TR><TH ALIGN=LEFT>CEO</TH>"
354 "<TD><INPUT TYPE=text NAME=\"lpr\" SIZE=40 VALUE=\""
355 << the.clients->lpr << "\"></TD></TR>"
356 "<TR><TH ALIGN=LEFT>Address</TH>"
357 "<TD><INPUT TYPE=text NAME=\"addr\" SIZE=40 VALUE=\""
358 << the.clients->addr << "\"></TD></TR>"
359 "<TR><TH ALIGN=LEFT>Information</TH>"
360 "<TD><INPUT TYPE=text NAME=\"info\" SIZE=40 VALUE=\""
361 << the.clients->info << "\"></TD></TR>"
362 "<TR><TH ALIGN=LEFT>Status</TH>"
363 "<TD><INPUT TYPE=text NAME=\"status\" SIZE=40 VALUE=\""
364 << the.clients->status << "\"></TD></TR></TABLE><P>";
365 if (the.managers->flags & (Manager::isAdministrator|Manager::isMinAdmin)) {
366 con << TAG
367 << "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Update\"> ";
368 }
369 if (the.managers->flags & Manager::isAdministrator) {
370 con << TAG << "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
371 }
372 con << TAG << "</FORM><P>"
373 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
374 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
375 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editHistoryForm\">"
376 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << the.name << "\">"
377 "<INPUT TYPE=hidden NAME=\"client\" VALUE=" << client << "\">"
378 "<SELECT SIZE=10 NAME=\"messageId\">";
379 the.managerForm = false;
380 the.messagesArray = &the.clients->history;
381 if (the.messages.select(the.qMessages) != 0) {
382 print(con, the.messages);
383 con << TAG <<
384 "</SELECT><BR><INPUT TYPE=submit VALUE=\"Select\"> ";
385 } else {
386 con << TAG << EMPTY_LIST;
387 }
388 con << TAG <<
389 "<INPUT TYPE=submit NAME=\"new\" VALUE=\"New message\"></FORM>";
390 mainMenuReference(con);
391 return true;
392 }
393
394
editSegmentForm(WWWconnection & con)395 bool editSegmentForm(WWWconnection& con)
396 {
397 if (con.get("new")) {
398 return addSegmentForm(con);
399 }
400 ThreadContext& the = ThreadContext::of(con);
401 the.name = con.get("name");
402 if (the.name == NULL) {
403 return error(con, "No segment was selected");
404 }
405 if (the.segments.select(the.qSegment) == 0) {
406 return error(con, "No such segment");
407 }
408 char* manager = con.get("manager");
409
410 con << TAG <<
411 HTML_HEAD "<TITLE>Edit segment</TITLE></HEAD>"
412 BODY
413 "<H2>Update segment</H2>"
414 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
415 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
416 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editSegment\">"
417 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << manager << "\">"
418 "<INPUT TYPE=hidden NAME=\"oldName\" VALUE=\"" << the.name << "\">"
419 "<TABLE><TR><TH ALIGN=LEFT>Segment name </TH>"
420 "<TD><INPUT TYPE=text NAME=\"name\" SIZE=30 VALUE=\""
421 << the.segments->name << "\"></TD></TR>"
422 "</TD></TR></TABLE><P>"
423 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Update\"> "
424 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\"></FORM><P>"
425
426 "<H2>Select manager</H2>"
427 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
428 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
429 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editManagerForm\">"
430 "<INPUT TYPE=hidden NAME=\"segment\" VALUE=\"" << the.name << "\">"
431 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << manager << "\">"
432 "<SELECT NAME=\"name\" SIZE=10>";
433 the.managersArray = &the.segments->managers;
434 if (the.managers.select(the.qManagers) != 0) {
435 print(con, the.managers);
436 con << TAG <<
437 "</SELECT><BR><INPUT TYPE=submit VALUE=\"Select\"> ";
438 } else {
439 con << TAG << EMPTY_LIST;
440 }
441 con << TAG << "<INPUT TYPE=submit NAME=\"new\" VALUE=\"New\"></FORM><P>"
442 "<H2>Select client</H2>"
443 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
444 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
445 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editClientForm\">"
446 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << manager << "\">"
447 "<INPUT TYPE=hidden NAME=\"segment\" VALUE=\"" << the.name << "\">"
448 "<SELECT NAME=\"client\" SIZE=10>";
449 the.clientsArray = &the.segments->clients;
450 if (the.clients.select(the.qClients) != 0) {
451 print(con, the.clients);
452 con << TAG <<
453 "</SELECT><BR><INPUT TYPE=submit VALUE=\"Select\"> ";
454 } else {
455 con << TAG << EMPTY_LIST;
456 }
457 con << TAG << "<INPUT TYPE=submit NAME=\"new\" VALUE=\"New\"></FORM>";
458
459 mainMenuReference(con);
460 return true;
461 }
462
463
editHistoryForm(WWWconnection & con)464 bool editHistoryForm(WWWconnection& con)
465 {
466 if (con.get("new")) {
467 return addHistoryForm(con);
468 }
469 ThreadContext& the = ThreadContext::of(con);
470 char buf[64];
471 char* messageId = con.get("messageId");
472 if (messageId == NULL) {
473 return error(con, "No message was selected");
474 }
475 the.messageId = atoi(messageId);
476 if (the.messages.select(the.qMessage) == 0) {
477 return error(con, "No such message");
478 }
479 the.name = con.get("manager");
480 the.clients.at(the.messages->client);
481 if (the.messages->manager != null) {
482 the.managers.at(the.messages->manager);
483 }
484 con << TAG <<
485 HTML_HEAD "<TITLE>Edit message</TITLE></HEAD>"
486 BODY
487 "<H2>Edit message</H2>"
488 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
489 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
490 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editHistory\">"
491 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << the.name << "\">"
492 "<INPUT TYPE=hidden NAME=\"messageId\" VALUE=" << messageId << "\">"
493 "<TABLE><TR><TH ALIGN=LEFT>Client</TH>"
494 "<TD><A HREF=\"" << con.getStub() << "?socket=" << con.getAddress()
495 << "&page=editClientForm&manager=" << URL << the.name
496 << "&client=" << the.clients->clientId << "\">"
497 << the.clients->organization << "</A></TD></TR>";
498 if (the.messages->manager != null) {
499 con << TAG <<
500 "<TR><TH ALIGN=LEFT>Manager</TH><TD><A HREF=\""
501 << con.getStub() << "?socket=" << con.getAddress()
502 << "&page=editManagerForm&manager=" << URL << the.name
503 << "&name=" << URL << the.managers->name << "\">"
504 << the.managers->name << "</A></TD></TR>";
505 }
506 con << TAG <<
507 "<TR><TH ALIGN=LEFT>Date</TH>"
508 "<TD><INPUT TYPE=text SIZE=30 VALUE=\""
509 << the.messages->date.asString(buf, sizeof buf) << "\"></TD></TR>"
510 "</TABLE><P>"
511 "<TEXTAREA NAME=\"message\" ROWS=10 COLS=60>"
512 << the.messages->message << "</TEXTAREA><P>";
513 if (the.managers.select(the.qManager) == 0) {
514 return error(con, "No such manager");
515 }
516 if ((the.managers->flags & (Manager::isAdministrator|Manager::isMinAdmin))
517 || the.managers.currentId() == the.messages->manager)
518 {
519 con << TAG
520 << "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Update\"> "
521 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
522 }
523 con << TAG << "</FORM>";
524 mainMenuReference(con);
525 return true;
526 }
527
528
managerForm(WWWconnection & con)529 bool managerForm(WWWconnection& con)
530 {
531 ThreadContext& the = ThreadContext::of(con);
532 the.name = con.get("manager");
533 if (the.managers.select(the.qManager) == 0) {
534 return error(con, "No such manager");
535 }
536 if (the.managers->flags & Manager::isAdministrator) {
537 con << TAG <<
538 HTML_HEAD "<TITLE>Administrator menu</TITLE></HEAD>"
539 BODY
540 "<H2>Administrator menu</H2>"
541 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
542 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""<< con.getAddress() <<
543 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editManager\">"
544 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << the.name << "\">"
545 "<INPUT TYPE=hidden NAME=\"oldName\" VALUE=\"" << the.name << "\">"
546 "<TABLE><TR><TH ALIGN=LEFT>Manager name</TH>"
547 "<TD><INPUT TYPE=text NAME=\"name\" SIZE=30 VALUE=\""
548 << the.managers->name << "\"></TD></TR>"
549 "<TR><TH ALIGN=LEFT>Manager host IP address</TH>"
550 "<TD><INPUT TYPE=text NAME=\"ipaddr\" SIZE=16 VALUE=\""
551 << the.managers->IPaddr << "\"</TD></TR></TABLE>"
552 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Change\"></FORM><P>"
553 "<H2>Select segment</H2>"
554 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
555 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""<< con.getAddress() <<
556 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editSegmentForm\">"
557 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << the.name << "\">"
558 "<SELECT SIZE=15 NAME=\"name\">";
559 if (the.segments.select() != 0) {
560 print(con, the.segments);
561 con << TAG <<
562 "</SELECT><BR><INPUT TYPE=submit VALUE=\"Select\"> ";
563 } else {
564 con << TAG << EMPTY_LIST;
565 }
566 con << TAG <<
567 "<INPUT TYPE=submit NAME=\"new\" VALUE=\"New segment\"></FORM>"
568 "<P><HR>"
569 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
570 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""<< con.getAddress() <<
571 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"shutdown\">"
572 "<CENTER><INPUT TYPE=submit VALUE=\"Shutdown server\"></CENTER>"
573 "</FORM>";
574 } else {
575 con << TAG <<
576 HTML_HEAD "<TITLE>Manager menu</TITLE></HEAD>"
577 BODY
578 "<H2>Manager menu</H2>"
579 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
580 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""<< con.getAddress() <<
581 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editManager\">"
582 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << the.name << "\">"
583 "<INPUT TYPE=hidden NAME=\"oldName\" VALUE=\"" << the.name << "\">";
584 if (the.managers->flags & Manager::isMinAdmin) {
585 con << TAG <<"<INPUT TYPE=hidden NAME=\"miniadmin\" VALUE=\"on\">";
586 }
587 the.segments.at(the.managers->segment);
588 con << TAG <<
589 "<TABLE><TR><TH ALIGN=LEFT>Manager name</TH>"
590 "<TD><INPUT TYPE=text NAME=\"name\" SIZE=30 VALUE=\""
591 << the.managers->name << "\"></TD></TR>"
592 "<TR><TH ALIGN=LEFT>Manager host IP address</TH>"
593 "<TD><INPUT TYPE=text NAME=\"ipaddr\" SIZE=16 VALUE=\""
594 << the.managers->IPaddr << "\"</TD></TR></TABLE>"
595 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Change\"></FORM><P>"
596 "<H2>Select client</H2>"
597 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
598 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""<< con.getAddress() <<
599 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"editClientForm\">"
600 "<INPUT TYPE=hidden NAME=\"manager\" VALUE=\"" << the.name << "\">"
601 "<INPUT TYPE=hidden NAME=\"segment\" VALUE=\""
602 << the.segments->name << "\">"
603 "<SELECT SIZE=15 NAME=\"client\">";
604 the.clientsArray = &the.segments->clients;
605 if (the.clients.select(the.qClients) != 0) {
606 print(con, the.clients);
607 con << TAG <<
608 "</SELECT><BR><INPUT TYPE=submit VALUE=\"Select\"> ";
609 } else {
610 con << TAG << EMPTY_LIST;
611 }
612 con << TAG << "<INPUT TYPE=submit NAME=\"new\" VALUE=\"New\"></FORM>";
613 }
614 con << TAG << "</BODY></HTML>";
615 return true;
616 }
617
618
login(WWWconnection & con)619 bool login(WWWconnection& con)
620 {
621 ThreadContext& the = ThreadContext::of(con);
622 the.name = con.get("name");
623 if (the.managers.select(the.qManager) == 0) {
624 return error(con, "No such manager");
625 }
626 if (!Manager::loginFromAnyHost
627 && strcmp(the.managers->IPaddr, "*") != 0
628 && strcmp(the.managers->IPaddr, con.getPeer()) != 0)
629 {
630 return error(con, "You can not login from this host");
631 }
632 con.addPair("manager", the.name);
633 return managerForm(con);
634 }
635
shutdown(WWWconnection & con)636 bool shutdown(WWWconnection& con)
637 {
638 con << TAG <<
639 HTML_HEAD "<TITLE>ClientDB message</TITLE></HEAD><BODY>"
640 "<H1>ClientDB server is terminated</H1></BODY></HTML>";
641 return false;
642 }
643
addManager(WWWconnection & con)644 bool addManager(WWWconnection& con)
645 {
646 ThreadContext& the = ThreadContext::of(con);
647 Manager manager;
648 the.name = con.get("segment");
649 if (the.segments.select(the.qSegment, dbCursorForUpdate) == 0) {
650 return error(con, "No such segment");
651 }
652 the.name = con.get("name");
653 if (the.managers.select(the.qManager) != 0) {
654 return error(con, "Manager with such name already exists");
655 }
656 manager.name = con.get("name");
657 manager.IPaddr = con.get("ipaddr");
658 manager.flags = con.get("miniadmin") ? Manager::isMinAdmin : 0;
659 manager.segment = the.segments.currentId();
660 insert(manager);
661 return managerForm(con);
662 }
663
addClient(WWWconnection & con)664 bool addClient(WWWconnection& con)
665 {
666 ThreadContext& the = ThreadContext::of(con);
667 Client client;
668 the.sequencer.select(dbCursorForUpdate);
669 the.name = con.get("segment");
670 if (the.segments.select(the.qSegment) == 0) {
671 return error(con, "No such segment");
672 }
673 client.organization = con.get("organization");
674 client.phone = con.get("phone");
675 client.phone2 = con.get("phone2");
676 client.fax = con.get("fax");
677 client.email = con.get("email");
678 client.www = con.get("www");
679 client.person = con.get("person");
680 client.person2 = con.get("person2");
681 client.lpr = con.get("lpr");
682 client.addr = con.get("addr");
683 client.info = con.get("info");
684 client.status = con.get("status");
685 client.clientId = ++the.sequencer->lastClientId;
686 client.segment = the.segments.currentId();
687 the.sequencer.update();
688 insert(client);
689 return managerForm(con);
690 }
691
addSegment(WWWconnection & con)692 bool addSegment(WWWconnection& con)
693 {
694 ThreadContext& the = ThreadContext::of(con);
695 Segment segment;
696 segment.name = the.name = con.get("name");
697 if (the.segments.select(the.qSegment, dbCursorForUpdate) != 0) {
698 return error(con, "Segment with such name already exists");
699 }
700 insert(segment);
701 return managerForm(con);
702 }
703
addHistory(WWWconnection & con)704 bool addHistory(WWWconnection& con)
705 {
706 ThreadContext& the = ThreadContext::of(con);
707 the.sequencer.select(dbCursorForUpdate);
708 the.clientId = atoi(con.get("client"));
709 if (the.clients.select(the.qClient) == 0) {
710 error(con, "No such client");
711 return true;
712 }
713 History his;
714 his.messageId = ++the.sequencer->lastMessageId;
715 his.message = con.get("message");
716 his.client = the.clients.currentId();
717 the.name = con.get("manager");
718 if (the.managers.select(the.qManager) == 0) {
719 error(con, "No such manger");
720 return true;
721 }
722 his.manager = the.managers.currentId();
723 his.date = dbDateTime::current();
724 insert(his);
725 the.sequencer.update();
726 return managerForm(con);
727 }
728
editManager(WWWconnection & con)729 bool editManager(WWWconnection& con)
730 {
731 ThreadContext& the = ThreadContext::of(con);
732 the.name = con.get("oldName");
733 if (the.managers.select(the.qManager, dbCursorForUpdate) == 0) {
734 error(con, "No such manager");
735 return true;
736 }
737 if (strcmp(con.get("action"), "Remove") == 0) {
738 the.managers.remove();
739 return managerForm(con);
740 }
741 the.managers->name = con.get("name");
742 the.managers->IPaddr = con.get("ipaddr");
743 if (con.get("miniadmin")) {
744 the.managers->flags |= Manager::isMinAdmin;
745 } else {
746 the.managers->flags &= ~Manager::isMinAdmin;
747 }
748 the.managers.update();
749 return managerForm(con);
750 }
751
editClient(WWWconnection & con)752 bool editClient(WWWconnection& con)
753 {
754 ThreadContext& the = ThreadContext::of(con);
755 the.clientId = atoi(con.get("client"));
756 if (the.clients.select(the.qClient, dbCursorForUpdate) == 0) {
757 error(con, "No such client");
758 return true;
759 }
760 if (strcmp(con.get("action"), "Remove") == 0) {
761 the.clients.remove();
762 } else {
763 the.clients->organization = con.get("organization");
764 the.clients->phone = con.get("phone");
765 the.clients->phone2 = con.get("phone2");
766 the.clients->fax = con.get("fax");
767 the.clients->email = con.get("email");
768 the.clients->www = con.get("www");
769 the.clients->person = con.get("person");
770 the.clients->person2 = con.get("person2");
771 the.clients->lpr = con.get("lpr");
772 the.clients->addr = con.get("addr");
773 the.clients->info = con.get("info");
774 the.clients->status = con.get("status");
775 the.clients.update();
776 }
777 return managerForm(con);
778 }
779
editSegment(WWWconnection & con)780 bool editSegment(WWWconnection& con)
781 {
782 ThreadContext& the = ThreadContext::of(con);
783 the.name = con.get("oldName");
784 if (the.segments.select(the.qSegment, dbCursorForUpdate) == 0) {
785 error(con, "No such segment");
786 return true;
787 }
788 if (strcmp(con.get("action"), "Remove") == 0) {
789 the.segments.remove();
790 } else {
791 the.segments->name = con.get("name");
792 the.segments.update();
793 }
794 return managerForm(con);
795 }
796
editHistory(WWWconnection & con)797 bool editHistory(WWWconnection& con)
798 {
799 ThreadContext& the = ThreadContext::of(con);
800 the.messageId = atoi(con.get("messageId"));
801 if (the.messages.select(the.qMessage, dbCursorForUpdate) == 0) {
802 error(con, "No such message");
803 return true;
804 }
805 if (strcmp(con.get("action"), "Remove") == 0) {
806 the.messages.remove();
807 } else {
808 the.messages->message = con.get("message");
809 the.messages.update();
810 }
811 return managerForm(con);
812 }
813
814
815 WWWapi::dispatcher dispatchTable[] = {
816 {"addManagerForm", addManagerForm},
817 {"addClientForm", addClientForm},
818 {"addSegmentForm", addSegmentForm},
819 {"addHistoryForm", addHistoryForm},
820 {"editManagerForm", editManagerForm},
821 {"editClientForm", editClientForm},
822 {"editSegmentForm", editSegmentForm},
823 {"editHistoryForm", editHistoryForm},
824 {"managerForm", managerForm},
825 {"login", login},
826 {"shutdown", shutdown},
827 {"addManager", addManager},
828 {"addClient", addClient},
829 {"addSegment", addSegment},
830 {"addHistory", addHistory},
831 {"editManager", editManager},
832 {"editClient", editClient},
833 {"editSegment", editSegment},
834 {"editHistory", editHistory}
835 };
836
837 #ifdef USE_EXTERNAL_HTTP_SERVER
838 CGIapi wwwServer(db, itemsof(dispatchTable), dispatchTable);
839 char* defaultAddress = "localhost:6101";
840 socket_t::socket_domain domain = socket_t::sock_local_domain;
841 #else
842 #ifdef USE_QUEUE_MANAGER
843 HTTPapi wwwServer(db, itemsof(dispatchTable), dispatchTable, true);
844 #else
845 HTTPapi wwwServer(db, itemsof(dispatchTable), dispatchTable, false);
846 #endif
847 char* defaultAddress = "localhost:80";
848 socket_t::socket_domain domain = socket_t::sock_global_domain;
849 #endif
850
main(int argc,char * argv[])851 int main(int argc, char* argv[])
852 {
853 char* address = (argc > 1) ? argv[1] : defaultAddress;
854 if (!wwwServer.open(address, domain)) {
855 fprintf(stderr, "Failed to open WWW session\n");
856 return EXIT_FAILURE;
857 }
858 if (!db.open(_T("clidb"))) {
859 fprintf(stderr, "Failed to open database\n");
860 return EXIT_FAILURE;
861 }
862 dbCursor<Sequencer> sequencer;
863 if (sequencer.select() == 0) {
864 Sequencer seq;
865 seq.lastClientId = 0;
866 seq.lastMessageId = 0;
867 insert(seq);
868
869 Manager administrator;
870 administrator.name = "administrator";
871 administrator.IPaddr = "*";
872 administrator.flags = Manager::isAdministrator;
873 insert(administrator);
874 }
875 db.commit();
876 if (argc > 2 && strcmp(argv[2], "login_from_any_host") == 0) {
877 Manager::loginFromAnyHost = true;
878 }
879 #ifdef USE_QUEUE_MANAGER
880 QueueManager qmgr(wwwServer, db);
881 qmgr.start();
882 #else
883 WWWconnection con;
884 while (wwwServer.connect(con) && wwwServer.serve(con));
885 #endif
886 db.close();
887 printf("End of session\n");
888 return EXIT_SUCCESS;
889 }
890