acpi: Select proper one shot timer based on CPUs' C3 state.
[dragonfly.git] / contrib / bsdinstaller-1.1.6 / src / frontends / cgi / dfuife_cgi.c
1 /*
2  * Copyright (c) 2004 Scott Ullrich <GeekGod@GeekGod.com> 
3  * Portions Copyright (c) 2004 Chris Pressey <cpressey@catseye.mine.nu>
4  *
5  * Copyright (c) 2004 The DragonFly Project.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The DragonFly Project
9  * by Scott Ullrich and Chris Pressey (see above for e-mail addresses).
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in
20  *    the documentation and/or other materials provided with the
21  *    distribution.
22  *
23  * 3. Neither the name of The DragonFly Project nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific, prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
31  * COPYRIGHT HOLDERS, CONTRIBUTORS OR VOICES IN THE AUTHOR'S HEAD
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY
33  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
34  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
37  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
38  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
41  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
43  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  */
48
49 /*
50  * dfuife_cgi.c
51  * CGI frontend for DFUI.
52  * $Id: dfuife_cgi.c,v 1.46 2005/03/09 22:55:55 cpressey Exp $
53  *
54  * NOTE: 
55  * With CAPS, this CGI only seems to work with thttpd (where user =
56  * the user that the DFUI backend is running as.)  No luck with Apache.
57  */
58
59 #define SAVED_ENVIRONMENT "/tmp/cgicsave.env"
60 #define LINEMAX 1024   /* an arbitrary buffer size */
61  
62 #include <signal.h>
63 #include <stdio.h>
64 #include <fcntl.h>
65 #include <string.h>
66 #include <stdlib.h>
67 #include <time.h>
68
69 #include "dfui/dfui.h"
70 #include "dfui/dump.h"
71
72 #include "cgic.h"
73
74 #ifndef DFUIFE_CSS
75 #define DFUIFE_CSS "dfuife.css"
76 #endif
77
78 #ifndef DFUIFE_CGI
79 #define DFUIFE_CGI "dfuife.cgi"
80 #endif
81
82 #ifndef DFUIFE_JS
83 #define DFUIFE_JS "dfuife.js"
84 #endif
85
86 static void      signal_handler(int signo);
87 static void      output_html_header(const char *title);
88 static void      output_html_footer(void);
89 static void      cl_progress_bar_begin(void);
90 static void      create_html_from_dfui_form(const struct dfui_form *f);
91 static void      create_html_from_dfui_form_single(const struct dfui_form *f);
92 static void      create_html_from_dfui_form_multiple(const struct dfui_form *f);
93 static void      cl_progress_bar_stop(void);
94 static void      cl_progress_bar_update(int percent, const char *pbstatus);
95 static void      convert_nl_to_br(const char *string_to_convert);
96 static int       field_name_has_type(const char *arrayFieldName);
97
98 int headers_outputted = 0;
99 int last_progress_amount = -1;
100 int is_streaming_progress_bar = 0;
101
102 volatile sig_atomic_t caught_signal;
103
104 static void
105 signal_handler(int signo)
106 {
107         caught_signal = signo;
108 }
109
110 static void
111 output_html_header(const char *title)
112 {
113         struct tm *tp;
114         time_t now;
115
116         if (headers_outputted == 1)
117                 return;
118
119         headers_outputted = 1;
120
121         setvbuf(cgiOut, NULL, _IONBF, 0);
122
123         now = time(NULL);
124         tp = localtime(&now); 
125         fprintf(cgiOut, "Cache-Control: no-cache\n");
126         fprintf(cgiOut, "Cache-Control: no-store\n");
127         fprintf(cgiOut, "Pragma: no-cache\n");
128         fprintf(cgiOut, "Content-type: text/html\n\n");
129         fprintf(cgiOut, "\n<?xml version='1.0' encoding='UTF-8'?>\n");
130         fprintf(cgiOut, "\n<!DOCTYPE html ");
131         fprintf(cgiOut, "PUBLIC '-//W3C//Dtd XHTML 1.0 Strict//EN'");
132         fprintf(cgiOut, " 'http://www.w3.org/tr/xhtml1/Dtd/xhtml1-strict.dtd'>\n");
133         fprintf(cgiOut, "\n<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n");
134         fprintf(cgiOut, "\n<head>");
135         fprintf(cgiOut, "\n<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />");
136         fprintf(cgiOut, "\n<title>%s</title>", title);
137         fprintf(cgiOut, "<link rel=\"stylesheet\" type=\"text/css\" href=\"" DFUIFE_CSS "\" /> \n ");
138         fprintf(cgiOut, "\n</head>");
139         fprintf(cgiOut, "\n<body onunload=\"if(loaded == 0) { event.returnValue = 'An install in progress.'; } \"> ");
140         fprintf(cgiOut, "\n<form name='dfuife' id='dfuife' method='post' action='" DFUIFE_CGI "'>\n");
141
142         /* javascript form helper functions */
143         fprintf(cgiOut, "\n<script type=\"text/javascript\" language=\"javascript\" src=\"" DFUIFE_JS "\">\n</script>\n");
144
145         fprintf(cgiOut, "\n<div class=\"main\">\n");
146         
147         fprintf(cgiOut, "<div class=\"maintitle\">\n");
148         fprintf(cgiOut, "       DragonFly Installer\n");
149         fprintf(cgiOut, "</div>\n");
150
151         fprintf(cgiOut, "<div class=\"title\">\n");
152         fprintf(cgiOut, "       %s\n",title);
153         fprintf(cgiOut, "</div>\n");
154 }
155
156 static void
157 output_html_footer(void)
158 {
159         fprintf(cgiOut, "\n</tbody>\n</table>\n");
160         fprintf(cgiOut, "\n</div>\n");
161         fprintf(cgiOut, "\n</div>\n");
162         fprintf(cgiOut, "\n</form>\n");
163         fprintf(cgiOut, "\n\n<script type=\"text/javascript\" language='javascript'>\nloaded = 1;\n</script>\n");
164         fprintf(cgiOut, "\n<p />");
165         fprintf(cgiOut, "\n</body>\n</html>\n");
166 }
167
168 static void
169 create_html_from_dfui_form_single(const struct dfui_form *f)
170 {
171         struct dfui_action *a;
172         struct dfui_celldata *cd;
173         struct dfui_field *fi;
174         const char *field_id;
175         const char *field_name;
176         const char *field_descr;
177         const char *field_value;
178         const char *field_type;
179         const char *form_name;
180         const char *form_short_description;
181         struct dfui_option *o;
182         const char *help_text;
183
184         help_text = dfui_info_get_long_desc(dfui_form_get_info(f));
185         form_name = dfui_info_get_name(dfui_form_get_info(f));
186         form_short_description = dfui_info_get_short_desc(dfui_form_get_info(f));
187
188         output_html_header(form_name);
189
190         if (dfui_form_property_is(f, "monospaced", "true")) {
191                 /* output the short description as-is */
192                 fprintf(cgiOut, "<div class=\"monospaced\">\n");
193                 fprintf(cgiOut, "<pre>%s</pre>", form_short_description);
194         } else {
195                 /* output the short desc with newlines converted to <br> */
196                 fprintf(cgiOut, "<div class=\"textbox\">\n");
197                 convert_nl_to_br(form_short_description);
198         }
199         fprintf(cgiOut, "</div>");
200
201         fprintf(cgiOut, "       <div class=\"mainform\">\n");
202         fprintf(cgiOut, "       <table class=\"maintable\" id=\"mainness\">");
203         fprintf(cgiOut, "       <tbody>\n");
204
205 #if 0
206         fprintf(cgiOut, "\n<table width=\"100%%\" border=\"0\"><tr><td colspan=\"15\"><center>");
207         fprintf(cgiOut, "<div class=\"textbox\">\n");
208         if (dfui_form_property_is(f, "monospaced", "true")) {
209                 fprintf(cgiOut, "<pre>");
210         }
211         /* ouput this text with newlines converted to <br> */
212         convert_nl_to_br(form_short_description);
213         if (dfui_form_property_is(f, "monospaced", "true")) {
214                 fprintf(cgiOut, "</pre>");
215         }
216         fprintf(cgiOut, "</div>\n<center>\n");
217 #endif
218
219         if (dfui_form_is_extensible(f)) {
220                 fprintf(cgiOut, "<input type='hidden' name='isextensible' value='isextensible'></input>\n");            
221         }
222
223         /*
224          * TODO: * get accurate colspan
225          *       * size all columns in a grid pattern
226          */
227
228         help_text = dfui_info_get_long_desc(dfui_form_get_info(f));
229
230         for (fi = dfui_form_field_get_first(f); fi != NULL; fi = dfui_field_get_next(fi)) {
231                 field_id = dfui_field_get_id(fi);
232                 field_name = dfui_info_get_name(dfui_field_get_info(fi));
233                 field_descr = dfui_info_get_short_desc(dfui_field_get_info(fi));
234                 if (strlen(field_descr) < 3)
235                         field_descr = field_name;
236
237                 cd = dfui_dataset_celldata_find(dfui_form_dataset_get_first(f), dfui_field_get_id(fi));
238                 field_value = dfui_celldata_get_value(cd);
239                 field_type = "textbox";
240                 if (dfui_field_property_is(fi, "control", "checkbox"))
241                         field_type = "checkbox";
242                 if (dfui_field_property_is(fi, "control", "button"))
243                         field_type = "button";
244                 if (dfui_field_property_is(fi, "control", "radio"))
245                         field_type = "radio";
246                 if (dfui_field_property_is(fi, "control", "checkbox")) {
247                         fprintf(cgiOut, "<tr><td colspan=\"2\" align=middle><center>%s: "
248                                         "<input type='checkbox' name='%s' title='%s'"
249                                         "%s></input>\n",
250                             field_name, field_id, field_descr,
251                             strcmp(field_value, "Y") == 0 ? " CHECKED" : " ");
252                         fprintf(cgiOut, "<input type='hidden' name='%s_type' value='checkbox'></input></td></tr>\n",
253                             field_id);
254                 } else {
255                         o = dfui_field_option_get_first(fi);
256                         if (o != NULL) {
257                             fprintf(cgiOut, "<tr><td align=right>%s:</td>"
258                                             "<td align=left><select name='%s' "
259                                             "title='%s'>\n",
260                                 field_name, field_id, field_descr);
261                             for (o = dfui_field_option_get_first(fi); o != NULL; o = dfui_option_get_next(o)) {
262                                 /*
263                                  * Render this option as a choice
264                                  * in a drop-down list box.
265                                  */
266                                 fprintf(cgiOut, "<option value='%s'>%s</option>\n",
267                                     dfui_option_get_value(o), dfui_option_get_value(o));
268                             }
269                             fprintf(cgiOut, "</select>\n</td></tr>\n");
270                         } else {
271                                 fprintf(cgiOut, "<tr><td align=right>%s:</td>"
272                                                 "<td align='left'><input class='button' "
273                                                 "type='%s' name='%s' value='%s' %s"
274                                                 "title='%s'></input>\n",
275                                     field_name,
276                                     dfui_field_property_is(fi, "obscured", "true") ?
277                                         "password" : "textbox",
278                                     field_id, field_value,
279                                     dfui_field_property_is(fi, "editable", "false") ?
280                                         " onFocus=\"this.blur();\" " : " ",
281                                     field_descr);
282                                 fprintf(cgiOut, "<input type='hidden' name='%s_type' value='%s'></input></td></tr>\n",
283                                     field_id, field_type);
284                         }
285                 }
286         }
287         fprintf(cgiOut, "\n<tr><td colspan=\"15\">&nbsp;<br /><center>");
288         for (a = dfui_form_action_get_first(f); a != NULL;  a = dfui_action_get_next(a)) {
289                 const char *action_id, *action_name;
290
291                 action_id = dfui_action_get_id(a);
292                 action_name = dfui_info_get_name(dfui_action_get_info(a));
293                 fprintf(cgiOut, "<input class='button' type='submit' name='%s' value='%s'></input> \n",
294                     action_id, action_name);
295                 fprintf(cgiOut, "<input type='hidden' name='%s_type' value='button'></input> \n",
296                     action_id);
297                 if (dfui_form_property_is(f, "role", "menu")) {
298                         fprintf(cgiOut, "<br />&nbsp;<br />");
299                 }
300         }
301         fprintf(cgiOut, "</center>");
302         fprintf(cgiOut, "</td></tr></table>");
303
304         if (strlen(help_text) > 0) {
305                 fprintf(cgiOut, "<center><p><a href='#' onClick='javascript:alert(\"%s\");'>Help</a></p></center>", help_text);
306         }
307
308         output_html_footer();
309 }
310
311 static void
312 create_html_from_dfui_form_multiple(const struct dfui_form *f)
313 {
314         struct dfui_action *a;
315         struct dfui_celldata *cd;
316         struct dfui_dataset *ds;
317         struct dfui_field *fi;
318         struct dfui_option *o;
319         const char *field_descr;
320         const char *field_name;
321         const char *field_value;
322         const char *field_type;
323         const char *form_name;
324         const char *form_short_description;
325         int field_counter;
326         int field_counter_js = 0;
327         int rows = 0;
328         const char *help_text;
329
330         form_name = dfui_info_get_name(dfui_form_get_info(f));
331         form_short_description = dfui_info_get_short_desc(dfui_form_get_info(f));
332
333         output_html_header(form_name);
334
335         fprintf(cgiOut, "       <div class=\"mainform\">\n");
336         fprintf(cgiOut, "       <table width=\"100%%\" class=\"maintable\" id=\"mainness\">");
337
338         fprintf(cgiOut, "       <tbody>\n<tr><td><center>");
339
340         fprintf(cgiOut, "\n<center>\n<table border=\"0\"><tr><td colspan=\"15\"><center>");
341
342         fprintf(cgiOut, "<input type='hidden' name='ismultiple' value='true'></input>\n");
343         
344         if (dfui_form_is_extensible(f))
345                 fprintf(cgiOut, "<input type='hidden' name='isextensible' value='isextensible'></input>\n");            
346
347         if (dfui_form_property_is(f, "monospaced", "true")) {
348                 fprintf(cgiOut, "<div class=\"monospaced\">\n");
349                 fprintf(cgiOut, "<pre>%s</pre>", form_short_description);
350         } else {
351                 /* output this text with newlines converted to <br> */
352                 fprintf(cgiOut, "<div class=\"textbox\">\n");
353                 convert_nl_to_br(form_short_description);
354         }
355         fprintf(cgiOut, "</div>\n<center>\n");
356
357         fprintf(cgiOut, "<p></p>\n<table width=\"100%%\" name=\"maintablearea\" id=\"maintablearea\"><tr>");
358
359         rows = 0;
360         for (fi = dfui_form_field_get_first(f); fi != NULL;  fi = dfui_field_get_next(fi)) {
361                 field_descr = dfui_info_get_name(dfui_field_get_info(fi));
362                 fprintf(cgiOut, "<td><b>%s</b></td>", field_descr);
363                 fprintf(cgiOut, "\n<script type=\"text/javascript\" language='javascript'>\n");
364                 field_name = dfui_field_get_id(fi);
365                 fprintf(cgiOut, "rowname[%i] = \"%s\";\n", rows, field_name);
366
367                 field_type = "textbox";
368                 if (dfui_field_property_is(fi, "control", "checkbox"))
369                         field_type = "checkbox";
370                 if (dfui_field_property_is(fi, "control", "button"))
371                         field_type = "button";
372                 if (dfui_field_property_is(fi, "control", "textbox"))
373                         field_type = "textbox";
374                 if (dfui_field_property_is(fi, "control", "radio"))
375                         field_type = "radio";
376
377                 fprintf(cgiOut, "rowtype[%i] = \"%s\";\n", rows, field_type);
378                 fprintf(cgiOut, "</script>\n");
379                 fprintf(cgiOut, "<input type='hidden' name='%s_type' value='%s'></input>\n<p></p>\n",
380                     field_name, field_type);
381                 field_counter_js++;
382                 rows++;
383         }
384
385         if (dfui_form_is_extensible(f))
386             fprintf(cgiOut, "\n<td>\n<input class='button' type=\"button\" "
387                             "onclick=\"addRowTo('maintablearea')\" value=\"Add\">\n</td>\n");
388
389         fprintf(cgiOut, "\n</tr>\n<tr>");
390         rows = 0;
391         field_counter = 0;
392         for (ds = dfui_form_dataset_get_first(f); ds != NULL; ds = dfui_dataset_get_next(ds)) {
393                 fprintf(cgiOut, "<tr>");
394                 for (fi = dfui_form_field_get_first(f); fi != NULL;  fi = dfui_field_get_next(fi)) {
395                         cd = dfui_dataset_celldata_find(ds, dfui_field_get_id(fi));
396                         field_name = dfui_field_get_id(fi);
397                         field_value = dfui_celldata_get_value(cd);
398                         field_descr = dfui_info_get_short_desc(dfui_field_get_info(fi));
399
400                         if (dfui_field_property_is(fi, "control", "checkbox")) {
401                                 fprintf(cgiOut, "<td><center><input type='checkbox' name='%s-%d'%s></input>\n",
402                                     field_name, field_counter, strcmp(field_value, "Y") == 0 ? " CHECKED" : " ");
403
404                                 fprintf(cgiOut, "<input type='hidden' name='%s_row-%d' value='%d'></input><p></td>",
405                                     field_name, field_counter, field_counter);
406                         } else {
407                                 o = dfui_field_option_get_first(fi);
408                                 if (o != NULL) {
409                                         fprintf(cgiOut, "<td><select name=\"%s-%d\">\n",
410                                             field_name, field_counter);
411                                         for (o = dfui_field_option_get_first(fi); o != NULL; o = dfui_option_get_next(o)) {
412                                                 /*
413                                                  * Render this option as a choice
414                                                  * in a drop-down list box.
415                                                  */
416                                                 fprintf(cgiOut, "<option value='%s'>%s</option>\n",
417                                                     dfui_option_get_value(o), dfui_option_get_value(o));
418                                         }
419                                         fprintf(cgiOut, "</select>\n</td>");
420                                 } else {
421                                         fprintf(cgiOut, "<td><input class='button' type='%s' name='%s-%d' "
422                                                         "value='%s' %s title='%s'></input>\n",
423                                             dfui_field_property_is(fi, "obscured","true") ?
424                                                 "password" : "textbox",
425                                             field_name, field_counter,
426                                             field_value,
427                                             dfui_field_property_is(fi, "editable", "false") ?
428                                                 " onFocus=\"this.blur();\" " : " ",
429                                             field_descr);
430
431                                         fprintf(cgiOut, "<input type='hidden' name='%s_row-%d' value='%d'></input>\n<p />\n</td>",
432                                             field_name, field_counter, field_counter);
433                                 }
434                         }
435                 }
436                 field_counter++;
437                 rows++;
438                 if (dfui_form_is_extensible(f))
439                         fprintf(cgiOut, "\n<td>\n<input class='button' type='button' "
440                                         "value='Delete' onclick='removeRow(this)'>\n</td>\n");
441
442                 fprintf(cgiOut, "\n</tr>");
443         }
444         fprintf(cgiOut, "</table><table>");
445         fprintf(cgiOut, "<tr><td>\n");
446         fprintf(cgiOut, "\n<script type=\"text/javascript\" language='javascript'>\n");
447         fprintf(cgiOut, "field_counter_js = %d;\n", field_counter_js);
448         fprintf(cgiOut, "rows = %d;\n", (field_counter-1));
449         fprintf(cgiOut, "totalrows = %d;\n", (rows-1));
450         fprintf(cgiOut, "</script>\n\n");
451         for (a = dfui_form_action_get_first(f); a != NULL;  a = dfui_action_get_next(a)) {
452                 field_name = dfui_action_get_id(a);
453                 field_value = dfui_info_get_name(dfui_action_get_info(a));
454                 fprintf(cgiOut, "\n<input class='button' type='submit' name='%s' value='%s'></input> \n", field_name, field_value);
455                 fprintf(cgiOut, "\n<input type='hidden' name='%s_type' value='button'></input>\n", field_name);
456                 if (dfui_form_property_is(f, "role", "menu"))
457                         fprintf(cgiOut, "\n<br />&nbsp;<br />");
458         }
459         fprintf(cgiOut, "</td></tr></table>\n");
460
461         help_text = dfui_info_get_long_desc(dfui_form_get_info(f));
462
463         if (strlen(help_text) > 0) {
464                 fprintf(cgiOut, "<center><p><a href='#' onClick='javascript:alert(\"%s\");'>Help</a></p></center>", help_text);
465         }
466
467         output_html_footer();
468 }
469
470 static void
471 create_html_from_dfui_form(const struct dfui_form *f)
472 {
473         if (dfui_form_is_multiple(f))
474                 create_html_from_dfui_form_multiple(f);
475         else
476                 create_html_from_dfui_form_single(f);
477 }
478
479 static struct dfui_response *
480 create_response_from_posted_data_single(const char *form_id)
481 {
482         struct dfui_dataset *ds;
483         struct dfui_response *r;
484         char **array, **arrayStep;
485         char *field_name;
486         char arrayFieldName[80];
487         char field_type[80];
488         char tmp[30];
489         char value[80];
490
491         if (cgiFormEntries(&array) != cgiFormSuccess)
492                 return(r);
493         
494         arrayStep = array;
495         while (*arrayStep != NULL) {
496                 snprintf(tmp, 29, "%s_type", *arrayStep); 
497                 cgiFormStringNoNewlines(tmp, field_type, 80);
498                 if (cgiFormSubmitClicked(*arrayStep) == cgiFormSuccess &&
499                     strcmp(field_type, "button") == 0) {
500                         field_name = *arrayStep;
501                         break;
502                 }
503                 arrayStep++;
504         }
505
506         r = dfui_response_new(form_id, field_name);
507
508         /* Add the contents of all form inputs to r's dataset. */
509         ds = dfui_dataset_new();
510
511         #ifdef DEBUG
512                 output_html_header("DEBUG TURNED ON");
513         #endif /* DEBUG */
514
515         arrayStep = array;
516         /*
517          * TODO: revise this since it doesn't seem to include
518          *       unchecked boxes.
519          */
520         while (*arrayStep != NULL) {
521                 strncpy(arrayFieldName, *arrayStep, 30);
522                 if (field_name_has_type(arrayFieldName)) {
523                         arrayStep++;
524                         continue;
525                 }
526                 /* copy cgi value to value var */
527                 cgiFormStringNoNewlines(*arrayStep, value, 81); 
528                 /* we posted a extra hint about this field */
529                 snprintf(tmp, 29, "%s_type", *arrayStep); 
530                 /* copy the hint type to observe what kind of field we have. */
531                 cgiFormStringNoNewlines(tmp, field_type, 80);
532                 /* if it's a checkbox: */
533                 
534                 /* TODO: Check for _type at end of string */
535                 if (strcmp(field_type, "checkbox") == 0) {
536                         if (cgiFormCheckboxSingle(*arrayStep) ==
537                             cgiFormSuccess) { 
538                                 snprintf(value, 2, "Y");
539                                 #ifdef DEBUG
540                                         fprintf(cgiOut, "Adding %s %s<P>", 
541                                             arrayFieldName, value);
542                                 #endif /* DEBUG */
543                                 dfui_dataset_celldata_add(ds, 
544                                     arrayFieldName, value);
545                         } else {
546                                 snprintf(value, 2, "N");
547                                 #ifdef DEBUG
548                                         fprintf(cgiOut, "Adding %s %s<P>", 
549                                             arrayFieldName, value);
550                                 #endif /* DEBUG */
551                                 dfui_dataset_celldata_add(ds, 
552                                     arrayFieldName, value);
553                         }
554                 } else {
555                         /* if it's a textbox or a checkbox: */
556                         if (strcmp(field_type, "textbox") == 0 || 
557                             strcmp(field_type, "checkbox") == 0) {
558                                 #ifdef DEBUG
559                                         fprintf(cgiOut, "Adding %s %s<P>", 
560                                             arrayFieldName, value);
561                                 #endif /* DEBUG */
562                                 dfui_dataset_celldata_add(ds, arrayFieldName, value);
563                         }
564                 }
565                 arrayStep++;
566         }
567         cgiStringArrayFree(array);
568         dfui_response_dataset_add(r, ds);
569         return(r);
570 }
571
572 static int
573 field_name_has_type(const char *arrayFieldName)
574 {
575         if (strstr(arrayFieldName, "_type") != NULL ||
576             strstr(arrayFieldName, "_row") != NULL) {
577                 return(1); /* field is okay to post to backend. */
578         } else {
579                 return(0); /* field is not okay to post to backend. */
580         }
581 }
582
583 static struct dfui_response *
584 create_response_from_posted_data_multiple(const char *form_id)
585 {
586         struct dfui_dataset *ds;
587         struct dfui_response *r;
588         char **array, **arrayStep;
589         char *field_name;
590         char arrayFieldName[80];
591         char field_type[80];
592         char tmp[30];
593         char value[80];
594         int arrayFieldNumber;
595         int ismultiple;
596         size_t x;
597         int row = 0, found = 0;
598
599         ismultiple = 0;
600         cgiFormStringNoNewlines("ismultiple", tmp, 20);
601         if (strcmp(tmp, "true") == 0)
602                 ismultiple = 1;
603
604         if (cgiFormEntries(&array) != cgiFormSuccess) {
605                 return(r);
606         }
607
608         arrayStep = array;
609         while (*arrayStep != NULL) {
610                 snprintf(tmp, 29, "%s_type", *arrayStep);
611                 cgiFormStringNoNewlines(tmp, field_type, 80);
612                 if (cgiFormSubmitClicked(*arrayStep) == cgiFormSuccess &&
613                     strcmp(field_type, "button") == 0) {
614                         field_name = *arrayStep;
615                         break;
616                 }
617                 arrayStep++;
618         }
619
620         r = dfui_response_new(form_id, field_name);
621
622         #ifdef DEBUG
623                 output_html_header("DEBUG TURNED ON");
624         #endif /* DEBUG */
625
626         /*
627          * TODO: revise this since it doesn't seem to include
628          *       unchecked boxes.
629          */
630         row = 0;
631         do {
632                 ds = dfui_dataset_new();
633                 found = 0;
634                 for (arrayStep = array; *arrayStep != NULL; arrayStep++) {
635                         strncpy(arrayFieldName, *arrayStep, 30);
636                         if (field_name_has_type(arrayFieldName)) {
637                                 continue;
638                         }
639                         /* copy cgi value to value var */
640                         cgiFormStringNoNewlines(*arrayStep, value, 81);
641                         /* walk arrayFieldName and remove -[0-1000] */
642                         arrayFieldNumber = -1;
643                         for (x = 0; x < strlen(arrayFieldName); x++) {
644                                 if (arrayFieldName[x] == '-') {
645                                         arrayFieldName[x] = '\0';
646                                         arrayFieldNumber = atoi(&arrayFieldName[x+1]);
647                                         break;
648                                 }
649                         }
650                         #ifdef DEBUG
651                                 fprintf(cgiOut, "HTML input name: %s, arrayFieldName: %s, "
652                                                 "arrayFieldNumber: %d<p></p>",
653                                                 *arrayStep, arrayFieldName, arrayFieldNumber);
654                                 fflush(cgiOut);
655                         #endif /* DEBUG */
656                         /*
657                          * In any given iteration of this (inner) loop, we only care about
658                          * one set of fields, the fields which have an arrayFieldNumber
659                          * (that is, the bit after the hyphen) which is the same as 'row'.
660                          * So, if it's different, try again; if it's the same, count it.
661                          */
662                         if (arrayFieldNumber != row || arrayFieldNumber == -1) {
663                                 continue;
664                         } else {
665                                 found++;
666                         }
667                         /* we posted a extra hint about this field */
668                         snprintf(tmp, 29, "%s_type", arrayFieldName);
669                         /* copy the hint type to observe what kind of field we have. */
670                         cgiFormStringNoNewlines(tmp, field_type, 80);
671                         /* XXX temporarily override */
672
673                         /* if it's a checkbox: */
674                         if (strcmp(field_type, "checkbox") == 0) {
675                                 if (cgiFormCheckboxSingle(*arrayStep) ==
676                                     cgiFormSuccess) {
677                                         snprintf(value, 2, "Y");
678                                         #ifdef DEBUG
679                                                 fprintf(cgiOut, "Adding %s %s<P>",
680                                                     arrayFieldName, value);
681                                         #endif /* DEBUG */
682                                         dfui_dataset_celldata_add(ds,
683                                             arrayFieldName, value);
684                                 } else {
685                                         snprintf(value, 2, "N");
686                                         #ifdef DEBUG
687                                                 fprintf(cgiOut, "Adding %s %s<P>",
688                                                     arrayFieldName, value);
689                                         #endif /* DEBUG */
690                                         dfui_dataset_celldata_add(ds,
691                                             arrayFieldName, value);
692                                 }
693                         } else {
694                                 /* if it's a textbox or a checkbox: */
695                                 if (strcmp(field_type, "textbox") == 0 ||
696                                     strcmp(field_type, "checkbox") == 0) {
697                                         #ifdef DEBUG
698                                                 fprintf(cgiOut, "Adding %s %s<P>",
699                                                 arrayFieldName, value);
700                                         #endif /* DEBUG */
701                                         if (strcmp(arrayFieldName, "") != 0)
702                                                 dfui_dataset_celldata_add(ds, arrayFieldName, value);
703                                 }
704                         }
705                 }
706                 if (found > 0) {
707                         if (strcmp(arrayFieldName, "") != 0) {
708                            cgiFormStringNoNewlines("isextensible", tmp, 80);
709                            dfui_response_dataset_add(r, ds);
710                         }
711                 } else {
712                         dfui_dataset_free(ds);
713                 }
714                 row++;
715         } while (row < 100);
716         cgiStringArrayFree(array);
717         return(r);
718 }
719
720 static int
721 request_method_is(const char *method)
722 {
723         if (!strcasecmp(method, cgiRequestMethod))
724                 return(1);
725         else
726                 return(0);
727 }
728
729 int 
730 cgiMain(void)
731 {
732         struct dfui_connection *c;
733         struct dfui_form *f;
734         struct dfui_progress *pr;
735         struct dfui_property *gp;
736         struct dfui_response *r;
737         void *payload;
738         char msgtype;
739         char tmp[30];
740         int done = 0;
741         char environmental_payload[256];
742
743         int progress_amount;
744         #ifdef DEBUG
745                 dfui_debug_file = fopen("/tmp/dfuife_cgi_debug.log", "a");
746         #endif /* DEBUG */
747         setvbuf(cgiOut, NULL, _IONBF, 0);
748
749         /* Deterimine if the user is setting the transport via a environmental variable */
750
751         snprintf(environmental_payload, 256, "%s", getenv("BSD_INSTALLER_TRANSPORT"));
752         if (strcmp(environmental_payload,"CAPS") == 0) {
753                 c = dfui_connection_new(DFUI_TRANSPORT_CAPS, "test");
754         } else if (strcmp(environmental_payload,"NPIPE") == 0) {
755                 c = dfui_connection_new(DFUI_TRANSPORT_NPIPE, "test");
756         } else if (strcmp(environmental_payload,"TCP") == 0) {
757                 c = dfui_connection_new(DFUI_TRANSPORT_TCP, "9999");
758         } else {
759                 c = dfui_connection_new(DFUI_TRANSPORT_TCP, "9999");
760         }
761
762         dfui_fe_connect(c);
763
764         /* TODO: Additional error checking if we could not connect. */
765
766         if (request_method_is("POST")) {
767                 char form_id[81];
768
769                 if (cgiFormSubmitClicked("cancelinstal") == cgiFormSuccess) {
770                         /* cancel install */
771                         dfui_fe_progress_cancel(c);
772                 }
773                 cgiFormStringNoNewlines("form_id", form_id, 80);
774                 cgiFormStringNoNewlines("ismultiple",tmp, 20);
775                 if (strcmp(tmp, "true") == 0) {
776                          r = create_response_from_posted_data_multiple(form_id);
777                 } else {
778                          r = create_response_from_posted_data_single(form_id);
779                 }
780                 dfui_fe_submit(c, r);
781                 dfui_response_free(r);
782         }
783
784         while (!done) {
785                 dfui_fe_receive(c, &msgtype, &payload);
786                 switch (msgtype) {
787                 case DFUI_BE_MSG_PRESENT:
788                         f = (struct dfui_form *)payload;
789                         create_html_from_dfui_form(f);
790                         dfui_form_free(f);
791                         done = 1;
792                         break;
793                 case DFUI_BE_MSG_PROG_BEGIN:
794                         caught_signal = 0;
795                         signal(SIGPIPE, signal_handler);
796                         pr = (struct dfui_progress *)payload;
797                         is_streaming_progress_bar = dfui_progress_get_streaming(pr);
798                         fprintf(cgiOut, "<script language=javascript>\n");
799                         fprintf(cgiOut, "is_streaming_progress_bar = 1; \n");
800                         fprintf(cgiOut, "</script>\n");
801                         cl_progress_bar_begin();
802                         dfui_progress_free(pr);
803                         dfui_fe_progress_continue(c);
804                         break;
805                 case DFUI_BE_MSG_PROG_UPDATE:
806                         pr = (struct dfui_progress *)payload;
807                         progress_amount = dfui_progress_get_amount(pr);
808                         if (last_progress_amount != progress_amount)
809                               cl_progress_bar_update(progress_amount, dfui_info_get_short_desc(dfui_progress_get_info(pr)));
810                         dfui_progress_free(pr);
811                         if (caught_signal != 0) {
812                                 dfui_fe_progress_cancel(c);
813                                 done = 1;
814                         } else {
815                                 dfui_fe_progress_continue(c);
816                         }
817                         break;
818                 case DFUI_BE_MSG_PROG_END:
819                         signal(SIGPIPE, SIG_DFL);
820                         cl_progress_bar_stop();
821                         dfui_fe_progress_continue(c);
822                         done = 1;
823                         break;
824                 case DFUI_BE_MSG_SET_GLOBAL:
825                         gp = (struct dfui_property *)payload;
826
827                         /*
828                          * Check for a change to the "lang" setting...
829                          */
830                         if (strcmp(dfui_property_get_name(gp), "lang") == 0) {
831                                 /*
832                                  * TODO: call the appropriate gettext function.
833                                  */
834                         }
835
836                         dfui_fe_confirm_set_global(c);
837                         dfui_property_free(gp);
838                         break;
839                 case DFUI_BE_MSG_STOP:
840                         /* end of cycle, return to opening screen. */
841                         dfui_fe_confirm_stop(c);
842                         cgiHeaderLocation("/");
843                         done = 1;
844                         break;
845                 }
846                 /* sleep(1); */
847         }
848         fflush(cgiOut);
849         dfui_fe_disconnect(c);
850         #ifdef DEBUG
851                 fclose(dfui_debug_file);
852         #endif /* DEBUG */      
853         return(0);
854 }
855
856 static void
857 cl_progress_bar_stop(void)
858 {
859         fprintf(cgiOut, "\n<script type=\"text/javascript\" language='javascript'>\n");
860         fprintf(cgiOut, "document.progressbar.style.width='100%%';\n");
861         fprintf(cgiOut, "</script>\n");
862         fprintf(cgiOut, "\n\n<meta http-equiv='refresh' content='1;url=" DFUIFE_CGI "'>\n");
863         fflush(cgiOut);
864 }
865
866 static void
867 cl_progress_bar_begin(void)
868 {
869         int rows;
870         int cols;
871
872         if (is_streaming_progress_bar) {
873                 rows = 14;
874                 cols = 80;
875         } else {
876                 rows = 5;
877                 cols = 40;
878         }
879         output_html_header("Operation in progress, please wait...");
880         fprintf(cgiOut, "\n\n<p>&nbsp;</p>\n<center>\n\n");
881         fprintf(cgiOut, "<table height='40' border='1' bordercolor='black' width='400' bordercolordark='#000000' bordercolorlight='#000000' style='border-collapse: collapse' colspacing='2' cellpadding='2' cellspacing='2'><tr><td>");
882         fprintf(cgiOut, "\n<img border='0' src='dfly-pg.gif' width='280' height='43' name='progressbar' id='progressbar'>");
883         fprintf(cgiOut, "\n</td>\n</tr>\n</table>\n<br />\n<form>\n<center>\n<textarea rows='%d' onFocus=\"this.blur();\" cols='%d' name='pbstatus' id='pbstatus'>\n</textarea>", rows, cols);
884         fprintf(cgiOut, "\n<form method='post' action='" DFUIFE_CGI "'><p><input class='button' type='submit' name='cancelinstall' value='Cancel'></p>");
885         fflush(cgiOut);
886         output_html_footer();
887 }
888
889 static void
890 cl_progress_bar_update(int percent, const char *pbstatus)
891 {
892         fprintf(cgiOut, "\n\n<script type=\"text/javascript\" language='javascript'>\n");
893         fprintf(cgiOut, "document.progressbar.style.width='%d%%';\n", percent);
894         if (is_streaming_progress_bar) {
895                 fprintf(cgiOut, "temp_streaming_text = document.forms[0].pbstatus.value;\n");
896                 fprintf(cgiOut, "document.forms[0].pbstatus.value = temp_streaming_text + \"%s\\n\";\n", pbstatus);
897         } else {
898                 fprintf(cgiOut, "document.forms[0].pbstatus.value='%s';\n", pbstatus);
899         }
900         fprintf(cgiOut, "</script>\n\n");
901         last_progress_amount = percent;
902         fflush(cgiOut);
903 }
904
905 static void
906 convert_nl_to_br(const char *string_to_convert)
907 {
908         size_t x;
909
910         for (x = 0; x < strlen(string_to_convert); x++) {
911                 if (string_to_convert[x] == 10) {       /* newline character */
912                         fprintf(cgiOut, "&nbsp;<br />");
913                 } else if (string_to_convert[x] == '>') {
914                         fprintf(cgiOut, "&gt;");
915                 } else if (string_to_convert[x] == '<') {
916                         fprintf(cgiOut, "&lt;");
917                 } else {
918                         fprintf(cgiOut, "%c", string_to_convert[x]);
919                 }
920         }
921 }