Dillo v3.1.1-111-gd4f56d0d
Loading...
Searching...
No Matches
form.cc
Go to the documentation of this file.
1/*
2 * File: form.cc
3 *
4 * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org>
5 * Copyright 2024 Rodrigo Arias Mallo <rodarima@gmail.com>
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
13#include "form.hh"
14#include "html_common.hh"
15
16#include <errno.h>
17#include <iconv.h>
18
19#include "lout/misc.hh"
20#include "dw/core.hh"
21#include "dw/textblock.hh"
22
23#include "dlib/dlib.h"
24#include "misc.h"
25#include "msg.h"
26#include "prefs.h"
27#include "uicmd.hh"
28#include "dialog.hh"
29
30using namespace lout;
31using namespace dw;
32using namespace dw::core;
33using namespace dw::core::style;
34using namespace dw::core::ui;
35
36/*
37 * Forward declarations
38 */
39
40class DilloHtmlReceiver;
41class DilloHtmlSelect;
42
43static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize);
44
45static void Html_option_finish(DilloHtml *html);
46
47/*
48 * Typedefs
49 */
50
70
71/*
72 * Class declarations
73 */
74
75class DilloHtmlForm {
76 friend class DilloHtmlReceiver;
77 friend class DilloHtmlInput;
78
79 DilloHtml *html;
80 bool showing_hiddens;
81 bool enabled;
82 void eventHandler(Resource *resource, EventButton *event);
83 DilloUrl *buildQueryUrl(DilloHtmlInput *active_input);
84 Dstr *buildQueryData(DilloHtmlInput *active_submit);
85 char *makeMultipartBoundary(iconv_t char_encoder,
86 DilloHtmlInput *active_submit);
87 Dstr *encodeText(iconv_t char_encoder, Dstr **input);
88 void strUrlencodeAppend(Dstr *dstr, const char *str);
89 void inputUrlencodeAppend(Dstr *data, const char *name, const char *value);
90 void inputMultipartAppend(Dstr *data, const char *boundary,
91 const char *name, const char *value);
92 void filesInputMultipartAppend(Dstr* data, const char *boundary,
93 const char *name, Dstr *file,
94 const char *filename);
95 void imageInputUrlencodeAppend(Dstr *data, Dstr *name, Dstr *x, Dstr *y);
96 void imageInputMultipartAppend(Dstr *data, const char *boundary, Dstr *name,
97 Dstr *x, Dstr *y);
98
99public: //BUG: for now everything is public
100 DilloHtmlMethod method;
101 DilloUrl *action;
102 DilloHtmlEnc content_type;
103 char *submit_charset;
104
106
107 int num_entry_fields;
108
109 DilloHtmlReceiver *form_receiver;
110
111public:
112 DilloHtmlForm (DilloHtml *html,
113 DilloHtmlMethod method, const DilloUrl *action,
114 DilloHtmlEnc content_type, const char *charset,
115 bool enabled);
116 ~DilloHtmlForm ();
117 DilloHtmlInput *getInput (Resource *resource);
118 DilloHtmlInput *getRadioInput (const char *name);
119 void submit(DilloHtmlInput *active_input, EventButton *event);
120 void reset ();
121 void display_hiddens(bool display);
122 void addInput(DilloHtmlInput *input, DilloHtmlInputType type);
123 void setEnabled(bool enabled);
124};
125
126class DilloHtmlReceiver:
129{
130 friend class DilloHtmlForm;
131 DilloHtmlForm* form;
132 DilloHtmlReceiver (DilloHtmlForm* form2) { form = form2; }
133 ~DilloHtmlReceiver () { }
134 void activate (Resource *resource);
135 void enter (Resource *resource);
136 void leave (Resource *resource);
137 void clicked (Resource *resource, EventButton *event);
138};
139
140class DilloHtmlInput {
141
142 // DilloHtmlForm::addInput() calls connectTo()
143 friend class DilloHtmlForm;
144
145public: //BUG: for now everything is public
147 Embed *embed; /* May be NULL (think: hidden input) */
148 char *name;
149 char *init_str; /* note: some overloading - for buttons, init_str
150 is simply the value of the button; for text
151 entries, it is the initial value */
152 DilloHtmlSelect *select;
153 bool init_val; /* only meaningful for buttons */
154 Dstr *file_data; /* only meaningful for file inputs.
155 TODO: may become a list... */
156
157private:
158 void connectTo(DilloHtmlReceiver *form_receiver);
159 void activate(DilloHtmlForm *form, int num_entry_fields,EventButton *event);
160 void readFile(BrowserWindow *bw);
161
162public:
163 DilloHtmlInput (DilloHtmlInputType type, Embed *embed,
164 const char *name, const char *init_str, bool init_val);
165 ~DilloHtmlInput ();
166 void appendValuesTo(Dlist *values, bool is_active_submit);
167 void reset();
168 void setEnabled(bool enabled) {if (embed) embed->setEnabled(enabled); };
169};
170
171class DilloHtmlOptbase
172{
173public:
174 virtual ~DilloHtmlOptbase () {};
175 virtual bool isSelected() {return false;}
176 virtual bool select() {return false;}
177 virtual const char *getValue() {return NULL;}
178 virtual void setContent(const char *str, int len)
179 {MSG_ERR("Form: Optbase setContent()\n");}
180 virtual void addSelf(SelectionResource *res) = 0;
181};
182
183class DilloHtmlOptgroup : public DilloHtmlOptbase {
184private:
185 char *label;
186 bool enabled;
187public:
188 DilloHtmlOptgroup (char *label, bool enabled);
189 virtual ~DilloHtmlOptgroup ();
190 void addSelf (SelectionResource *res)
191 {res->pushGroup(label, enabled);}
192};
193
194class DilloHtmlOptgroupClose : public DilloHtmlOptbase {
195public:
196 virtual ~DilloHtmlOptgroupClose () {};
197 void addSelf (SelectionResource *res)
198 {res->popGroup();}
199};
200
201class DilloHtmlOption : public DilloHtmlOptbase {
202 friend class DilloHtmlSelect;
203public:
204 char *value, *label, *content;
205 bool selected, enabled;
206 DilloHtmlOption (char *value, char *label, bool selected, bool enabled);
207 virtual ~DilloHtmlOption ();
208 bool isSelected() {return selected;}
209 bool select() {return (selected = true);}
210 const char *getValue() {return value ? value : content;}
211 void setContent(const char *str, int len) {content = dStrndup(str, len);}
212 void addSelf (SelectionResource *res)
213 {res->addItem(label ? label : content, enabled, selected);}
214};
215
216class DilloHtmlSelect {
217 friend class DilloHtmlInput;
218private:
220 DilloHtmlSelect ();
221 ~DilloHtmlSelect ();
222public:
223 DilloHtmlOptbase *getCurrentOpt ();
224 void addOpt (DilloHtmlOptbase *opt);
225 void ensureSelection ();
226 void addOptsTo (SelectionResource *res);
227 void reset (SelectionResource *res);
228 void appendValuesTo (Dlist *values, SelectionResource *res);
229};
230
231/*
232 * Form API
233 */
234
235DilloHtmlForm *a_Html_form_new (DilloHtml *html, DilloHtmlMethod method,
236 const DilloUrl *action,
237 DilloHtmlEnc content_type, const char *charset,
238 bool enabled)
239{
240 return new DilloHtmlForm (html, method, action, content_type, charset,
241 enabled);
242}
243
244void a_Html_form_delete (DilloHtmlForm *form)
245{
246 delete form;
247}
248
249void a_Html_input_delete (DilloHtmlInput *input)
250{
251 delete input;
252}
253
254void a_Html_form_submit2(void *vform)
255{
256 ((DilloHtmlForm *)vform)->submit(NULL, NULL);
257}
258
259void a_Html_form_reset2(void *vform)
260{
261 ((DilloHtmlForm *)vform)->reset();
262}
263
264void a_Html_form_display_hiddens2(void *vform, bool display)
265{
266 ((DilloHtmlForm *)vform)->display_hiddens(display);
267}
268
269/*
270 * Form parsing functions
271 */
272
277 Embed *embed, const char *name,
278 const char *init_str, bool init_val)
279{
280 _MSG("name=[%s] init_str=[%s] init_val=[%d]\n", name, init_str, init_val);
281 DilloHtmlInput *input = new DilloHtmlInput(type, embed, name, init_str,
282 init_val);
283 if (html->InFlags & IN_FORM) {
284 html->getCurrentForm()->addInput(input, type);
285 } else {
286 int ni = html->inputs_outside_form->size();
288 html->inputs_outside_form->set(ni, input);
289
290 if (html->bw->NumPendingStyleSheets > 0) {
291 input->setEnabled(false);
292 }
293 }
294}
295
299static DilloHtmlInput *Html_get_radio_input(DilloHtml *html, const char *name)
300{
301 if (name) {
303
304 if (html->InFlags & IN_FORM)
305 inputs = html->getCurrentForm()->inputs;
306 else
307 inputs = html->inputs_outside_form;
308
309 for (int idx = 0; idx < inputs->size(); idx++) {
310 DilloHtmlInput *input = inputs->get(idx);
311 if (input->type == DILLO_HTML_INPUT_RADIO &&
312 input->name && !dStrAsciiCasecmp(input->name, name))
313 return input;
314 }
315 }
316 return NULL;
317}
318
322static DilloHtmlInput *Html_get_current_input(DilloHtml *html)
323{
325
326 if (html->InFlags & IN_FORM)
327 inputs = html->getCurrentForm()->inputs;
328 else
329 inputs = html->inputs_outside_form;
330
331 return (inputs && inputs->size() > 0) ?
332 inputs->get (inputs->size() - 1) : NULL;
333}
334
338void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
339{
340 DilloUrl *action;
341 DilloHtmlMethod method;
342 DilloHtmlEnc content_type;
343 char *charset, *first;
344 const char *attrbuf;
345
346 HT2TB(html)->addParbreak (9, html->wordStyle ());
347
348 if (html->InFlags & IN_FORM) {
349 BUG_MSG("Nested <form>.");
350 return;
351 }
352 html->InFlags |= IN_FORM;
353 html->InFlags &= ~IN_SELECT;
354 html->InFlags &= ~IN_OPTION;
355 html->InFlags &= ~IN_TEXTAREA;
356
357 method = DILLO_HTML_METHOD_GET;
358 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "method"))) {
359 if (!dStrAsciiCasecmp(attrbuf, "post")) {
360 method = DILLO_HTML_METHOD_POST;
361 } else if (dStrAsciiCasecmp(attrbuf, "get")) {
362 BUG_MSG("<form> submission method unknown: '%s'.", attrbuf);
363 }
364 }
365 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "action")))
366 action = a_Html_url_new(html, attrbuf, NULL, 0);
367 else {
368 if (html->DocType != DT_HTML || html->DocTypeVersion <= 4.01f)
369 BUG_MSG("<form> requires action attribute.");
370 action = a_Url_dup(html->base_url);
371 }
372 content_type = DILLO_HTML_ENC_URLENCODED;
373 if ((method == DILLO_HTML_METHOD_POST) &&
374 ((attrbuf = a_Html_get_attr(html, tag, tagsize, "enctype")))) {
375 if (!dStrAsciiCasecmp(attrbuf, "multipart/form-data"))
376 content_type = DILLO_HTML_ENC_MULTIPART;
377 }
378 charset = NULL;
379 first = NULL;
380 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "accept-charset"))) {
381 /* a list of acceptable charsets, separated by commas or spaces */
382 char *ptr = first = dStrdup(attrbuf);
383 while (ptr && !charset) {
384 char *curr = dStrsep(&ptr, " ,");
385 if (!dStrAsciiCasecmp(curr, "utf-8")) {
386 charset = curr;
387 } else if (!dStrAsciiCasecmp(curr, "UNKNOWN")) {
388 /* defined to be whatever encoding the document is in */
389 charset = html->charset;
390 }
391 }
392 if (!charset)
393 charset = first;
394 }
395 if (!charset)
396 charset = html->charset;
397 html->formNew(method, action, content_type, charset);
398 dFree(first);
399 a_Url_free(action);
400}
401
403{
404 html->InFlags &= ~IN_FORM;
405 html->InFlags &= ~IN_SELECT;
406 html->InFlags &= ~IN_OPTION;
407 html->InFlags &= ~IN_TEXTAREA;
408}
409
413static int Html_input_get_size(DilloHtml *html, const char *attrbuf)
414{
415 const int MAX_SIZE = 1024;
416 int size = 20;
417
418 if (attrbuf) {
419 size = strtol(attrbuf, NULL, 10);
420 if (size < 1 || size > MAX_SIZE) {
421 int badSize = size;
422 size = (size < 1 ? 20 : MAX_SIZE);
423 BUG_MSG("<input> size=%d, using size=%d instead.", badSize, size);
424 }
425 }
426 return size;
427}
428
432void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
433{
434 DilloHtmlInputType inp_type;
435 Resource *resource = NULL;
436 Embed *embed = NULL;
437 char *value, *name, *type, *init_str, *placeholder = NULL;
438 const char *attrbuf, *label;
439 bool init_val = false;
440 ResourceFactory *factory;
441
442 if (html->InFlags & IN_SELECT) {
443 BUG_MSG("<input> inside <select>.");
444 return;
445 }
446 if (html->InFlags & IN_BUTTON) {
447 BUG_MSG("<input> inside <button>.");
448 return;
449 }
450
451 factory = HT2LT(html)->getResourceFactory();
452
453 /* Get 'value', 'name' and 'type' */
454 value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
455 name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
456 type = a_Html_get_attr_wdef(html, tag, tagsize, "type", "");
457
458 init_str = NULL;
459 inp_type = DILLO_HTML_INPUT_UNKNOWN;
460 if (!dStrAsciiCasecmp(type, "password")) {
461 inp_type = DILLO_HTML_INPUT_PASSWORD;
462 placeholder = a_Html_get_attr_wdef(html, tag,tagsize,"placeholder",NULL);
463 attrbuf = a_Html_get_attr(html, tag, tagsize, "size");
464 int size = Html_input_get_size(html, attrbuf);
465 resource = factory->createEntryResource (size, true, NULL, placeholder);
466 init_str = value;
467 } else if (!dStrAsciiCasecmp(type, "checkbox")) {
468 inp_type = DILLO_HTML_INPUT_CHECKBOX;
469 resource = factory->createCheckButtonResource(false);
470 init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL);
471 init_str = (value) ? value : dStrdup("on");
472 } else if (!dStrAsciiCasecmp(type, "radio")) {
473 inp_type = DILLO_HTML_INPUT_RADIO;
474 RadioButtonResource *rb_r = NULL;
475 DilloHtmlInput *input = Html_get_radio_input(html, name);
476 if (input)
477 rb_r = (RadioButtonResource*) input->embed->getResource();
478 resource = factory->createRadioButtonResource(rb_r, false);
479 init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL);
480 init_str = value;
481 } else if (!dStrAsciiCasecmp(type, "hidden")) {
482 inp_type = DILLO_HTML_INPUT_HIDDEN;
483 init_str = value;
484 int size = Html_input_get_size(html, NULL);
485 resource = factory->createEntryResource(size, false, name, NULL);
486 } else if (!dStrAsciiCasecmp(type, "submit")) {
487 inp_type = DILLO_HTML_INPUT_SUBMIT;
488 init_str = (value) ? value : dStrdup("submit");
489 resource = factory->createLabelButtonResource(init_str);
490 } else if (!dStrAsciiCasecmp(type, "reset")) {
491 inp_type = DILLO_HTML_INPUT_RESET;
492 init_str = (value) ? value : dStrdup("Reset");
493 resource = factory->createLabelButtonResource(init_str);
494 } else if (!dStrAsciiCasecmp(type, "image")) {
495 if (URL_FLAGS(html->base_url) & URL_SpamSafe) {
496 /* Don't request the image; make a text submit button instead */
497 inp_type = DILLO_HTML_INPUT_SUBMIT;
498 attrbuf = a_Html_get_attr(html, tag, tagsize, "alt");
499 label = attrbuf ? attrbuf : value ? value : name ? name : "Submit";
500 init_str = dStrdup(label);
501 resource = factory->createLabelButtonResource(init_str);
502 } else {
503 inp_type = DILLO_HTML_INPUT_IMAGE;
504 /* use a dw_image widget */
505 embed = Html_input_image(html, tag, tagsize);
506 init_str = value;
507 }
508 } else if (!dStrAsciiCasecmp(type, "file")) {
509 bool valid = true;
510 if (html->InFlags & IN_FORM) {
511 DilloHtmlForm *form = html->getCurrentForm();
512 if (form->method != DILLO_HTML_METHOD_POST) {
513 valid = false;
514 BUG_MSG("<form> with file input MUST use HTTP POST method.");
515 MSG("File input ignored in form not using HTTP POST method\n");
516 } else if (form->content_type != DILLO_HTML_ENC_MULTIPART) {
517 valid = false;
518 BUG_MSG("<form> with file input MUST use multipart/form-data"
519 " encoding.");
520 MSG("File input ignored in form not using multipart/form-data"
521 " encoding\n");
522 }
523 }
524 if (valid) {
525 inp_type = DILLO_HTML_INPUT_FILE;
526 init_str = dStrdup("File selector");
527 resource = factory->createLabelButtonResource(init_str);
528 }
529 } else if (!dStrAsciiCasecmp(type, "button")) {
530 inp_type = DILLO_HTML_INPUT_BUTTON;
531 if (value) {
532 init_str = value;
533 resource = factory->createLabelButtonResource(init_str);
534 }
535 } else {
536 /* Text input, which also is the default */
537 inp_type = DILLO_HTML_INPUT_TEXT;
538 placeholder = a_Html_get_attr_wdef(html, tag,tagsize,"placeholder",NULL);
539 attrbuf = a_Html_get_attr(html, tag, tagsize, "size");
540 int size = Html_input_get_size(html, attrbuf);
541 resource = factory->createEntryResource(size, false, NULL, placeholder);
542 init_str = value;
543 }
544 if (resource)
545 embed = new Embed (resource);
546
547 if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
548 Html_add_input(html, inp_type, embed, name,
549 (init_str) ? init_str : "", init_val);
550 }
551
552 if (embed != NULL && inp_type != DILLO_HTML_INPUT_IMAGE &&
553 inp_type != DILLO_HTML_INPUT_UNKNOWN) {
554 if (inp_type == DILLO_HTML_INPUT_HIDDEN) {
555 /* TODO Perhaps do this with access to current form setting */
556 embed->setDisplayed(false);
557 }
558 if (inp_type == DILLO_HTML_INPUT_TEXT ||
559 inp_type == DILLO_HTML_INPUT_PASSWORD) {
560 if (a_Html_get_attr(html, tag, tagsize, "readonly"))
561 ((EntryResource *) resource)->setEditable(false);
562
563 /* Maximum length of the text in the entry */
564 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "maxlength"))) {
565 int maxlen = strtol(attrbuf, NULL, 10);
566 ((EntryResource *) resource)->setMaxLength(maxlen);
567 }
568 }
569 if (prefs.show_tooltip &&
570 (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
571
573 attrbuf);
574 }
575 HT2TB(html)->addWidget (embed, html->backgroundStyle());
576 }
577 dFree(type);
578 dFree(name);
579 if (init_str != value)
580 dFree(init_str);
581 dFree(placeholder);
582 dFree(value);
583}
584
589void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
590{
591 DilloUrl *action;
592 Embed *embed;
593 const char *attrbuf;
594
595 if (html->InFlags & IN_FORM) {
596 MSG("<isindex> inside <form> not handled.\n");
597 return;
598 }
599
600 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "action")))
601 action = a_Html_url_new(html, attrbuf, NULL, 0);
602 else
603 action = a_Url_dup(html->base_url);
604
606 html->charset);
607 html->InFlags |= IN_FORM;
608
609 HT2TB(html)->addParbreak (9, html->wordStyle ());
610
611 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt")))
612 HT2TB(html)->addText(attrbuf, html->wordStyle ());
613
614 ResourceFactory *factory = HT2LT(html)->getResourceFactory();
615 EntryResource *entryResource = factory->createEntryResource (20, false,
616 NULL, NULL);
617 embed = new Embed (entryResource);
618 Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE);
619
620 HT2TB(html)->addWidget (embed, html->backgroundStyle ());
621
622 a_Url_free(action);
623 html->InFlags &= ~IN_FORM;
624}
625
626void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize)
627{
628 assert((html->InFlags & (IN_BUTTON | IN_SELECT | IN_TEXTAREA)) == 0);
629
630 html->InFlags |= IN_TEXTAREA;
631}
632
636void Html_tag_content_textarea(DilloHtml *html, const char *tag, int tagsize)
637{
638 const int MAX_COLS=1024, MAX_ROWS=10000;
639
640 char *name;
641 const char *attrbuf;
642 int cols, rows;
643
644 a_Html_stash_init(html);
645 S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
646
647 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cols"))) {
648 cols = strtol(attrbuf, NULL, 10);
649 } else {
650 if (html->DocType != DT_HTML || html->DocTypeVersion <= 4.01f)
651 BUG_MSG("<textarea> requires cols attribute.");
652 cols = 20;
653 }
654 if (cols < 1 || cols > MAX_COLS) {
655 int badCols = cols;
656 cols = (cols < 1 ? 20 : MAX_COLS);
657 BUG_MSG("<textarea> cols=%d, using cols=%d instead.", badCols, cols);
658 }
659 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rows"))) {
660 rows = strtol(attrbuf, NULL, 10);
661 } else {
662 if (html->DocType != DT_HTML || html->DocTypeVersion <= 4.01f)
663 BUG_MSG("<textarea> requires rows attribute.");
664 rows = 3;
665 }
666 if (rows < 1 || rows > MAX_ROWS) {
667 int badRows = rows;
668 rows = (rows < 1 ? 2 : MAX_ROWS);
669 BUG_MSG("<textarea> rows=%d, using rows=%d instead.", badRows, rows);
670 }
671 name = NULL;
672 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name")))
673 name = dStrdup(attrbuf);
674
675 attrbuf = a_Html_get_attr(html, tag, tagsize, "placeholder");
676
677 ResourceFactory *factory = HT2LT(html)->getResourceFactory();
678 MultiLineTextResource *textres =
679 factory->createMultiLineTextResource (cols, rows, attrbuf);
680
681 Embed *embed = new Embed(textres);
682 /* Readonly or not? */
683 if (a_Html_get_attr(html, tag, tagsize, "readonly"))
684 textres->setEditable(false);
685 Html_add_input(html, DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, false);
686
687 HT2TB(html)->addWidget (embed, html->backgroundStyle ());
688 dFree(name);
689}
690
696{
697 char *str;
698 DilloHtmlInput *input;
699 int i;
700
701 if (html->InFlags & IN_TEXTAREA && !S_TOP(html)->display_none) {
702 /* Remove the line ending that follows the opening tag */
703 if (html->Stash->str[0] == '\r')
704 dStr_erase(html->Stash, 0, 1);
705 if (html->Stash->str[0] == '\n')
706 dStr_erase(html->Stash, 0, 1);
707
708 /* As the spec recommends to canonicalize line endings, it is safe
709 * to replace '\r' with '\n'. It will be canonicalized anyway! */
710 for (i = 0; i < html->Stash->len; ++i) {
711 if (html->Stash->str[i] == '\r') {
712 if (html->Stash->str[i + 1] == '\n')
713 dStr_erase(html->Stash, i, 1);
714 else
715 html->Stash->str[i] = '\n';
716 }
717 }
718
719 /* The HTML3.2 spec says it can have "text and character entities". */
720 str = a_Html_parse_entities(html, html->Stash->str, html->Stash->len);
721 input = Html_get_current_input(html);
722 if (input) {
723 input->init_str = str;
724 ((MultiLineTextResource *)input->embed->getResource ())->setText(str);
725 }
726
727 }
728 html->InFlags &= ~IN_TEXTAREA;
729}
730
731/*
732 * <SELECT>
733 */
734/* The select tag is quite tricky, because of gorpy html syntax. */
735void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize)
736{
737 const char *attrbuf;
738 int rows = 0;
739
740 assert((html->InFlags & (IN_BUTTON | IN_SELECT | IN_TEXTAREA)) == 0);
741
742 html->InFlags |= IN_SELECT;
743 html->InFlags &= ~IN_OPTION;
744
745 char *name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
746 ResourceFactory *factory = HT2LT(html)->getResourceFactory ();
749 bool multi = a_Html_get_attr(html, tag, tagsize, "multiple") != NULL;
750
751 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size"))) {
752 rows = strtol(attrbuf, NULL, 10);
753 if (rows > 100)
754 rows = 100;
755 }
756 if (rows < 1)
757 rows = multi ? 10 : 1;
758
759 if (rows == 1 && multi == false) {
761 res = factory->createOptionMenuResource ();
762 } else {
764
768 res = factory->createListResource (mode, rows);
769 }
770 Embed *embed = new Embed(res);
771
772 if (prefs.show_tooltip &&
773 (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
774
776 attrbuf);
777 }
778 HT2TB(html)->addWidget (embed, html->backgroundStyle ());
779
780 Html_add_input(html, type, embed, name, NULL, false);
781 a_Html_stash_init(html);
782 dFree(name);
783}
784
785/*
786 * ?
787 */
789{
790 if (html->InFlags & IN_SELECT) {
791 if (html->InFlags & IN_OPTION)
792 Html_option_finish(html);
793 html->InFlags &= ~IN_SELECT;
794 html->InFlags &= ~IN_OPTION;
795
796 DilloHtmlInput *input = Html_get_current_input(html);
797 if (input) {
798 DilloHtmlSelect *select = input->select;
799 if (input->type == DILLO_HTML_INPUT_SELECT) {
800 // option menu interface requires that something be selected */
801 select->ensureSelection ();
802 }
803 select->addOptsTo ((SelectionResource*)input->embed->getResource());
804 }
805 }
806}
807
808void Html_tag_open_optgroup(DilloHtml *html, const char *tag, int tagsize)
809{
810 if (!(html->InFlags & IN_SELECT)) {
811 BUG_MSG("<optgroup> outside <select>.");
812 return;
813 }
814 if (html->InFlags & IN_OPTGROUP) {
815 BUG_MSG("Nested <optgroup>.");
816 return;
817 }
818 if (html->InFlags & IN_OPTION) {
819 Html_option_finish(html);
820 html->InFlags &= ~IN_OPTION;
821 }
822
823 html->InFlags |= IN_OPTGROUP;
824
825 DilloHtmlInput *input = Html_get_current_input(html);
826 if (input &&
827 (input->type == DILLO_HTML_INPUT_SELECT ||
828 input->type == DILLO_HTML_INPUT_SEL_LIST)) {
829 char *label = a_Html_get_attr_wdef(html, tag, tagsize, "label", NULL);
830 bool enabled = (a_Html_get_attr(html, tag, tagsize, "disabled") == NULL);
831
832 if (!label) {
833 BUG_MSG("<optgroup> requires label attribute.");
834 label = dStrdup("");
835 }
836
837 DilloHtmlOptgroup *opt =
838 new DilloHtmlOptgroup (label, enabled);
839
840 input->select->addOpt(opt);
841 }
842}
843
845{
846 if (html->InFlags & IN_OPTGROUP) {
847 html->InFlags &= ~IN_OPTGROUP;
848
849 if (html->InFlags & IN_OPTION) {
850 Html_option_finish(html);
851 html->InFlags &= ~IN_OPTION;
852 }
853
854 DilloHtmlInput *input = Html_get_current_input(html);
855 if (input &&
856 (input->type == DILLO_HTML_INPUT_SELECT ||
857 input->type == DILLO_HTML_INPUT_SEL_LIST)) {
858 DilloHtmlOptgroupClose *opt = new DilloHtmlOptgroupClose ();
859
860 input->select->addOpt(opt);
861 }
862 }
863}
864
865/*
866 * <OPTION>
867 */
868void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize)
869{
870 if (!(html->InFlags & IN_SELECT)) {
871 BUG_MSG("<option> outside <select>.");
872 return;
873 }
874 if (html->InFlags & IN_OPTION)
875 Html_option_finish(html);
876 html->InFlags |= IN_OPTION;
877
878 DilloHtmlInput *input = Html_get_current_input(html);
879 if (input &&
880 (input->type == DILLO_HTML_INPUT_SELECT ||
881 input->type == DILLO_HTML_INPUT_SEL_LIST)) {
882 char *value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
883 char *label = a_Html_get_attr_wdef(html, tag, tagsize, "label", NULL);
884 bool selected = (a_Html_get_attr(html, tag, tagsize,"selected") != NULL);
885 bool enabled = (a_Html_get_attr(html, tag, tagsize, "disabled") == NULL);
886
887 DilloHtmlOption *option =
888 new DilloHtmlOption (value, label, selected, enabled);
889
890 input->select->addOpt(option);
891 }
892
893 a_Html_stash_init(html);
894}
895
897{
898 if (html->InFlags & IN_OPTION) {
899 Html_option_finish(html);
900 html->InFlags &= ~IN_OPTION;
901 }
902}
903
904/*
905 * <BUTTON>
906 */
907void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize)
908{
909 /*
910 * Buttons are rendered on one line, this is (at several levels) a
911 * bit simpler. May be changed in the future.
912 */
913 DilloHtmlInputType inp_type;
914 char *type;
915
916 assert((html->InFlags & (IN_BUTTON | IN_SELECT | IN_TEXTAREA)) == 0);
917
918 html->InFlags |= IN_BUTTON;
919 type = a_Html_get_attr_wdef(html, tag, tagsize, "type", "");
920
921 if (!dStrAsciiCasecmp(type, "button")) {
922 inp_type = DILLO_HTML_INPUT_BUTTON;
923 } else if (!dStrAsciiCasecmp(type, "reset")) {
925 } else if (!dStrAsciiCasecmp(type, "submit") || !*type) {
926 /* submit button is the default */
928 } else {
929 inp_type = DILLO_HTML_INPUT_UNKNOWN;
930 BUG_MSG("<button> type unknown: '%s'.", type);
931 }
932
933 if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
934 /* Render the button */
935 Widget *page;
936 Embed *embed;
937 const char *attrbuf;
938 char *name, *value;
939
940 if (prefs.show_tooltip &&
941 (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
942
944 attrbuf);
945 }
946 /* We used to have Textblock (prefs.limit_text_width, ...) here,
947 * but it caused 100% CPU usage.
948 */
949 page = new Textblock (false, true);
950 page->setStyle (html->backgroundStyle ());
951
952 ResourceFactory *factory = HT2LT(html)->getResourceFactory();
953 Resource *resource = factory->createComplexButtonResource(page, true);
954 embed = new Embed(resource);
955// a_Dw_button_set_sensitive (DW_BUTTON (button), FALSE);
956
957 HT2TB(html)->addWidget (embed, html->backgroundStyle ());
958
959 S_TOP(html)->textblock = html->dw = page;
960
961 value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
962 name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
963
964 Html_add_input(html, inp_type, embed, name, value, FALSE);
965 dFree(name);
966 dFree(value);
967 }
968 dFree(type);
969}
970
975{
976 html->InFlags &= ~IN_BUTTON;
977}
978
979/*
980 * Class implementations
981 */
982
983/*
984 * DilloHtmlForm
985 */
986
987/*
988 * Constructor
989 */
990DilloHtmlForm::DilloHtmlForm (DilloHtml *html2,
991 DilloHtmlMethod method2,
992 const DilloUrl *action2,
993 DilloHtmlEnc content_type2,
994 const char *charset, bool enabled)
995{
996 html = html2;
997 method = method2;
998 action = a_Url_dup(action2);
999 content_type = content_type2;
1000 submit_charset = dStrdup(charset);
1001 inputs = new misc::SimpleVector <DilloHtmlInput*> (4);
1002 num_entry_fields = 0;
1003 showing_hiddens = false;
1004 this->enabled = enabled;
1005 form_receiver = new DilloHtmlReceiver (this);
1006}
1007
1008/*
1009 * Destructor
1010 */
1011DilloHtmlForm::~DilloHtmlForm ()
1012{
1013 a_Url_free(action);
1014 dFree(submit_charset);
1015 for (int j = 0; j < inputs->size(); j++)
1016 delete inputs->get(j);
1017 delete(inputs);
1018 if (form_receiver)
1019 delete(form_receiver);
1020}
1021
1022void DilloHtmlForm::eventHandler(Resource *resource, EventButton *event)
1023{
1024 _MSG("DilloHtmlForm::eventHandler\n");
1025 if (event && (event->button == 3)) {
1026 a_UIcmd_form_popup(html->bw, html->page_url, this, showing_hiddens);
1027 } else {
1028 DilloHtmlInput *input = getInput(resource);
1029 if (input) {
1030 input->activate (this, num_entry_fields, event);
1031 } else {
1032 MSG("DilloHtmlForm::eventHandler: ERROR, input not found!\n");
1033 }
1034 }
1035}
1036
1037/*
1038 * Submit.
1039 * (Called by eventHandler())
1040 */
1041void DilloHtmlForm::submit(DilloHtmlInput *active_input, EventButton *event)
1042{
1043 if (!dStrAsciiCasecmp(URL_SCHEME(html->page_url), "https") &&
1044 dStrAsciiCasecmp(URL_SCHEME(action), "https")) {
1045 int choice = a_Dialog_choice("Dillo: Insecure form submission",
1046 "A form on a SECURE page wants to use an "
1047 "INSECURE protocol to submit data.",
1048 "Continue", "Cancel", NULL);
1049 if (choice != 1)
1050 return;
1051 }
1052
1053 DilloUrl *url = buildQueryUrl(active_input);
1054 if (url) {
1055 if (event && event->button == 2) {
1057 int focus = prefs.focus_new_tab ? 1 : 0;
1058 if (event->state == SHIFT_MASK) focus = !focus;
1059 a_UIcmd_open_url_nt(html->bw, url, focus);
1060 } else {
1061 a_UIcmd_open_url_nw(html->bw, url);
1062 }
1063 } else {
1064 a_UIcmd_open_url(html->bw, url);
1065 }
1066 a_Url_free(url);
1067 }
1068}
1069
1074DilloUrl *DilloHtmlForm::buildQueryUrl(DilloHtmlInput *active_input)
1075{
1076 DilloUrl *new_url = NULL;
1077
1078 if ((method == DILLO_HTML_METHOD_GET) ||
1079 (method == DILLO_HTML_METHOD_POST)) {
1080 Dstr *DataStr;
1081 DilloHtmlInput *active_submit = NULL;
1082
1083 _MSG("DilloHtmlForm::buildQueryUrl: action=%s\n",URL_STR_(action));
1084
1085 if (active_input) {
1086 if ((active_input->type == DILLO_HTML_INPUT_SUBMIT) ||
1087 (active_input->type == DILLO_HTML_INPUT_IMAGE) ||
1088 (active_input->type == DILLO_HTML_INPUT_BUTTON_SUBMIT)) {
1089 active_submit = active_input;
1090 }
1091 }
1092
1093 DataStr = buildQueryData(active_submit);
1094 if (DataStr) {
1095 /* action was previously resolved against base URL */
1096 char *action_str = dStrdup(URL_STR(action));
1097
1098 if (method == DILLO_HTML_METHOD_POST) {
1099 new_url = a_Url_new(action_str, NULL);
1100 /* new_url keeps the dStr and sets DataStr to NULL */
1101 a_Url_set_data(new_url, &DataStr);
1102 a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Post);
1103 if (content_type == DILLO_HTML_ENC_MULTIPART)
1104 a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_MultipartEnc);
1105 } else {
1106 /* remove <fragment> and <query> sections if present */
1107 char *url_str, *p;
1108 if ((p = strchr(action_str, '#')))
1109 *p = 0;
1110 if ((p = strchr(action_str, '?')))
1111 *p = 0;
1112
1113 url_str = dStrconcat(action_str, "?", DataStr->str, NULL);
1114 new_url = a_Url_new(url_str, NULL);
1115 a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Get);
1116 dFree(url_str);
1117 }
1118 dStr_free(DataStr, 1);
1119 dFree(action_str);
1120 }
1121 } else {
1122 MSG("DilloHtmlForm::buildQueryUrl: Method unknown\n");
1123 }
1124
1125 return new_url;
1126}
1127
1131Dstr *DilloHtmlForm::buildQueryData(DilloHtmlInput *active_submit)
1132{
1133 Dstr *DataStr = NULL;
1134 char *boundary = NULL;
1135 iconv_t char_encoder = (iconv_t) -1;
1136
1137 if (submit_charset && dStrAsciiCasecmp(submit_charset, "UTF-8")) {
1138 /* Some iconv implementations, given "//TRANSLIT", will do their best to
1139 * transliterate the string. Under the circumstances, doing so is likely
1140 * for the best.
1141 */
1142 char *translit = dStrconcat(submit_charset, "//TRANSLIT", NULL);
1143
1144 char_encoder = iconv_open(translit, "UTF-8");
1145 dFree(translit);
1146
1147 if (char_encoder == (iconv_t) -1)
1148 char_encoder = iconv_open(submit_charset, "UTF-8");
1149
1150 if (char_encoder == (iconv_t) -1) {
1151 MSG_WARN("Cannot convert to character encoding '%s'\n",
1152 submit_charset);
1153 } else {
1154 MSG("Form character encoding: '%s'\n", submit_charset);
1155 }
1156 }
1157
1158 if (content_type == DILLO_HTML_ENC_MULTIPART) {
1159 if (!(boundary = makeMultipartBoundary(char_encoder, active_submit)))
1160 MSG_ERR("Cannot generate multipart/form-data boundary.\n");
1161 }
1162
1163 if ((content_type == DILLO_HTML_ENC_URLENCODED) || (boundary != NULL)) {
1164 Dlist *values = dList_new(5);
1165
1166 DataStr = dStr_sized_new(4096);
1167 for (int i = 0; i < inputs->size(); i++) {
1168 DilloHtmlInput *input = inputs->get (i);
1169 Dstr *name = dStr_new(input->name);
1170 bool is_active_submit = (input == active_submit);
1171 int valcount;
1172
1173 name = encodeText(char_encoder, &name);
1174
1175 input->appendValuesTo(values, is_active_submit);
1176
1177 if ((valcount = dList_length(values)) > 0) {
1178 if (input->type == DILLO_HTML_INPUT_FILE) {
1179 if (valcount > 1)
1180 MSG_WARN("multiple files per form control not supported\n");
1181 Dstr *file = (Dstr *) dList_nth_data(values, 0);
1182 dList_remove(values, file);
1183
1184 /* Get filename and encode it. Do not encode file contents. */
1185 LabelButtonResource *lbr =
1186 (LabelButtonResource*) input->embed->getResource();
1187 const char *filename = lbr->getLabel();
1188 if (filename[0] && strcmp(filename, input->init_str)) {
1189 const char *p = strrchr(filename, '/');
1190 if (p)
1191 filename = p + 1; /* don't reveal path */
1192 Dstr *dfilename = dStr_new(filename);
1193 dfilename = encodeText(char_encoder, &dfilename);
1194 filesInputMultipartAppend(DataStr, boundary, name->str,
1195 file, dfilename->str);
1196 dStr_free(dfilename, 1);
1197 }
1198 dStr_free(file, 1);
1199 } else if (input->type == DILLO_HTML_INPUT_INDEX) {
1200 /* no name */
1201 Dstr *val = (Dstr *) dList_nth_data(values, 0);
1202 dList_remove(values, val);
1203 val = encodeText(char_encoder, &val);
1204 strUrlencodeAppend(DataStr, val->str);
1205 dStr_free(val, 1);
1206 } else if (input->type == DILLO_HTML_INPUT_IMAGE) {
1207 Dstr *x, *y;
1208 x = (Dstr *) dList_nth_data(values, 0);
1209 dList_remove(values, x);
1210 y = (Dstr *) dList_nth_data(values, 0);
1211 dList_remove(values, y);
1212 if (content_type == DILLO_HTML_ENC_URLENCODED)
1213 imageInputUrlencodeAppend(DataStr, name, x, y);
1214 else if (content_type == DILLO_HTML_ENC_MULTIPART)
1215 imageInputMultipartAppend(DataStr, boundary, name, x, y);
1216 dStr_free(x, 1);
1217 dStr_free(y, 1);
1218 } else {
1219 for (int j = 0; j < valcount; j++) {
1220 Dstr *val = (Dstr *) dList_nth_data(values, 0);
1221 dList_remove(values, val);
1222 val = encodeText(char_encoder, &val);
1223 if (content_type == DILLO_HTML_ENC_URLENCODED)
1224 inputUrlencodeAppend(DataStr, name->str, val->str);
1225 else if (content_type == DILLO_HTML_ENC_MULTIPART)
1226 inputMultipartAppend(DataStr, boundary, name->str,
1227 val->str);
1228 dStr_free(val, 1);
1229 }
1230 }
1231 }
1232 dStr_free(name, 1);
1233 }
1234 if (DataStr->len > 0) {
1235 if (content_type == DILLO_HTML_ENC_URLENCODED) {
1236 if (DataStr->str[DataStr->len - 1] == '&')
1237 dStr_truncate(DataStr, DataStr->len - 1);
1238 } else if (content_type == DILLO_HTML_ENC_MULTIPART) {
1239 dStr_append(DataStr, "--");
1240 }
1241 }
1242 dList_free(values);
1243 }
1244 dFree(boundary);
1245 if (char_encoder != (iconv_t) -1)
1246 (void)iconv_close(char_encoder);
1247 return DataStr;
1248}
1249
1256static void generate_boundary(Dstr *boundary)
1257{
1258 /* Extracted from RFC 2046, section 5.1.1. */
1259 static const char set[] = "abcdefghijklmnopqrstuvwxyz"
1260 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1261 "0123456789";
1262 static const size_t n = strlen(set);
1263
1264 for (int i = 0; i < 70; i++) {
1265 int c = (unsigned char) set[rand() % n];
1266 dStr_append_c(boundary, c);
1267 }
1268}
1269
1274char *DilloHtmlForm::makeMultipartBoundary(iconv_t char_encoder,
1275 DilloHtmlInput *active_submit)
1276{
1277 Dlist *values = dList_new(5);
1278 Dstr *DataStr = dStr_new("");
1279 Dstr *boundary = dStr_new("");
1280 char *ret = NULL;
1281
1282 /* fill DataStr with names, filenames, and values */
1283 for (int i = 0; i < inputs->size(); i++) {
1284 Dstr *dstr;
1285 DilloHtmlInput *input = inputs->get (i);
1286 bool is_active_submit = (input == active_submit);
1287 input->appendValuesTo(values, is_active_submit);
1288
1289 if (input->name) {
1290 dstr = dStr_new(input->name);
1291 dstr = encodeText(char_encoder, &dstr);
1292 dStr_append_l(DataStr, dstr->str, dstr->len);
1293 dStr_free(dstr, 1);
1294 }
1295 if (input->type == DILLO_HTML_INPUT_FILE) {
1296 LabelButtonResource *lbr =
1297 (LabelButtonResource*)input->embed->getResource();
1298 const char *filename = lbr->getLabel();
1299 if (filename[0] && strcmp(filename, input->init_str)) {
1300 dstr = dStr_new(filename);
1301 dstr = encodeText(char_encoder, &dstr);
1302 dStr_append_l(DataStr, dstr->str, dstr->len);
1303 dStr_free(dstr, 1);
1304 }
1305 }
1306 int length = dList_length(values);
1307 for (int i = 0; i < length; i++) {
1308 dstr = (Dstr *) dList_nth_data(values, 0);
1309 dList_remove(values, dstr);
1310 if (input->type != DILLO_HTML_INPUT_FILE)
1311 dstr = encodeText(char_encoder, &dstr);
1312 dStr_append_l(DataStr, dstr->str, dstr->len);
1313 dStr_free(dstr, 1);
1314 }
1315 }
1316
1317 generate_boundary(boundary);
1318 ret = boundary->str;
1319 dList_free(values);
1320 dStr_free(DataStr, 1);
1321 dStr_free(boundary, (ret == NULL));
1322 return ret;
1323}
1324
1330Dstr *DilloHtmlForm::encodeText(iconv_t char_encoder, Dstr **input)
1331{
1332 int rc = 0;
1333 Dstr *output;
1334 const int bufsize = 128;
1335 inbuf_t *inPtr;
1336 char *buffer, *outPtr;
1337 size_t inLeft, outRoom;
1338 bool bad_chars = false;
1339
1340 if ((char_encoder == (iconv_t) -1) || *input == NULL || (*input)->len == 0)
1341 return *input;
1342
1343 output = dStr_new("");
1344 inPtr = (*input)->str;
1345 inLeft = (*input)->len;
1346 buffer = dNew(char, bufsize);
1347
1348 while ((rc != EINVAL) && (inLeft > 0)) {
1349
1350 outPtr = buffer;
1351 outRoom = bufsize;
1352
1353 rc = iconv(char_encoder, &inPtr, &inLeft, &outPtr, &outRoom);
1354
1355 // iconv() on success, number of bytes converted
1356 // -1, errno == EILSEQ illegal byte sequence found
1357 // EINVAL partial character ends source buffer
1358 // E2BIG destination buffer is full
1359 //
1360 // GNU iconv has the undocumented(!) behavior that EILSEQ is also
1361 // returned when a character cannot be converted.
1362
1363 dStr_append_l(output, buffer, bufsize - outRoom);
1364
1365 if (rc == -1) {
1366 rc = errno;
1367 }
1368 if (rc == EILSEQ){
1369 /* count chars? (would be utf-8-specific) */
1370 bad_chars = true;
1371 inPtr++;
1372 inLeft--;
1373 dStr_append_c(output, '?');
1374 } else if (rc == EINVAL) {
1375 MSG_ERR("Form encode text: bad source string.\n");
1376 }
1377 }
1378
1379 if (bad_chars) {
1380 /*
1381 * It might be friendly to inform the caller, who would know whether
1382 * it is safe to display the beginning of the string in a message
1383 * (isn't, e.g., a password).
1384 */
1385 MSG_WARN("Form encode text: string cannot be converted cleanly.\n");
1386 }
1387
1388 dFree(buffer);
1389 dStr_free(*input, 1);
1390
1391 return output;
1392}
1393
1397void DilloHtmlForm::strUrlencodeAppend(Dstr *dstr, const char *str)
1398{
1399 char *encoded = a_Url_encode_hex_str(str);
1400 dStr_append(dstr, encoded);
1401 dFree(encoded);
1402}
1403
1407void DilloHtmlForm::inputUrlencodeAppend(Dstr *data, const char *name,
1408 const char *value)
1409{
1410 if (name && name[0]) {
1411 strUrlencodeAppend(data, name);
1412 dStr_append_c(data, '=');
1413 strUrlencodeAppend(data, value);
1414 dStr_append_c(data, '&');
1415 }
1416}
1417
1422void DilloHtmlForm::filesInputMultipartAppend(Dstr* data,
1423 const char *boundary,
1424 const char *name,
1425 Dstr *file,
1426 const char *filename)
1427{
1428 const char *ctype, *ext;
1429
1430 if (name && name[0]) {
1431 (void)a_Misc_get_content_type_from_data(file->str, file->len, &ctype);
1432 /* Heuristic: text/plain with ".htm[l]" extension -> text/html */
1433 if ((ext = strrchr(filename, '.')) &&
1434 !dStrAsciiCasecmp(ctype, "text/plain") &&
1435 (!dStrAsciiCasecmp(ext, ".html") || !dStrAsciiCasecmp(ext, ".htm"))){
1436 ctype = "text/html";
1437 }
1438
1439 if (data->len == 0) {
1440 dStr_append(data, "--");
1441 dStr_append(data, boundary);
1442 }
1443 dStr_sprintfa(data,
1444 "\r\n"
1445 "Content-Disposition: form-data; name=\"%s\"; "
1446 "filename=\"", name);
1447 /*
1448 * Replace the characters that are the most likely to damage things.
1449 * For a while, there was some momentum to standardize on an encoding,
1450 * but HTML5/Ian Hickson/his Google masters are, as of late 2012,
1451 * evidently standing in opposition to all of that for some reason.
1452 */
1453 for (int i = 0; char c = filename[i]; i++) {
1454 if (c == '\"' || c == '\r' || c == '\n')
1455 c = '_';
1456 dStr_append_c(data, c);
1457 }
1458 dStr_sprintfa(data,
1459 "\"\r\n"
1460 "Content-Type: %s\r\n"
1461 "\r\n", ctype);
1462
1463 dStr_append_l(data, file->str, file->len);
1464
1465 dStr_sprintfa(data,
1466 "\r\n"
1467 "--%s", boundary);
1468 }
1469}
1470
1474void DilloHtmlForm::inputMultipartAppend(Dstr *data,
1475 const char *boundary,
1476 const char *name,
1477 const char *value)
1478{
1479 if (name && name[0]) {
1480 if (data->len == 0) {
1481 dStr_append(data, "--");
1482 dStr_append(data, boundary);
1483 }
1484 dStr_sprintfa(data,
1485 "\r\n"
1486 "Content-Disposition: form-data; name=\"%s\"\r\n"
1487 "\r\n"
1488 "%s\r\n"
1489 "--%s",
1490 name, value, boundary);
1491 }
1492}
1493
1497void DilloHtmlForm::imageInputUrlencodeAppend(Dstr *data, Dstr *name, Dstr *x,
1498 Dstr *y)
1499{
1500 if (name->len) {
1501 strUrlencodeAppend(data, name->str);
1502 dStr_sprintfa(data, ".x=%s&", x->str);
1503 strUrlencodeAppend(data, name->str);
1504 dStr_sprintfa(data, ".y=%s&", y->str);
1505 } else
1506 dStr_sprintfa(data, "x=%s&y=%s&", x->str, y->str);
1507}
1508
1512void DilloHtmlForm::imageInputMultipartAppend(Dstr *data, const char *boundary,
1513 Dstr *name, Dstr *x, Dstr *y)
1514{
1515 int orig_len = name->len;
1516
1517 if (orig_len)
1518 dStr_append_c(name, '.');
1519 dStr_append_c(name, 'x');
1520
1521 inputMultipartAppend(data, boundary, name->str, x->str);
1522 dStr_truncate(name, name->len - 1);
1523 dStr_append_c(name, 'y');
1524 inputMultipartAppend(data, boundary, name->str, y->str);
1525 dStr_truncate(name, orig_len);
1526}
1527
1532void DilloHtmlForm::reset ()
1533{
1534 int size = inputs->size();
1535 for (int i = 0; i < size; i++)
1536 inputs->get(i)->reset();
1537}
1538
1542void DilloHtmlForm::display_hiddens(bool display)
1543{
1544 int size = inputs->size();
1545 for (int i = 0; i < size; i++) {
1546 DilloHtmlInput *input = inputs->get(i);
1547 if (input->type == DILLO_HTML_INPUT_HIDDEN) {
1548 input->embed->setDisplayed(display);
1549 }
1550 }
1551 showing_hiddens = display;
1552}
1553
1554void DilloHtmlForm::setEnabled(bool enabled)
1555{
1556 for (int i = 0; i < inputs->size(); i++)
1557 inputs->get(i)->setEnabled(enabled);
1558}
1559
1563void DilloHtmlForm::addInput(DilloHtmlInput *input, DilloHtmlInputType type)
1564{
1565 input->connectTo (form_receiver);
1566 input->setEnabled (enabled);
1567 int ni = inputs->size ();
1568 inputs->increase ();
1569 inputs->set (ni,input);
1570
1571 /* some stats */
1572 if (type == DILLO_HTML_INPUT_PASSWORD ||
1573 type == DILLO_HTML_INPUT_TEXT) {
1574 num_entry_fields++;
1575 }
1576}
1577
1581DilloHtmlInput *DilloHtmlForm::getInput (Resource *resource)
1582{
1583 for (int idx = 0; idx < inputs->size(); idx++) {
1584 DilloHtmlInput *input = inputs->get(idx);
1585 if (input->embed &&
1586 resource == input->embed->getResource())
1587 return input;
1588 }
1589 return NULL;
1590}
1591
1595DilloHtmlInput *DilloHtmlForm::getRadioInput (const char *name)
1596{
1597 for (int idx = 0; idx < inputs->size(); idx++) {
1598 DilloHtmlInput *input = inputs->get(idx);
1599 if (input->type == DILLO_HTML_INPUT_RADIO &&
1600 input->name && !dStrAsciiCasecmp(input->name, name))
1601 return input;
1602 }
1603 return NULL;
1604}
1605
1606/*
1607 * DilloHtmlReceiver
1608 *
1609 * TODO: Currently there's "clicked" for buttons, we surely need "enter" for
1610 * textentries, and maybe the "mouseover, ...." set for Javascript.
1611 */
1612
1613void DilloHtmlReceiver::activate (Resource *resource)
1614{
1615 form->eventHandler(resource, NULL);
1616}
1617
1622void DilloHtmlReceiver::enter (Resource *resource)
1623{
1624 DilloHtml *html = form->html;
1625 DilloHtmlInput *input = form->getInput(resource);
1626 const char *msg = "";
1627
1628 if ((input->type == DILLO_HTML_INPUT_SUBMIT) ||
1629 (input->type == DILLO_HTML_INPUT_IMAGE) ||
1630 (input->type == DILLO_HTML_INPUT_BUTTON_SUBMIT) ||
1631 (input->type == DILLO_HTML_INPUT_INDEX) ||
1632 ((prefs.enterpress_forces_submit || form->num_entry_fields == 1) &&
1633 ((input->type == DILLO_HTML_INPUT_PASSWORD) ||
1634 (input->type == DILLO_HTML_INPUT_TEXT)))) {
1635 /* The control can submit form. Show action URL. */
1636 msg = URL_STR(form->action);
1637 }
1638 a_UIcmd_set_msg(html->bw, "%s", msg);
1639}
1640
1644void DilloHtmlReceiver::leave (Resource *resource)
1645{
1646 DilloHtml *html = form->html;
1647 a_UIcmd_set_msg(html->bw, "");
1648}
1649
1650void DilloHtmlReceiver::clicked (Resource *resource,
1651 EventButton *event)
1652{
1653 form->eventHandler(resource, event);
1654}
1655
1656/*
1657 * DilloHtmlInput
1658 */
1659
1660/*
1661 * Constructor
1662 */
1663DilloHtmlInput::DilloHtmlInput (DilloHtmlInputType type2, Embed *embed2,
1664 const char *name2, const char *init_str2,
1665 bool init_val2)
1666{
1667 type = type2;
1668 embed = embed2;
1669 name = (name2) ? dStrdup(name2) : NULL;
1670 init_str = (init_str2) ? dStrdup(init_str2) : NULL;
1671 init_val = init_val2;
1672 select = NULL;
1673 switch (type) {
1676 select = new DilloHtmlSelect;
1677 break;
1678 default:
1679 break;
1680 }
1681 file_data = NULL;
1682 reset ();
1683}
1684
1685/*
1686 * Destructor
1687 */
1688DilloHtmlInput::~DilloHtmlInput ()
1689{
1690 dFree(name);
1691 dFree(init_str);
1692 dStr_free(file_data, 1);
1693 if (select)
1694 delete select;
1695}
1696
1700void DilloHtmlInput::connectTo(DilloHtmlReceiver *form_receiver)
1701{
1702 Resource *resource;
1703 if (embed && (resource = embed->getResource())) {
1704 resource->connectClicked (form_receiver);
1705 if (type == DILLO_HTML_INPUT_SUBMIT ||
1706 type == DILLO_HTML_INPUT_RESET ||
1709 type == DILLO_HTML_INPUT_IMAGE ||
1710 type == DILLO_HTML_INPUT_FILE ||
1711 type == DILLO_HTML_INPUT_TEXT ||
1712 type == DILLO_HTML_INPUT_PASSWORD ||
1713 type == DILLO_HTML_INPUT_INDEX) {
1714 resource->connectActivate (form_receiver);
1715 }
1716 }
1717}
1718
1722void DilloHtmlInput::activate(DilloHtmlForm *form, int num_entry_fields,
1723 EventButton *event)
1724{
1725 switch (type) {
1727 readFile (form->html->bw);
1728 break;
1731 form->reset();
1732 break;
1735 if (!(prefs.enterpress_forces_submit || num_entry_fields == 1)) {
1736 break;
1737 }
1738 /* fallthrough */
1743 form->submit(this, event);
1744 break;
1745 default:
1746 break;
1747 }
1748}
1749
1753void DilloHtmlInput::readFile (BrowserWindow *bw)
1754{
1755 const char *filename = a_UIcmd_select_file();
1756 if (filename) {
1757 a_UIcmd_set_msg(bw, "Loading file...");
1758 dStr_free(file_data, 1);
1759 file_data = a_Misc_file2dstr(filename);
1760 if (file_data) {
1761 a_UIcmd_set_msg(bw, "File loaded.");
1763 lbr->setLabel(filename);
1764 } else {
1765 a_UIcmd_set_msg(bw, "ERROR: can't load: %s", filename);
1766 }
1767 }
1768}
1769
1773void DilloHtmlInput::appendValuesTo(Dlist *values, bool is_active_submit)
1774{
1775 switch (type) {
1780 {
1781 EntryResource *entryres = (EntryResource*)embed->getResource();
1782 dList_append(values, dStr_new(entryres->getText()));
1783 }
1784 break;
1786 {
1787 MultiLineTextResource *textres =
1789 dList_append(values, dStr_new(textres->getText()));
1790 }
1791 break;
1794 {
1795 ToggleButtonResource *cb_r =
1797 if (name && init_str && cb_r->isActivated()) {
1798 dList_append(values, dStr_new(init_str));
1799 }
1800 }
1801 break;
1804 if (is_active_submit)
1805 dList_append(values, dStr_new(init_str));
1806 break;
1809 {
1810 SelectionResource *sel_res = (SelectionResource*)embed->getResource();
1811 select->appendValuesTo (values, sel_res);
1812 }
1813 break;
1815 {
1817 const char *filename = lbr->getLabel();
1818 if (filename[0] && strcmp(filename, init_str)) {
1819 if (file_data) {
1820 Dstr *file = dStr_sized_new(file_data->len);
1821 dStr_append_l(file, file_data->str, file_data->len);
1822 dList_append(values, file);
1823 } else {
1824 MSG("FORM file input \"%s\" not loaded.\n", filename);
1825 }
1826 }
1827 }
1828 break;
1830 if (is_active_submit) {
1833 Dstr *strX = dStr_new("");
1834 Dstr *strY = dStr_new("");
1835 dStr_sprintf(strX, "%d", cbr->getClickX());
1836 dStr_sprintf(strY, "%d", cbr->getClickY());
1837 dList_append(values, strX);
1838 dList_append(values, strY);
1839 }
1840 break;
1841 default:
1842 break;
1843 }
1844}
1845
1849void DilloHtmlInput::reset ()
1850{
1851 switch (type) {
1856 {
1857 EntryResource *entryres = (EntryResource*)embed->getResource();
1858 entryres->setText(init_str ? init_str : "");
1859 }
1860 break;
1863 {
1864 ToggleButtonResource *tb_r =
1866 tb_r->setActivated(init_val);
1867 }
1868 break;
1871 if (select != NULL) {
1873 select->reset(sr);
1874 }
1875 break;
1877 if (init_str != NULL) {
1878 MultiLineTextResource *textres =
1880 textres->setText(init_str ? init_str : "");
1881 }
1882 break;
1884 {
1886 lbr->setLabel(init_str);
1887 }
1888 break;
1889 default:
1890 break;
1891 }
1892}
1893
1894/*
1895 * DilloHtmlSelect
1896 */
1897
1898/*
1899 * Constructor
1900 */
1901DilloHtmlSelect::DilloHtmlSelect ()
1902{
1904}
1905
1906/*
1907 * Destructor
1908 */
1909DilloHtmlSelect::~DilloHtmlSelect ()
1910{
1911 int size = opts->size ();
1912 for (int k = 0; k < size; k++)
1913 delete opts->get (k);
1914 delete opts;
1915}
1916
1917DilloHtmlOptbase *DilloHtmlSelect::getCurrentOpt ()
1918{
1919 return opts->get (opts->size() - 1);
1920}
1921
1922void DilloHtmlSelect::addOpt (DilloHtmlOptbase *opt)
1923{
1924 int size = opts->size ();
1925 opts->increase ();
1926 opts->set (size, opt);
1927}
1928
1932void DilloHtmlSelect::ensureSelection()
1933{
1934 int size = opts->size ();
1935 if (size > 0) {
1936 for (int i = 0; i < size; i++) {
1937 DilloHtmlOptbase *opt = opts->get (i);
1938 if (opt->isSelected())
1939 return;
1940 }
1941 for (int i = 0; i < size; i++) {
1942 DilloHtmlOptbase *opt = opts->get (i);
1943 if (opt->select())
1944 break;
1945 }
1946 }
1947}
1948
1949void DilloHtmlSelect::addOptsTo (SelectionResource *res)
1950{
1951 int size = opts->size ();
1952 for (int i = 0; i < size; i++) {
1953 DilloHtmlOptbase *opt = opts->get (i);
1954 opt->addSelf(res);
1955 }
1956}
1957
1958void DilloHtmlSelect::reset (SelectionResource *res)
1959{
1960 int size = opts->size ();
1961 for (int i = 0; i < size; i++) {
1962 DilloHtmlOptbase *opt = opts->get (i);
1963 res->setItem(i, opt->isSelected());
1964 }
1965}
1966
1967void DilloHtmlSelect::appendValuesTo (Dlist *values, SelectionResource *res)
1968{
1969 int size = opts->size ();
1970 for (int i = 0; i < size; i++) {
1971 if (res->isSelected (i)) {
1972 DilloHtmlOptbase *opt = opts->get (i);
1973 const char *val = opt->getValue();
1974
1975 if (val)
1976 dList_append(values, dStr_new(val));
1977 }
1978 }
1979}
1980
1981DilloHtmlOptgroup::DilloHtmlOptgroup (char *label, bool enabled)
1982{
1983 this->label = label;
1984 this->enabled = enabled;
1985}
1986
1987DilloHtmlOptgroup::~DilloHtmlOptgroup ()
1988{
1989 dFree(label);
1990}
1991
1992/*
1993 * DilloHtmlOption
1994 */
1995
1996/*
1997 * Constructor
1998 */
1999DilloHtmlOption::DilloHtmlOption (char *value2, char *label2, bool selected2,
2000 bool enabled2)
2001{
2002 value = value2;
2003 label = label2;
2004 content = NULL;
2005 selected = selected2;
2006 enabled = enabled2;
2007}
2008
2009/*
2010 * Destructor
2011 */
2012DilloHtmlOption::~DilloHtmlOption ()
2013{
2014 dFree(value);
2015 dFree(label);
2016 dFree(content);
2017}
2018
2019/*
2020 * Utilities
2021 */
2022
2026static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize)
2027{
2029 Embed *button = NULL;
2030
2031 html->styleEngine->setPseudoLink ();
2032
2033 /* create new image and add it to the button */
2034 a_Html_common_image_attrs(html, tag, tagsize);
2035 if ((Image = a_Html_image_new(html, tag, tagsize))) {
2036 // At this point, we know that Image->ir represents an image
2037 // widget. Notice that the order of the casts matters, because
2038 // of multiple inheritance.
2039 dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)Image->img_rndr;
2040 dwi->setStyle (html->backgroundStyle ());
2041 ResourceFactory *factory = HT2LT(html)->getResourceFactory();
2042 ComplexButtonResource *complex_b_r =
2043 factory->createComplexButtonResource(dwi, false);
2044 button = new Embed(complex_b_r);
2045 HT2TB(html)->addWidget (button, html->style ());
2046 }
2047 if (!button)
2048 MSG("Html_input_image: unable to create image submit.\n");
2049 return button;
2050}
2051
2052/*
2053 * ?
2054 */
2056{
2057 DilloHtmlInput *input = Html_get_current_input(html);
2058 if (input &&
2059 (input->type == DILLO_HTML_INPUT_SELECT ||
2060 input->type == DILLO_HTML_INPUT_SEL_LIST)) {
2061 DilloHtmlOptbase *opt = input->select->getCurrentOpt ();
2062 opt->setContent (html->Stash->str, html->Stash->len);
2063 }
2064}
#define _MSG(...)
Definition bookmarks.c:45
#define MSG(...)
Definition bookmarks.c:46
int InFlags
tracks which elements we are in
DilloHtmlDocumentType DocType
DilloUrl * base_url
dw::core::style::Style * backgroundStyle()
int formNew(DilloHtmlMethod method, const DilloUrl *action, DilloHtmlEnc enc, const char *charset)
Allocate and insert form information.
Definition html.cc:667
float DocTypeVersion
Dstr * Stash
lout::misc::SimpleVector< DilloHtmlInput * > * inputs_outside_form
dw::core::style::Style * wordStyle()
BrowserWindow * bw
dw::core::style::Style * style()
dw::core::Widget * dw
char * charset
StyleEngine * styleEngine
DilloHtmlForm * getCurrentForm()
Get the current form.
Definition html.cc:684
void setNonCssHint(CssPropertyName name, CssValueType type, CssPropertyValue value)
void setPseudoLink()
set the CSS pseudo class :link.
Displays an instance of dw::core::Imgbuf.
Definition image.hh:120
A Widget for rendering text blocks, i.e.
Definition textblock.hh:206
Represents a button press or release event.
Definition events.hh:58
ButtonState state
Definition events.hh:42
The base class of all dillo widgets.
Definition widget.hh:44
virtual void setStyle(style::Style *style)
Change the style of a widget.
Definition widget.cc:1316
A widget for embedding UI widgets.
Definition ui.hh:224
void setEnabled(bool enabled)
Definition ui.cc:136
void setDisplayed(bool displayed)
Definition ui.cc:131
Resource * getResource()
Definition ui.hh:263
Interface for labelled buttons resources.
Definition ui.hh:400
virtual const char * getLabel()=0
virtual void setLabel(const char *label)=0
@ SELECTION_AT_MOST_ONE
At most one item is selected.
Definition ui.hh:503
@ SELECTION_MULTIPLE
An arbitrary number of items may be selected.
Definition ui.hh:508
A factory for the common resource.
Definition ui.hh:581
virtual OptionMenuResource * createOptionMenuResource()=0
virtual EntryResource * createEntryResource(int size, bool password, const char *label, const char *placeholder)=0
virtual MultiLineTextResource * createMultiLineTextResource(int cols, int rows, const char *placeholder)=0
virtual RadioButtonResource * createRadioButtonResource(RadioButtonResource *groupedWith, bool activated)=0
virtual CheckButtonResource * createCheckButtonResource(bool activated)=0
virtual ListResource * createListResource(ListResource::SelectionMode selectionMode, int rows)=0
virtual ComplexButtonResource * createComplexButtonResource(Widget *widget, bool relief)=0
virtual LabelButtonResource * createLabelButtonResource(const char *label)=0
Receiver interface for the "activate" signal.
Definition ui.hh:297
virtual void activate(Resource *resource)=0
virtual void leave(Resource *resource)=0
virtual void enter(Resource *resource)=0
Receiver interface for the "clicked" signal.
Definition ui.hh:307
virtual void clicked(Resource *resource, EventButton *event)=0
Basic interface for all resources.
Definition ui.hh:289
void connectClicked(ClickedReceiver *receiver)
Definition ui.hh:388
void connectActivate(ActivateReceiver *receiver)
Definition ui.hh:386
Base interface for dw::core::ui::ListResource and dw::core::ui::OptionMenuResource.
Definition ui.hh:467
virtual void pushGroup(const char *name, bool enabled)=0
virtual bool isSelected(int index)=0
virtual void setItem(int index, bool selected)=0
virtual void addItem(const char *str, bool enabled, bool selected)=0
virtual void setText(const char *text)=0
virtual const char * getText()=0
virtual void setEditable(bool editable)=0
virtual void setActivated(bool activated)=0
Simple (simpler than container::untyped::Vector and container::typed::Vector) template based vector.
Definition misc.hh:115
void increase()
Increase the vector size by one.
Definition misc.hh:181
void set(int i, T t)
Store an object in the vector.
Definition misc.hh:267
T get(int i) const
Return the one element, explicitly.
Definition misc.hh:222
int size() const
Return the number of elements put into this vector.
Definition misc.hh:162
@ PROPERTY_X_TOOLTIP
Definition css.hh:251
@ CSS_TYPE_STRING
<string>
Definition css.hh:58
static const int bufsize
Definition decode.c:21
int a_Dialog_choice(const char *title, const char *msg,...)
Make a question-dialog with a question and alternatives.
Definition dialog.cc:342
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:102
char * dStrsep(char **orig, const char *delim)
strsep() implementation
Definition dlib.c:159
void dFree(void *mem)
Definition dlib.c:68
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:203
void dStr_sprintfa(Dstr *ds, const char *format,...)
Printf-like function that appends.
Definition dlib.c:464
void dStr_append(Dstr *ds, const char *s)
Append a C string to a Dstr.
Definition dlib.c:316
char * dStrdup(const char *s)
Definition dlib.c:77
Dlist * dList_new(int size)
Create a new empty list.
Definition dlib.c:548
Dstr * dStr_sized_new(int sz)
Create a new string with a given size.
Definition dlib.c:254
void dStr_erase(Dstr *ds, int pos_0, int len)
Erase a substring.
Definition dlib.c:388
int dList_length(Dlist *lp)
For completing the ADT.
Definition dlib.c:613
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
Definition dlib.c:662
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:337
void dStr_append_l(Dstr *ds, const char *s, int l)
Append a C string to a Dstr (providing length).
Definition dlib.c:308
void dStr_append_c(Dstr *ds, int c)
Append one character.
Definition dlib.c:349
char * dStrndup(const char *s, size_t sz)
Definition dlib.c:88
void dStr_sprintf(Dstr *ds, const char *format,...)
Printf-like function.
Definition dlib.c:450
Dstr * dStr_new(const char *s)
Create a new string.
Definition dlib.c:325
void dList_append(Dlist *lp, void *data)
Append a data item to the list.
Definition dlib.c:597
void dList_free(Dlist *lp)
Free a list (not its elements)
Definition dlib.c:564
void dStr_truncate(Dstr *ds, int len)
Truncate a Dstr to be 'len' bytes long.
Definition dlib.c:368
void dList_remove(Dlist *lp, const void *data)
Definition dlib.c:641
#define FALSE
Definition dlib.h:19
#define dNew(type, count)
Definition dlib.h:49
#define MSG_ERR(...)
Definition dpid_common.h:23
const char * a_Html_get_attr(DilloHtml *html, const char *tag, int tagsize, const char *attrname)
Call Html_get_attr2 telling it to parse entities and strip the result.
Definition html.cc:4267
void a_Html_stash_init(DilloHtml *html)
Initialize the stash buffer.
Definition html.cc:843
DilloUrl * a_Html_url_new(DilloHtml *html, const char *url_str, const char *base_url, int use_base_url)
Wrapper for a_Url_new that adds an error detection message.
Definition html.cc:172
DilloImage * a_Html_image_new(DilloHtml *html, const char *tag, int tagsize)
Definition html.cc:2133
void a_Html_common_image_attrs(DilloHtml *html, const char *tag, int tagsize)
Read image-associated tag attributes and create new image.
Definition html.cc:2063
char * a_Html_get_attr_wdef(DilloHtml *html, const char *tag, int tagsize, const char *attrname, const char *def)
"a_Html_get_attr with default" Call a_Html_get_attr() and dStrdup() the returned string.
Definition html.cc:4281
char * a_Html_parse_entities(DilloHtml *html, const char *token, int toksize)
Parse all the entities in a token.
Definition html.cc:1070
#define HT2TB(html)
"html struct" to Textblock
@ DILLO_HTML_PARSE_MODE_VERBATIM
#define BUG_MSG(...)
Add a bug-meter message.
#define S_TOP(html)
Top of the parsing stack.
@ IN_OPTGROUP
@ IN_BUTTON
@ IN_OPTION
@ IN_TEXTAREA
@ IN_SELECT
@ IN_FORM
#define HT2LT(html)
"html struct" to "Layout"
@ DT_HTML
#define MSG_WARN(...)
Definition msg.h:26
Dstr * a_Misc_file2dstr(const char *filename)
Load a local file into a dStr.
Definition misc.c:464
int a_Misc_get_content_type_from_data(void *Data, size_t Size, const char **PT)
Detects 'Content-Type' from a data stream sample.
Definition misc.c:136
Anything related to Dillo Widget styles is defined here.
Definition style.cc:34
Anything related to embedded UI widgets is defined here.
Definition core.hh:36
The core of Dw is defined in this namespace.
Definition core.hh:23
@ SHIFT_MASK
Definition events.hh:17
Dw is in this namespace, or sub namespaces of this one.
Definition form.cc:25
DilloPrefs prefs
Global Data.
Definition prefs.c:33
void Html_tag_close_form(DilloHtml *html)
Definition form.cc:402
void a_Html_form_display_hiddens2(void *vform, bool display)
Definition form.cc:264
void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:626
void Html_tag_content_textarea(DilloHtml *html, const char *tag, int tagsize)
The textarea tag.
Definition form.cc:636
void Html_tag_close_button(DilloHtml *html)
Handle close <BUTTON>
Definition form.cc:974
void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:868
static void Html_option_finish(DilloHtml *html)
Definition form.cc:2055
static void Html_add_input(DilloHtml *html, DilloHtmlInputType type, Embed *embed, const char *name, const char *init_str, bool init_val)
Add an HTML control.
Definition form.cc:276
DilloHtmlForm * a_Html_form_new(DilloHtml *html, DilloHtmlMethod method, const DilloUrl *action, DilloHtmlEnc content_type, const char *charset, bool enabled)
Definition form.cc:235
static int Html_input_get_size(DilloHtml *html, const char *attrbuf)
get size, restrict it to reasonable value
Definition form.cc:413
void Html_tag_open_optgroup(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:808
void a_Html_form_reset2(void *vform)
Definition form.cc:259
void a_Html_form_delete(DilloHtmlForm *form)
Definition form.cc:244
void a_Html_input_delete(DilloHtmlInput *input)
Definition form.cc:249
static DilloHtmlInput * Html_get_current_input(DilloHtml *html)
Get the current input if available.
Definition form.cc:322
void Html_tag_close_select(DilloHtml *html)
Definition form.cc:788
void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
The ISINDEX tag is just a deprecated form of <INPUT type=text>> with implied FORM,...
Definition form.cc:589
void Html_tag_close_optgroup(DilloHtml *html)
Definition form.cc:844
void Html_tag_close_textarea(DilloHtml *html)
Close textarea.
Definition form.cc:695
void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:735
static void generate_boundary(Dstr *boundary)
Generate a random boundary.
Definition form.cc:1256
static Embed * Html_input_image(DilloHtml *html, const char *tag, int tagsize)
Create input image for the form.
Definition form.cc:2026
void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
Add a new input to current form.
Definition form.cc:432
void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:907
void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
Handle <FORM> tag.
Definition form.cc:338
DilloHtmlInputType
Definition form.cc:51
@ DILLO_HTML_INPUT_SEL_LIST
Definition form.cc:66
@ DILLO_HTML_INPUT_RADIO
Definition form.cc:56
@ DILLO_HTML_INPUT_HIDDEN
Definition form.cc:60
@ DILLO_HTML_INPUT_TEXTAREA
Definition form.cc:67
@ DILLO_HTML_INPUT_UNKNOWN
Definition form.cc:52
@ DILLO_HTML_INPUT_BUTTON_RESET
Definition form.cc:64
@ DILLO_HTML_INPUT_CHECKBOX
Definition form.cc:55
@ DILLO_HTML_INPUT_RESET
Definition form.cc:62
@ DILLO_HTML_INPUT_INDEX
Definition form.cc:68
@ DILLO_HTML_INPUT_TEXT
Definition form.cc:53
@ DILLO_HTML_INPUT_SUBMIT
Definition form.cc:61
@ DILLO_HTML_INPUT_SELECT
Definition form.cc:65
@ DILLO_HTML_INPUT_BUTTON
Definition form.cc:59
@ DILLO_HTML_INPUT_PASSWORD
Definition form.cc:54
@ DILLO_HTML_INPUT_BUTTON_SUBMIT
Definition form.cc:63
@ DILLO_HTML_INPUT_FILE
Definition form.cc:58
@ DILLO_HTML_INPUT_IMAGE
Definition form.cc:57
static DilloHtmlInput * Html_get_radio_input(DilloHtml *html, const char *name)
Find radio input by name.
Definition form.cc:299
void a_Html_form_submit2(void *vform)
Definition form.cc:254
void Html_tag_close_option(DilloHtml *html)
Definition form.cc:896
DilloHtmlMethod
Definition form.hh:10
@ DILLO_HTML_METHOD_GET
Definition form.hh:12
@ DILLO_HTML_METHOD_POST
Definition form.hh:13
DilloHtmlEnc
Definition form.hh:16
@ DILLO_HTML_ENC_URLENCODED
Definition form.hh:17
@ DILLO_HTML_ENC_MULTIPART
Definition form.hh:18
Contains the specific data for a single window.
Definition bw.h:27
int NumPendingStyleSheets
Number of not yet arrived style sheets.
Definition bw.h:48
bool_t enterpress_forces_submit
Definition prefs.h:112
bool_t show_tooltip
Definition prefs.h:66
bool_t focus_new_tab
Definition prefs.h:74
bool_t middle_click_opens_new_tab
Definition prefs.h:113
Definition url.h:88
Definition dlib.h:131
Definition dlib.h:102
Dstr_char_t * str
Definition dlib.h:105
int len
Definition dlib.h:104
void a_UIcmd_set_msg(BrowserWindow *bw, const char *format,...)
Definition uicmd.cc:1563
void a_UIcmd_form_popup(void *vbw, const DilloUrl *url, void *vform, bool_t showing_hiddens)
Definition uicmd.cc:1289
void a_UIcmd_open_url_nw(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:836
const char * a_UIcmd_select_file()
Definition uicmd.cc:1123
void a_UIcmd_open_url(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:801
void a_UIcmd_open_url_nt(void *vbw, const DilloUrl *url, int focus)
Definition uicmd.cc:852
void a_Url_set_flags(DilloUrl *u, int flags)
Set DilloUrl flags.
Definition url.c:527
char * a_Url_encode_hex_str(const char *str)
Urlencode 'str'.
Definition url.c:620
void a_Url_free(DilloUrl *url)
Free a DilloUrl.
Definition url.c:208
void a_Url_set_data(DilloUrl *u, Dstr **data)
Set DilloUrl data (like POST info, etc.)
Definition url.c:536
DilloUrl * a_Url_new(const char *url_str, const char *base_url)
Transform (and resolve) an URL string into the respective DilloURL.
Definition url.c:371
DilloUrl * a_Url_dup(const DilloUrl *ori)
Duplicate a Url structure.
Definition url.c:477
#define URL_SpamSafe
Definition url.h:40
#define URL_FLAGS(u)
Definition url.h:79
#define URL_MultipartEnc
Definition url.h:42
#define URL_STR(u)
Definition url.h:76
#define URL_STR_(u)
Definition url.h:55
#define URL_SCHEME(u)
Definition url.h:70
#define URL_Post
Definition url.h:33
#define URL_Get
Definition url.h:32