1 //-< BUGDB.CPP >----------------------------------------------------*--------*
2 // GigaBASE 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>"
838 "</HEAD><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><H2>" << name << "</H2><FONT SIZE=\"+1\">"
890 "<UL><LI><A HREF=\"" << con.getStub() << "?socket="
891 << con.getAddress() << "&page=createBugReportForm&myself="
892 << URL << myself << "\">Create bug report</A>";
893 if (persons->sEmailAddress[0] != '\0') {
894 con << TAG <<
895 "<LI><A HREF=\"mailto:" << persons->sEmailAddress
896 << "\">Send e-mail</A>"
897 "<LI><A HREF=\"" << con.getStub() << "?socket=" << con.getAddress()
898 << "&page=bugQueryForm&myself=" << URL << myself
899 << "\">Find a bug</A>";
900 }
901 if (strcmp(myself, name) == 0 || selfStatus == Person::isAdministrator) {
902 con << TAG << "<LI><A HREF=\"" << con.getStub() << "?socket="
903 << con.getAddress() << "&page=changePasswordForm&myself="
904 << URL << myself << "&name=" << URL << name <<
905 "\">Change password</A>";
906 }
907 con << TAG <<
908 "</UL></FONT><P><TABLE><TR><TH ALIGN=LEFT>Person name:</TH>"
909 "<TD><FORM METHOD=POST ACTION=\""
910 << con.getStub() << "\"><INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
911 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\""
912 "updatePerson\"><INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself
913 << "\"><INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
914 "<INPUT TYPE=text NAME=\"newname\" SIZE=30 VALUE=\""
915 << name << "\"><INPUT TYPE=submit VALUE=\"Change\"></FORM></TD></TR>"
916 "<TR><TH ALIGN=LEFT>E-Mail:</TH>"
917 "<TD><FORM METHOD=POST ACTION=\""
918 << con.getStub() << "\"><INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
919 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\""
920 "updatePerson\"><INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself
921 << "\"><INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
922 "<INPUT TYPE=text NAME=\"email\" SIZE=30 VALUE=\""
923 << persons->sEmailAddress << "\">"
924 "<INPUT TYPE=submit VALUE=\"Change\"></FORM></TD></TR>";
925 if (persons->status != Person::isUser) {
926 con << TAG << "<TR><TH ALIGN=LEFT>Projects:</TH>"
927 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
928 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
929 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
930 "VALUE=\"softwareForm\">"
931 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
932 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
933 "<SELECT NAME=\"software\" SIZE=1>";
934 if (persons->setProjects.length() != 0) {
935 print(con, persons->setProjects);
936 con << TAG <<
937 "</SELECT><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">"
938 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Detach\">";
939 } else {
940 con << TAG << EMPTY_LIST;
941 }
942 if (products.select() != 0) {
943 con << TAG <<
944 "</FORM></TD></TR>"
945 "<TR><TH ALIGN=LEFT>Attach to project:</TH>"
946 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
947 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
948 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
949 "VALUE=\"attachToProject\">"
950 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<"\">"
951 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
952 "<SELECT NAME=\"software\" SIZE=1>";
953 print(con, products);
954 con << TAG << "</SELECT><INPUT TYPE=submit VALUE=\"Attach\">";
955 }
956 con << TAG <<
957 "</FORM></TD></TR>"
958 "<TR><TH ALIGN=LEFT>Find a person:</TH>"
959 "<TD><FORM METHOD=POST ACTION=\""
960 << con.getStub() << "\">"
961 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
962 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
963 "VALUE=\"userForm\">"
964 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
965 "<INPUT TYPE=text NAME=\"name\" SIZE=30>"
966 "<INPUT TYPE=submit VALUE=\"Find\"></FORM></TD></TR>";
967 }
968 con << TAG << "<TR><TH ALIGN=LEFT>Used software:</TH>"
969 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
970 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
971 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
972 "VALUE=\"softwareForm\">"
973 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
974 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
975 "<SELECT NAME=\"software\" SIZE=1>";
976 if (persons->setUsedSoftware.length() != 0) {
977 print(con, persons->setUsedSoftware);
978 con << TAG <<
979 "</SELECT><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">"
980 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Unregister\">";
981 } else {
982 con << TAG << EMPTY_LIST;
983 }
984 if (products.select() != 0) {
985 con << TAG <<
986 "</FORM></TD></TR>"
987 "<TR><TH ALIGN=LEFT>Register as software user:</TH>"
988 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
989 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
990 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
991 "VALUE=\"registerSoftware\">"
992 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
993 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
994 "<SELECT NAME=\"software\" SIZE=1>";
995 print(con, products);
996 con << TAG << "</SELECT><INPUT TYPE=submit VALUE=\"Register\">";
997 }
998 con << TAG << "</FORM></TD></TR></TABLE><P>"
999 "<B>Reported bugs:</B><BR>"
1000 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1001 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1002 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
1003 "VALUE=\"bugForm\">"
1004 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1005 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
1006 "<SELECT NAME=\"bug\" SIZE=5>";
1007 if (persons->setReportedBugs.length() != 0) {
1008 print(con, persons->setReportedBugs);
1009 con << TAG <<
1010 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
1011 } else {
1012 con << TAG << EMPTY_LIST;
1013 }
1014 con << TAG << "</FORM><P>";
1015 if (persons->status != Person::isUser) {
1016 con << TAG <<
1017 "<P><B>Assigned bugs:</B><BR>"
1018 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1019 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1020 << con.getAddress() << "\"><INPUT TYPE=hidden "
1021 "NAME=\"page\" VALUE=\"bugForm\">"
1022 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1023 "<INPUT TYPE=hidden NAME=\"name\" VALUE=\"" << name << "\">"
1024 "<SELECT NAME=\"bug\" SIZE=5>";
1025 if (persons->setAssignedBugs.length() != 0) {
1026 print(con, persons->setAssignedBugs);
1027 con << TAG <<
1028 "</SELECT><BR>"
1029 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\"> "
1030 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Deassign\">";
1031 } else {
1032 con << TAG << EMPTY_LIST;
1033 }
1034 con << TAG << "</FORM>";
1035 }
1036 if (strcmp(name, myself) == 0) {
1037 con << TAG << "</BODY></HTML>";
1038 } else {
1039 mainMenuReference(con);
1040 }
1041 return true;
1042 }
1043
1044
createBugReportForm(WWWconnection & con)1045 bool createBugReportForm(WWWconnection& con)
1046 {
1047 int i;
1048 sequencer.select();
1049 con << TAG <<
1050 HTML_HEAD "<TITLE>Bug</TITLE></HEAD>"
1051 BODY
1052 "<H2>Bug</H2>"
1053 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1054 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1055 << con.getAddress() << "\"><INPUT TYPE=hidden "
1056 "NAME=\"page\" VALUE=\"createBugReport\">"
1057 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\""<<con.get("myself")<<"\">"
1058 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << ++sequencer->nBugs << ">"
1059 "<TABLE><TH ALIGN=LEFT>Summary:</TH>"
1060 "<TD><INPUT TYPE=text NAME=\"summary\" SIZE=40></TD></TR>"
1061 "<TR><TH ALIGN=LEFT>Category:</TH>"
1062 "<TD><SELECT NAME=\"category\" SIZE=1>";
1063 for (i = 1; eCATEGORY_STRING[i] != NULL; i++) {
1064 con << TAG << "<OPTION SELECTED VALUE=" << i << ">"
1065 << eCATEGORY_STRING[i] << "</OPTION>";
1066 }
1067 con << TAG << "</SELECT></TD></TR>"
1068 "<TR><TH ALIGN=LEFT>Severity:</TH>"
1069 "<TD><SELECT NAME=\"severity\" SIZE=1>";
1070 for (i = 1; eSEVERITY_STRING[i] != NULL; i++) {
1071 con << TAG << "<OPTION SELECTED VALUE=" << i << ">"
1072 << eSEVERITY_STRING[i] << "</OPTION>";
1073 }
1074 con << TAG <<
1075 "</SELECT></TD></TR>"
1076 "<TR><TH ALIGN=LEFT>Priority:</TH>"
1077 "<TD><SELECT NAME=\"priority\" SIZE=1>";
1078 for (i = 1; eFIXING_PRIORITY_STRING[i] != NULL; i++) {
1079 con << TAG << "<OPTION SELECTED VALUE=" << i << ">"
1080 << eFIXING_PRIORITY_STRING[i] << "</OPTION>";
1081 }
1082 con << TAG <<
1083 "</SELECT></TD></TR>"
1084 "<TR><TH ALIGN=LEFT>Software:</TH>"
1085 "<TD><SELECT NAME=\"software\" SIZE=1>";
1086 if (products.select() != 0) {
1087 print(con, products);
1088 }
1089 con << TAG <<
1090 "</SELECT></TD></TR>"
1091 "<TR><TH ALIGN=LEFT>Version:</TH>"
1092 "<TD><INPUT TYPE=text NAME=\"version\"></TD></TR>"
1093 "<TR><TH ALIGN=LEFT>Platform:</TH>"
1094 "<TD><INPUT TYPE=text NAME=\"platform\"></TD></TR>"
1095 "<TR><TH ALIGN=LEFT>OS:</TH>"
1096 "<TD><INPUT TYPE=text NAME=\"os\"></TD></TR></TABLE><P>"
1097 "<INPUT TYPE=submit VALUE=\"Submit\"> "
1098 "<INPUT TYPE=reset></FORM>";
1099 mainMenuReference(con);
1100 sequencer.update();
1101 return true;
1102 }
1103
1104 bool bugForm(WWWconnection& con);
1105
createBugReport(WWWconnection & con)1106 bool createBugReport(WWWconnection& con)
1107 {
1108 key = con.get("myself");
1109 if (persons.select(qPerson) == 0) {
1110 error(con, "Author unknown");
1111 return true;
1112 }
1113 key = con.get("software");
1114 if (products.select(qSoftware) == 0) {
1115 error(con, "No such software product");
1116 return true;
1117 }
1118 if (sscanf(con.get("version"), "%d.%d", &majorVersion, &minorVersion) != 2)
1119 {
1120 error(con, "Bad version format");
1121 return true;
1122 }
1123 initialVersion = products->pVersions;
1124 if (versions.select(qVersion) == 0) {
1125 error(con, "No such software product version");
1126 return true;
1127 }
1128
1129 Bug bug;
1130 bug.bugId = atoi(con.get("bug"));
1131 bug.sOneLineSummary = con.get("summary");
1132 bug.eCategory = atoi(con.get("category"));
1133 bug.eFixingPriority = atoi(con.get("priority"));
1134 bug.eSeverity = atoi(con.get("severity"));
1135 bug.sOperatingSystem = con.get("os");
1136 bug.sHardwarePlatform = con.get("platform");
1137 bug.pReportedBy = persons.currentId();
1138 bug.pAssignedTo = null;
1139 bug.pSoftware = products.currentId();
1140 bug.pVersion = versions.currentId();
1141 bug.nReports = 0;
1142 insert(bug);
1143 con.addPair("action", "Select");
1144 return bugForm(con);
1145 }
1146
bugForm(WWWconnection & con)1147 bool bugForm(WWWconnection& con)
1148 {
1149 int i;
1150 char* bugStr = con.get("bug");
1151 bugId = atoi(bugStr);
1152 if (bugs.select(qBug) == 0) {
1153 error(con, "No bug was selected");
1154 return true;
1155 }
1156 char* myself = con.get("myself");
1157 if (strcmp(con.get("action"), "Remove") == 0) {
1158 dbReference<Bug> pBug = bugs.currentId();
1159 bugId = atoi(con.get("relatedbug"));
1160 if (bugs.select(qBug) == 0) {
1161 error(con, "No such bug");
1162 return true;
1163 }
1164 int i = rindex(bugs->setSimilarBugs, pBug);
1165 if (i < 0) {
1166 error(con, "No such related bug");
1167 return true;
1168 }
1169 bugs->setSimilarBugs.remove(i);
1170 bugs.update();
1171 con.addPair("action", "Select");
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><BODY>"
1197 "<H2>Bug in " << products->sName << " v. "
1198 << versions->getVersionString() << "</H2>"
1199 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1200 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1201 << con.getAddress() << "\"><INPUT TYPE=hidden "
1202 "NAME=\"page\" VALUE=\"updateBug\">"
1203 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1204 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1205 "<TABLE><TH ALIGN=LEFT>Summary:</TH>"
1206 "<TD><INPUT TYPE=text NAME=\"summary\" SIZE=40 VALUE=\""
1207 << bugs->sOneLineSummary << "\"></TD></TR>"
1208 "<TR><TH ALIGN=LEFT>Category:</TH>"
1209 "<TD><SELECT NAME=\"category\" SIZE=1>"
1210 "<OPTION SELECTED VALUE=" << bugs->eCategory << ">"
1211 << eCATEGORY_STRING[bugs->eCategory] << "</OPTION>";
1212 for (i = 1; eCATEGORY_STRING[i] != NULL; i++) {
1213 con << TAG << "<OPTION VALUE=" << i << ">"
1214 << eCATEGORY_STRING[i] << "</OPTION>";
1215 }
1216 con << TAG <<
1217 "</SELECT></TD></TR>"
1218 "<TR><TH ALIGN=LEFT>Severity:</TH>"
1219 "<TD><SELECT NAME=\"severity\" SIZE=1>"
1220 "<OPTION SELECTED VALUE=" << bugs->eSeverity << ">"
1221 << eSEVERITY_STRING[bugs->eSeverity] << "</OPTION>";
1222 for (i = 1; eSEVERITY_STRING[i] != NULL; i++) {
1223 con << TAG << "<OPTION VALUE=" << i << ">"
1224 << eSEVERITY_STRING[i] << "</OPTION>";
1225 }
1226 con << TAG <<
1227 "</SELECT></TD></TR>"
1228 "<TR><TH ALIGN=LEFT>Priority:</TH>"
1229 "<TD><SELECT NAME=\"priority\" SIZE=1>"
1230 "<OPTION SELECTED VALUE=" << bugs->eFixingPriority << ">"
1231 << eFIXING_PRIORITY_STRING[bugs->eFixingPriority] << "</OPTION>";
1232 for (i = 1; eFIXING_PRIORITY_STRING[i] != NULL; i++) {
1233 con << TAG << "<OPTION VALUE=" << i << ">"
1234 << eFIXING_PRIORITY_STRING[i] << "</OPTION>";
1235 }
1236 con << TAG <<
1237 "</SELECT></TD></TR>"
1238 "<TR><TH ALIGN=LEFT>Platform:</TH>"
1239 "<TD><INPUT TYPE=text NAME=\"platform\" VALUE=\""
1240 << bugs->sHardwarePlatform << "\"></TD></TR>"
1241 "<TR><TH ALIGN=LEFT>OS:</TH>"
1242 "<TD><INPUT TYPE=text NAME=\"os\"VALUE=\""
1243 << bugs->sOperatingSystem << "\"></TD></TR>"
1244 "<TR><TH ALIGN=LEFT>Assigned to:</TH>"
1245 "<TD><SELECT SIZE=1 NAME=\"name\">";
1246 if (bugs->pAssignedTo != null) {
1247 persons.at(bugs->pAssignedTo);
1248 con << TAG << "<OPTION SELECTED VALUE=\"" << persons->sName
1249 << "\">" << persons->sName << "</OPTION>";
1250 } else {
1251 con << TAG << "<OPTION SELECTED VALUE=\"\"></OPTION>";
1252 }
1253 print(con, products->setEngineers);
1254 con << TAG << "</SELECT></TD></TR>"
1255 "<TR><TH ALIGN=LEFT>Similar with:</TH>"
1256 "<TD><SELECT NAME=\"similar\" SIZE=1>"
1257 "<OPTION SELECTED VALUE=\"\"></OPTION>";
1258 allBugs.select();
1259 print(con, allBugs);
1260 con << TAG << "</SELECT></TD></TR></TABLE><BR>";
1261
1262 if (personStatus != Person::isUser) {
1263 con << TAG <<
1264 "<INPUT TYPE=submit NAME=\"action\" VALUE=\"Update\"> "
1265 "<INPUT TYPE=reset VALUE=\"Reset\">";
1266 }
1267 con << TAG << "</FORM><P><FORM METHOD=POST ACTION=\"" << con.getStub()
1268 << "\"><INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1269 << con.getAddress() << "\">"
1270 "<INPUT TYPE=hidden NAME=\"page\" VALUE=\"updateReportForm\">"
1271 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1272 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1273 "<B>Report history:</B><BR><SELECT NAME=\"report\" SIZE=5>";
1274 firstReport = bugs->pReportHistory;
1275 if (reports.select(qAllReports) != 0) {
1276 print(con, reports);
1277 con << TAG <<
1278 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">"
1279 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Add\">";
1280 if (personStatus == Person::isAdministrator) {
1281 con << TAG <<
1282 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
1283 }
1284 } else {
1285 con << TAG << EMPTY_LIST
1286 "<BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Add\">";
1287 }
1288 con << TAG << "</FORM><P>";
1289
1290 con << TAG <<
1291 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1292 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1293 << con.getAddress() << "\"><INPUT TYPE=hidden "
1294 "NAME=\"page\" VALUE=\"updateWorkAroundForm\">"
1295 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1296 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1297 "<B>Work arounds:</B><BR><SELECT NAME=\"workaround\" SIZE=5>";
1298 firstReport = bugs->pWorkArounds;
1299 if (reports.select(qAllReports) != 0) {
1300 print(con, reports);
1301 con << TAG <<
1302 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">"
1303 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Add\">";
1304 if (personStatus == Person::isAdministrator) {
1305 con << TAG <<
1306 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
1307 }
1308 } else {
1309 con << TAG << EMPTY_LIST
1310 "<BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Add\">";
1311 }
1312 con << TAG << "</FORM><P>";
1313
1314 if (bugs->setSimilarBugs.length() != 0) {
1315 con << TAG <<
1316 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1317 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1318 << con.getAddress() << "\"><INPUT TYPE=hidden "
1319 "NAME=\"page\" VALUE=\"bugForm\">"
1320 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1321 "<INPUT TYPE=hidden NAME=\"relatedbug\" VALUE=" << bugStr << ">"
1322 "<B>Similar bugs:</B><BR><SELECT NAME=\"bug\" SIZE=1>";
1323 print(con, bugs->setSimilarBugs);
1324 con << TAG <<
1325 "</SELECT><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
1326 if (personStatus == Person::isAdministrator) {
1327 con << TAG <<
1328 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
1329 }
1330 con << TAG << "</FORM><P>";
1331 }
1332 con << TAG <<
1333 "</FORM><P>"
1334 "<FONT SIZE=\"+1\"><UL>";
1335 if (personStatus == Person::isUser) {
1336 if (bugs->pAssignedTo != null) {
1337 persons.at(bugs->pAssignedTo);
1338 con << TAG << "<LI>Assigned to <A HREF=\"mailto:"
1339 << persons->sEmailAddress << "\">"
1340 << persons->sName << "</A>";
1341 }
1342 persons.at(bugs->pReportedBy);
1343 con << TAG << "<LI>Reported by <A HREF=\"mailto:"
1344 << persons->sEmailAddress << "\">"
1345 << persons->sName << "</A></OL></FONT>";
1346 } else {
1347 if (bugs->pAssignedTo != null) {
1348 persons.at(bugs->pAssignedTo);
1349 con << TAG << "<LI>Assigned to <A HREF=\"" << con.getStub()
1350 << "?socket=" << con.getAddress()
1351 << "&page=userForm&myself=" << URL << myself
1352 << "&name=" << URL << persons->sName << "\">"
1353 << persons->sName << "</A>";
1354 }
1355 persons.at(bugs->pReportedBy);
1356 con << TAG
1357 << "<LI>Reported by <A HREF=\"" << con.getStub() << "?socket="
1358 << con.getAddress()
1359 << "&page=userForm&myself=" << URL << myself
1360 << "&name=" << URL << persons->sName << "\">"
1361 << persons->sName << "</A></OL></FONT>";
1362 }
1363 mainMenuReference(con);
1364 return true;
1365 }
1366
updateBug(WWWconnection & con)1367 bool updateBug(WWWconnection& con)
1368 {
1369 char* bugStr = con.get("bug");
1370 bugId = atoi(bugStr);
1371 if (bugs.select(qBug) == 0) {
1372 error(con, "No such bug");
1373 return true;
1374 }
1375 char* similar = con.get("similar");
1376 if (*similar != '\0') {
1377 int id = atoi(similar);
1378 if (id != bugId) {
1379 bugId = id;
1380 if (allBugs.select(qBug) != 0) {
1381 if (rindex(bugs->setSimilarBugs, allBugs.currentId()) < 0) {
1382 bugs->setSimilarBugs.append(allBugs.currentId());
1383 }
1384 }
1385 }
1386 }
1387 key = con.get("name");
1388 if (*key != '\0') {
1389 if (persons.select(qPerson) == 0 ||
1390 persons->status == Person::isUser)
1391 {
1392 error(con, "No such engineer");
1393 return true;
1394 }
1395 bugs->pAssignedTo = persons.currentId();
1396 }
1397 bugs.update();
1398 return bugForm(con);
1399 }
1400
1401
addReportForm(WWWconnection & con)1402 bool addReportForm(WWWconnection& con)
1403 {
1404 char* bugStr = con.get("bug");
1405 bugId = atoi(bugStr);
1406 if (bugs.select(qBug) == 0) {
1407 error(con, "No such bug");
1408 return true;
1409 }
1410 con << TAG <<
1411 HTML_HEAD "<TITLE>Bug report</TITLE></HEAD>"
1412 BODY
1413 "<H2>Bug report</H2>"
1414 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1415 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1416 << con.getAddress() << "\"><INPUT TYPE=hidden "
1417 "NAME=\"page\" VALUE=\"addReport\">"
1418 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1419 "<INPUT TYPE=hidden NAME=\"index\" VALUE=" << ++bugs->nReports
1420 << "><INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself")
1421 << "\"><B>Status: </B><SELECT SIZE=1 NAME=\"status\">";
1422 for (int i = 1; eSTATUS_STRING[i] != NULL; i++) {
1423 con << TAG << "<OPTION VALUE=" << i << ">" << eSTATUS_STRING[i]
1424 << "</OPTION>";
1425 }
1426 con << TAG <<
1427 "</SELECT><P>"
1428 "<B>Bug description:</B><P>"
1429 "<TEXTAREA COLS=40 ROWS=5 NAME=\"description\"></TEXTAREA><P>"
1430 "<INPUT TYPE=submit VALUE=\"Add\"> "
1431 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
1432 bugs.update();
1433 mainMenuReference(con);
1434 return true;
1435 }
1436
addReport(WWWconnection & con)1437 bool addReport(WWWconnection& con)
1438 {
1439 bugId = atoi(con.get("bug"));
1440 if (bugs.select(qBug) == 0) {
1441 error(con, "No such bug");
1442 return true;
1443 }
1444 key = con.get("myself");
1445 if (persons.select(qPerson) == 0) {
1446 error(con, "No such person");
1447 return true;
1448 }
1449 reportId = atoi(con.get("index"));
1450 firstReport = bugs->pReportHistory;
1451 if (reports.select(qReport) == 0) {
1452 Report report;
1453 report.pAuthor = persons.currentId();
1454 persons->nReports += 1;
1455 report.sDescription = con.get("description");
1456 report.index = reportId;
1457 report.pNext = bugs->pReportHistory;
1458 report.status = atoi(con.get("status"));
1459 report.creationDate = dbDateTime::current();
1460 bugs->pReportHistory = insert(report);
1461 persons.update();
1462 bugs.update();
1463 }
1464 con.addPair("action", "Select");
1465 return bugForm(con);
1466 }
1467
addWorkAroundForm(WWWconnection & con)1468 bool addWorkAroundForm(WWWconnection& con)
1469 {
1470 char* bugStr = con.get("bug");
1471 bugId = atoi(bugStr);
1472 if (bugs.select(qBug) == 0) {
1473 error(con, "No such bug");
1474 return true;
1475 }
1476 con << TAG <<
1477 HTML_HEAD "<TITLE>Work around</TITLE></HEAD>"
1478 BODY
1479 "<H2>Work around</H2>"
1480 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1481 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1482 << con.getAddress() << "\"><INPUT TYPE=hidden "
1483 "NAME=\"page\" VALUE=\"addWorkAround\">"
1484 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1485 "<INPUT TYPE=hidden NAME=\"index\" VALUE=" << ++bugs->nReports
1486 << "><INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << con.get("myself")
1487 << "\"><B>Status: </B><SELECT SIZE=1 NAME=\"status\">";
1488 for (int i = 1; eSTATUS_STRING[i] != NULL; i++) {
1489 con << TAG << "<OPTION VALUE=" << i << ">" << eSTATUS_STRING[i]
1490 << "</OPTION>";
1491 }
1492 con << TAG <<
1493 "</SELECT><P>"
1494 "<B>Description:</B><P>"
1495 "<TEXTAREA COLS=40 ROWS=5 NAME=\"description\"></TEXTAREA><P>"
1496 "<INPUT TYPE=submit VALUE=\"Add\"> "
1497 "<INPUT TYPE=reset VALUE=\"Reset\"></FORM>";
1498 bugs.update();
1499 mainMenuReference(con);
1500 return true;
1501 }
1502
addWorkAround(WWWconnection & con)1503 bool addWorkAround(WWWconnection& con)
1504 {
1505 bugId = atoi(con.get("bug"));
1506 if (bugs.select(qBug) == 0) {
1507 error(con, "No such bug");
1508 return true;
1509 }
1510 key = con.get("myself");
1511 if (persons.select(qPerson) == 0) {
1512 error(con, "No such person");
1513 return true;
1514 }
1515 reportId = atoi(con.get("index"));
1516 firstReport = bugs->pWorkArounds;
1517 if (reports.select(qReport) == 0) {
1518 Report report;
1519 report.pAuthor = persons.currentId();
1520 persons->nReports += 1;
1521 report.sDescription = con.get("description");
1522 report.index = reportId;
1523 report.pNext = bugs->pWorkArounds;
1524 report.status = atoi(con.get("status"));
1525 report.creationDate = dbDateTime::current();
1526 bugs->pWorkArounds = insert(report);
1527 persons.update();
1528 bugs.update();
1529 }
1530 con.addPair("action", "Select");
1531 return bugForm(con);
1532 }
1533
updateReportForm(WWWconnection & con)1534 bool updateReportForm(WWWconnection& con)
1535 {
1536 if (strcmp(con.get("action"), "Add") == 0) {
1537 return addReportForm(con);
1538 }
1539 char* bugStr = con.get("bug");
1540 bugId = atoi(bugStr);
1541 if (bugs.select(qBug) == 0) {
1542 error(con, "No such bug");
1543 return true;
1544 }
1545 char* report = con.get("report");
1546 if (report == NULL) {
1547 error(con, "No report was selected");
1548 return true;
1549 }
1550 int index = atoi(report);
1551 dbReference<Report> prev, curr = null, next = bugs->pReportHistory;
1552 do {
1553 prev = curr;
1554 if (next == null) {
1555 error(con, "No such report");
1556 return true;
1557 }
1558 reports.at(next);
1559 curr = next;
1560 next = reports->pNext;
1561 } while (reports->index != index);
1562
1563 if (strcmp(con.get("action"), "Remove") == 0) {
1564 reports.remove();
1565 bugs->nReports -= 1;
1566 if (prev == null) {
1567 bugs->pReportHistory = next;
1568 } else {
1569 reports.at(prev);
1570 reports->pNext = next;
1571 reports.update();
1572 }
1573 bugs.update();
1574 con.addPair("action", "Select");
1575 return bugForm(con);
1576 }
1577 char date[64];
1578 reports->creationDate.asString(date, sizeof date);
1579 char* myself = con.get("myself");
1580 key = myself;
1581 if (persons.select(qPerson) == 0) {
1582 error(con, "No such person");
1583 return true;
1584 }
1585 int personStatus = persons->status;
1586 persons.at(reports->pAuthor);
1587 con << TAG <<
1588 HTML_HEAD "<TITLE>Bug report from " << date << "</TITLE></HEAD>"
1589 BODY
1590 "<H2>Bug report from " << date << "</H2>"
1591 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1592 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1593 << con.getAddress() << "\"><INPUT TYPE=hidden "
1594 "NAME=\"page\" VALUE=\"updateReport\">"
1595 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1596 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1597 "\"><INPUT TYPE=hidden NAME=\"report\" VALUE=" << index << ">"
1598 "<B>Created by ";
1599 if (personStatus == Person::isUser) {
1600 con << TAG << "<A HREF=\"mailto:"
1601 << persons->sEmailAddress << "\">"
1602 << persons->sName << "</A>";
1603 } else {
1604 con << TAG <<
1605 "<A HREF=\"" << con.getStub() << "?socket="
1606 << con.getAddress()
1607 << "&page=userForm&myself=" << URL << myself
1608 << "&name=" << URL << persons->sName << "\">"
1609 << persons->sName << "</A>";
1610 }
1611 con << TAG << "<P>Status: </B><SELECT SIZE=1 NAME=\"status\">"
1612 "<OPTION SELECTED VALUE=" << reports->status << ">"
1613 << eSTATUS_STRING[reports->status] << "</OPTION>";
1614 for (int i = 1; eSTATUS_STRING[i] != NULL; i++) {
1615 con << TAG << "<OPTION VALUE=" << i << ">" << eSTATUS_STRING[i]
1616 << "</OPTION>";
1617 }
1618 con << TAG <<
1619 "</SELECT><P>"
1620 "<B>Bug description:</B><BR>"
1621 "<TEXTAREA COLS=40 ROWS=5 NAME=\"description\">"
1622 << reports->sDescription << "</TEXTAREA><P>";
1623 if (personStatus != Person::isUser) {
1624 con << TAG <<
1625 "<INPUT TYPE=submit VALUE=\"Update\"> "
1626 "<INPUT TYPE=reset VALUE=\"Reset\">";
1627 }
1628 con << TAG << "</FORM>";
1629 mainMenuReference(con);
1630 return true;
1631 }
1632
updateWorkAroundForm(WWWconnection & con)1633 bool updateWorkAroundForm(WWWconnection& con)
1634 {
1635 if (strcmp(con.get("action"), "Add") == 0) {
1636 return addWorkAroundForm(con);
1637 }
1638 char* bugStr = con.get("bug");
1639 bugId = atoi(bugStr);
1640 if (bugs.select(qBug) == 0) {
1641 error(con, "No such bug");
1642 return true;
1643 }
1644 char* workaround = con.get("workaround");
1645 int index = atoi(workaround);
1646 dbReference<Report> prev, curr = null, next = bugs->pWorkArounds;
1647 do {
1648 prev = curr;
1649 if (next == null) {
1650 error(con, "No such report");
1651 return true;
1652 }
1653 reports.at(next);
1654 curr = next;
1655 next = reports->pNext;
1656 } while (reports->index != index);
1657
1658 if (strcmp(con.get("action"), "Remove") == 0) {
1659 reports.remove();
1660 bugs->nReports -= 1;
1661 if (prev == null) {
1662 bugs->pWorkArounds = next;
1663 } else {
1664 reports.at(prev);
1665 reports->pNext = next;
1666 reports.update();
1667 }
1668 bugs.update();
1669 con.addPair("action", "Select");
1670 return bugForm(con);
1671 }
1672 char date[64];
1673 reports->creationDate.asString(date, sizeof date);
1674 char* myself = con.get("myself");
1675 key = myself;
1676 if (persons.select(qPerson) == 0) {
1677 error(con, "No such person");
1678 return true;
1679 }
1680 int personStatus = persons->status;
1681 persons.at(reports->pAuthor);
1682 con << TAG <<
1683 HTML_HEAD "<TITLE>Work around " << date << "</TITLE></HEAD>"
1684 BODY
1685 "<H2>Work around " << date << "</H2>"
1686 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1687 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1688 << con.getAddress() << "\"><INPUT TYPE=hidden "
1689 "NAME=\"page\" VALUE=\"updateWorkAround\">"
1690 "<INPUT TYPE=hidden NAME=\"bug\" VALUE=" << bugStr << ">"
1691 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1692 "\"><INPUT TYPE=hidden NAME=\"workaround\" VALUE=" << index <<
1693 "><B>Created by ";
1694 if (personStatus == Person::isUser) {
1695 con << TAG << "<A HREF=\"mailto:"
1696 << persons->sEmailAddress << "\">"
1697 << persons->sName << "</A>";
1698 } else {
1699 con << TAG <<
1700 "<A HREF=\"" << con.getStub() << "?socket="
1701 << con.getAddress()
1702 << "&page=userForm&myself=" << URL << myself
1703 << "&name=" << URL << persons->sName << "\">"
1704 << persons->sName << "</A>";
1705 }
1706 con << TAG << "<P>Status: </B><SELECT SIZE=1 NAME=\"status\">"
1707 "<OPTION SELECTED VALUE=" << reports->status << ">"
1708 << eSTATUS_STRING[reports->status] << "</OPTION>";
1709 for (int i = 1; eSTATUS_STRING[i] != NULL; i++) {
1710 con << TAG << "<OPTION VALUE=" << i << ">" << eSTATUS_STRING[i]
1711 << "</OPTION>";
1712 }
1713 con << TAG <<
1714 "</SELECT><P>"
1715 "<B>Bug description:</B><BR>"
1716 "<TEXTAREA COLS=40 ROWS=5 NAME=\"description\">"
1717 << reports->sDescription << "</TEXTAREA><P>";
1718 if (personStatus != Person::isUser) {
1719 con << TAG <<
1720 "<INPUT TYPE=submit VALUE=\"Update\"> "
1721 "<INPUT TYPE=reset VALUE=\"Reset\">";
1722 }
1723 con << TAG << "</FORM>";
1724 mainMenuReference(con);
1725 return true;
1726 }
1727
updateReport(WWWconnection & con)1728 bool updateReport(WWWconnection& con)
1729 {
1730 bugId = atoi(con.get("bug"));
1731 if (bugs.select(qBug) == 0) {
1732 error(con, "No such bug");
1733 return true;
1734 }
1735 reportId = atoi(con.get("report"));
1736 firstReport = bugs->pReportHistory;
1737 if (reports.select(qReport) == 0) {
1738 error(con, "No report was selected");
1739 return true;
1740 }
1741 reports->sDescription = con.get("description");
1742 reports->status = atoi(con.get("status"));
1743 reports.update();
1744 con.addPair("action", "Select");
1745 return bugForm(con);
1746 }
1747
updateWorkAround(WWWconnection & con)1748 bool updateWorkAround(WWWconnection& con)
1749 {
1750 bugId = atoi(con.get("bug"));
1751 if (bugs.select(qBug) == 0) {
1752 error(con, "No such bug");
1753 return true;
1754 }
1755 reportId = atoi(con.get("workaround"));
1756 firstReport = bugs->pWorkArounds;
1757 if (reports.select(qReport) == 0) {
1758 error(con, "No report was selected");
1759 return true;
1760 }
1761 reports->sDescription = con.get("description");
1762 reports->status = atoi(con.get("status"));
1763 reports.update();
1764 con.addPair("action", "Select");
1765 return bugForm(con);
1766 }
1767
1768
attachToProject(WWWconnection & con)1769 bool attachToProject(WWWconnection& con)
1770 {
1771 key = con.get("name");
1772 if (persons.select(qPerson) == 0 || persons->status == Person::isUser) {
1773 error(con, "No such engineer");
1774 } else {
1775 key = con.get("software");
1776 if (products.select(qSoftware) == 0) {
1777 error(con, "No such software product");
1778 } else {
1779 if (rindex(products->setEngineers, persons.currentId()) >= 0) {
1780 error(con, "Engineer already attached to the project");
1781 } else {
1782 products->setEngineers.append(persons.currentId());
1783 products.update();
1784 return userForm(con);
1785 }
1786 }
1787 }
1788 return true;
1789 }
1790
1791
registerSoftware(WWWconnection & con)1792 bool registerSoftware(WWWconnection& con)
1793 {
1794 key = con.get("name");
1795 if (persons.select(qPerson) == 0) {
1796 error(con, "No such person");
1797 } else {
1798 key = con.get("software");
1799 if (products.select(qSoftware) == 0) {
1800 error(con, "No such software product");
1801 } else {
1802 if (rindex(products->setUsers, persons.currentId()) >= 0) {
1803 error(con, "User already registered this software");
1804 } else {
1805 products->setUsers.append(persons.currentId());
1806 products.update();
1807 return userForm(con);
1808 }
1809 }
1810 }
1811 return true;
1812 }
1813
1814
softwareForm(WWWconnection & con)1815 bool softwareForm(WWWconnection& con)
1816 {
1817 char* software = con.get("software");
1818 if (software == NULL) {
1819 error(con, "No software product was selected");
1820 return true;
1821 }
1822 key = software;
1823 if (products.select(qSoftware) == 0) {
1824 error(con, "No such software product");
1825 return true;
1826 }
1827 if (strcmp(con.get("action"), "Detach") == 0) {
1828 key = con.get("name");
1829 if (persons.select(qPerson) == 0) {
1830 error(con, "No such person");
1831 return true;
1832 }
1833 int i = rindex(persons->setProjects, products.currentId());
1834 if (i < 0) {
1835 error(con, "Person was not attached to the project");
1836 return true;
1837 }
1838 persons->setProjects.remove(i);
1839 persons.update();
1840 return userForm(con);
1841 }
1842 if (strcmp(con.get("action"), "Unregister") == 0) {
1843 key = con.get("name");
1844 if (persons.select(qPerson) == 0) {
1845 error(con, "No such person");
1846 return true;
1847 }
1848 int i = rindex(persons->setUsedSoftware, products.currentId());
1849 if (i < 0) {
1850 error(con, "Person was not registered");
1851 return true;
1852 }
1853 persons->setProjects.remove(i);
1854 persons.update();
1855 return userForm(con);
1856 }
1857 char* myself = con.get("myself");
1858 key = myself;
1859 if (persons.select(qPerson) == 0) {
1860 error(con, "No such person");
1861 return true;
1862 }
1863 int personStatus = persons->status;
1864 con << TAG <<
1865 HTML_HEAD "<TITLE>" << software << "</TITLE></HEAD>"
1866 BODY
1867 "<H2>" << software << "</H2>"
1868 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1869 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
1870 << con.getAddress() << "\"><INPUT TYPE=hidden "
1871 "NAME=\"page\" VALUE=\"updateSoftware\">"
1872 "<INPUT TYPE=hidden NAME=\"software\" VALUE=\"" << software << "\">"
1873 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
1874 "<TABLE><TR><TH ALIGN=LEFT>Product name:</TH>"
1875 "<TD><INPUT TYPE=text NAME=\"newname\" VALUE=\"" << software << "\">"
1876 "</TD></TR>";
1877 if (products->pVersions != null) {
1878 versions.at(products->pVersions);
1879 con << TAG <<
1880 "<TR><TH ALIGN=LEFT>Current version:</TH>"
1881 "<TD><INPUT TYPE=text NAME=\"version\" SIZE=8 VALUE=\""
1882 << versions->getVersionString() << "\"></TD></TR>"
1883 "<TR><TH ALIGN=LEFT>Current version label:</TH>"
1884 "<TD><INPUT TYPE=text NAME=\"label\" SIZE=20 VALUE=\""
1885 << versions->sLabel << "\"></TD></TR>"
1886 "<TR><TH ALIGN=LEFT>Current version comment:</TH>"
1887 "<TD><INPUT TYPE=text NAME=\"comment\" SIZE=40 VALUE=\""
1888 << versions->sComment << "\"></TD></TR>";
1889 } else {
1890 con << TAG <<
1891 "<TR><TH ALIGN=LEFT>Current version:</TH>"
1892 "<TD><INPUT TYPE=text NAME=\"version\" SIZE=8></TD></TR>"
1893 "<TR><TH ALIGN=LEFT>Current version label:</TH>"
1894 "<TD><INPUT TYPE=text NAME=\"label\" SIZE=20></TD></TR>"
1895 "<TR><TH ALIGN=LEFT>Current version comment:</TH>"
1896 "<TD><INPUT TYPE=text NAME=\"comment\" SIZE=40></TD></TR>";
1897 }
1898 con << TAG << "</TABLE><BR>";
1899 if (personStatus != Person::isUser) {
1900 con << TAG <<
1901 "<INPUT TYPE=submit VALUE=\"Update\"> <INPUT TYPE=reset>";
1902 }
1903 con << TAG << "</FORM><P>"
1904 "<TABLE><TR><TH ALIGN=LEFT>Engineers:</TH>"
1905 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1906 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress()
1907 << "\"><INPUT TYPE=HIDDEN NAME=\"page\" VALUE=\"userForm\">"
1908 "<INPUT TYPE=HIDDEN NAME=\"myself\" VALUE=\"" << myself <<
1909 "\"><SELECT NAME=\"name\" SIZE=1>";
1910 if (products->setEngineers.length() != 0) {
1911 print(con, products->setEngineers);
1912 con << TAG << "</SELECT>";
1913 if (personStatus != Person::isUser) {
1914 con << TAG << "<INPUT TYPE=submit VALUE=\"Select\">";
1915 }
1916 } else {
1917 con << TAG << EMPTY_LIST;
1918 }
1919 con << TAG <<
1920 "</FORM></TD></TR>"
1921 "<TR><TH ALIGN=LEFT>Users:</TH>"
1922 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1923 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress()
1924 << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"userForm\">"
1925 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1926 "\"><SELECT NAME=\"name\" SIZE=1>";
1927 if (products->setUsers.length() != 0) {
1928 print(con, products->setUsers);
1929 con << TAG << "</SELECT>";
1930 if (personStatus != Person::isUser) {
1931 con << TAG << "<INPUT TYPE=submit VALUE=\"Select\">";
1932 }
1933 } else {
1934 con << TAG << EMPTY_LIST;
1935 }
1936 con << TAG <<
1937 "</FORM></TD></TR>"
1938 "<TR><TH ALIGN=LEFT>Bugs:</TH>"
1939 "<TD><FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
1940 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress()
1941 << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"bugForm\">"
1942 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1943 "\"><SELECT NAME=\"bug\" SIZE=1>";
1944 if (products->setBugs.length() != 0) {
1945 print(con, products->setBugs);
1946 con << TAG <<
1947 "</SELECT><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
1948 } else {
1949 con << TAG << EMPTY_LIST;
1950 }
1951 con << TAG <<
1952 "</FORM></TD></TR>"
1953 "<TR><TH ALIGN=LEFT>Versions:</TH><TD>"
1954 "<FORM METHOD=POST ACTION=\""<<con.getStub() << "\">"
1955 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\"" << con.getAddress()
1956 << "\"><INPUT TYPE=hidden NAME=\"page\" VALUE=\"versionForm\">"
1957 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself <<
1958 "\"><INPUT TYPE=HIDDEN NAME=\"software\" VALUE=\"" << software <<
1959 "\"><SELECT NAME=\"version\" SIZE=1>";
1960 initialVersion = products->pVersions;
1961 if (versions.select(qAllVersions) != 0) {
1962 print(con, versions);
1963 con << TAG << "</SELECT><INPUT TYPE=submit VALUE=\"Select\">";
1964 } else {
1965 con << TAG << EMPTY_LIST;
1966 }
1967 con << TAG << "</FORM></TD></TR></TABLE>";
1968 mainMenuReference(con);
1969 return true;
1970 }
1971
1972
updateSoftware(WWWconnection & con)1973 bool updateSoftware(WWWconnection& con)
1974 {
1975 char* software = con.get("software");
1976 key = software;
1977 if (products.select(qSoftware) == 0) {
1978 error(con, "No such software product");
1979 return true;
1980 }
1981 Version version;
1982 char* currentVersion = con.get("version");
1983 version.sLabel = con.get("label");
1984 version.sComment = con.get("comment");
1985 if (sscanf(currentVersion, "%d.%d", &majorVersion, &minorVersion) != 2)
1986 {
1987 error(con, "Bad version number (MAJOR.MINOR expected)");
1988 return true;
1989 }
1990 products->sName = con.get("newname");
1991 version.majorVersionNumber = majorVersion;
1992 version.minorVersionNumber = minorVersion;
1993 version.released = dbDateTime::current();
1994 if (products->pVersions != null) {
1995 initialVersion = products->pVersions;
1996 if (versions.select(qVersion) != 0) {
1997 versions->sComment = version.sComment;
1998 versions->sLabel = version.sLabel;
1999 } else {
2000 versions.at(products->pVersions);
2001 if (versions->majorVersionNumber > majorVersion ||
2002 (versions->majorVersionNumber == majorVersion &&
2003 versions->minorVersionNumber > minorVersion))
2004 {
2005 error(con, "Version number less than of current version");
2006 return true;
2007 }
2008 version.pNext = products->pVersions;
2009 products->pVersions = insert(version);
2010 }
2011 } else {
2012 version.pNext = null;
2013 products->pVersions = insert(version);
2014 }
2015 products.update();
2016 con.addPair("name", con.get("myself"));
2017 return userForm(con);
2018 }
2019
2020
versionForm(WWWconnection & con)2021 bool versionForm(WWWconnection& con)
2022 {
2023 char* software = con.get("software");
2024 char* myself = con.get("myself");
2025 char buf[64];
2026 key = software;
2027 if (products.select(qSoftware) == 0) {
2028 error(con, "No such software product");
2029 return true;
2030 }
2031 char* versionString = con.get("version");
2032 if (sscanf(versionString, "%d.%d", &majorVersion, &minorVersion) != 2) {
2033 error(con, "Bad version format");
2034 return true;
2035 }
2036 initialVersion = products->pVersions;
2037 if (versions.select(qVersion) == 0) {
2038 error(con, "No such version");
2039 return true;
2040 }
2041 key = myself;
2042 if (persons.select(qPerson) == 0) {
2043 error(con, "No such person");
2044 return true;
2045 }
2046 con << TAG <<
2047 HTML_HEAD "<TITLE>" << software << " v. " << versionString <<
2048 "</TITLE></HEAD>"
2049 BODY
2050 "<H2>" << software << " v. " << versionString << "</H2>"
2051 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
2052 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
2053 << con.getAddress() << "\"><INPUT TYPE=hidden "
2054 "NAME=\"page\" VALUE=\"updateVersion\">"
2055 "<INPUT TYPE=hidden NAME=\"software\" VALUE=\"" << software << "\">"
2056 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
2057 "<INPUT TYPE=hidden NAME=\"version\" VALUE=\"" << versionString <<"\">"
2058 "<TABLE><TR><TH ALIGN=LEFT>Released:</TH>"
2059 "<TD>" << versions->released.asString(buf, sizeof buf) << "</TD></TR>"
2060 "<TR><TH ALIGN=LEFT>Label:</TH>"
2061 "<TD><INPUT TYPE=text NAME=\"label\" SIZE=20 VALUE=\""
2062 << versions->sLabel << "\"></TD></TR>"
2063 "<TR><TH ALIGN=LEFT>Comment:</TH>"
2064 "<TD><INPUT TYPE=text NAME=\"comment\" SIZE=40 VALUE=\""
2065 << versions->sComment << "\"></TD></TR></TABLE>";
2066 if (persons->status != Person::isUser) {
2067 con << TAG <<
2068 "<P><INPUT TYPE=submit NAME=\"action\" VALUE=\"Update\">";
2069 if (persons->status == Person::isAdministrator) {
2070 con << TAG <<
2071 " <INPUT TYPE=submit NAME=\"action\" VALUE=\"Remove\">";
2072 }
2073 con << TAG << " <INPUT TYPE=reset>";
2074 }
2075 con << TAG << "<P></FORM>"
2076 "<B>Bugs:</B><BR>"
2077 "<FORM METHOD=POST ACTION=\"" << con.getStub() << "\">"
2078 "<INPUT TYPE=HIDDEN NAME=\"socket\" VALUE=\""
2079 << con.getAddress() << "\"><INPUT TYPE=hidden NAME=\"page\" "
2080 "VALUE=\"bugForm\">"
2081 "<INPUT TYPE=hidden NAME=\"myself\" VALUE=\"" << myself << "\">"
2082 "<SELECT NAME=\"bug\" SIZE=5>";
2083 if (versions->setBugs.length() != 0) {
2084 print(con, versions->setBugs);
2085 con << TAG <<
2086 "</SELECT><BR><INPUT TYPE=submit NAME=\"action\" VALUE=\"Select\">";
2087 } else {
2088 con << TAG << EMPTY_LIST;
2089 }
2090 con << TAG << "</FORM>";
2091 mainMenuReference(con);
2092 return true;
2093 }
2094
updateVersion(WWWconnection & con)2095 bool updateVersion(WWWconnection& con)
2096 {
2097 char* software = con.get("software");
2098 key = software;
2099 if (products.select(qSoftware) == 0) {
2100 error(con, "No such software product");
2101 return true;
2102 }
2103 if (sscanf(con.get("version"), "%d.%d", &majorVersion, &minorVersion) != 2)
2104 {
2105 error(con, "Bad version format");
2106 return true;
2107 }
2108 if (strcmp(con.get("action"), "Remove") == 0) {
2109 dbReference<Version> prev, curr = null, next = products->pVersions;
2110 do {
2111 prev = curr;
2112 if (next == null) {
2113 error(con, "No such version");
2114 return true;
2115 }
2116 versions.at(next);
2117 curr = next;
2118 next = versions->pNext;
2119 } while (versions->majorVersionNumber != majorVersion ||
2120 versions->minorVersionNumber != minorVersion);
2121 if (versions->setBugs.length() != 0) {
2122 error(con, "Can not remove version with non-empty bugs list");
2123 return true;
2124 }
2125 versions.remove();
2126 if (prev == null) {
2127 products->pVersions = next;
2128 products.update();
2129 } else {
2130 versions.at(prev);
2131 versions->pNext = next;
2132 versions.update();
2133 }
2134 con.addPair("action", "Select");
2135 return softwareForm(con);
2136 }
2137 initialVersion = products->pVersions;
2138 if (versions.select(qVersion) == 0) {
2139 error(con, "No such version");
2140 return true;
2141 }
2142 versions->sComment = con.get("comment");
2143 versions->sLabel = con.get("label");
2144 versions.update();
2145 return versionForm(con);
2146 }
2147
2148 WWWapi::dispatcher dispatchTable[] = {
2149 {"addUserForm", addUserForm},
2150 {"addEngineerForm", addEngineerForm},
2151 {"addSoftwareForm", addSoftwareForm},
2152 {"selectSoftwareForm", selectSoftwareForm},
2153 {"removeSoftwareForm", removeSoftwareForm},
2154 {"selectPersonForm", selectPersonForm},
2155 {"removePersonForm", removePersonForm},
2156 {"selectBugForm", selectBugForm},
2157 {"removeBugForm", removeBugForm},
2158 {"changePasswordForm", changePasswordForm},
2159 {"shutdown", shutdown},
2160 {"userForm", userForm},
2161 {"softwareForm", softwareForm},
2162 {"addUser", addUser},
2163 {"addEngineer", addEngineer},
2164 {"removePerson", removePerson},
2165 {"addSoftware", addSoftware},
2166 {"removeSoftware", removeSoftware},
2167 {"removeBug", removeBug},
2168 {"changePassword", changePassword},
2169 {"updatePerson", updatePerson},
2170 {"login", login},
2171 {"bugQueryForm", bugQueryForm},
2172 {"bugQuery", bugQuery},
2173 {"userForm", userForm},
2174 {"createBugReportForm", createBugReportForm},
2175 {"bugForm", bugForm},
2176 {"createBugReport", createBugReport},
2177 {"bugForm", bugForm},
2178 {"updateBug", updateBug},
2179 {"updateReportForm", updateReportForm},
2180 {"updateWorkAroundForm", updateWorkAroundForm},
2181 {"addReportForm", addReportForm},
2182 {"addReport", addReport},
2183 {"addWorkAroundForm", addWorkAroundForm},
2184 {"addWorkAround", addWorkAround},
2185 {"updateReport", updateReport},
2186 {"updateWorkAround", updateWorkAround},
2187 {"attachToProject", attachToProject},
2188 {"registerSoftware", registerSoftware},
2189 {"softwareForm", softwareForm},
2190 {"updateSoftware", updateSoftware},
2191 {"versionForm", versionForm},
2192 {"updateVersion", updateVersion}
2193 };
2194
2195 #ifdef USE_EXTERNAL_HTTP_SERVER
2196 CGIapi wwwServer(db, itemsof(dispatchTable), dispatchTable);
2197 char* defaultAddress = "localhost:6101";
2198 socket_t::socket_domain domain = socket_t::sock_local_domain;
2199 #else
2200 HTTPapi wwwServer(db, itemsof(dispatchTable), dispatchTable);
2201 char* defaultAddress = "localhost:80";
2202 socket_t::socket_domain domain = socket_t::sock_global_domain;
2203 #endif
2204
main(int argc,char * argv[])2205 int __cdecl main(int argc, char* argv[])
2206 {
2207 char* address = (argc > 1) ? argv[1] : defaultAddress;
2208 if (!wwwServer.open(address, domain)) {
2209 fprintf(stderr, "Failed to open WWW session\n");
2210 return EXIT_FAILURE;
2211 }
2212 if (!db.open("bugdb.dbs")) {
2213 fprintf(stderr, "Failed to open database\n");
2214 return EXIT_FAILURE;
2215 }
2216 qBug = "bugId=",bugId;
2217 qReport = "index=",reportId,"start from",firstReport,"follow by pNext";
2218 qAllReports = "start from",firstReport,"follow by pNext";
2219 qVersion = "majorVersionNumber=",majorVersion,"and minorVersionNumber=",
2220 minorVersion,"start from",initialVersion,"follow by pNext";
2221 qAllVersions = "start from",initialVersion,"follow by pNext";
2222 qPerson = "sName=",&key;
2223 qSoftware = "sName=",&key;
2224
2225 if (sequencer.select() == 0) {
2226 BugSequencer seq;
2227 seq.nBugs = 0;
2228 insert(seq);
2229 }
2230 if (persons.select() == 0) {
2231 Person administrator;
2232 administrator.sName = "administrator";
2233 administrator.sEmailAddress = "root";
2234 administrator.sPassword = "";
2235 administrator.status = Person::isAdministrator;
2236 administrator.nReports = 0;
2237 insert(administrator);
2238 }
2239 WWWconnection con;
2240 while (wwwServer.connect(con) && wwwServer.serve(con));
2241 db.close();
2242 printf("End of session\n");
2243 return EXIT_SUCCESS;
2244 }
2245
2246