1 //-< BUGDB.CPP >----------------------------------------------------*--------*
2 // FastDB Version 1.0 (c) 1999 GARRET * ? *
3 // (Main Memory Database Management System) * /\| *
4 // * / \ *
5 // Created: 27-Mar-99 K.A. Knizhnik * / [] \ *
6 // Last update: 30-Jun-99 K.A. Knizhnik * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Example of database Web publishing: Bug Tracking Database
9 //-------------------------------------------------------------------*--------*
10
11 #include "bugdb.h"
12
13 //#define USE_EXTERNAL_HTTP_SERVER 1
14
15 char const* const eCATEGORY_STRING[] =
16 {
17 "",
18 "CRASH",
19 "PROGRAM_HANGS",
20 "UI_DISPLAY",
21 "UI_BEHAVIOR",
22 "CALCULATION",
23 "ERROR_HANDLING",
24 "PERFORMANCE",
25 "LICENSING",
26 "INSTALLATION",
27 "DOCUMENTATION",
28 "ENHANCEMENT",
29 "HOW_TO_QUESTION",
30 NULL
31 };
32
33 char const* const eSTATUS_STRING[] = {
34 "",
35 "OPENED",
36 "FIXED",
37 "CLOSED",
38 "PENDING_ENGINEER",
39 "PENDING_USER",
40 "POSTPONED",
41 "IRREPRODUCIBLE",
42 "WITHDRAWN",
43 "AS_DESIGNED",
44 NULL
45 };
46
47 char const* const eSEVERITY_STRING[] = {
48 "",
49 "FATAL",
50 "SERIOUS",
51 "MINOR",
52 NULL
53 };
54
55 char const* const eFIXING_PRIORITY_STRING[] = {
56 "",
57 "FIX_IMMEDIATELY",
58 "FIX_BEFORE_NEXT_BUILD_RELEASE",
59 "FIX_BEFORE_NEXT_MINOR_RELEASE",
60 "FIX_BEFORE_NEXT_MAJOR_RELEASE",
61 "FIX_IF_POSSIBLE",
62 "OPTIONAL",
63 NULL
64 };
65
66 dbDatabase db;
67
68 dbCursor<Bug> allBugs;
69 dbCursor<Bug> bugs(dbCursorForUpdate);
70 dbCursor<Report> reports(dbCursorForUpdate);
71 dbCursor<Person> persons(dbCursorForUpdate);
72 dbCursor<Software> products(dbCursorForUpdate);
73 dbCursor<Version> versions(dbCursorForUpdate);
74 dbCursor<BugSequencer> sequencer(dbCursorForUpdate);
75
76 dbQuery qBug;
77 dbQuery qReport;
78 dbQuery qAllReports;
79 dbQuery qVersion;
80 dbQuery qAllVersions;
81 dbQuery qPerson;
82 dbQuery qSoftware;
83
84 //
85 // Query paramters
86 //
87 char* key;
88 int bugId;
89 int reportId;
90 dbReference<Report> firstReport;
91 dbReference<Version> initialVersion;
92 int majorVersion;
93 int minorVersion;
94
95
96 //- Person ------------------------------------------------
97
print(WWWconnection & con) const98 void Person::print(WWWconnection& con) const
99 {
100 con << TAG << "<OPTION VALUE=\"" << sName << "\">" << sName << "</OPTION>";
101 }
102
103 REGISTER(Person);
104
105 //------- Version ---------------------------------------
106
print(WWWconnection & con) const107 void Version::print(WWWconnection& con) const
108 {
109 char buf[64];
110 con << TAG << "<OPTION VALUE=\"" << getVersionString() <<
111 "\">Version " << getVersionString() << " " << sLabel <<
112 " " << released.asString(buf, sizeof buf) << "</OPTION>";
113 }
114
getVersion() const115 int Version::getVersion() const
116 {
117 return majorVersionNumber*100 + minorVersionNumber;
118 }
119
getVersionString() const120 char* Version::getVersionString() const
121 {
122 static char buf[16];
123 sprintf(buf, "%d.%02d", majorVersionNumber, minorVersionNumber);
124 return buf;
125 }
126
127 REGISTER(Version);
128
129 //----- Software -------------------------------------
130
getLastVersion() const131 int Software::getLastVersion() const
132 {
133 if (pVersions == null) {
134 return 0;
135 }
136 versions.at(pVersions);
137 return versions->getVersion();
138 }
139
getLastVersionString() const140 char* Software::getLastVersionString() const
141 {
142 if (pVersions == null) {
143 return "";
144 }
145 versions.at(pVersions);
146 return versions->getVersionString();
147 }
148
print(WWWconnection & con) const149 void Software::print(WWWconnection& con) const
150 {
151 con << TAG << "<OPTION VALUE=\"" << sName << "\">" << sName << "</OPTION>";
152 }
153
154 REGISTER(Software);
155
156 //----- Report -------------------------------------------
157
print(WWWconnection & con) const158 void Report::print(WWWconnection& con) const
159 {
160 char buf[64];
161 if (pAuthor != null) {
162 persons.at(pAuthor);
163 con << TAG << "<OPTION VALUE=" << index << ">" << persons->sName << " "
164 << creationDate.asString(buf, sizeof buf) << "</OPTION>";
165 } else {
166 con << TAG << "<OPTION VALUE=" << index << ">" << "Report from "
167 << creationDate.asString(buf, sizeof buf) << "</OPTION>";
168 }
169 }
170
171 REGISTER(Report);
172
173 //--- Bug -----------------------------------------
174
print(WWWconnection & con) const175 void Bug::print(WWWconnection& con) const
176 {
177 con << TAG << "<OPTION VALUE=" << bugId << ">" << sOneLineSummary
178 << "</OPTION>";
179 }
180
181 REGISTER(Bug);
182
183 //---- BugSequencer -------------------------------------
184
185 REGISTER(BugSequencer);
186
187 template<class T>
print(WWWconnection & con,dbCursor<T> & cursor)188 void print(WWWconnection& con, dbCursor<T>& cursor) {
189 do {
190 cursor->print(con);
191 } while(cursor.next());
192 }
193
194 template<class T>
print(WWWconnection & con,dbArray<dbReference<T>> const & arr)195 void print(WWWconnection& con, dbArray<dbReference<T> > const& arr) {
196 dbCursor<T> cursor;
197 for (int i = 0, n = (int)arr.length(); i < n; i++) {
198 cursor.at(arr[i])->print(con);
199 }
200 }
201
202 //--- HTML specific part -------------------------------------------
203
204 #define HTML_HEAD "Content-type: text/html\r\n\r\n\
205 <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\"><HTML><HEAD>"
206
207 #define BODY "<BODY BGCOLOR=\"#c0c0c0\">"
208
209 #define EMPTY_LIST "<OPTION> </OPTION></SELECT>"
210
mainMenuReference(WWWconnection & con)211 void mainMenuReference(WWWconnection& con)
212 {
213 char* myself = con.get("myself");
214 if (myself != NULL) {
215 con << TAG
216 << "<P><HR><CENTER><A HREF=\"" << con.getStub() << "?socket="
217 << con.getAddress() << "&page=userForm&myself="
218 << URL << myself << "&name=" << URL << myself
219 << "\">Back to main menu</A></CENTER>";
220 }
221 con << TAG << "</BODY></HTML>";
222 }
223
error(WWWconnection & con,char const * msg)224 void error(WWWconnection& con, char const* msg)
225 {
226 con << TAG <<
227 HTML_HEAD "<TITLE>BUGDB error</TITLE></HEAD><BODY>"
228 "<H1><FONT COLOR=\"#FF0000\">"
229 << msg << "</FONT></H1></BODY></HTML>";
230 mainMenuReference(con);
231 }
232
233
message(WWWconnection & con,char const * msg)234 void message(WWWconnection& con, char const* msg)
235 {
236 con << TAG <<
237 HTML_HEAD "<TITLE>BUGDB message</TITLE></HEAD><BODY>"
238 "<H1><FONT COLOR=\"#004000\">"
239 << msg << "</FONT></H1></BODY></HTML>";
240 mainMenuReference(con);
241 }
242
243
addUserForm(WWWconnection & con)244 bool addUserForm(WWWconnection& con)
245 {
246 con << TAG <<
247 HTML_HEAD "<TITLE>Enter new user</TITLE></HEAD>"
248 BODY
249 "<H2>Add user</H2>"
250 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
251 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
252 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"addUser\">"
253 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
254 "\"><TABLE>"
255 "<TR><TH ALIGN=LEFT>User name:</TH>"
256 "<TD><INPUT TYPE=text NAME=\"name\" SIZE=30</TD></TR>"
257 "<TR><TH ALIGN=LEFT>E-mail:</TH>"
258 "<TD><INPUT TYPE=text NAME=\"email\" SIZE=30 </TD></TR></TABLE><P>"
259 "<INPUT TYPE=submit VALUE=\"Add\"> "
260 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
261 mainMenuReference(con);
262 return true;
263 }
264
addEngineerForm(WWWconnection & con)265 bool addEngineerForm(WWWconnection& con)
266 {
267 con << TAG <<
268 HTML_HEAD "<TITLE>Enter new engineer</TITLE></HEAD>"
269 BODY
270 "<H2>Add engineer</H2>"
271 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
272 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
273 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"addEngineer\">"
274 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
275 "\"><TABLE>"
276 "<TR><TH ALIGN=LEFT>Engineer name:</TH>"
277 "<TD><INPUT TYPE=text NAME=\"name\" SIZE=30</TD></TR>"
278 "<TR><TH ALIGN=LEFT>E-mail:</TH>"
279 "<TD><INPUT TYPE=text NAME=\"email\" SIZE=30 </TD></TR></TABLE><P>"
280 "<INPUT TYPE=submit VALUE=\"Add\"> "
281 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
282 mainMenuReference(con);
283 return true;
284 }
285
addSoftwareForm(WWWconnection & con)286 bool addSoftwareForm(WWWconnection& con)
287 {
288 con << TAG <<
289 HTML_HEAD "<TITLE>Enter new software product</TITLE></HEAD>"
290 BODY
291 "<H2>Add software product</H2>"
292 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
293 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
294 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"addSoftware\">"
295 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
296 "\"><TABLE>"
297 "<TR><TH ALIGN=LEFT>Software name:</TH>"
298 "<TD><INPUT TYPE=text NAME=\"software\" SIZE=40</TD></TR>"
299 "<TR><TH ALIGN=LEFT>Version number:</TH>"
300 "<TD><INPUT TYPE=text NAME=\"version\" SIZE=8</TD></TR>"
301 "<TR><TH ALIGN=LEFT>Version label:</TH>"
302 "<TD><INPUT TYPE=text NAME=\"label\" SIZE=20</TD></TR>"
303 "<TR><TH ALIGN=LEFT>Version comment:</TH>"
304 "<TD><INPUT TYPE=text NAME=\"comment\" SIZE=40</TD></TR>"
305 "</TABLE><P><INPUT TYPE=submit VALUE=\"Add\"> "
306 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
307 mainMenuReference(con);
308 return true;
309 }
310
selectSoftwareForm(WWWconnection & con)311 bool selectSoftwareForm(WWWconnection& con)
312 {
313 con << TAG <<
314 HTML_HEAD "<TITLE>Select software product</TITLE></HEAD>"
315 BODY
316 "<H2>Select software product</H2>"
317 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
318 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
319 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"softwareForm\">"
320 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
321 "\"><SELECT SIZE=15 NAME=\"software\">";
322 if (products.select() > 0) {
323 print(con, products);
324 con << TAG <<
325 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
326 } else {
327 con << TAG << EMPTY_LIST;
328 }
329 con << TAG << "</FORM>";
330 mainMenuReference(con);
331 return true;
332 }
333
removeSoftwareForm(WWWconnection & con)334 bool removeSoftwareForm(WWWconnection& con)
335 {
336 con << TAG <<
337 HTML_HEAD "<TITLE>Remove software product</TITLE></HEAD>"
338 BODY
339 "<H2>Remove software product</H2>"
340 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
341 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
342 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"removeSoftware\">"
343 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
344 "\"><SELECT SIZE=15 NAME=\"software\">";
345 if (products.select() != 0) {
346 print(con, products);
347 con << TAG << "</SELECT><BR><INPUT TYPE=\"submit\" VALUE=\"Remove\">";
348 } else {
349 con << TAG << EMPTY_LIST;
350 }
351 con << TAG << "</FORM>";
352 mainMenuReference(con);
353 return true;
354 }
355
selectPersonForm(WWWconnection & con)356 bool selectPersonForm(WWWconnection& con)
357 {
358 con << TAG <<
359 HTML_HEAD "<TITLE>Select a person</TITLE></HEAD>"
360 BODY
361 "<H2>Select a person</H2>"
362 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
363 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
364 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"userForm\">"
365 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
366 "\"><SELECT SIZE=20 NAME=\"name\">";
367 if (persons.select() != 0) {
368 print(con, persons);
369 con << TAG << "</SELECT><BR><INPUT TYPE=submit VALUE=\"Select\">";
370 } else {
371 con << TAG << EMPTY_LIST;
372 }
373 con << TAG << "</FORM>";
374 mainMenuReference(con);
375 return true;
376 }
377
removePersonForm(WWWconnection & con)378 bool removePersonForm(WWWconnection& con)
379 {
380 con << TAG <<
381 HTML_HEAD "<TITLE>Remove a person</TITLE></HEAD>"
382 BODY
383 "<H2>Remove a person</H2>"
384 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
385 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
386 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"removePerson\">"
387 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
388 "\"><SELECT SIZE=20 NAME=\"name\">";
389 if (persons.select() != 0) {
390 print(con, persons);
391 con << TAG << "</SELECT><BR><INPUT TYPE=submit VALUE=\"Remove\">";
392 } else {
393 con << TAG << EMPTY_LIST;
394 }
395 con << TAG << "</FORM>";
396 mainMenuReference(con);
397 return true;
398 }
399
selectBugForm(WWWconnection & con)400 bool selectBugForm(WWWconnection& con)
401 {
402 con << TAG <<
403 HTML_HEAD "<TITLE>Select a bug</TITLE></HEAD>"
404 BODY
405 "<H2>Select a bug</H2>"
406 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
407 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
408 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"bugForm\">"
409 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
410 "\"><SELECT SIZE=15 NAME=\"bug\">";
411 if (bugs.select() != 0) {
412 print(con, bugs);
413 con << TAG <<
414 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
415 } else {
416 con << TAG << EMPTY_LIST;
417 }
418 con << TAG << "</FORM>";
419 mainMenuReference(con);
420 return true;
421 }
422
removeBugForm(WWWconnection & con)423 bool removeBugForm(WWWconnection& con)
424 {
425 con << TAG <<
426 HTML_HEAD "<TITLE>Remove a bug</TITLE></HEAD>"
427 BODY
428 "<H2>Remove a bug</H2>"
429 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
430 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
431 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"removeBug\">"
432 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
433 "\"><SELECT SIZE=15 NAME=\"bug\">";
434 if (bugs.select() != 0) {
435 print(con, bugs);
436 con << TAG << "</SELECT><BR><INPUT TYPE=submit VALUE=\"Remove\">";
437 } else {
438 con << TAG << EMPTY_LIST;
439 }
440 con << TAG << "</FORM>";
441 mainMenuReference(con);
442 return true;
443 }
444
changePasswordForm(WWWconnection & con)445 bool changePasswordForm(WWWconnection& con)
446 {
447 con << TAG <<
448 HTML_HEAD "<TITLE>Change password</TITLE></HEAD>"
449 BODY
450 "<H2>Change password</H2>"
451 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
452 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
453 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"changePassword\">"
454 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
455 "\"><INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << con.get("name") <<
456 "\"><TABLE>"
457 "<TR><TH ALIGN=LEFT>New password:</TH>"
458 "<TD><INPUT TYPE=password NAME=\"password\" SIZE=20</TD></TR>"
459 "<TR><TH ALIGN=LEFT>Re-type password:</TH>"
460 "<TD><INPUT TYPE=password NAME=\"password2\" SIZE=20</TD></TR>"
461 "</TABLE><P>"
462 "<INPUT TYPE=submit VALUE=\"Change\"> "
463 "<INPUT TYPE=reset VALUE=\"Reset\">"
464 "</FORM>";
465 con << TAG << "</FORM>";
466 mainMenuReference(con);
467 return true;
468 }
469
shutdown(WWWconnection & con)470 bool shutdown(WWWconnection& con)
471 {
472 con << TAG <<
473 HTML_HEAD "<TITLE>BUGDB message</TITLE></HEAD><BODY>"
474 "<H1>BUGDB server is terminated</H1></BODY></HTML>";
475 return false;
476 }
477
478 bool userForm(WWWconnection& con);
479 bool userGroupForm(WWWconnection& con);
480 bool softwareForm(WWWconnection& con);
481
addUser(WWWconnection & con)482 bool addUser(WWWconnection& con)
483 {
484 Person person;
485 person.sName = key = con.get("name");
486 person.sEmailAddress = con.get("email");
487 person.sPassword = "";
488 person.status = Person::isUser;
489 person.nReports = 0;
490 if (persons.select(qPerson) != 0) {
491 error(con, "Person already exists");
492 return true;
493 }
494 insert(person);
495 return userForm(con);
496 }
497
addEngineer(WWWconnection & con)498 bool addEngineer(WWWconnection& con)
499 {
500 Person person;
501 person.sName = key = con.get("name");
502 person.sEmailAddress = con.get("email");
503 person.sPassword = "";
504 person.status = Person::isEngineer;
505 person.nReports = 0;
506 if (persons.select(qPerson) != 0) {
507 error(con, "Person already exists");
508 return true;
509 }
510 insert(person);
511 return userForm(con);
512 }
513
removePerson(WWWconnection & con)514 bool removePerson(WWWconnection& con)
515 {
516 key = con.get("name");
517 if (key == NULL) {
518 error(con, "No person was selected");
519 return true;
520 }
521 if (persons.select(qPerson) == 0) {
522 error(con, "No such person");
523 } else if (persons->nReports > 0
524 || persons->setReportedBugs.length() > 0)
525 {
526 error(con, "It is not possible to delete person who is author "
527 "of existed bug reports");
528 } else {
529 persons.remove();
530 message(con, "Person is removed");
531 }
532 return true;
533 }
534
addSoftware(WWWconnection & con)535 bool addSoftware(WWWconnection& con)
536 {
537 Software software;
538 Version version;
539 software.sName = key = con.get("software");
540 if (products.select(qSoftware) != 0) {
541 error(con, "Software product already exists");
542 return true;
543 }
544 char* versionStr = con.get("version");
545 if (sscanf(versionStr, "%d.%d", &version.majorVersionNumber,
546 &version.minorVersionNumber) != 2)
547 {
548 error(con, "Bad version number (MAJOR.MINOR expected)");
549 return true;
550 }
551 version.sComment = con.get("comment");
552 version.sLabel = con.get("label");
553 version.released = dbDateTime::current();
554 software.pVersions = insert(version);
555 insert(software);
556 con.addPair("action", "Select");
557 return softwareForm(con);
558 }
559
removeSoftware(WWWconnection & con)560 bool removeSoftware(WWWconnection& con)
561 {
562 key = con.get("software");
563 if (products.select(qSoftware) == 0) {
564 error(con, "No such software product");
565 return true;
566 }
567 if (products->setBugs.length() != 0) {
568 error(con, "Can not remove software with non-empty reported bug list");
569 return true;
570 }
571 products.remove();
572 message(con, "Software product is removed");
573 return true;
574 }
575
removeBug(WWWconnection & con)576 bool removeBug(WWWconnection& con)
577 {
578 char* bug = con.get("bug");
579 if (bug == NULL) {
580 error(con, "No bug was selected");
581 } else {
582 bugId = atoi(bug);
583 if (bugs.select(qBug) == 0) {
584 error(con, "No such bug");
585 } else {
586 if (bugs->pReportHistory != null ||
587 bugs->pWorkArounds != null)
588 {
589 error(con, "Can not remove bug with existed reports");
590 return true;
591 }
592 bugs.remove();
593 message(con, "Bug is removed");
594 }
595 }
596 return true;
597 }
598
changePassword(WWWconnection & con)599 bool changePassword(WWWconnection& con)
600 {
601 char* password = con.get("password");
602 char* password2 = con.get("password2");
603 if (strcmp(password, password2) != 0) {
604 error(con, "Passwords are not equal");
605 } else {
606 key = con.get("name");
607 if (persons.select(qPerson) == 0) {
608 error(con, "No such person");
609 } else {
610 persons->sPassword = password;
611 persons.update();
612 message(con, "Password changed");
613 }
614 }
615 return true;
616 }
617
updatePerson(WWWconnection & con)618 bool updatePerson(WWWconnection& con)
619 {
620 char* name = con.get("name");
621 key = name;
622 if (persons.select(qPerson) == 0) {
623 error(con, "No such person");
624 return true;
625 } else {
626 char* newName = con.get("newname");
627 char* eMail = con.get("email");
628 if (eMail != NULL) {
629 persons->sEmailAddress = eMail;
630 }
631 if (newName != NULL) {
632 persons->sName = newName;
633 con.addPair("name", newName);
634 if (strcmp(name, con.get("myself")) == 0) {
635 con.addPair("myself", newName);
636 }
637 }
638 persons.update();
639 }
640 return userForm(con);
641 }
642
login(WWWconnection & con)643 bool login(WWWconnection& con)
644 {
645 char* name = con.get("name");
646 key = con.get("name");
647 if (persons.select(qPerson) == 0) {
648 error(con, "No such person");
649 return true;
650 }
651 if (!persons->checkPassword(con.get("password"))) {
652 error(con, "Incorrect password");
653 return true;
654 }
655 con.addPair("myself", name);
656 return userForm(con);
657 }
658
bugQueryForm(WWWconnection & con)659 bool bugQueryForm(WWWconnection& con)
660 {
661 int i;
662 con << TAG <<
663 HTML_HEAD "<TITLE>Query to locate bug</TITLE></HEAD>"
664 BODY
665 "<H2>Bug query</H2>"
666 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
667 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
668 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"bugQuery\">"
669 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
670 "\"><TABLE>"
671 "<TR><TH ALIGN=LEFT>Description substring:</TH>"
672 "<TD><INPUT TYPE=text NAME=\"summary\" SIZE=30</TD></TR>"
673 "<TR><TH ALIGN=LEFT>Category:</TH>"
674 "<TD><SELECT NAME=\"category\" SIZE=1>"
675 "<OPTION VALUE=0 SELECTED></OPTION>";
676 for (i = 1; eCATEGORY_STRING[i] != NULL; i++) {
677 con << TAG << "<OPTION VALUE=" << i << ">"
678 << eCATEGORY_STRING[i] << "</OPTION>";
679 }
680 con << TAG << "</SELECT></TD></TR>"
681 "<TR><TH ALIGN=LEFT>Severity:</TH>"
682 "<TD><SELECT NAME=\"severity\" SIZE=1>"
683 "<OPTION VALUE=0 SELECTED></OPTION>";
684 for (i = 1; eSEVERITY_STRING[i] != NULL; i++) {
685 con << TAG << "<OPTION VALUE=" << i << ">"
686 << eSEVERITY_STRING[i] << "</OPTION>";
687 }
688 con << TAG << "</SELECT></TD></TR>"
689 "<TR><TH ALIGN=LEFT>Fixing priority:</TH>"
690 "<TD><SELECT NAME=\"priority\" SIZE=1>"
691 "<OPTION VALUE=0 SELECTED></OPTION>";
692 for (i = 1; eFIXING_PRIORITY_STRING[i] != NULL; i++) {
693 con << TAG << "<OPTION VALUE=" << i << ">"
694 << eFIXING_PRIORITY_STRING[i] << "</OPTION>";
695 }
696 con << TAG <<
697 "</SELECT></TD></TR>"
698 "<TR><TH ALIGN=LEFT>Platform:</TH>"
699 "<TD><INPUT TYPE=text NAME=\"platform\"</TD></TR>"
700 "<TR><TH ALIGN=LEFT>OS</TH>"
701 "<TD><INPUT TYPE=text NAME=\"os\"</TD></TR>"
702 "<TR><TH ALIGN=LEFT>Software:</TH>"
703 "<TD><INPUT TYPE=text NAME=\"software\"</TD></TR>"
704 "<TR><TH ALIGN=LEFT>Assigned to:</TH>"
705 "<TD><INPUT TYPE=text NAME=\"engineer\"</TD></TR>"
706 "<TR><TH ALIGN=LEFT>Reported by:</TH>"
707 "<TD><INPUT TYPE=text NAME=\"user\"</TD></TR>"
708 "<TR><TH ALIGN=LEFT>Major version number:</TH>"
709 "<TD>from <INPUT TYPE=text NAME=\"minmajor\" SIZE=4>"
710 " to <INPUT TYPE=text NAME=\"maxmajor\" SIZE=4</TD></TR>"
711 "<TR><TH ALIGN=LEFT>Minor version number:</TH>"
712 "<TD>from <INPUT TYPE=text NAME=\"minminor\" SIZE=4</TD>"
713 " to <INPUT TYPE=text NAME=\"maxminor\" SIZE=4</TD></TR></TABLE><P>"
714 "<INPUT TYPE=submit VALUE=\"Search\"> "
715 "<INPUT TYPE=reset VALUE=\"Reset\">"
716 "</FORM></BODY></HTML>";
717 return true;
718 }
719
720
bugQuery(WWWconnection & con)721 bool bugQuery(WWWconnection& con)
722 {
723 char* p;
724 dbQuery query;
725 query.reset();
726 p = con.get("software");
727 if (*p != '\0') {
728 query.add("pSoftware.sName like").add(p);
729 }
730 int4 category = atoi(con.get("category"));
731 if (category != 0) {
732 query.And("eCategory=").add(category);
733 }
734 int4 severity = atoi(con.get("severity"));
735 if (severity != 0) {
736 query.And("eSeverity=").add(severity);
737 }
738 int4 priority = atoi(con.get("priority"));
739 if (priority != 0) {
740 query.And("eFixingPriority=").add(priority);
741 }
742 p = con.get("os");
743 if (*p != '\0') {
744 query.And("sOperatingSystem like").add(p);
745 }
746 p = con.get("platform");
747 if (*p != '\0') {
748 query.And("sHardwarePlatform like").add(p);
749 }
750 p = con.get("engineer");
751 if (*p != '\0') {
752 query.And("pAssignedTo is not null and pAssignedTo.sName like").add(p);
753 }
754 p = con.get("user");
755 if (*p != '\0') {
756 query.And("pReportedBy.sName like").add(p);
757 }
758 p = con.get("summary");
759 if (*p != '\0') {
760 query.And("sOneLineSummary like").add(p);
761 }
762 p = con.get("minmajor");
763 int minMajorVersionNumber = (*p == '\0') ? 0 : atoi(p);
764 p = con.get("maxmajor");
765 int maxMajorVersionNumber = (*p == '\0') ? INT_MAX : atoi(p);
766 p = con.get("minminor");
767 int minMinorVersionNumber = (*p == '\0') ? 0 : atoi(p);
768 p = con.get("maxminor");
769 int maxMinorVersionNumber = (*p == '\0') ? INT_MAX : atoi(p);
770 if (minMajorVersionNumber != 0) {
771 if (maxMajorVersionNumber != INT_MAX) {
772 query.And("pVersion.majorVersionNumber between")
773 .add(minMajorVersionNumber)
774 .add("and").add(maxMajorVersionNumber);
775 } else {
776 query.And("pVersion.majorVersionNumber>=")
777 .add(minMajorVersionNumber);
778 }
779 } else if (maxMajorVersionNumber != INT_MAX) {
780 query.And("pVersion.majorVersionNumber<=").add(maxMajorVersionNumber);
781 }
782 if (minMinorVersionNumber != 0) {
783 if (maxMinorVersionNumber != INT_MAX) {
784 query.And("pVersion.minorVersionNumber between")
785 .add(minMinorVersionNumber)
786 .add("and").add(maxMinorVersionNumber);
787 } else {
788 query.And("pVersion.minorVersionNumber>=")
789 .add(minMinorVersionNumber);
790 }
791 } else if (maxMinorVersionNumber != INT_MAX) {
792 query.And("pVersion.minorVersionNumber<=").add(maxMinorVersionNumber);
793 }
794 con << TAG <<
795 HTML_HEAD "<TITLE>List of selected bugs</TITLE></HEAD>"
796 BODY
797 "<H2>Selected bugs</H2>"
798 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
799 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress() <<
800 "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"bugForm\">"
801 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself") <<
802 "\"><SELECT NAME=\"bug\" SIZE=20>";
803 if (bugs.select(query) != 0) {
804 print(con, bugs);
805 con << TAG <<
806 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
807 } else {
808 con << TAG << EMPTY_LIST;
809 }
810 con << TAG << "</FORM>";
811 mainMenuReference(con);
812 return true;
813 }
814
815
userForm(WWWconnection & con)816 bool userForm(WWWconnection& con)
817 {
818 char* name = con.get("name");
819 if (name == NULL) {
820 error(con, "No person was selected");
821 return true;
822 }
823 char* myself = con.get("myself");
824 key = myself;
825 if (persons.select(qPerson) == 0) {
826 error(con, "Person authorization failed");
827 return true;
828 }
829 int selfStatus = persons->status;
830 key = name;
831 if (persons.select(qPerson) == 0) {
832 error(con, "Person not found");
833 return true;
834 }
835 if (persons->status == Person::isAdministrator) {
836 con << TAG <<
837 HTML_HEAD "<TITLE>BUGDB Administrator</TITLE></HEAD>"
838 BODY
839 "<H2>Administrator menu</H2><FONT SIZE=\"+1\">"
840 "<UL><LI><A HREF=\"" << con.getStub() << "?socket="
841 << con.getAddress()
842 << "&page=addUserForm&myself=" << URL << myself
843 << "\">Add user</A>"
844 "<LI><A HREF=\"" << con.getStub() << "?socket=" << con.getAddress()
845 << "&page=addEngineerForm&myself=" << URL << myself
846 << "\">Add engineer</A>"
847 "<LI><A HREF=\"" << con.getStub() << "?socket=" << con.getAddress()
848 << "&page=selectPersonForm&myself=" << URL << myself
849 << "\">Select person"
850 "</A>"
851 "<LI><A HREF=\"" << con.getStub() << "?socket=" << con.getAddress()
852 << "&page=removePersonForm&myself=" << URL << myself
853 << "\">Remove person</A></UL>"
854
855 "<UL><LI><A HREF=\"" << con.getStub() << "?socket="
856 << con.getAddress()
857 << "&page=addSoftwareForm&myself=" << URL << myself
858 << "\">Add software product</A>"
859 "<LI><A HREF=\"" << con.getStub() << "?socket=" << con.getAddress()
860 << "&page=selectSoftwareForm&myself=" << URL << myself
861 << "\">Select software product</A>"
862 "<LI><A HREF=\"" << con.getStub() << "?socket=" << con.getAddress()
863 << "&page=removeSoftwareForm&myself=" << URL << myself
864 << "\">Remove software product</A></UL>"
865
866 "<UL><LI><A HREF=\"" << con.getStub() << "?socket="
867 << con.getAddress()
868 << "&page=selectBugForm&myself=" << URL << myself
869 << "\">Select bug</A>"
870 "<LI><A HREF=\"" << con.getStub() << "?socket="
871 << con.getAddress()
872 << "&page=removeBugForm&myself=" << URL << myself
873 << "\">Remove bug</A></UL>";
874 if (selfStatus == Person::isAdministrator) {
875 con << TAG <<
876 "<UL><LI><A HREF=\"" << con.getStub() << "?socket="
877 << con.getAddress() << "&page=changePasswordForm"
878 "&myself=administrator&name=" << URL << myself
879 << "\">Change password</A>"
880 "<LI><A HREF=\"" << con.getStub() << "?socket="
881 << con.getAddress()
882 << "&page=shutdown\">Shutdown server</A></UL>";
883 }
884 con << TAG << "</FONT></BODY></HTML>";
885 return true;
886 }
887 con <<
888 HTML_HEAD "<TITLE>" << name << "</TITLE></HEAD>"
889 BODY
890 "<H2>" << name << "</H2><FONT SIZE=\"+1\">"
891 "<UL><LI><A HREF=\"" << con.getStub() << "?socket="
892 << con.getAddress() << "&page=createBugReportForm&myself="
893 << URL << myself << "\">Create bug report</A>";
894 if (persons->sEmailAddress[0] != '\0') {
895 con << TAG <<
896 "<LI><A HREF=\"mailto:" << persons->sEmailAddress
897 << "\">Send e-mail</A>"
898 "<LI><A HREF=\"" << con.getStub() << "?socket=" << con.getAddress()
899 << "&page=bugQueryForm&myself=" << URL << myself
900 << "\">Find a bug</A>";
901 }
902 if (strcmp(myself, name) == 0 || selfStatus == Person::isAdministrator) {
903 con << TAG << "<LI><A HREF=\"" << con.getStub() << "?socket="
904 << con.getAddress() << "&page=changePasswordForm&myself="
905 << URL << myself << "&name=" << URL << name <<
906 "\">Change password</A>";
907 }
908 con << TAG <<
909 "</UL></FONT><P><TABLE><TR><TH ALIGN=LEFT>Person name:</TH>"
910 "<TD><FORM METHOD=POST ACTION=\""
911 << con.getStub() << "\"><INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
912 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\""
913 "updatePerson\"><INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself
914 << "\"><INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
915 "<INPUT TYPE=text NAME=\"newname\" SIZE=30 VALUE=\""
916 << name << "\"><INPUT TYPE=submit VALUE=\"Change\"></FORM></TD></TR>"
917 "<TR><TH ALIGN=LEFT>E-Mail:</TH>"
918 "<TD><FORM METHOD=POST ACTION=\""
919 << con.getStub() << "\"><INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
920 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\""
921 "updatePerson\"><INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself
922 << "\"><INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
923 "<INPUT TYPE=text NAME=\"email\" SIZE=30 VALUE=\""
924 << persons->sEmailAddress << "\">"
925 "<INPUT TYPE=submit VALUE=\"Change\"></FORM></TD></TR>";
926 if (persons->status != Person::isUser) {
927 con << TAG << "<TR><TH ALIGN=LEFT>Projects:</TH>"
928 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
929 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
930 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
931 "VALUE=\"softwareForm\">"
932 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
933 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
934 "<SELECT NAME=\"software\" SIZE=1>";
935 if (persons->setProjects.length() != 0) {
936 print(con, persons->setProjects);
937 con << TAG <<
938 "</SELECT><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">"
939 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Detach\">";
940 } else {
941 con << TAG << EMPTY_LIST;
942 }
943 if (products.select() != 0) {
944 con << TAG <<
945 "</FORM></TD></TR>"
946 "<TR><TH ALIGN=LEFT>Attach to project:</TH>"
947 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
948 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
949 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
950 "VALUE=\"attachToProject\">"
951 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<"\">"
952 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
953 "<SELECT NAME=\"software\" SIZE=1>";
954 print(con, products);
955 con << TAG << "</SELECT><INPUT TYPE=submit VALUE=\"Attach\">";
956 }
957 con << TAG <<
958 "</FORM></TD></TR>"
959 "<TR><TH ALIGN=LEFT>Find a person:</TH>"
960 "<TD><FORM METHOD=POST ACTION=\""
961 << con.getStub() << "\">"
962 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
963 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
964 "VALUE=\"userForm\">"
965 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
966 "<INPUT TYPE=text NAME=\"name\" SIZE=30>"
967 "<INPUT TYPE=submit VALUE=\"Find\"></FORM></TD></TR>";
968 }
969 con << TAG << "<TR><TH ALIGN=LEFT>Used software:</TH>"
970 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
971 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
972 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
973 "VALUE=\"softwareForm\">"
974 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
975 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
976 "<SELECT NAME=\"software\" SIZE=1>";
977 if (persons->setUsedSoftware.length() != 0) {
978 print(con, persons->setUsedSoftware);
979 con << TAG <<
980 "</SELECT><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">"
981 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Unregister\">";
982 } else {
983 con << TAG << EMPTY_LIST;
984 }
985 if (products.select() != 0) {
986 con << TAG <<
987 "</FORM></TD></TR>"
988 "<TR><TH ALIGN=LEFT>Register as software user:</TH>"
989 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
990 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
991 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
992 "VALUE=\"registerSoftware\">"
993 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
994 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
995 "<SELECT NAME=\"software\" SIZE=1>";
996 print(con, products);
997 con << TAG << "</SELECT><INPUT TYPE=submit VALUE=\"Register\">";
998 }
999 con << TAG << "</FORM></TD></TR></TABLE><P>"
1000 "<B>Reported bugs:</B><BR>"
1001 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1002 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1003 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
1004 "VALUE=\"bugForm\">"
1005 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1006 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
1007 "<SELECT NAME=\"bug\" SIZE=5>";
1008 if (persons->setReportedBugs.length() != 0) {
1009 print(con, persons->setReportedBugs);
1010 con << TAG <<
1011 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
1012 } else {
1013 con << TAG << EMPTY_LIST;
1014 }
1015 con << TAG << "</FORM><P>";
1016 if (persons->status != Person::isUser) {
1017 con << TAG <<
1018 "<P><B>Assigned bugs:</B><BR>"
1019 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1020 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1021 << con.getAddress() << "\"><INPUT TYPE=hidden "
1022 "NAME=\"page\" VALUE=\"bugForm\">"
1023 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1024 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
1025 "<SELECT NAME=\"bug\" SIZE=5>";
1026 if (persons->setAssignedBugs.length() != 0) {
1027 print(con, persons->setAssignedBugs);
1028 con << TAG <<
1029 "</SELECT><BR>"
1030 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\"> "
1031 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Deassign\">";
1032 } else {
1033 con << TAG << EMPTY_LIST;
1034 }
1035 con << TAG << "</FORM>";
1036 }
1037 if (strcmp(name, myself) == 0) {
1038 con << TAG << "</BODY></HTML>";
1039 } else {
1040 mainMenuReference(con);
1041 }
1042 return true;
1043 }
1044
1045
createBugReportForm(WWWconnection & con)1046 bool createBugReportForm(WWWconnection& con)
1047 {
1048 int i;
1049 sequencer.select();
1050 con << TAG <<
1051 HTML_HEAD "<TITLE>Bug</TITLE></HEAD>"
1052 BODY
1053 "<H2>Bug</H2>"
1054 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1055 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1056 << con.getAddress() << "\"><INPUT TYPE=hidden "
1057 "NAME=\"page\" VALUE=\"createBugReport\">"
1058 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\""<<con.get("myself")<<"\">"
1059 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << ++sequencer->nBugs << ">"
1060 "<TABLE><TH ALIGN=LEFT>Summary:</TH>"
1061 "<TD><INPUT TYPE=text NAME=\"summary\" SIZE=40></TD></TR>"
1062 "<TR><TH ALIGN=LEFT>Category:</TH>"
1063 "<TD><SELECT NAME=\"category\" SIZE=1>";
1064 for (i = 1; eCATEGORY_STRING[i] != NULL; i++) {
1065 con << TAG << "<OPTION SELECTED VALUE=" << i << ">"
1066 << eCATEGORY_STRING[i] << "</OPTION>";
1067 }
1068 con << TAG << "</SELECT></TD></TR>"
1069 "<TR><TH ALIGN=LEFT>Severity:</TH>"
1070 "<TD><SELECT NAME=\"severity\" SIZE=1>";
1071 for (i = 1; eSEVERITY_STRING[i] != NULL; i++) {
1072 con << TAG << "<OPTION SELECTED VALUE=" << i << ">"
1073 << eSEVERITY_STRING[i] << "</OPTION>";
1074 }
1075 con << TAG <<
1076 "</SELECT></TD></TR>"
1077 "<TR><TH ALIGN=LEFT>Priority:</TH>"
1078 "<TD><SELECT NAME=\"priority\" SIZE=1>";
1079 for (i = 1; eFIXING_PRIORITY_STRING[i] != NULL; i++) {
1080 con << TAG << "<OPTION SELECTED VALUE=" << i << ">"
1081 << eFIXING_PRIORITY_STRING[i] << "</OPTION>";
1082 }
1083 con << TAG <<
1084 "</SELECT></TD></TR>"
1085 "<TR><TH ALIGN=LEFT>Software:</TH>"
1086 "<TD><SELECT NAME=\"software\" SIZE=1>";
1087 if (products.select() != 0) {
1088 print(con, products);
1089 }
1090 con << TAG <<
1091 "</SELECT></TD></TR>"
1092 "<TR><TH ALIGN=LEFT>Version:</TH>"
1093 "<TD><INPUT TYPE=text NAME=\"version\"></TD></TR>"
1094 "<TR><TH ALIGN=LEFT>Platform:</TH>"
1095 "<TD><INPUT TYPE=text NAME=\"platform\"</TD></TR>"
1096 "<TR><TH ALIGN=LEFT>OS:</TH>"
1097 "<TD><INPUT TYPE=text NAME=\"os\"></TD></TR></TABLE><P>"
1098 "<INPUT TYPE=submit VALUE=\"Submit\"> "
1099 "<INPUT TYPE=reset></FORM>";
1100 mainMenuReference(con);
1101 sequencer.update();
1102 return true;
1103 }
1104
1105 bool bugForm(WWWconnection& con);
1106
createBugReport(WWWconnection & con)1107 bool createBugReport(WWWconnection& con)
1108 {
1109 key = con.get("myself");
1110 if (persons.select(qPerson) == 0) {
1111 error(con, "Author unknown");
1112 return true;
1113 }
1114 key = con.get("software");
1115 if (products.select(qSoftware) == 0) {
1116 error(con, "No such software product");
1117 return true;
1118 }
1119 if (sscanf(con.get("version"), "%d.%d", &majorVersion, &minorVersion) != 2)
1120 {
1121 error(con, "Bad version format");
1122 return true;
1123 }
1124 initialVersion = products->pVersions;
1125 if (versions.select(qVersion) == 0) {
1126 error(con, "No such software product version");
1127 return true;
1128 }
1129
1130 Bug bug;
1131 bug.bugId = atoi(con.get("bug"));
1132 bug.sOneLineSummary = con.get("summary");
1133 bug.eCategory = atoi(con.get("category"));
1134 bug.eFixingPriority = atoi(con.get("priority"));
1135 bug.eSeverity = atoi(con.get("severity"));
1136 bug.sOperatingSystem = con.get("os");
1137 bug.sHardwarePlatform = con.get("platform");
1138 bug.pReportedBy = persons.currentId();
1139 bug.pAssignedTo = null;
1140 bug.pSoftware = products.currentId();
1141 bug.pVersion = versions.currentId();
1142 bug.nReports = 0;
1143 insert(bug);
1144 con.addPair("action", "Select");
1145 return bugForm(con);
1146 }
1147
bugForm(WWWconnection & con)1148 bool bugForm(WWWconnection& con)
1149 {
1150 int i;
1151 char* bugStr = con.get("bug");
1152 bugId = atoi(bugStr);
1153 if (bugs.select(qBug) == 0) {
1154 error(con, "No bug was selected");
1155 return true;
1156 }
1157 char* myself = con.get("myself");
1158 if (strcmp(con.get("action"), "Remove") == 0) {
1159 dbReference<Bug> pBug = bugs.currentId();
1160 bugId = atoi(con.get("relatedbug"));
1161 if (bugs.select(qBug) == 0) {
1162 error(con, "No such bug");
1163 return true;
1164 }
1165 int i = rindex(bugs->setSimilarBugs, pBug);
1166 if (i < 0) {
1167 error(con, "No such related bug");
1168 return true;
1169 }
1170 bugs->setSimilarBugs.remove(i);
1171 bugs.update();
1172 return bugForm(con);
1173 }
1174 key = myself;
1175 if (persons.select(qPerson) == 0) {
1176 error(con, "No such user");
1177 return true;
1178 }
1179 if (strcmp(con.get("action"), "Deassign") == 0) {
1180 int i = rindex(persons->setAssignedBugs, bugs.currentId());
1181 if (i < 0) {
1182 error(con, "Bug was not assigned");
1183 return true;
1184 }
1185 persons->setAssignedBugs.remove(i);
1186 persons.update();
1187 con.addPair("name", myself);
1188 return userForm(con);
1189 }
1190
1191 int personStatus = persons->status;
1192 products.at(bugs->pSoftware);
1193 versions.at(bugs->pVersion);
1194 con << TAG <<
1195 HTML_HEAD "<TITLE>Bug in " << products->sName << " v. " <<
1196 versions->getVersionString() << "</TITLE></HEAD>"
1197 BODY
1198 "<H2>Bug in " << products->sName << " v. "
1199 << versions->getVersionString() << "</H2>"
1200 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1201 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1202 << con.getAddress() << "\"><INPUT TYPE=hidden "
1203 "NAME=\"page\" VALUE=\"updateBug\">"
1204 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1205 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1206 "<TABLE><TH ALIGN=LEFT>Summary:</TH>"
1207 "<TD><INPUT TYPE=text NAME=\"summary\" SIZE=40 VALUE=\""
1208 << bugs->sOneLineSummary << "\"></TD></TR>"
1209 "<TR><TH ALIGN=LEFT>Category:</TH>"
1210 "<TD><SELECT NAME=\"category\" SIZE=1>"
1211 "<OPTION SELECTED VALUE=" << bugs->eCategory << ">"
1212 << eCATEGORY_STRING[bugs->eCategory] << "</OPTION>";
1213 for (i = 1; eCATEGORY_STRING[i] != NULL; i++) {
1214 con << TAG << "<OPTION VALUE=" << i << ">"
1215 << eCATEGORY_STRING[i] << "</OPTION>";
1216 }
1217 con << TAG <<
1218 "</SELECT></TD></TR>"
1219 "<TR><TH ALIGN=LEFT>Severity:</TH>"
1220 "<TD><SELECT NAME=\"severity\" SIZE=1>"
1221 "<OPTION SELECTED VALUE=" << bugs->eSeverity << ">"
1222 << eSEVERITY_STRING[bugs->eSeverity] << "</OPTION>";
1223 for (i = 1; eSEVERITY_STRING[i] != NULL; i++) {
1224 con << TAG << "<OPTION VALUE=" << i << ">"
1225 << eSEVERITY_STRING[i] << "</OPTION>";
1226 }
1227 con << TAG <<
1228 "</SELECT></TD></TR>"
1229 "<TR><TH ALIGN=LEFT>Priority:</TH>"
1230 "<TD><SELECT NAME=\"priority\" SIZE=1>"
1231 "<OPTION SELECTED VALUE=" << bugs->eFixingPriority << ">"
1232 << eFIXING_PRIORITY_STRING[bugs->eFixingPriority] << "</OPTION>";
1233 for (i = 1; eFIXING_PRIORITY_STRING[i] != NULL; i++) {
1234 con << TAG << "<OPTION VALUE=" << i << ">"
1235 << eFIXING_PRIORITY_STRING[i] << "</OPTION>";
1236 }
1237 con << TAG <<
1238 "</SELECT></TD></TR>"
1239 "<TR><TH ALIGN=LEFT>Platform:</TH>"
1240 "<TD><INPUT TYPE=text NAME=\"platform\" VALUE=\""
1241 << bugs->sHardwarePlatform << "\"></TD></TR>"
1242 "<TR><TH ALIGN=LEFT>OS:</TH>"
1243 "<TD><INPUT TYPE=text NAME=\"os\"VALUE=\""
1244 << bugs->sOperatingSystem << "\"></TD></TR>"
1245 "<TR><TH ALIGN=LEFT>Assigned to:</TH>"
1246 "<TD><SELECT SIZE=1 NAME=\"name\">";
1247 if (bugs->pAssignedTo != null) {
1248 persons.at(bugs->pAssignedTo);
1249 con << TAG << "<OPTION SELECTED VALUE=\"" << persons->sName
1250 << "\">" << persons->sName << "</OPTION>";
1251 } else {
1252 con << TAG << "<OPTION SELECTED VALUE=\"\"></OPTION>";
1253 }
1254 print(con, products->setEngineers);
1255 con << TAG << "</SELECT></TD></TR>"
1256 "<TR><TH ALIGN=LEFT>Similar with:</TH>"
1257 "<TD><SELECT NAME=\"similar\" SIZE=1>"
1258 "<OPTION SELECTED VALUE=\"\"></OPTION>";
1259 allBugs.select();
1260 print(con, allBugs);
1261 con << TAG << "</SELECT></TD></TR></TABLE><BR>";
1262
1263 if (personStatus != Person::isUser) {
1264 con << TAG <<
1265 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Update\"> "
1266 "<INPUT TYPE=reset VALUE=\"Reset\">";
1267 }
1268 con << TAG << "</FORM><P><FORM METHOD=POST ACTION=\"" << con.getStub()
1269 << "\"><INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1270 << con.getAddress() << "\">"
1271 "<INPUT TYPE=hidden NAME=\"page\" VALUE=\"updateReportForm\">"
1272 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1273 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1274 "<B>Report history:</B><BR><SELECT NAME=\"report\" SIZE=5>";
1275 firstReport = bugs->pReportHistory;
1276 if (reports.select(qAllReports) != 0) {
1277 print(con, reports);
1278 con << TAG <<
1279 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">"
1280 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Add\">";
1281 if (personStatus == Person::isAdministrator) {
1282 con << TAG <<
1283 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
1284 }
1285 } else {
1286 con << TAG << EMPTY_LIST
1287 "<BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Add\">";
1288 }
1289 con << TAG << "</FORM><P>";
1290
1291 con << TAG <<
1292 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1293 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1294 << con.getAddress() << "\"><INPUT TYPE=hidden "
1295 "NAME=\"page\" VALUE=\"updateWorkAroundForm\">"
1296 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1297 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1298 "<B>Work arounds:</B><BR><SELECT NAME=\"workaround\" SIZE=5>";
1299 firstReport = bugs->pWorkArounds;
1300 if (reports.select(qAllReports) != 0) {
1301 print(con, reports);
1302 con << TAG <<
1303 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">"
1304 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Add\">";
1305 if (personStatus == Person::isAdministrator) {
1306 con << TAG <<
1307 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
1308 }
1309 } else {
1310 con << TAG << EMPTY_LIST
1311 "<BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Add\">";
1312 }
1313 con << TAG << "</FORM><P>";
1314
1315 if (bugs->setSimilarBugs.length() != 0) {
1316 con << TAG <<
1317 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1318 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1319 << con.getAddress() << "\"><INPUT TYPE=hidden "
1320 "NAME=\"page\" VALUE=\"bugForm\">"
1321 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1322 "<INPUT TYPE=hidden NAME=\"relatedbug\" VALUE=" << bugStr << ">"
1323 "<B>Similar bugs:</B><BR><SELECT NAME=\"bug\" SIZE=1>";
1324 print(con, bugs->setSimilarBugs);
1325 con << TAG <<
1326 "</SELECT><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
1327 if (personStatus == Person::isAdministrator) {
1328 con << TAG <<
1329 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
1330 }
1331 con << TAG << "</FORM><P>";
1332 }
1333 con << TAG <<
1334 "</FORM><P>"
1335 "<FONT SIZE=\"+1\"><UL>";
1336 if (personStatus == Person::isUser) {
1337 if (bugs->pAssignedTo != null) {
1338 persons.at(bugs->pAssignedTo);
1339 con << TAG << "<LI>Assigned to <A HREF=\"mailto:"
1340 << persons->sEmailAddress << "\">"
1341 << persons->sName << "</A>";
1342 }
1343 persons.at(bugs->pReportedBy);
1344 con << TAG << "<LI>Reported by <A HREF=\"mailto:"
1345 << persons->sEmailAddress << "\">"
1346 << persons->sName << "</A></OL></FONT>";
1347 } else {
1348 if (bugs->pAssignedTo != null) {
1349 persons.at(bugs->pAssignedTo);
1350 con << TAG << "<LI>Assigned to <A HREF=\"" << con.getStub()
1351 << "?socket=" << con.getAddress()
1352 << "&page=userForm&myself=" << URL << myself
1353 << "&name=" << URL << persons->sName << "\">"
1354 << persons->sName << "</A>";
1355 }
1356 persons.at(bugs->pReportedBy);
1357 con << TAG
1358 << "<LI>Reported by <A HREF=\"" << con.getStub() << "?socket="
1359 << con.getAddress()
1360 << "&page=userForm&myself=" << URL << myself
1361 << "&name=" << URL << persons->sName << "\">"
1362 << persons->sName << "</A></OL></FONT>";
1363 }
1364 mainMenuReference(con);
1365 return true;
1366 }
1367
updateBug(WWWconnection & con)1368 bool updateBug(WWWconnection& con)
1369 {
1370 char* bugStr = con.get("bug");
1371 bugId = atoi(bugStr);
1372 if (bugs.select(qBug) == 0) {
1373 error(con, "No such bug");
1374 return true;
1375 }
1376 char* similar = con.get("similar");
1377 if (*similar != '\0') {
1378 int id = atoi(similar);
1379 if (id != bugId) {
1380 bugId = id;
1381 if (allBugs.select(qBug) != 0) {
1382 if (rindex(bugs->setSimilarBugs, allBugs.currentId()) < 0) {
1383 bugs->setSimilarBugs.append(allBugs.currentId());
1384 }
1385 }
1386 }
1387 }
1388 key = con.get("name");
1389 if (*key != '\0') {
1390 if (persons.select(qPerson) == 0 ||
1391 persons->status == Person::isUser)
1392 {
1393 error(con, "No such engineer");
1394 return true;
1395 }
1396 bugs->pAssignedTo = persons.currentId();
1397 }
1398 bugs.update();
1399 return bugForm(con);
1400 }
1401
1402
addReportForm(WWWconnection & con)1403 bool addReportForm(WWWconnection& con)
1404 {
1405 char* bugStr = con.get("bug");
1406 bugId = atoi(bugStr);
1407 if (bugs.select(qBug) == 0) {
1408 error(con, "No such bug");
1409 return true;
1410 }
1411 con << TAG <<
1412 HTML_HEAD "<TITLE>Bug report</TITLE></HEAD>"
1413 BODY
1414 "<H2>Bug report</H2>"
1415 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1416 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1417 << con.getAddress() << "\"><INPUT TYPE=hidden "
1418 "NAME=\"page\" VALUE=\"addReport\">"
1419 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1420 "<INPUT TYPE=hidden NAME=\"index\" VALUE=" << ++bugs->nReports
1421 << "><INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself")
1422 << "\"><B>Status: </B><SELECT SIZE=1 NAME=\"status\">";
1423 for (int i = 1; eSTATUS_STRING[i] != NULL; i++) {
1424 con << TAG << "<OPTION VALUE=" << i << ">" << eSTATUS_STRING[i]
1425 << "</OPTION>";
1426 }
1427 con << TAG <<
1428 "</SELECT><P>"
1429 "<B>Bug description:</B><P>"
1430 "<TEXTAREA COLS=40 ROWS=5 NAME=\"description\"></TEXTAREA><P>"
1431 "<INPUT TYPE=submit VALUE=\"Add\"> "
1432 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
1433 bugs.update();
1434 mainMenuReference(con);
1435 return true;
1436 }
1437
addReport(WWWconnection & con)1438 bool addReport(WWWconnection& con)
1439 {
1440 bugId = atoi(con.get("bug"));
1441 if (bugs.select(qBug) == 0) {
1442 error(con, "No such bug");
1443 return true;
1444 }
1445 key = con.get("myself");
1446 if (persons.select(qPerson) == 0) {
1447 error(con, "No such person");
1448 return true;
1449 }
1450 reportId = atoi(con.get("index"));
1451 firstReport = bugs->pReportHistory;
1452 if (reports.select(qReport) == 0) {
1453 Report report;
1454 report.pAuthor = persons.currentId();
1455 persons->nReports += 1;
1456 report.sDescription = con.get("description");
1457 report.index = reportId;
1458 report.pNext = bugs->pReportHistory;
1459 report.status = atoi(con.get("status"));
1460 report.creationDate = dbDateTime::current();
1461 bugs->pReportHistory = insert(report);
1462 persons.update();
1463 bugs.update();
1464 }
1465 con.addPair("action", "Select");
1466 return bugForm(con);
1467 }
1468
addWorkAroundForm(WWWconnection & con)1469 bool addWorkAroundForm(WWWconnection& con)
1470 {
1471 char* bugStr = con.get("bug");
1472 bugId = atoi(bugStr);
1473 if (bugs.select(qBug) == 0) {
1474 error(con, "No such bug");
1475 return true;
1476 }
1477 con << TAG <<
1478 HTML_HEAD "<TITLE>Work around</TITLE></HEAD>"
1479 BODY
1480 "<H2>Work around</H2>"
1481 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1482 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1483 << con.getAddress() << "\"><INPUT TYPE=hidden "
1484 "NAME=\"page\" VALUE=\"addWorkAround\">"
1485 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1486 "<INPUT TYPE=hidden NAME=\"index\" VALUE=" << ++bugs->nReports
1487 << "><INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself")
1488 << "\"><B>Status: </B><SELECT SIZE=1 NAME=\"status\">";
1489 for (int i = 1; eSTATUS_STRING[i] != NULL; i++) {
1490 con << TAG << "<OPTION VALUE=" << i << ">" << eSTATUS_STRING[i]
1491 << "</OPTION>";
1492 }
1493 con << TAG <<
1494 "</SELECT><P>"
1495 "<B>Description:</B><P>"
1496 "<TEXTAREA COLS=40 ROWS=5 NAME=\"description\"></TEXTAREA><P>"
1497 "<INPUT TYPE=submit VALUE=\"Add\"> "
1498 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
1499 bugs.update();
1500 mainMenuReference(con);
1501 return true;
1502 }
1503
addWorkAround(WWWconnection & con)1504 bool addWorkAround(WWWconnection& con)
1505 {
1506 bugId = atoi(con.get("bug"));
1507 if (bugs.select(qBug) == 0) {
1508 error(con, "No such bug");
1509 return true;
1510 }
1511 key = con.get("myself");
1512 if (persons.select(qPerson) == 0) {
1513 error(con, "No such person");
1514 return true;
1515 }
1516 reportId = atoi(con.get("index"));
1517 firstReport = bugs->pWorkArounds;
1518 if (reports.select(qReport) == 0) {
1519 Report report;
1520 report.pAuthor = persons.currentId();
1521 persons->nReports += 1;
1522 report.sDescription = con.get("description");
1523 report.index = reportId;
1524 report.pNext = bugs->pWorkArounds;
1525 report.status = atoi(con.get("status"));
1526 report.creationDate = dbDateTime::current();
1527 bugs->pWorkArounds = insert(report);
1528 persons.update();
1529 bugs.update();
1530 }
1531 con.addPair("action", "Select");
1532 return bugForm(con);
1533 }
1534
updateReportForm(WWWconnection & con)1535 bool updateReportForm(WWWconnection& con)
1536 {
1537 if (strcmp(con.get("action"), "Add") == 0) {
1538 return addReportForm(con);
1539 }
1540 char* bugStr = con.get("bug");
1541 bugId = atoi(bugStr);
1542 if (bugs.select(qBug) == 0) {
1543 error(con, "No such bug");
1544 return true;
1545 }
1546 char* report = con.get("report");
1547 if (report == NULL) {
1548 error(con, "No report was selected");
1549 return true;
1550 }
1551 int index = atoi(report);
1552 dbReference<Report> prev, curr = null, next = bugs->pReportHistory;
1553 do {
1554 prev = curr;
1555 if (next == null) {
1556 error(con, "No such report");
1557 return true;
1558 }
1559 reports.at(next);
1560 curr = next;
1561 next = reports->pNext;
1562 } while (reports->index != index);
1563
1564 if (strcmp(con.get("action"), "Remove") == 0) {
1565 reports.remove();
1566 bugs->nReports -= 1;
1567 if (prev == null) {
1568 bugs->pReportHistory = next;
1569 } else {
1570 reports.at(prev);
1571 reports->pNext = next;
1572 reports.update();
1573 }
1574 bugs.update();
1575 con.addPair("action", "Select");
1576 return bugForm(con);
1577 }
1578 char date[64];
1579 reports->creationDate.asString(date, sizeof date);
1580 char* myself = con.get("myself");
1581 key = myself;
1582 if (persons.select(qPerson) == 0) {
1583 error(con, "No such person");
1584 return true;
1585 }
1586 int personStatus = persons->status;
1587 persons.at(reports->pAuthor);
1588 con << TAG <<
1589 HTML_HEAD "<TITLE>Bug report from " << date << "</TITLE></HEAD>"
1590 BODY
1591 "<H2>Bug report from " << date << "</H2>"
1592 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1593 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1594 << con.getAddress() << "\"><INPUT TYPE=hidden "
1595 "NAME=\"page\" VALUE=\"updateReport\">"
1596 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1597 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1598 "\"><INPUT TYPE=hidden NAME=\"report\" VALUE=" << index << ">"
1599 "<B>Created by ";
1600 if (personStatus == Person::isUser) {
1601 con << TAG << "<A HREF=\"mailto:"
1602 << persons->sEmailAddress << "\">"
1603 << persons->sName << "</A>";
1604 } else {
1605 con << TAG <<
1606 "<A HREF=\"" << con.getStub() << "?socket="
1607 << con.getAddress()
1608 << "&page=userForm&myself=" << URL << myself
1609 << "&name=" << URL << persons->sName << "\">"
1610 << persons->sName << "</A>";
1611 }
1612 con << TAG << "<P>Status: </B><SELECT SIZE=1 NAME=\"status\">"
1613 "<OPTION SELECTED VALUE=" << reports->status << ">"
1614 << eSTATUS_STRING[reports->status] << "</OPTION>";
1615 for (int i = 1; eSTATUS_STRING[i] != NULL; i++) {
1616 con << TAG << "<OPTION VALUE=" << i << ">" << eSTATUS_STRING[i]
1617 << "</OPTION>";
1618 }
1619 con << TAG <<
1620 "</SELECT><P>"
1621 "<B>Bug description:</B><BR>"
1622 "<TEXTAREA COLS=40 ROWS=5 NAME=\"description\">"
1623 << reports->sDescription << "</TEXTAREA><P>";
1624 if (personStatus != Person::isUser) {
1625 con << TAG <<
1626 "<INPUT TYPE=submit VALUE=\"Update\"> "
1627 "<INPUT TYPE=reset VALUE=\"Reset\">";
1628 }
1629 con << TAG << "</FORM>";
1630 mainMenuReference(con);
1631 return true;
1632 }
1633
updateWorkAroundForm(WWWconnection & con)1634 bool updateWorkAroundForm(WWWconnection& con)
1635 {
1636 if (strcmp(con.get("action"), "Add") == 0) {
1637 return addWorkAroundForm(con);
1638 }
1639 char* bugStr = con.get("bug");
1640 bugId = atoi(bugStr);
1641 if (bugs.select(qBug) == 0) {
1642 error(con, "No such bug");
1643 return true;
1644 }
1645 char* workaround = con.get("workaround");
1646 int index = atoi(workaround);
1647 dbReference<Report> prev, curr = null, next = bugs->pWorkArounds;
1648 do {
1649 prev = curr;
1650 if (next == null) {
1651 error(con, "No such report");
1652 return true;
1653 }
1654 reports.at(next);
1655 curr = next;
1656 next = reports->pNext;
1657 } while (reports->index != index);
1658
1659 if (strcmp(con.get("action"), "Remove") == 0) {
1660 reports.remove();
1661 bugs->nReports -= 1;
1662 if (prev == null) {
1663 bugs->pWorkArounds = next;
1664 } else {
1665 reports.at(prev);
1666 reports->pNext = next;
1667 reports.update();
1668 }
1669 bugs.update();
1670 con.addPair("action", "Select");
1671 return bugForm(con);
1672 }
1673 char date[64];
1674 reports->creationDate.asString(date, sizeof date);
1675 char* myself = con.get("myself");
1676 key = myself;
1677 if (persons.select(qPerson) == 0) {
1678 error(con, "No such person");
1679 return true;
1680 }
1681 int personStatus = persons->status;
1682 persons.at(reports->pAuthor);
1683 con << TAG <<
1684 HTML_HEAD "<TITLE>Work around " << date << "</TITLE></HEAD>"
1685 BODY
1686 "<H2>Work around " << date << "</H2>"
1687 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1688 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1689 << con.getAddress() << "\"><INPUT TYPE=hidden "
1690 "NAME=\"page\" VALUE=\"updateWorkAround\">"
1691 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1692 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1693 "\"><INPUT TYPE=hidden NAME=\"workaround\" VALUE=" << index <<
1694 "><B>Created by ";
1695 if (personStatus == Person::isUser) {
1696 con << TAG << "<A HREF=\"mailto:"
1697 << persons->sEmailAddress << "\">"
1698 << persons->sName << "</A>";
1699 } else {
1700 con << TAG <<
1701 "<A HREF=\"" << con.getStub() << "?socket="
1702 << con.getAddress()
1703 << "&page=userForm&myself=" << URL << myself
1704 << "&name=" << URL << persons->sName << "\">"
1705 << persons->sName << "</A>";
1706 }
1707 con << TAG << "<P>Status: </B><SELECT SIZE=1 NAME=\"status\">"
1708 "<OPTION SELECTED VALUE=" << reports->status << ">"
1709 << eSTATUS_STRING[reports->status] << "</OPTION>";
1710 for (int i = 1; eSTATUS_STRING[i] != NULL; i++) {
1711 con << TAG << "<OPTION VALUE=" << i << ">" << eSTATUS_STRING[i]
1712 << "</OPTION>";
1713 }
1714 con << TAG <<
1715 "</SELECT><P>"
1716 "<B>Bug description:</B><BR>"
1717 "<TEXTAREA COLS=40 ROWS=5 NAME=\"description\">"
1718 << reports->sDescription << "</TEXTAREA><P>";
1719 if (personStatus != Person::isUser) {
1720 con << TAG <<
1721 "<INPUT TYPE=submit VALUE=\"Update\"> "
1722 "<INPUT TYPE=reset VALUE=\"Reset\">";
1723 }
1724 con << TAG << "</FORM>";
1725 mainMenuReference(con);
1726 return true;
1727 }
1728
updateReport(WWWconnection & con)1729 bool updateReport(WWWconnection& con)
1730 {
1731 bugId = atoi(con.get("bug"));
1732 if (bugs.select(qBug) == 0) {
1733 error(con, "No such bug");
1734 return true;
1735 }
1736 reportId = atoi(con.get("report"));
1737 firstReport = bugs->pReportHistory;
1738 if (reports.select(qReport) == 0) {
1739 error(con, "No report was selected");
1740 return true;
1741 }
1742 reports->sDescription = con.get("description");
1743 reports->status = atoi(con.get("status"));
1744 reports.update();
1745 con.addPair("action", "Select");
1746 return bugForm(con);
1747 }
1748
updateWorkAround(WWWconnection & con)1749 bool updateWorkAround(WWWconnection& con)
1750 {
1751 bugId = atoi(con.get("bug"));
1752 if (bugs.select(qBug) == 0) {
1753 error(con, "No such bug");
1754 return true;
1755 }
1756 reportId = atoi(con.get("workaround"));
1757 firstReport = bugs->pWorkArounds;
1758 if (reports.select(qReport) == 0) {
1759 error(con, "No report was selected");
1760 return true;
1761 }
1762 reports->sDescription = con.get("description");
1763 reports->status = atoi(con.get("status"));
1764 reports.update();
1765 con.addPair("action", "Select");
1766 return bugForm(con);
1767 }
1768
1769
attachToProject(WWWconnection & con)1770 bool attachToProject(WWWconnection& con)
1771 {
1772 key = con.get("name");
1773 if (persons.select(qPerson) == 0 || persons->status == Person::isUser) {
1774 error(con, "No such engineer");
1775 } else {
1776 key = con.get("software");
1777 if (products.select(qSoftware) == 0) {
1778 error(con, "No such software product");
1779 } else {
1780 if (rindex(products->setEngineers, persons.currentId()) >= 0) {
1781 error(con, "Engineer already attached to the project");
1782 } else {
1783 products->setEngineers.append(persons.currentId());
1784 products.update();
1785 return userForm(con);
1786 }
1787 }
1788 }
1789 return true;
1790 }
1791
1792
registerSoftware(WWWconnection & con)1793 bool registerSoftware(WWWconnection& con)
1794 {
1795 key = con.get("name");
1796 if (persons.select(qPerson) == 0) {
1797 error(con, "No such person");
1798 } else {
1799 key = con.get("software");
1800 if (products.select(qSoftware) == 0) {
1801 error(con, "No such software product");
1802 } else {
1803 if (rindex(products->setUsers, persons.currentId()) >= 0) {
1804 error(con, "User already registered this software");
1805 } else {
1806 products->setUsers.append(persons.currentId());
1807 products.update();
1808 return userForm(con);
1809 }
1810 }
1811 }
1812 return true;
1813 }
1814
1815
softwareForm(WWWconnection & con)1816 bool softwareForm(WWWconnection& con)
1817 {
1818 char* software = con.get("software");
1819 if (software == NULL) {
1820 error(con, "No software product was selected");
1821 return true;
1822 }
1823 key = software;
1824 if (products.select(qSoftware) == 0) {
1825 error(con, "No such software product");
1826 return true;
1827 }
1828 if (strcmp(con.get("action"), "Detach") == 0) {
1829 key = con.get("name");
1830 if (persons.select(qPerson) == 0) {
1831 error(con, "No such person");
1832 return true;
1833 }
1834 int i = rindex(persons->setProjects, products.currentId());
1835 if (i < 0) {
1836 error(con, "Person was not attached to the project");
1837 return true;
1838 }
1839 persons->setProjects.remove(i);
1840 persons.update();
1841 return userForm(con);
1842 }
1843 if (strcmp(con.get("action"), "Unregister") == 0) {
1844 key = con.get("name");
1845 if (persons.select(qPerson) == 0) {
1846 error(con, "No such person");
1847 return true;
1848 }
1849 int i = rindex(persons->setUsedSoftware, products.currentId());
1850 if (i < 0) {
1851 error(con, "Person was not registered");
1852 return true;
1853 }
1854 persons->setProjects.remove(i);
1855 persons.update();
1856 return userForm(con);
1857 }
1858 char* myself = con.get("myself");
1859 key = myself;
1860 if (persons.select(qPerson) == 0) {
1861 error(con, "No such person");
1862 return true;
1863 }
1864 int personStatus = persons->status;
1865 con << TAG <<
1866 HTML_HEAD "<TITLE>" << software << "</TITLE></HEAD>"
1867 BODY
1868 "<H2>" << software << "</H2>"
1869 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1870 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1871 << con.getAddress() << "\"><INPUT TYPE=hidden "
1872 "NAME=\"page\" VALUE=\"updateSoftware\">"
1873 "<INPUT TYPE=hidden NAME=\"software\" VALUE=\"" << software << "\">"
1874 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1875 "<TABLE><TR><TH ALIGN=LEFT>Product name:</TH>"
1876 "<TD><INPUT TYPE=text NAME=\"newname\" VALUE=\"" << software << "\">"
1877 "</TD></TR>";
1878 if (products->pVersions != null) {
1879 versions.at(products->pVersions);
1880 con << TAG <<
1881 "<TR><TH ALIGN=LEFT>Current version:</TH>"
1882 "<TD><INPUT TYPE=text NAME=\"version\" SIZE=8 VALUE=\""
1883 << versions->getVersionString() << "\"></TD></TR>"
1884 "<TR><TH ALIGN=LEFT>Current version label:</TH>"
1885 "<TD><INPUT TYPE=text NAME=\"label\" SIZE=20 VALUE=\""
1886 << versions->sLabel << "\"></TD></TR>"
1887 "<TR><TH ALIGN=LEFT>Current version comment:</TH>"
1888 "<TD><INPUT TYPE=text NAME=\"comment\" SIZE=40 VALUE=\""
1889 << versions->sComment << "\"></TD></TR>";
1890 } else {
1891 con << TAG <<
1892 "<TR><TH ALIGN=LEFT>Current version:</TH>"
1893 "<TD><INPUT TYPE=text NAME=\"version\" SIZE=8></TD></TR>"
1894 "<TR><TH ALIGN=LEFT>Current version label:</TH>"
1895 "<TD><INPUT TYPE=text NAME=\"label\" SIZE=20></TD></TR>"
1896 "<TR><TH ALIGN=LEFT>Current version comment:</TH>"
1897 "<TD><INPUT TYPE=text NAME=\"comment\" SIZE=40></TD></TR>";
1898 }
1899 con << TAG << "</TABLE><BR>";
1900 if (personStatus != Person::isUser) {
1901 con << TAG <<
1902 "<INPUT TYPE=submit VALUE=\"Update\"> <INPUT TYPE=reset>";
1903 }
1904 con << TAG << "</FORM><P>"
1905 "<TABLE><TR><TH ALIGN=LEFT>Engineers:</TH>"
1906 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1907 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress()
1908 << "\"><INPUT TYPE=HIDDEN NAME=\"page\" VALUE=\"userForm\">"
1909 "<INPUT TYPE=HIDDEN NAME=\"myself\" VALUE=\"" << myself <<
1910 "\"><SELECT NAME=\"name\" SIZE=1>";
1911 if (products->setEngineers.length() != 0) {
1912 print(con, products->setEngineers);
1913 con << TAG << "</SELECT>";
1914 if (personStatus != Person::isUser) {
1915 con << TAG << "<INPUT TYPE=submit VALUE=\"Select\">";
1916 }
1917 } else {
1918 con << TAG << EMPTY_LIST;
1919 }
1920 con << TAG <<
1921 "</FORM></TD></TR>"
1922 "<TR><TH ALIGN=LEFT>Users:</TH>"
1923 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1924 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress()
1925 << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"userForm\">"
1926 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1927 "\"><SELECT NAME=\"name\" SIZE=1>";
1928 if (products->setUsers.length() != 0) {
1929 print(con, products->setUsers);
1930 con << TAG << "</SELECT>";
1931 if (personStatus != Person::isUser) {
1932 con << TAG << "<INPUT TYPE=submit VALUE=\"Select\">";
1933 }
1934 } else {
1935 con << TAG << EMPTY_LIST;
1936 }
1937 con << TAG <<
1938 "</FORM></TD></TR>"
1939 "<TR><TH ALIGN=LEFT>Bugs:</TH>"
1940 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1941 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress()
1942 << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"bugForm\">"
1943 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1944 "\"><SELECT NAME=\"bug\" SIZE=1>";
1945 if (products->setBugs.length() != 0) {
1946 print(con, products->setBugs);
1947 con << TAG <<
1948 "</SELECT><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
1949 } else {
1950 con << TAG << EMPTY_LIST;
1951 }
1952 con << TAG <<
1953 "</FORM></TD></TR>"
1954 "<TR><TH ALIGN=LEFT>Versions:</TH><TD>"
1955 "<FORM METHOD=POST ACTION=\""<<con.getStub() << "\">"
1956 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress()
1957 << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"versionForm\">"
1958 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1959 "\"><INPUT TYPE=HIDDEN NAME=\"software\" VALUE=\"" << software <<
1960 "\"><SELECT NAME=\"version\" SIZE=1>";
1961 initialVersion = products->pVersions;
1962 if (versions.select(qAllVersions) != 0) {
1963 print(con, versions);
1964 con << TAG << "</SELECT><INPUT TYPE=submit VALUE=\"Select\">";
1965 } else {
1966 con << TAG << EMPTY_LIST;
1967 }
1968 con << TAG << "</FORM></TD></TR></TABLE>";
1969 mainMenuReference(con);
1970 return true;
1971 }
1972
1973
updateSoftware(WWWconnection & con)1974 bool updateSoftware(WWWconnection& con)
1975 {
1976 char* software = con.get("software");
1977 key = software;
1978 if (products.select(qSoftware) == 0) {
1979 error(con, "No such software product");
1980 return true;
1981 }
1982 Version version;
1983 char* currentVersion = con.get("version");
1984 version.sLabel = con.get("label");
1985 version.sComment = con.get("comment");
1986 if (sscanf(currentVersion, "%d.%d", &majorVersion, &minorVersion) != 2)
1987 {
1988 error(con, "Bad version number (MAJOR.MINOR expected)");
1989 return true;
1990 }
1991 products->sName = con.get("newname");
1992 version.majorVersionNumber = majorVersion;
1993 version.minorVersionNumber = minorVersion;
1994 version.released = dbDateTime::current();
1995 if (products->pVersions != null) {
1996 initialVersion = products->pVersions;
1997 if (versions.select(qVersion) != 0) {
1998 versions->sComment = version.sComment;
1999 versions->sLabel = version.sLabel;
2000 } else {
2001 versions.at(products->pVersions);
2002 if (versions->majorVersionNumber > majorVersion ||
2003 (versions->majorVersionNumber == majorVersion &&
2004 versions->minorVersionNumber > minorVersion))
2005 {
2006 error(con, "Version number less than of current version");
2007 return true;
2008 }
2009 version.pNext = products->pVersions;
2010 products->pVersions = insert(version);
2011 }
2012 } else {
2013 version.pNext = null;
2014 products->pVersions = insert(version);
2015 }
2016 products.update();
2017 con.addPair("name", con.get("myself"));
2018 return userForm(con);
2019 }
2020
2021
versionForm(WWWconnection & con)2022 bool versionForm(WWWconnection& con)
2023 {
2024 char* software = con.get("software");
2025 char* myself = con.get("myself");
2026 char buf[64];
2027 key = software;
2028 if (products.select(qSoftware) == 0) {
2029 error(con, "No such software product");
2030 return true;
2031 }
2032 char* versionString = con.get("version");
2033 if (sscanf(versionString, "%d.%d", &majorVersion, &minorVersion) != 2) {
2034 error(con, "Bad version format");
2035 return true;
2036 }
2037 initialVersion = products->pVersions;
2038 if (versions.select(qVersion) == 0) {
2039 error(con, "No such version");
2040 return true;
2041 }
2042 key = myself;
2043 if (persons.select(qPerson) == 0) {
2044 error(con, "No such person");
2045 return true;
2046 }
2047 con << TAG <<
2048 HTML_HEAD "<TITLE>" << software << " v. " << versionString <<
2049 "</TITLE></HEAD>"
2050 BODY
2051 "<H2>" << software << " v. " << versionString << "</H2>"
2052 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
2053 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
2054 << con.getAddress() << "\"><INPUT TYPE=hidden "
2055 "NAME=\"page\" VALUE=\"updateVersion\">"
2056 "<INPUT TYPE=hidden NAME=\"software\" VALUE=\"" << software << "\">"
2057 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
2058 "<INPUT TYPE=hidden NAME=\"version\" VALUE=\"" << versionString <<"\">"
2059 "<TABLE><TR><TH ALIGN=LEFT>Released:</TH>"
2060 "<TD>" << versions->released.asString(buf, sizeof buf) << "</TD></TR>"
2061 "<TR><TH ALIGN=LEFT>Label:</TH>"
2062 "<TD><INPUT TYPE=text NAME=\"label\" SIZE=20 VALUE=\""
2063 << versions->sLabel << "\"></TD></TR>"
2064 "<TR><TH ALIGN=LEFT>Comment:</TH>"
2065 "<TD><INPUT TYPE=text NAME=\"comment\" SIZE=40 VALUE=\""
2066 << versions->sComment << "\"></TD></TR></TABLE>";
2067 if (persons->status != Person::isUser) {
2068 con << TAG <<
2069 "<P><INPUT TYPE=submit NAME=\"action\" VALUE=\"Update\">";
2070 if (persons->status == Person::isAdministrator) {
2071 con << TAG <<
2072 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
2073 }
2074 con << TAG << " <INPUT TYPE=reset>";
2075 }
2076 con << TAG << "<P></FORM>"
2077 "<B>Bugs:</B><BR>"
2078 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
2079 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
2080 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
2081 "VALUE=\"bugForm\">"
2082 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
2083 "<SELECT NAME=\"bug\" SIZE=5>";
2084 if (versions->setBugs.length() != 0) {
2085 print(con, versions->setBugs);
2086 con << TAG <<
2087 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
2088 } else {
2089 con << TAG << EMPTY_LIST;
2090 }
2091 con << TAG << "</FORM>";
2092 mainMenuReference(con);
2093 return true;
2094 }
2095
updateVersion(WWWconnection & con)2096 bool updateVersion(WWWconnection& con)
2097 {
2098 char* software = con.get("software");
2099 key = software;
2100 if (products.select(qSoftware) == 0) {
2101 error(con, "No such software product");
2102 return true;
2103 }
2104 if (sscanf(con.get("version"), "%d.%d", &majorVersion, &minorVersion) != 2)
2105 {
2106 error(con, "Bad version format");
2107 return true;
2108 }
2109 if (strcmp(con.get("action"), "Remove") == 0) {
2110 dbReference<Version> prev, curr = null, next = products->pVersions;
2111 do {
2112 prev = curr;
2113 if (next == null) {
2114 error(con, "No such version");
2115 return true;
2116 }
2117 versions.at(next);
2118 curr = next;
2119 next = versions->pNext;
2120 } while (versions->majorVersionNumber != majorVersion ||
2121 versions->minorVersionNumber != minorVersion);
2122 if (versions->setBugs.length() != 0) {
2123 error(con, "Can not remove version with non-empty bugs list");
2124 return true;
2125 }
2126 versions.remove();
2127 if (prev == null) {
2128 products->pVersions = next;
2129 products.update();
2130 } else {
2131 versions.at(prev);
2132 versions->pNext = next;
2133 versions.update();
2134 }
2135 con.addPair("action", "Select");
2136 return softwareForm(con);
2137 }
2138 initialVersion = products->pVersions;
2139 if (versions.select(qVersion) == 0) {
2140 error(con, "No such version");
2141 return true;
2142 }
2143 versions->sComment = con.get("comment");
2144 versions->sLabel = con.get("label");
2145 versions.update();
2146 return versionForm(con);
2147 }
2148
2149 WWWapi::dispatcher dispatchTable[] = {
2150 {"addUserForm", addUserForm},
2151 {"addEngineerForm", addEngineerForm},
2152 {"addSoftwareForm", addSoftwareForm},
2153 {"selectSoftwareForm", selectSoftwareForm},
2154 {"removeSoftwareForm", removeSoftwareForm},
2155 {"selectPersonForm", selectPersonForm},
2156 {"removePersonForm", removePersonForm},
2157 {"selectBugForm", selectBugForm},
2158 {"removeBugForm", removeBugForm},
2159 {"changePasswordForm", changePasswordForm},
2160 {"shutdown", shutdown},
2161 {"userForm", userForm},
2162 {"softwareForm", softwareForm},
2163 {"addUser", addUser},
2164 {"addEngineer", addEngineer},
2165 {"removePerson", removePerson},
2166 {"addSoftware", addSoftware},
2167 {"removeSoftware", removeSoftware},
2168 {"removeBug", removeBug},
2169 {"changePassword", changePassword},
2170 {"updatePerson", updatePerson},
2171 {"login", login},
2172 {"bugQueryForm", bugQueryForm},
2173 {"bugQuery", bugQuery},
2174 {"userForm", userForm},
2175 {"createBugReportForm", createBugReportForm},
2176 {"bugForm", bugForm},
2177 {"createBugReport", createBugReport},
2178 {"bugForm", bugForm},
2179 {"updateBug", updateBug},
2180 {"updateReportForm", updateReportForm},
2181 {"updateWorkAroundForm", updateWorkAroundForm},
2182 {"addReportForm", addReportForm},
2183 {"addReport", addReport},
2184 {"addWorkAroundForm", addWorkAroundForm},
2185 {"addWorkAround", addWorkAround},
2186 {"updateReport", updateReport},
2187 {"updateWorkAround", updateWorkAround},
2188 {"attachToProject", attachToProject},
2189 {"registerSoftware", registerSoftware},
2190 {"softwareForm", softwareForm},
2191 {"updateSoftware", updateSoftware},
2192 {"versionForm", versionForm},
2193 {"updateVersion", updateVersion}
2194 };
2195
2196 #ifdef USE_EXTERNAL_HTTP_SERVER
2197 CGIapi wwwServer(db, itemsof(dispatchTable), dispatchTable);
2198 char* defaultAddress = "localhost:6101";
2199 socket_t::socket_domain domain = socket_t::sock_local_domain;
2200 #else
2201 HTTPapi wwwServer(db, itemsof(dispatchTable), dispatchTable);
2202 char* defaultAddress = "localhost:80";
2203 socket_t::socket_domain domain = socket_t::sock_global_domain;
2204 #endif
2205
main(int argc,char * argv[])2206 int main(int argc, char* argv[])
2207 {
2208 char* address = (argc > 1) ? argv[1] : defaultAddress;
2209 if (!wwwServer.open(address, domain)) {
2210 fprintf(stderr, "Failed to open WWW session\n");
2211 return EXIT_FAILURE;
2212 }
2213 if (!db.open(_T("bugdb"))) {
2214 fprintf(stderr, "Failed to open database\n");
2215 return EXIT_FAILURE;
2216 }
2217 qBug = "bugId=",bugId;
2218 qReport = "index=",reportId,"start from",firstReport,"follow by pNext";
2219 qAllReports = "start from",firstReport,"follow by pNext";
2220 qVersion = "majorVersionNumber=",majorVersion,"and minorVersionNumber=",
2221 minorVersion,"start from",initialVersion,"follow by pNext";
2222 qAllVersions = "start from",initialVersion,"follow by pNext";
2223 qPerson = "sName=",&key;
2224 qSoftware = "sName=",&key;
2225
2226 if (sequencer.select() == 0) {
2227 BugSequencer seq;
2228 seq.nBugs = 0;
2229 insert(seq);
2230 }
2231 if (persons.select() == 0) {
2232 Person administrator;
2233 administrator.sName = "administrator";
2234 administrator.sEmailAddress = "root";
2235 administrator.sPassword = "";
2236 administrator.status = Person::isAdministrator;
2237 administrator.nReports = 0;
2238 insert(administrator);
2239 }
2240 WWWconnection con;
2241 while (wwwServer.connect(con) && wwwServer.serve(con));
2242 db.close();
2243 printf("End of session\n");
2244 return EXIT_SUCCESS;
2245 }
2246