1 //
2 // anyRemote
3 // a wi-fi or bluetooth remote for your PC.
4 //
5 // Copyright (C) 2006-2016 Mikhail Fedotov <anyremote@mail.ru>
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 //
21 
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "str.h"
28 #include "var.h"
29 #include "utils.h"
30 #include "conf.h"
31 #include "state.h"
32 #include "gen_html.h"
33 #include "mutex.h"
34 
35 extern char      tmp[MAXMAXLEN];
36 
37 // Predefined templates
38 #define HTTP_HEAD1 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n<head>\n<title>"
39 #define HTTP_HEAD2 "</title>\n"
40 #define HTTP_HEAD3 "<meta "
41 #define HTTP_HEAD4 " content=\"text/html; charset=utf-8\">\n"
42 #define HTTP_HEAD5 "</head>\n<body"
43 #define HTTP_HEAD6 ">\n<center>"
44 #define HTTP_SCRIPT      "<script>\nfunction clearForms()\n{\n  var i;\n  for (i = 0; (i < document.forms.length); i++) {\n    document.forms[i].reset();\n  }\n}\n</script>\n"
45 #define HTTP_SCRIPT_CALL " onload=\"clearForms()\""
46 
47 #define HTTP_HEAD_CSS_0  "<style type=\"text/css\">\n"
48 #define HTTP_HEAD_CSS_1  "table{\n\ttext-align:left;\n}\n"
49 #define HTTP_HEAD_CSS_B1 "body {\n\tcolor:#"
50 #define HTTP_HEAD_CSS_B2 "; \n\tbackground-color:#"
51 #define HTTP_HEAD_CSS_B3 ";\n}\n"
52 #define HTTP_HEAD_CSS_L1 "#menubutton{\n\tborder-radius:5px;\n\t-moz-border-radius:5px;\n\t-webkit-border-radius:10px;\n}\nselect {\n\tcolor:#"
53 #define HTTP_HEAD_CSS_L3 "; \n\twidth:"
54 #define HTTP_HEAD_CSS_BT1 "button {\n\tcolor:#"
55 
56 #define HTTP_HEAD_CSS_MENU1 ".menu {\n\twidth:"
57 
58 #define HTTP_HEAD_CSS_MENU2 "px;\n\theight:30px;\n\tfont-size:0.85em;\n\tposition: fixed;\n\tbottom: 0;\n}\n\
59 .menu ul {\n\tpadding:0;\n\tmargin:0;\n\tlist-style-type:none;\n}\n\
60 .menu input {\n\tpadding:0;\n\tmargin:0;\n}\n.menu ul ul,\n.menu ul input\n{\n\twidth:"
61 
62 #define HTTP_HEAD_CSS_MENU3 "px;\n}\n.menu li,\n.menu input {\n\tfloat:left;\n\twidth:"
63 #define HTTP_HEAD_CSS_MENU4 "px;\n\tposition:relative;\n}\n.menu input {\n\tdisplay:block;\n\tfont-size:13px;\n\ttext-decoration:none;\n\tcolor:#ffffff;\n\twidth:"
64 
65 #define HTTP_HEAD_CSS_MENU5 "px;\
66   height:30px;\
67   border:1px solid #999999;\
68   border-width:1px 1px 0 0;\
69   background:#7582aa;\
70   padding-left:10px;\
71   line-height:29px;\n}\n.menu ul ul input:hover {\
72   color:#fff;\
73   background:#949eaa;\
74 }\n.menu ul ul {\nvisibility:hidden;\
75   position:absolute;\
76   bottom:31px;\
77   left:0; \
78   width:" // W/2
79 
80 #define HTTP_HEAD_CSS_MENU6 "px;\n}\n.menu ul ul input {\n\tbackground:#a4a8aa;\n\tcolor:#000;\n\theight:30px;\n\tline-height:1em;\n\tpadding:5px 10px\n\twidth:"
81 
82 #define HTTP_HEAD_CSS_MENU7 "px;\n}\n.menu ul input:hover {\n\tcolor:#000;\n\tbackground:#949eaa;\n}\n.menu ul li:hover ul {\n\tvisibility:visible;\n\theight:auto;\n}\n"
83 
84 #define HTTP_HEAD_CSS_99 "</style>\n"
85 
86 #define HTTP_TABLE1 "\n<table border=\"0\" cellpadding=\""
87 #define HTTP_TABLE2 "\" cellspacing=\"2\">\n<tbody>\n<tr>\n"
88 //#define HTTP_TABLE3 "	<td style=\"vertical-align: top; text-align: center; width=5%;\">"
89 #define HTTP_TABLE3 "	<td>"
90 
91 #define HTTP_MENU1 "\n [<a href=\""
92 #define HTTP_MENU2 ".menu\">"
93 #define HTTP_MENU3 "</a>] "
94 
95 #define HTTP_LIST1 "<select name=\"list\" size=15>\n"
96 
97 #define HTTP_FORM  "\n<form action=\"/\" method=\"post\">\n"
98 
99 #define HTTP_EDIT1 "<h4>"
100 #define HTTP_EDIT2 "</h4></center>\n<form action=\"\" method=\"post\">\n<input type=\"text\" name=\"http_editfield\" value=\""
101 #define HTTP_EDIT3 "</h4></center>\n<form action=\"\" method=\"post\">\n<input type=\"password\" name=\"http_editfield\" value=\""
102 #define HTTP_EDIT4 "\" />\n<hr>"
103 
104 #define HTTP_TAIL "\n<h6><a href=\"/\">Reload page</a></h6>\n</center></body>\n</html>\n"
105 
106 int _screenSize = 540;  // min(width,heigth)
107 
initHtmlGenerator()108 void initHtmlGenerator()
109 {
110     char* v1 = dupVarValue("ScreenSize");
111     if (v1 != NULL) {
112         _screenSize = atoi(v1);
113         if (_screenSize <= 0) {
114             _screenSize = 540;
115         }
116         free(v1);
117     }
118     INFO2("[WS]: $(ScreenSize) = %d", _screenSize);
119 }
120 
htmlScreenWidth()121 int htmlScreenWidth()
122 {
123     return _screenSize;
124 }
125 
htmlScreenHeight()126 int htmlScreenHeight()
127 {
128     return _screenSize;
129 }
130 
fontHTML(const char * f)131 string_t* fontHTML(const char* f)
132 {
133     string_t* fh = stringNew("");
134 
135     if (strncmp(f,"small",5) == 0) {
136 	    stringAppend(fh, "h6>\n");
137     } else if (strncmp(f,"medium",6) == 0) {
138     	stringAppend(fh, "h4>\n");
139     } else if (strncmp(f,"large",5) == 0) {
140     	stringAppend(fh, "h2>\n");
141     }
142 
143     return fh;
144 }
145 
getUseCSS()146 static int getUseCSS()
147 {
148     return 0;
149 }
150 
151 char abuf[8];
152 
getAccessKey(int index)153 static char* getAccessKey(int index)
154 {
155     if (index == 10) {
156         abuf[0] = '*';
157         abuf[1] = '\0';
158     } else if (index == 11) {
159         abuf[0] = '0';
160         abuf[1] = '\0';
161     } else if (index == 12) {
162         abuf[0] = '#';
163         abuf[1] = '\0';
164     } else {
165         sprintf(abuf,"%d",index);
166     }
167     return abuf;
168 }
169 
addFormMenu(int formId,string_t * page)170 static void addFormMenu(int formId, string_t* page)
171 {
172     mutexLock(M_STATE);
173 
174     SingleList* list = userMenu();
175 
176     INFO2("[WS]: addFormMenu %d #%d", formId, listSingleLength(list));
177     switch (formId) {
178 
179     case CF:
180     case TX:
181     case WM:
182         if (listSingleLength(list) > 0) {
183 
184             string_t* menu = stringNew("<hr>");
185 
186             //stringAppend(menu, "<div style=\"width:240px; overflow:auto;\">");
187 
188             while(list) {
189 
190                 //INFO2("[WS]: addFormMenu add item ");
191                 if (list->data && ((string_t*) list->data)->str) {
192 
193                     stringAppend(menu, HTTP_MENU1);
194                     stringAppend(menu, ((string_t*) list->data)->str);
195                     stringAppend(menu, HTTP_MENU2);
196                     stringAppend(menu, ((string_t*) list->data)->str);
197                     stringAppend(menu, HTTP_MENU3);
198 
199                     //INFO2("[WS]: addFormMenu item %s", ((string_t*) list->data)->str);
200                 }
201                 list = listSingleNext(list);
202             }
203             //stringAppend(menu, "</div>");
204             stringAppend(menu, "<hr>");
205             stringAppend(page, menu->str);
206             stringFree(menu,  BOOL_YES);
207         }
208         break;
209 
210     case LI:
211     case EF:
212 
213         {
214             int listSz = listSingleLength(list);
215 
216             if (listSz > 0) {
217 
218                 int useCSS = getUseCSS();
219 
220                 if (useCSS) {
221 
222                     string_t* menu = stringNew("<div class=\"menu\">\n<ul>\n");
223                     int i = 0;
224                     while(list) {
225 
226                         if (i == 0) {
227                             stringAppend(menu, "<li><input name=\"action\" type=\"submit\" id=\"menubutton\" value=\"");
228                             stringAppend(menu, ((string_t*) list->data)->str);
229                             stringAppend(menu, "\"></li>\n");
230                         } else {
231                             if (i == 1 && listSz > 2) {
232                                 stringAppend(menu, "<li>\n\t<li><input type=\"text\" id=\"menubutton\" value=\"More\">\n\t<ul>\n\t");
233                             }
234                             stringAppend(menu, "<li><input name=\"action\" type=\"submit\" id=\"menubutton\" value=\"");
235                             stringAppend(menu, ((string_t*) list->data)->str);
236                             stringAppend(menu, "\"></li>\n\t");
237                         }
238 
239                         i++;
240                         list = listSingleNext(list);
241                     }
242                     if (listSz > 2) {
243                         stringAppend(menu, "</ul>\n");
244                     }
245                     stringAppend(menu, "</li>\n</ul>\n</div>\n");
246 
247                     stringAppend(page, menu->str);
248                     stringFree(menu,  BOOL_YES);
249 
250                 } else {
251 
252                     string_t* menu = stringNew("");
253 
254                     int i = 0;
255                     while(list) {
256 
257                         stringAppend(menu, "<input name=\"action\" type=\"submit\" id=\"menubutton\" value=\"");
258                         stringAppend(menu, ((string_t*) list->data)->str);
259                         stringAppend(menu, "\">\n");
260 
261                         i++;
262                         list = listSingleNext(list);
263                     }
264                     stringAppend(menu, "<hr>");
265                     stringAppend(page, menu->str);
266                     stringFree(menu,  BOOL_YES);
267                 }
268             }
269         }
270         break;
271     }
272 
273     mutexUnlock(M_STATE);
274 }
275 
renderFormHead(int form,const char * caption,const char * fg,const char * bg)276 string_t* renderFormHead(int form, const char* caption, const char* fg, const char* bg)
277 {
278     string_t* head = stringNew(HTTP_HEAD1);
279     stringAppend(head, caption);
280     stringAppend(head, HTTP_HEAD2);
281     if (form == LI) {
282         stringAppend(head, HTTP_SCRIPT);
283     }
284     stringAppend(head, HTTP_HEAD3);
285     stringAppend(head, HTTP_HEAD4);
286 
287     // Do some CSS styling
288     int useCSS = getUseCSS();
289 
290     stringAppend(head, HTTP_HEAD_CSS_0);
291     //stringAppend(head, HTTP_HEAD_CSS_1);
292 
293     char buf[16];
294     sprintf(buf,"%d",_screenSize);
295 
296     stringAppend(head, HTTP_HEAD_CSS_B1);
297     stringAppend(head, fg);
298     stringAppend(head, HTTP_HEAD_CSS_B2);
299     stringAppend(head, bg);
300 
301     if (form == LI) {
302         stringAppend(head, ";\n\twidth:");
303         stringAppend(head, buf);
304         stringAppend(head, "px");
305     }
306     stringAppend(head, HTTP_HEAD_CSS_B3);
307 
308 
309     if (form == CF) {
310 
311         stringAppend(head, HTTP_HEAD_CSS_BT1);
312         stringAppend(head, fg);
313         stringAppend(head, HTTP_HEAD_CSS_B2);
314         stringAppend(head, bg);
315         stringAppend(head, ";\n\tborder-radius:10px;\n\t-moz-border-radius:10px;\n\t-webkit-border-radius:10px;\n\tborder:2px solid ");
316         stringAppend(head, fg);
317         stringAppend(head, ";}\n");
318         stringAppend(head, "p.widthScr {\n\twidth:");
319 	    stringAppend(head, buf);
320         stringAppend(head, "px;\n\toverflow:auto;\n}\n");
321 
322     } else if (form == LI) {
323 
324 	    stringAppend(head, HTTP_HEAD_CSS_L1);
325         stringAppend(head, fg);
326         stringAppend(head, HTTP_HEAD_CSS_B2);
327         stringAppend(head, bg);
328         stringAppend(head, HTTP_HEAD_CSS_L3);
329         stringAppend(head, buf);
330         stringAppend(head, "px");
331         stringAppend(head, HTTP_HEAD_CSS_B3);
332 
333     } else if (form == TX) {
334 
335         stringAppend(head, "p.widthScr {\n\twidth:");
336         stringAppend(head, buf);
337         stringAppend(head, "px;\n\toverflow:auto;\n}\n");
338     }
339 
340     if (useCSS) {
341         char w2[16];
342         sprintf(w2,"%d",_screenSize/2);
343 
344         char w2_11[16];
345         sprintf(w2_11,"%d",_screenSize/2-11);
346 
347         char w2_10[16];
348         sprintf(w2_10,"%d",_screenSize/2+10);
349 
350         stringAppend(head, HTTP_HEAD_CSS_MENU1);
351         stringAppend(head, buf);
352         stringAppend(head, HTTP_HEAD_CSS_MENU2);
353         stringAppend(head, w2);
354         stringAppend(head, HTTP_HEAD_CSS_MENU3);
355         stringAppend(head, w2);
356         stringAppend(head, HTTP_HEAD_CSS_MENU4);
357         stringAppend(head, w2_11);
358         stringAppend(head, HTTP_HEAD_CSS_MENU5);
359         stringAppend(head, w2);
360         stringAppend(head, HTTP_HEAD_CSS_MENU6);
361         stringAppend(head, w2_10);
362         stringAppend(head, HTTP_HEAD_CSS_MENU7);
363     }
364 
365     stringAppend(head, HTTP_HEAD_CSS_99);
366 
367     stringAppend(head, HTTP_HEAD5);
368     if (form == LI) {
369         stringAppend(head, HTTP_SCRIPT_CALL);
370     }
371     stringAppend(head, HTTP_HEAD6);
372 
373     return head;
374 }
375 
renderCtrlHTMLForm(string_t * no_use,int port)376 string_t* renderCtrlHTMLForm(string_t* no_use, int port)
377 {
378     INFO2("[WS]: renderCtrlHTMLForm %d", bottomlineSkin());
379 
380     string_t* fontSpec = fontHTML(cfFont());
381 
382     string_t* page = renderFormHead(CF, cfCaption(), cfFg(), cfBg());
383 
384     stringAppend(page, "<");
385     stringAppend(page, fontSpec->str);
386     stringAppend(page, "\n<p class=\"widthScr\">");
387     stringAppend(page, cfStatus());
388     stringAppend(page, "</p>\n</");
389     stringAppend(page, fontSpec->str);
390 
391     mutexLock(M_STATE);
392     if (bottomlineSkin()) {
393         const char * nc = cfNamedCover();
394         const char * cv = cfCover();
395         //printf("COVER %s %s\n", nc ? "Y" : "N", cv ? "Y" : "N");
396         if (nc) {
397             stringAppend(page, "\n<img src=\"");
398             stringAppend(page, nc);
399             stringAppend(page, ".cover\" border=\"1\">");
400         } else if (cv) {
401             stringAppend(page, "\n<img src=\"");
402             stringAppend(page, cv);
403             stringAppend(page, "\" border=\"1\">");
404         }
405     }
406     mutexUnlock(M_STATE);
407 
408     stringAppend(page, HTTP_FORM);
409 
410     stringAppend(page, HTTP_TABLE1);
411 
412     char buf[8];
413     sprintf(buf,"%d",iconPadding());
414     stringAppend(page, buf);
415 
416     stringAppend(page, HTTP_TABLE2);
417 
418     int i = 0;
419     int col = 1;
420 
421     int iconMax = (bottomlineSkin() ? ICON_NUM_BTM : ICON_NUM);
422 
423     mutexLock(M_STATE);
424     while (i < iconMax) {
425 
426 
427         const char* icon = cfIcon(i);
428         const char* hint = cfHint(i);
429 
430 	    INFO2("[WS]: renderControlForm %d %s", i, (icon? icon : "NULL"));
431 
432         if (bottomlineSkin() && (!icon || strcmp(icon,"none") == 0)) {
433              break; // skip if empty icon specified
434         }
435 
436         stringAppend(page, HTTP_TABLE3);
437 
438         if (!icon || strcmp(icon,"none") == 0) {
439 
440             //<button <img src="XX" alt="" style="vertical-align: middle">label_empty</button>
441             stringAppend(page, "<button <img src=\"transparent.png\" border=\"0\" alt=\"");
442             if (hint && strlen(hint) > 0) {
443                 stringAppend(page, hint);
444                 stringAppend(page, "\" title=\"");
445                 stringAppend(page, hint);
446             }
447             stringAppend(page, "\" style=\"vertical-align: middle\"></button>");
448 
449 	    } else {
450 
451 
452             //<button accesskey="XX" type="submit" value="XX"> <img src="XX" alt="" style="vertical-align: middle">label_empty</button>
453             stringAppend(page, "<button name=\"action\" accesskey=\"");
454             stringAppend(page, getAccessKey(i+1));
455             stringAppend(page, "\" type=\"submit\" value=\"");
456 
457 	        char maze[8];
458 	        sprintf(maze,"%d",i+1);
459             stringAppend(page, maze);
460 
461             stringAppend(page, "\"> <img src=\"");
462             stringAppend(page, icon);
463             stringAppend(page, ".png\" border=\"0\" alt=\"");
464             if (hint && strlen(hint) > 0) {
465                 stringAppend(page, hint);
466                 stringAppend(page, "\" title=\"");
467                 stringAppend(page, hint);
468             }
469             stringAppend(page, "\" style=\"vertical-align: middle\"></button>");
470 
471         }
472 
473         stringAppend(page, "</td>\n");
474         if (!bottomlineSkin() && col == 3) {
475             stringAppend(page, "    \n</tr>\n<tr>\n");
476             col = 0;
477         }
478         i++;
479         col++;
480     }
481     mutexUnlock(M_STATE);
482 
483     stringAppend(page, "    </tr>\n</tbody>\n</table>");
484     stringAppend(page, "    </form>\n");
485 
486     stringAppend(page, "<");
487     stringAppend(page, fontSpec->str);
488     stringAppend(page, "\n<p class=\"widthScr\">");
489     stringAppend(page, cfTitle());
490     stringAppend(page, "</p>\n");
491 
492     const char* v = cfVolume();
493     if (useVolume() && v && strlen(v) > 0) {
494         stringAppend(page, "<p>");
495         stringAppend(page, v);
496         stringAppend(page, "%</p>");
497     }
498     stringAppend(page, "</");
499     stringAppend(page, fontSpec->str);
500     stringFree(fontSpec,  BOOL_YES);
501 
502     addFormMenu(CF, page);
503 
504     stringAppend(page, HTTP_TAIL);
505 
506     return page;
507 }
508 
renderTextHTMLForm(string_t * no_use,int port)509 string_t* renderTextHTMLForm(string_t* no_use, int port)
510 {
511     INFO2("[WS]: renderTextHTMLForm");
512 
513     string_t* fontSpec = fontHTML(tfFont());
514 
515     string_t* page = renderFormHead(TX,tfCaption(),tfFg(),tfBg());
516 
517     stringAppend(page, "<");
518     stringAppend(page, fontSpec->str);
519 
520     mutexLock(M_STATE);
521     const char* tx = tfText();
522 
523     if (tx) {
524 	    while (1) {
525             const char* tx2 = tx;
526 	        tx = strstr(tx2, "\n");
527 
528             stringAppend(page, "\n    <p class=\"widthScr\">");
529 
530 	        if (tx) {
531 		        stringAppendLen(page, tx2, tx - tx2);
532 	        } else {
533 		        stringAppend(page, tx2);
534 	        }
535 	        stringAppend(page, "</p>");
536 
537 	        if (!tx) break;
538 
539 	        tx++;
540 	    }
541     }
542     mutexUnlock(M_STATE);
543 
544     stringAppend(page, "\n</");
545     stringAppend(page, fontSpec->str);
546     stringFree(fontSpec,  BOOL_YES);
547 
548     addFormMenu(TX, page);
549 
550     stringAppend(page, HTTP_TAIL);
551 
552     return page;
553 }
554 
renderListHTMLForm(string_t * no_use,int port)555 string_t* renderListHTMLForm(string_t* no_use, int port)
556 {
557     INFO2("[WS]: renderListHTMLForm");
558 
559     string_t* fontSpec = fontHTML(lfFont());
560     string_t* page = renderFormHead(LI,lfCaption(),lfFg(),lfBg());
561 
562     stringAppend(page, "<");
563     stringAppend(page, fontSpec->str);
564     stringAppend(page, HTTP_FORM);
565     stringAppend(page, HTTP_LIST1);
566 
567     int idx = 0;
568 
569     mutexLock(M_STATE);
570 
571     SingleList* list = lfList();
572     char num[16];
573 
574     while (list) {
575 
576         sprintf(num,"%d", idx);
577 
578         stringAppend(page, "<option value=\"");
579         stringAppend(page, num);
580         stringAppend(page, "\"");
581         if (idx == lfIndex() - 1) {
582             stringAppend(page, " selected ");
583         }
584         stringAppend(page, ">");
585         stringAppend(page, ((ListItem*) list->data)->string->str);
586         stringAppend(page, "</option>\n");
587 
588         list = listSingleNext(list);
589         idx++;
590     }
591     mutexUnlock(M_STATE);
592 
593     stringAppend(page, "</select>\n<hr>\n");
594 
595     addFormMenu(LI, page);
596 
597     stringAppend(page, "</form>\n</");
598     stringAppend(page, fontSpec->str);
599     stringFree(fontSpec,  BOOL_YES);
600     stringAppend(page, "\n");
601     stringAppend(page, HTTP_TAIL);
602 
603     return page;
604 }
605 
renderWmanHTMLForm(string_t * no_use,int port)606 string_t* renderWmanHTMLForm(string_t* no_use, int port)
607 {
608     INFO2("[WS]: renderWmanHTMLForm");
609 
610     string_t* fontSpec = fontHTML(cfFont());
611     string_t* page = renderFormHead(WM, cfCaption(), cfFg(), cfBg());
612 
613     stringAppend(page, "<");
614     stringAppend(page, fontSpec->str);
615     stringAppend(page, cfTitle());
616     stringAppend(page, "</");
617     stringAppend(page, fontSpec->str);
618 
619     mutexLock(M_STATE);
620 
621     const char* window = wfImage();
622     if (window != NULL) {
623         stringAppend(page, "\n<img src=\"");
624         stringAppend(page,window);
625         stringAppend(page, "\" border=\"1\">");
626     }
627     mutexUnlock(M_STATE);
628 
629     addFormMenu(WM, page);
630 
631     stringAppend(page, HTTP_TAIL);
632     stringFree(fontSpec,  BOOL_YES);
633 
634     return page;
635 }
636 
renderEditHTMLForm(string_t * no_use,int port)637 string_t* renderEditHTMLForm(string_t* no_use, int port)
638 {
639     INFO2("[WS]: renderEditHTMLForm askpass=%d", efPassword());
640 
641     string_t* fontSpec = fontHTML(cfFont());
642     string_t* page = renderFormHead(EF, efCaption(), cfFg(), cfBg());
643 
644     stringAppend(page, "<");
645     stringAppend(page, fontSpec->str);
646     stringAppend(page, HTTP_EDIT1);
647 
648     mutexLock(M_STATE);
649 
650     stringAppend(page, efLabel());
651 
652     if (efPassword()) {
653         stringAppend(page, HTTP_EDIT3);
654     } else {
655         stringAppend(page, HTTP_EDIT2);
656     }
657 
658     stringAppend(page, efText());
659 
660     mutexUnlock(M_STATE);
661 
662     stringAppend(page, HTTP_EDIT4);
663 
664     addFormMenu(EF, page);
665 
666     stringAppend(page, "</form>\n</");
667     stringAppend(page, fontSpec->str);
668     stringAppend(page, "\n");
669     stringAppend(page, HTTP_TAIL);
670 
671     stringFree(fontSpec,  BOOL_YES);
672 
673     return page;
674 }
675 
676 //
677 // Use this for internal password check
678 //
renderPassHTMLForm(string_t * no_use,int port)679 string_t* renderPassHTMLForm(string_t* no_use, int port)
680 {
681     INFO2("[WS]: renderPasswordForm");
682 
683     string_t* fontSpec = fontHTML(cfFont());
684     string_t* page = renderFormHead(EF, "Enter Password", cfFg(), cfBg());
685 
686     stringAppend(page, "<");
687     stringAppend(page, fontSpec->str);
688     stringAppend(page, HTTP_EDIT1);
689     stringAppend(page, "Enter Password");
690     stringAppend(page, HTTP_EDIT3);
691     stringAppend(page, HTTP_EDIT4);
692 
693     // add menu manually
694     stringAppend(page, "<input name=\"action\" type=\"submit\" value=\"Ok\">\n");
695     stringAppend(page, "<input name=\"action\" type=\"submit\" value=\"Back\">\n");
696 
697     stringAppend(page, "<hr>\n</form>\n</");
698     stringAppend(page, fontSpec->str);
699     stringAppend(page, "\n");
700     stringAppend(page, HTTP_TAIL);
701 
702     stringFree(fontSpec,  BOOL_YES);
703 
704     return page;
705 }
706