Dillo v3.2.0-88-g47ab7c70
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-2025 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
145private:
146 Embed *embed; /* May be NULL (think: hidden input) */
147
148public: //BUG: for now everything is public
150 char *name;
151 char *init_str; /* note: some overloading - for buttons, init_str
152 is simply the value of the button; for text
153 entries, it is the initial value */
154 DilloHtmlSelect *select;
155 bool init_val; /* only meaningful for buttons */
156 Dstr *file_data; /* only meaningful for file inputs.
157 TODO: may become a list... */
158
159private:
160 void connectTo(DilloHtmlReceiver *form_receiver);
161 void activate(DilloHtmlForm *form, int num_entry_fields,EventButton *event);
162 void readFile(BrowserWindow *bw);
163
164public:
165 DilloHtmlInput (DilloHtmlInputType type, Embed *embed,
166 const char *name, const char *init_str, bool init_val);
167 ~DilloHtmlInput ();
168 void appendValuesTo(Dlist *values, bool is_active_submit);
169 void reset();
170 void setEnabled(bool enabled) {if (embed) embed->setEnabled(enabled); };
171 Resource *getResource() {if (embed) { return embed->getResource(); } else { return NULL; } };
172};
173
174class DilloHtmlOptbase
175{
176public:
177 virtual ~DilloHtmlOptbase () {};
178 virtual bool isSelected() {return false;}
179 virtual bool select() {return false;}
180 virtual const char *getValue() {return NULL;}
181 virtual void setContent(const char *str, int len)
182 {MSG_ERR("Form: Optbase setContent()\n");}
183 virtual void addSelf(SelectionResource *res) = 0;
184};
185
186class DilloHtmlOptgroup : public DilloHtmlOptbase {
187private:
188 char *label;
189 bool enabled;
190public:
191 DilloHtmlOptgroup (char *label, bool enabled);
192 virtual ~DilloHtmlOptgroup ();
193 void addSelf (SelectionResource *res)
194 {res->pushGroup(label, enabled);}
195};
196
197class DilloHtmlOptgroupClose : public DilloHtmlOptbase {
198public:
199 virtual ~DilloHtmlOptgroupClose () {};
200 void addSelf (SelectionResource *res)
201 {res->popGroup();}
202};
203
204class DilloHtmlOption : public DilloHtmlOptbase {
205 friend class DilloHtmlSelect;
206public:
207 char *value, *label, *content;
208 bool selected, enabled;
209 DilloHtmlOption (char *value, char *label, bool selected, bool enabled);
210 virtual ~DilloHtmlOption ();
211 bool isSelected() {return selected;}
212 bool select() {return (selected = true);}
213 const char *getValue() {return value ? value : content;}
214 void setContent(const char *str, int len) {content = dStrndup(str, len);}
215 void addSelf (SelectionResource *res)
216 {res->addItem(label ? label : content, enabled, selected);}
217};
218
219class DilloHtmlSelect {
220 friend class DilloHtmlInput;
221private:
223 DilloHtmlSelect ();
224 ~DilloHtmlSelect ();
225public:
226 DilloHtmlOptbase *getCurrentOpt ();
227 void addOpt (DilloHtmlOptbase *opt);
228 void ensureSelection ();
229 void addOptsTo (SelectionResource *res);
230 void reset (SelectionResource *res);
231 void appendValuesTo (Dlist *values, SelectionResource *res);
232};
233
234/*
235 * Form API
236 */
237
238DilloHtmlForm *a_Html_form_new (DilloHtml *html, DilloHtmlMethod method,
239 const DilloUrl *action,
240 DilloHtmlEnc content_type, const char *charset,
241 bool enabled)
242{
243 return new DilloHtmlForm (html, method, action, content_type, charset,
244 enabled);
245}
246
247void a_Html_form_delete (DilloHtmlForm *form)
248{
249 delete form;
250}
251
252void a_Html_input_delete (DilloHtmlInput *input)
253{
254 delete input;
255}
256
257void a_Html_form_submit2(void *vform)
258{
259 ((DilloHtmlForm *)vform)->submit(NULL, NULL);
260}
261
262void a_Html_form_reset2(void *vform)
263{
264 ((DilloHtmlForm *)vform)->reset();
265}
266
267void a_Html_form_display_hiddens2(void *vform, bool display)
268{
269 ((DilloHtmlForm *)vform)->display_hiddens(display);
270}
271
272/*
273 * Form parsing functions
274 */
275
280 Embed *embed, const char *name,
281 const char *init_str, bool init_val)
282{
283 _MSG("name=[%s] init_str=[%s] init_val=[%d]\n", name, init_str, init_val);
284 DilloHtmlInput *input = new DilloHtmlInput(type, embed, name, init_str,
285 init_val);
286 if (html->InFlags & IN_FORM) {
287 html->getCurrentForm()->addInput(input, type);
288 } else {
289 int ni = html->inputs_outside_form->size();
291 html->inputs_outside_form->set(ni, input);
292
293 if (html->bw->NumPendingStyleSheets > 0) {
294 input->setEnabled(false);
295 }
296 }
297}
298
302static DilloHtmlInput *Html_get_radio_input(DilloHtml *html, const char *name)
303{
304 if (name) {
306
307 if (html->InFlags & IN_FORM)
308 inputs = html->getCurrentForm()->inputs;
309 else
310 inputs = html->inputs_outside_form;
311
312 for (int idx = 0; idx < inputs->size(); idx++) {
313 DilloHtmlInput *input = inputs->get(idx);
314 if (input->type == DILLO_HTML_INPUT_RADIO &&
315 input->name && !dStrAsciiCasecmp(input->name, name))
316 return input;
317 }
318 }
319 return NULL;
320}
321
325static DilloHtmlInput *Html_get_current_input(DilloHtml *html)
326{
328
329 if (html->InFlags & IN_FORM)
330 inputs = html->getCurrentForm()->inputs;
331 else
332 inputs = html->inputs_outside_form;
333
334 return (inputs && inputs->size() > 0) ?
335 inputs->get (inputs->size() - 1) : NULL;
336}
337
341void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
342{
343 DilloUrl *action;
344 DilloHtmlMethod method;
345 DilloHtmlEnc content_type;
346 char *charset, *first;
347 const char *attrbuf;
348
349 /* Don't break paragraph if the form is under display:none */
350 if (a_Html_should_display(html))
351 HT2TB(html)->addParbreak (9, html->wordStyle ());
352
353 if (html->InFlags & IN_FORM) {
354 BUG_MSG("Nested <form>.");
355 return;
356 }
357 html->InFlags |= IN_FORM;
358 html->InFlags &= ~IN_SELECT;
359 html->InFlags &= ~IN_OPTION;
360 html->InFlags &= ~IN_TEXTAREA;
361
362 method = DILLO_HTML_METHOD_GET;
363 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "method"))) {
364 if (!dStrAsciiCasecmp(attrbuf, "post")) {
365 method = DILLO_HTML_METHOD_POST;
366 } else if (dStrAsciiCasecmp(attrbuf, "get")) {
367 BUG_MSG("<form> submission method unknown: '%s'.", attrbuf);
368 }
369 }
370 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "action")))
371 action = a_Html_url_new(html, attrbuf, NULL, 0);
372 else {
373 if (html->DocType != DT_HTML || html->DocTypeVersion <= 4.01f)
374 BUG_MSG("<form> requires action attribute.");
375 action = a_Url_dup(html->base_url);
376 }
377 content_type = DILLO_HTML_ENC_URLENCODED;
378 if ((method == DILLO_HTML_METHOD_POST) &&
379 ((attrbuf = a_Html_get_attr(html, tag, tagsize, "enctype")))) {
380 if (!dStrAsciiCasecmp(attrbuf, "multipart/form-data"))
381 content_type = DILLO_HTML_ENC_MULTIPART;
382 }
383 charset = NULL;
384 first = NULL;
385 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "accept-charset"))) {
386 /* a list of acceptable charsets, separated by commas or spaces */
387 char *ptr = first = dStrdup(attrbuf);
388 while (ptr && !charset) {
389 char *curr = dStrsep(&ptr, " ,");
390 if (!dStrAsciiCasecmp(curr, "utf-8")) {
391 charset = curr;
392 } else if (!dStrAsciiCasecmp(curr, "UNKNOWN")) {
393 /* defined to be whatever encoding the document is in */
394 charset = html->charset;
395 }
396 }
397 if (!charset)
398 charset = first;
399 }
400 if (!charset)
401 charset = html->charset;
402 html->formNew(method, action, content_type, charset);
403 dFree(first);
404 a_Url_free(action);
405}
406
408{
409 html->InFlags &= ~IN_FORM;
410 html->InFlags &= ~IN_SELECT;
411 html->InFlags &= ~IN_OPTION;
412 html->InFlags &= ~IN_TEXTAREA;
413}
414
418static int Html_input_get_size(DilloHtml *html, const char *attrbuf)
419{
420 const int MAX_SIZE = 1024;
421 int size = 20;
422
423 if (attrbuf) {
424 size = strtol(attrbuf, NULL, 10);
425 if (size < 1 || size > MAX_SIZE) {
426 int badSize = size;
427 size = (size < 1 ? 20 : MAX_SIZE);
428 BUG_MSG("<input> size=%d, using size=%d instead.", badSize, size);
429 }
430 }
431 return size;
432}
433
437void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
438{
439 DilloHtmlInputType inp_type;
440 Resource *resource = NULL;
441 Embed *embed = NULL;
442 char *value, *name, *type, *init_str, *placeholder = NULL;
443 const char *attrbuf, *label;
444 bool init_val = false;
445 ResourceFactory *factory;
446
447 if (html->InFlags & IN_SELECT) {
448 BUG_MSG("<input> inside <select>.");
449 return;
450 }
451 if (html->InFlags & IN_BUTTON) {
452 BUG_MSG("<input> inside <button>.");
453 return;
454 }
455
456 factory = HT2LT(html)->getResourceFactory();
457
458 /* Get 'value', 'name' and 'type' */
459 value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
460 name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
461 type = a_Html_get_attr_wdef(html, tag, tagsize, "type", "");
462
463 init_str = NULL;
464 inp_type = DILLO_HTML_INPUT_UNKNOWN;
465 if (!dStrAsciiCasecmp(type, "password")) {
466 inp_type = DILLO_HTML_INPUT_PASSWORD;
467 placeholder = a_Html_get_attr_wdef(html, tag,tagsize,"placeholder",NULL);
468 attrbuf = a_Html_get_attr(html, tag, tagsize, "size");
469 int size = Html_input_get_size(html, attrbuf);
470 if (a_Html_should_display(html))
471 resource = factory->createEntryResource (size, true, NULL, placeholder);
472 init_str = value;
473 } else if (!dStrAsciiCasecmp(type, "checkbox")) {
474 inp_type = DILLO_HTML_INPUT_CHECKBOX;
475 if (a_Html_should_display(html))
476 resource = factory->createCheckButtonResource(false);
477 init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL);
478 init_str = (value) ? value : dStrdup("on");
479 } else if (!dStrAsciiCasecmp(type, "radio")) {
480 inp_type = DILLO_HTML_INPUT_RADIO;
481 if (a_Html_should_display(html)) {
482 RadioButtonResource *rb_r = NULL;
483 DilloHtmlInput *input = Html_get_radio_input(html, name);
484 if (input && input->getResource())
485 rb_r = (RadioButtonResource*) input->getResource();
486 resource = factory->createRadioButtonResource(rb_r, false);
487 }
488 init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL);
489 init_str = value;
490 } else if (!dStrAsciiCasecmp(type, "hidden")) {
491 inp_type = DILLO_HTML_INPUT_HIDDEN;
492 init_str = value;
493 int size = Html_input_get_size(html, NULL);
494 if (a_Html_should_display(html))
495 resource = factory->createEntryResource(size, false, name, NULL);
496 } else if (!dStrAsciiCasecmp(type, "submit")) {
497 inp_type = DILLO_HTML_INPUT_SUBMIT;
498 init_str = (value) ? value : dStrdup("Submit");
499 if (a_Html_should_display(html))
500 resource = factory->createLabelButtonResource(init_str);
501 } else if (!dStrAsciiCasecmp(type, "reset")) {
502 inp_type = DILLO_HTML_INPUT_RESET;
503 init_str = (value) ? value : dStrdup("Reset");
504 if (a_Html_should_display(html))
505 resource = factory->createLabelButtonResource(init_str);
506 } else if (!dStrAsciiCasecmp(type, "image")) {
507 if (URL_FLAGS(html->base_url) & URL_SpamSafe) {
508 /* Don't request the image; make a text submit button instead */
509 inp_type = DILLO_HTML_INPUT_SUBMIT;
510 attrbuf = a_Html_get_attr(html, tag, tagsize, "alt");
511 label = attrbuf ? attrbuf : value ? value : name ? name : "Submit";
512 init_str = dStrdup(label);
513 if (a_Html_should_display(html))
514 resource = factory->createLabelButtonResource(init_str);
515 } else {
516 inp_type = DILLO_HTML_INPUT_IMAGE;
517 /* use a dw_image widget */
518 if (a_Html_should_display(html))
519 embed = Html_input_image(html, tag, tagsize);
520 init_str = value;
521 }
522 } else if (!dStrAsciiCasecmp(type, "file")) {
523 bool valid = true;
524 if (html->InFlags & IN_FORM) {
525 DilloHtmlForm *form = html->getCurrentForm();
526 if (form->method != DILLO_HTML_METHOD_POST) {
527 valid = false;
528 BUG_MSG("<form> with file input MUST use HTTP POST method.");
529 MSG("File input ignored in form not using HTTP POST method\n");
530 } else if (form->content_type != DILLO_HTML_ENC_MULTIPART) {
531 valid = false;
532 BUG_MSG("<form> with file input MUST use multipart/form-data"
533 " encoding.");
534 MSG("File input ignored in form not using multipart/form-data"
535 " encoding\n");
536 }
537 }
538 if (valid) {
539 inp_type = DILLO_HTML_INPUT_FILE;
540 init_str = dStrdup("File selector");
541 if (a_Html_should_display(html))
542 resource = factory->createLabelButtonResource(init_str);
543 }
544 } else if (!dStrAsciiCasecmp(type, "button")) {
545 inp_type = DILLO_HTML_INPUT_BUTTON;
546 if (value) {
547 init_str = value;
548 if (a_Html_should_display(html))
549 resource = factory->createLabelButtonResource(init_str);
550 }
551 } else {
552 /* Text input, which also is the default */
553 inp_type = DILLO_HTML_INPUT_TEXT;
554 placeholder = a_Html_get_attr_wdef(html, tag,tagsize,"placeholder",NULL);
555 attrbuf = a_Html_get_attr(html, tag, tagsize, "size");
556 int size = Html_input_get_size(html, attrbuf);
557 if (a_Html_should_display(html))
558 resource = factory->createEntryResource(size, false, NULL, placeholder);
559 init_str = value;
560 }
561
562 /* Resource should not be set with display:none */
563 assert(!resource || a_Html_should_display(html));
564
565 if (resource)
566 embed = new Embed (resource);
567
568 if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
569 Html_add_input(html, inp_type, embed, name,
570 (init_str) ? init_str : "", init_val);
571 }
572
573 /* Embed should not be set with display:none */
574 assert(!embed || a_Html_should_display(html));
575
576 if (embed != NULL && inp_type != DILLO_HTML_INPUT_IMAGE &&
577 inp_type != DILLO_HTML_INPUT_UNKNOWN) {
578 if (inp_type == DILLO_HTML_INPUT_HIDDEN) {
579 /* TODO Perhaps do this with access to current form setting */
580 embed->setDisplayed(false);
581 }
582 if (inp_type == DILLO_HTML_INPUT_TEXT ||
583 inp_type == DILLO_HTML_INPUT_PASSWORD) {
584 if (a_Html_get_attr(html, tag, tagsize, "readonly"))
585 ((EntryResource *) resource)->setEditable(false);
586
587 /* Maximum length of the text in the entry */
588 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "maxlength"))) {
589 int maxlen = strtol(attrbuf, NULL, 10);
590 ((EntryResource *) resource)->setMaxLength(maxlen);
591 }
592 }
593 if (prefs.show_tooltip &&
594 (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
595
597 attrbuf);
598 }
599
600 HT2TB(html)->addWidget (embed, html->backgroundStyle());
601 }
602 dFree(type);
603 dFree(name);
604 if (init_str != value)
605 dFree(init_str);
606 dFree(placeholder);
607 dFree(value);
608}
609
614void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
615{
616 DilloUrl *action;
617 const char *attrbuf;
618
619 if (html->InFlags & IN_FORM) {
620 MSG("<isindex> inside <form> not handled.\n");
621 return;
622 }
623
624 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "action")))
625 action = a_Html_url_new(html, attrbuf, NULL, 0);
626 else
627 action = a_Url_dup(html->base_url);
628
630 html->charset);
631 html->InFlags |= IN_FORM;
632
633 Embed *embed = NULL;
634
635 if (a_Html_should_display(html)) {
636 HT2TB(html)->addParbreak (9, html->wordStyle ());
637
638 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt")))
639 HT2TB(html)->addText(attrbuf, html->wordStyle ());
640
641 ResourceFactory *factory = HT2LT(html)->getResourceFactory();
642 EntryResource *entryResource = factory->createEntryResource (20, false,
643 NULL, NULL);
644 embed = new Embed (entryResource);
645
646 HT2TB(html)->addWidget (embed, html->backgroundStyle ());
647 }
648
649 Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE);
650
651 a_Url_free(action);
652 html->InFlags &= ~IN_FORM;
653}
654
655void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize)
656{
657 assert((html->InFlags & (IN_BUTTON | IN_SELECT | IN_TEXTAREA)) == 0);
658
659 html->InFlags |= IN_TEXTAREA;
660}
661
665void Html_tag_content_textarea(DilloHtml *html, const char *tag, int tagsize)
666{
667 const int MAX_COLS=1024, MAX_ROWS=10000;
668
669 char *name;
670 const char *attrbuf;
671 int cols, rows;
672
673 a_Html_stash_init(html);
674 S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
675
676 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cols"))) {
677 cols = strtol(attrbuf, NULL, 10);
678 } else {
679 if (html->DocType != DT_HTML || html->DocTypeVersion <= 4.01f)
680 BUG_MSG("<textarea> requires cols attribute.");
681 cols = 20;
682 }
683 if (cols < 1 || cols > MAX_COLS) {
684 int badCols = cols;
685 cols = (cols < 1 ? 20 : MAX_COLS);
686 BUG_MSG("<textarea> cols=%d, using cols=%d instead.", badCols, cols);
687 }
688 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rows"))) {
689 rows = strtol(attrbuf, NULL, 10);
690 } else {
691 if (html->DocType != DT_HTML || html->DocTypeVersion <= 4.01f)
692 BUG_MSG("<textarea> requires rows attribute.");
693 rows = 3;
694 }
695 if (rows < 1 || rows > MAX_ROWS) {
696 int badRows = rows;
697 rows = (rows < 1 ? 2 : MAX_ROWS);
698 BUG_MSG("<textarea> rows=%d, using rows=%d instead.", badRows, rows);
699 }
700 name = NULL;
701 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name")))
702 name = dStrdup(attrbuf);
703
704 attrbuf = a_Html_get_attr(html, tag, tagsize, "placeholder");
705
706 Embed *embed = NULL;
707 if (a_Html_should_display(html)) {
708 ResourceFactory *factory = HT2LT(html)->getResourceFactory();
709 MultiLineTextResource *textres =
710 factory->createMultiLineTextResource (cols, rows, attrbuf);
711
712 embed = new Embed(textres);
713 /* Readonly or not? */
714 if (a_Html_get_attr(html, tag, tagsize, "readonly"))
715 textres->setEditable(false);
716
717 HT2TB(html)->addWidget (embed, html->backgroundStyle ());
718 }
719
720 Html_add_input(html, DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, false);
721
722 dFree(name);
723}
724
730{
731 char *str;
732 DilloHtmlInput *input;
733 int i;
734
735 if (html->InFlags & IN_TEXTAREA && a_Html_should_display(html)) {
736 /* Remove the line ending that follows the opening tag */
737 if (html->Stash->str[0] == '\r')
738 dStr_erase(html->Stash, 0, 1);
739 if (html->Stash->str[0] == '\n')
740 dStr_erase(html->Stash, 0, 1);
741
742 /* As the spec recommends to canonicalize line endings, it is safe
743 * to replace '\r' with '\n'. It will be canonicalized anyway! */
744 for (i = 0; i < html->Stash->len; ++i) {
745 if (html->Stash->str[i] == '\r') {
746 if (html->Stash->str[i + 1] == '\n')
747 dStr_erase(html->Stash, i, 1);
748 else
749 html->Stash->str[i] = '\n';
750 }
751 }
752
753 /* The HTML3.2 spec says it can have "text and character entities". */
754 str = a_Html_parse_entities(html, html->Stash->str, html->Stash->len);
755 input = Html_get_current_input(html);
756 if (input) {
757 input->init_str = str;
758 Resource *res = input->getResource();
759 if (res)
760 ((MultiLineTextResource *)res)->setText(str);
761 }
762 }
763 html->InFlags &= ~IN_TEXTAREA;
764}
765
766/*
767 * <SELECT>
768 */
769/* The select tag is quite tricky, because of gorpy html syntax. */
770void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize)
771{
772 const char *attrbuf;
773 int rows = 0;
774
775 assert((html->InFlags & (IN_BUTTON | IN_SELECT | IN_TEXTAREA)) == 0);
776
777 html->InFlags |= IN_SELECT;
778 html->InFlags &= ~IN_OPTION;
779
780 char *name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
781 bool multi = a_Html_get_attr(html, tag, tagsize, "multiple") != NULL;
782
783 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size"))) {
784 rows = strtol(attrbuf, NULL, 10);
785 if (rows > 100)
786 rows = 100;
787 }
788 if (rows < 1)
789 rows = multi ? 10 : 1;
790
792
793 if (rows == 1 && multi == false)
795 else
797
798 Embed *embed = NULL;
799
800 if (a_Html_should_display(html)) {
801 ResourceFactory *factory = HT2LT(html)->getResourceFactory ();
803
804 if (type == DILLO_HTML_INPUT_SELECT) {
805 res = factory->createOptionMenuResource ();
806 } else {
811 res = factory->createListResource (mode, rows);
812 }
813
814 embed = new Embed(res);
815
816 if (prefs.show_tooltip &&
817 (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
818
820 attrbuf);
821 }
822
823 HT2TB(html)->addWidget (embed, html->backgroundStyle ());
824 }
825
826 Html_add_input(html, type, embed, name, NULL, false);
827 a_Html_stash_init(html);
828 dFree(name);
829}
830
831/*
832 * ?
833 */
835{
836 if (html->InFlags & IN_SELECT) {
837 if (html->InFlags & IN_OPTION)
838 Html_option_finish(html);
839 html->InFlags &= ~IN_SELECT;
840 html->InFlags &= ~IN_OPTION;
841
842 DilloHtmlInput *input = Html_get_current_input(html);
843 if (input) {
844 DilloHtmlSelect *select = input->select;
845 if (input->type == DILLO_HTML_INPUT_SELECT) {
846 // option menu interface requires that something be selected */
847 select->ensureSelection ();
848 }
849 /* May not have an embed or resource */
850 if (input->getResource())
851 select->addOptsTo ((SelectionResource*)input->getResource());
852 }
853 }
854}
855
856void Html_tag_open_optgroup(DilloHtml *html, const char *tag, int tagsize)
857{
858 if (!(html->InFlags & IN_SELECT)) {
859 BUG_MSG("<optgroup> outside <select>.");
860 return;
861 }
862 if (html->InFlags & IN_OPTGROUP) {
863 BUG_MSG("Nested <optgroup>.");
864 return;
865 }
866 if (html->InFlags & IN_OPTION) {
867 Html_option_finish(html);
868 html->InFlags &= ~IN_OPTION;
869 }
870
871 html->InFlags |= IN_OPTGROUP;
872
873 DilloHtmlInput *input = Html_get_current_input(html);
874 if (input &&
875 (input->type == DILLO_HTML_INPUT_SELECT ||
876 input->type == DILLO_HTML_INPUT_SEL_LIST)) {
877 char *label = a_Html_get_attr_wdef(html, tag, tagsize, "label", NULL);
878 bool enabled = (a_Html_get_attr(html, tag, tagsize, "disabled") == NULL);
879
880 if (!label) {
881 BUG_MSG("<optgroup> requires label attribute.");
882 label = dStrdup("");
883 }
884
885 DilloHtmlOptgroup *opt =
886 new DilloHtmlOptgroup (label, enabled);
887
888 input->select->addOpt(opt);
889 }
890}
891
893{
894 if (html->InFlags & IN_OPTGROUP) {
895 html->InFlags &= ~IN_OPTGROUP;
896
897 if (html->InFlags & IN_OPTION) {
898 Html_option_finish(html);
899 html->InFlags &= ~IN_OPTION;
900 }
901
902 DilloHtmlInput *input = Html_get_current_input(html);
903 if (input &&
904 (input->type == DILLO_HTML_INPUT_SELECT ||
905 input->type == DILLO_HTML_INPUT_SEL_LIST)) {
906 DilloHtmlOptgroupClose *opt = new DilloHtmlOptgroupClose ();
907
908 input->select->addOpt(opt);
909 }
910 }
911}
912
913/*
914 * <OPTION>
915 */
916void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize)
917{
918 if (!(html->InFlags & IN_SELECT)) {
919 BUG_MSG("<option> outside <select>.");
920 return;
921 }
922 if (html->InFlags & IN_OPTION)
923 Html_option_finish(html);
924 html->InFlags |= IN_OPTION;
925
926 DilloHtmlInput *input = Html_get_current_input(html);
927 if (input &&
928 (input->type == DILLO_HTML_INPUT_SELECT ||
929 input->type == DILLO_HTML_INPUT_SEL_LIST)) {
930 char *value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
931 char *label = a_Html_get_attr_wdef(html, tag, tagsize, "label", NULL);
932 bool selected = (a_Html_get_attr(html, tag, tagsize,"selected") != NULL);
933 bool enabled = (a_Html_get_attr(html, tag, tagsize, "disabled") == NULL);
934
935 DilloHtmlOption *option =
936 new DilloHtmlOption (value, label, selected, enabled);
937
938 input->select->addOpt(option);
939 }
940
941 a_Html_stash_init(html);
942}
943
945{
946 if (html->InFlags & IN_OPTION) {
947 Html_option_finish(html);
948 html->InFlags &= ~IN_OPTION;
949 }
950}
951
952/*
953 * <BUTTON>
954 */
955void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize)
956{
957 /*
958 * Buttons are rendered on one line, this is (at several levels) a
959 * bit simpler. May be changed in the future.
960 */
961 DilloHtmlInputType inp_type;
962 char *type;
963
964 assert((html->InFlags & (IN_BUTTON | IN_SELECT | IN_TEXTAREA)) == 0);
965
966 html->InFlags |= IN_BUTTON;
967 type = a_Html_get_attr_wdef(html, tag, tagsize, "type", "");
968
969 if (!dStrAsciiCasecmp(type, "button")) {
970 inp_type = DILLO_HTML_INPUT_BUTTON;
971 } else if (!dStrAsciiCasecmp(type, "reset")) {
973 } else if (!dStrAsciiCasecmp(type, "submit") || !*type) {
974 /* submit button is the default */
976 } else {
977 inp_type = DILLO_HTML_INPUT_UNKNOWN;
978 BUG_MSG("<button> type unknown: '%s'.", type);
979 }
980
981 if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
982 /* Render the button */
983 Embed *embed;
984 const char *attrbuf;
985
986 if (prefs.show_tooltip &&
987 (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
988
990 attrbuf);
991 }
992
993 ResourceFactory *factory = HT2LT(html)->getResourceFactory();
994
995 if (a_Html_should_display(html)) {
996 /* We used to have Textblock (prefs.limit_text_width, ...) here,
997 * but it caused 100% CPU usage.
998 */
999 Widget *page = new Textblock (false, true);
1000 page->setStyle (html->backgroundStyle ());
1001
1002 ComplexButtonResource *resource = factory->createComplexButtonResource(page, true);
1003 embed = new Embed(resource);
1004 HT2TB(html)->addWidget (embed, html->backgroundStyle ());
1005 S_TOP(html)->textblock = html->dw = page;
1006 } else {
1007 embed = NULL;
1008 }
1009
1010 /* Always add the input element, so is present in the form */
1011 char *value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
1012 char *name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
1013 Html_add_input(html, inp_type, embed, name, value, FALSE);
1014 dFree(name);
1015 dFree(value);
1016 }
1017 dFree(type);
1018}
1019
1024{
1025 html->InFlags &= ~IN_BUTTON;
1026}
1027
1028/*
1029 * Class implementations
1030 */
1031
1032/*
1033 * DilloHtmlForm
1034 */
1035
1036/*
1037 * Constructor
1038 */
1039DilloHtmlForm::DilloHtmlForm (DilloHtml *html2,
1040 DilloHtmlMethod method2,
1041 const DilloUrl *action2,
1042 DilloHtmlEnc content_type2,
1043 const char *charset, bool enabled)
1044{
1045 html = html2;
1046 method = method2;
1047 action = a_Url_dup(action2);
1048 content_type = content_type2;
1049 submit_charset = dStrdup(charset);
1050 inputs = new misc::SimpleVector <DilloHtmlInput*> (4);
1051 num_entry_fields = 0;
1052 showing_hiddens = false;
1053 this->enabled = enabled;
1054 form_receiver = new DilloHtmlReceiver (this);
1055}
1056
1057/*
1058 * Destructor
1059 */
1060DilloHtmlForm::~DilloHtmlForm ()
1061{
1062 a_Url_free(action);
1063 dFree(submit_charset);
1064 for (int j = 0; j < inputs->size(); j++)
1065 delete inputs->get(j);
1066 delete(inputs);
1067 if (form_receiver)
1068 delete(form_receiver);
1069}
1070
1071void DilloHtmlForm::eventHandler(Resource *resource, EventButton *event)
1072{
1073 _MSG("DilloHtmlForm::eventHandler\n");
1074 if (event && (event->button == 3)) {
1075 a_UIcmd_form_popup(html->bw, html->page_url, this, showing_hiddens);
1076 } else {
1077 DilloHtmlInput *input = getInput(resource);
1078 if (input) {
1079 input->activate (this, num_entry_fields, event);
1080 } else {
1081 MSG("DilloHtmlForm::eventHandler: ERROR, input not found!\n");
1082 }
1083 }
1084}
1085
1086/*
1087 * Submit.
1088 * (Called by eventHandler())
1089 */
1090void DilloHtmlForm::submit(DilloHtmlInput *active_input, EventButton *event)
1091{
1092 if (!dStrAsciiCasecmp(URL_SCHEME(html->page_url), "https") &&
1093 dStrAsciiCasecmp(URL_SCHEME(action), "https")) {
1094 int choice = a_Dialog_choice("Dillo: Insecure form submission",
1095 "A form on a SECURE page wants to use an "
1096 "INSECURE protocol to submit data.",
1097 "Continue", "Cancel", NULL);
1098 if (choice != 1)
1099 return;
1100 }
1101
1102 DilloUrl *url = buildQueryUrl(active_input);
1103 if (url) {
1104 if (event && event->button == 2) {
1106 int focus = prefs.focus_new_tab ? 1 : 0;
1107 if (event->state == SHIFT_MASK) focus = !focus;
1108 a_UIcmd_open_url_nt(html->bw, url, focus);
1109 } else {
1110 a_UIcmd_open_url_nw(html->bw, url);
1111 }
1112 } else {
1113 a_UIcmd_open_url(html->bw, url);
1114 }
1115 a_Url_free(url);
1116 }
1117}
1118
1123DilloUrl *DilloHtmlForm::buildQueryUrl(DilloHtmlInput *active_input)
1124{
1125 DilloUrl *new_url = NULL;
1126
1127 if ((method == DILLO_HTML_METHOD_GET) ||
1128 (method == DILLO_HTML_METHOD_POST)) {
1129 Dstr *DataStr;
1130 DilloHtmlInput *active_submit = NULL;
1131
1132 _MSG("DilloHtmlForm::buildQueryUrl: action=%s\n",URL_STR_(action));
1133
1134 if (active_input) {
1135 if ((active_input->type == DILLO_HTML_INPUT_SUBMIT) ||
1136 (active_input->type == DILLO_HTML_INPUT_IMAGE) ||
1137 (active_input->type == DILLO_HTML_INPUT_BUTTON_SUBMIT)) {
1138 active_submit = active_input;
1139 }
1140 }
1141
1142 DataStr = buildQueryData(active_submit);
1143 if (DataStr) {
1144 /* action was previously resolved against base URL */
1145 char *action_str = dStrdup(URL_STR(action));
1146
1147 if (method == DILLO_HTML_METHOD_POST) {
1148 new_url = a_Url_new(action_str, NULL);
1149 /* new_url keeps the dStr and sets DataStr to NULL */
1150 a_Url_set_data(new_url, &DataStr);
1151 a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Post);
1152 if (content_type == DILLO_HTML_ENC_MULTIPART)
1153 a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_MultipartEnc);
1154 } else {
1155 /* remove <fragment> and <query> sections if present */
1156 char *url_str, *p;
1157 if ((p = strchr(action_str, '#')))
1158 *p = 0;
1159 if ((p = strchr(action_str, '?')))
1160 *p = 0;
1161
1162 url_str = dStrconcat(action_str, "?", DataStr->str, NULL);
1163 new_url = a_Url_new(url_str, NULL);
1164 a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Get);
1165 dFree(url_str);
1166 }
1167 dStr_free(DataStr, 1);
1168 dFree(action_str);
1169 }
1170 } else {
1171 MSG("DilloHtmlForm::buildQueryUrl: Method unknown\n");
1172 }
1173
1174 return new_url;
1175}
1176
1180Dstr *DilloHtmlForm::buildQueryData(DilloHtmlInput *active_submit)
1181{
1182 Dstr *DataStr = NULL;
1183 char *boundary = NULL;
1184 iconv_t char_encoder = (iconv_t) -1;
1185
1186 if (submit_charset && dStrAsciiCasecmp(submit_charset, "UTF-8")) {
1187 /* Some iconv implementations, given "//TRANSLIT", will do their best to
1188 * transliterate the string. Under the circumstances, doing so is likely
1189 * for the best.
1190 */
1191 char *translit = dStrconcat(submit_charset, "//TRANSLIT", NULL);
1192
1193 char_encoder = iconv_open(translit, "UTF-8");
1194 dFree(translit);
1195
1196 if (char_encoder == (iconv_t) -1)
1197 char_encoder = iconv_open(submit_charset, "UTF-8");
1198
1199 if (char_encoder == (iconv_t) -1) {
1200 MSG_WARN("Cannot convert to character encoding '%s'\n",
1201 submit_charset);
1202 } else {
1203 MSG("Form character encoding: '%s'\n", submit_charset);
1204 }
1205 }
1206
1207 if (content_type == DILLO_HTML_ENC_MULTIPART) {
1208 if (!(boundary = makeMultipartBoundary(char_encoder, active_submit)))
1209 MSG_ERR("Cannot generate multipart/form-data boundary.\n");
1210 }
1211
1212 if ((content_type == DILLO_HTML_ENC_URLENCODED) || (boundary != NULL)) {
1213 Dlist *values = dList_new(5);
1214
1215 DataStr = dStr_sized_new(4096);
1216 for (int i = 0; i < inputs->size(); i++) {
1217 DilloHtmlInput *input = inputs->get (i);
1218 Dstr *name = dStr_new(input->name);
1219 bool is_active_submit = (input == active_submit);
1220 int valcount;
1221
1222 name = encodeText(char_encoder, &name);
1223
1224 input->appendValuesTo(values, is_active_submit);
1225
1226 if ((valcount = dList_length(values)) > 0) {
1227 if (input->type == DILLO_HTML_INPUT_FILE) {
1228 if (valcount > 1)
1229 MSG_WARN("multiple files per form control not supported\n");
1230 Dstr *file = (Dstr *) dList_nth_data(values, 0);
1231 dList_remove(values, file);
1232
1233 /* Get filename and encode it. Do not encode file contents. */
1234 if (input->getResource()) {
1235 LabelButtonResource *lbr =
1236 (LabelButtonResource*) input->getResource();
1237 const char *filename = lbr->getLabel();
1238 if (filename[0] && strcmp(filename, input->init_str)) {
1239 const char *p = strrchr(filename, '/');
1240 if (p)
1241 filename = p + 1; /* don't reveal path */
1242 Dstr *dfilename = dStr_new(filename);
1243 dfilename = encodeText(char_encoder, &dfilename);
1244 filesInputMultipartAppend(DataStr, boundary, name->str,
1245 file, dfilename->str);
1246 dStr_free(dfilename, 1);
1247 }
1248 }
1249 dStr_free(file, 1);
1250 } else if (input->type == DILLO_HTML_INPUT_INDEX) {
1251 /* no name */
1252 Dstr *val = (Dstr *) dList_nth_data(values, 0);
1253 dList_remove(values, val);
1254 val = encodeText(char_encoder, &val);
1255 strUrlencodeAppend(DataStr, val->str);
1256 dStr_free(val, 1);
1257 } else if (input->type == DILLO_HTML_INPUT_IMAGE) {
1258 Dstr *x, *y;
1259 x = (Dstr *) dList_nth_data(values, 0);
1260 dList_remove(values, x);
1261 y = (Dstr *) dList_nth_data(values, 0);
1262 dList_remove(values, y);
1263 if (content_type == DILLO_HTML_ENC_URLENCODED)
1264 imageInputUrlencodeAppend(DataStr, name, x, y);
1265 else if (content_type == DILLO_HTML_ENC_MULTIPART)
1266 imageInputMultipartAppend(DataStr, boundary, name, x, y);
1267 dStr_free(x, 1);
1268 dStr_free(y, 1);
1269 } else {
1270 for (int j = 0; j < valcount; j++) {
1271 Dstr *val = (Dstr *) dList_nth_data(values, 0);
1272 dList_remove(values, val);
1273 val = encodeText(char_encoder, &val);
1274 if (content_type == DILLO_HTML_ENC_URLENCODED)
1275 inputUrlencodeAppend(DataStr, name->str, val->str);
1276 else if (content_type == DILLO_HTML_ENC_MULTIPART)
1277 inputMultipartAppend(DataStr, boundary, name->str,
1278 val->str);
1279 dStr_free(val, 1);
1280 }
1281 }
1282 }
1283 dStr_free(name, 1);
1284 }
1285 if (DataStr->len > 0) {
1286 if (content_type == DILLO_HTML_ENC_URLENCODED) {
1287 if (DataStr->str[DataStr->len - 1] == '&')
1288 dStr_truncate(DataStr, DataStr->len - 1);
1289 } else if (content_type == DILLO_HTML_ENC_MULTIPART) {
1290 dStr_append(DataStr, "--");
1291 }
1292 }
1293 dList_free(values);
1294 }
1295 dFree(boundary);
1296 if (char_encoder != (iconv_t) -1)
1297 (void)iconv_close(char_encoder);
1298 return DataStr;
1299}
1300
1307static void generate_boundary(Dstr *boundary)
1308{
1309 /* Extracted from RFC 2046, section 5.1.1. */
1310 static const char set[] = "abcdefghijklmnopqrstuvwxyz"
1311 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1312 "0123456789";
1313 static const size_t n = strlen(set);
1314
1315 for (int i = 0; i < 70; i++) {
1316 int c = (unsigned char) set[rand() % n];
1317 dStr_append_c(boundary, c);
1318 }
1319}
1320
1325char *DilloHtmlForm::makeMultipartBoundary(iconv_t char_encoder,
1326 DilloHtmlInput *active_submit)
1327{
1328 Dlist *values = dList_new(5);
1329 Dstr *DataStr = dStr_new("");
1330 Dstr *boundary = dStr_new("");
1331 char *ret = NULL;
1332
1333 /* fill DataStr with names, filenames, and values */
1334 for (int i = 0; i < inputs->size(); i++) {
1335 Dstr *dstr;
1336 DilloHtmlInput *input = inputs->get (i);
1337 bool is_active_submit = (input == active_submit);
1338 input->appendValuesTo(values, is_active_submit);
1339
1340 if (input->name) {
1341 dstr = dStr_new(input->name);
1342 dstr = encodeText(char_encoder, &dstr);
1343 dStr_append_l(DataStr, dstr->str, dstr->len);
1344 dStr_free(dstr, 1);
1345 }
1346 if (input->type == DILLO_HTML_INPUT_FILE) {
1347 LabelButtonResource *lbr =
1348 (LabelButtonResource*)input->embed->getResource();
1349 const char *filename = lbr->getLabel();
1350 if (filename[0] && strcmp(filename, input->init_str)) {
1351 dstr = dStr_new(filename);
1352 dstr = encodeText(char_encoder, &dstr);
1353 dStr_append_l(DataStr, dstr->str, dstr->len);
1354 dStr_free(dstr, 1);
1355 }
1356 }
1357 int length = dList_length(values);
1358 for (int i = 0; i < length; i++) {
1359 dstr = (Dstr *) dList_nth_data(values, 0);
1360 dList_remove(values, dstr);
1361 if (input->type != DILLO_HTML_INPUT_FILE)
1362 dstr = encodeText(char_encoder, &dstr);
1363 dStr_append_l(DataStr, dstr->str, dstr->len);
1364 dStr_free(dstr, 1);
1365 }
1366 }
1367
1368 generate_boundary(boundary);
1369 ret = boundary->str;
1370 dList_free(values);
1371 dStr_free(DataStr, 1);
1372 dStr_free(boundary, (ret == NULL));
1373 return ret;
1374}
1375
1381Dstr *DilloHtmlForm::encodeText(iconv_t char_encoder, Dstr **input)
1382{
1383 int rc = 0;
1384 Dstr *output;
1385 const int bufsize = 128;
1386 inbuf_t *inPtr;
1387 char *buffer, *outPtr;
1388 size_t inLeft, outRoom;
1389 bool bad_chars = false;
1390
1391 if ((char_encoder == (iconv_t) -1) || *input == NULL || (*input)->len == 0)
1392 return *input;
1393
1394 output = dStr_new("");
1395 inPtr = (*input)->str;
1396 inLeft = (*input)->len;
1397 buffer = dNew(char, bufsize);
1398
1399 while ((rc != EINVAL) && (inLeft > 0)) {
1400
1401 outPtr = buffer;
1402 outRoom = bufsize;
1403
1404 rc = iconv(char_encoder, &inPtr, &inLeft, &outPtr, &outRoom);
1405
1406 // iconv() on success, number of bytes converted
1407 // -1, errno == EILSEQ illegal byte sequence found
1408 // EINVAL partial character ends source buffer
1409 // E2BIG destination buffer is full
1410 //
1411 // GNU iconv has the undocumented(!) behavior that EILSEQ is also
1412 // returned when a character cannot be converted.
1413
1414 dStr_append_l(output, buffer, bufsize - outRoom);
1415
1416 if (rc == -1) {
1417 rc = errno;
1418 }
1419 if (rc == EILSEQ){
1420 /* count chars? (would be utf-8-specific) */
1421 bad_chars = true;
1422 inPtr++;
1423 inLeft--;
1424 dStr_append_c(output, '?');
1425 } else if (rc == EINVAL) {
1426 MSG_ERR("Form encode text: bad source string.\n");
1427 }
1428 }
1429
1430 if (bad_chars) {
1431 /*
1432 * It might be friendly to inform the caller, who would know whether
1433 * it is safe to display the beginning of the string in a message
1434 * (isn't, e.g., a password).
1435 */
1436 MSG_WARN("Form encode text: string cannot be converted cleanly.\n");
1437 }
1438
1439 dFree(buffer);
1440 dStr_free(*input, 1);
1441
1442 return output;
1443}
1444
1448void DilloHtmlForm::strUrlencodeAppend(Dstr *dstr, const char *str)
1449{
1450 char *encoded = a_Url_encode_hex_str(str);
1451 dStr_append(dstr, encoded);
1452 dFree(encoded);
1453}
1454
1458void DilloHtmlForm::inputUrlencodeAppend(Dstr *data, const char *name,
1459 const char *value)
1460{
1461 if (name && name[0]) {
1462 strUrlencodeAppend(data, name);
1463 dStr_append_c(data, '=');
1464 strUrlencodeAppend(data, value);
1465 dStr_append_c(data, '&');
1466 }
1467}
1468
1473void DilloHtmlForm::filesInputMultipartAppend(Dstr* data,
1474 const char *boundary,
1475 const char *name,
1476 Dstr *file,
1477 const char *filename)
1478{
1479 const char *ctype, *ext;
1480
1481 if (name && name[0]) {
1482 (void)a_Misc_get_content_type_from_data(file->str, file->len, &ctype);
1483 /* Heuristic: text/plain with ".htm[l]" extension -> text/html */
1484 if ((ext = strrchr(filename, '.')) &&
1485 !dStrAsciiCasecmp(ctype, "text/plain") &&
1486 (!dStrAsciiCasecmp(ext, ".html") || !dStrAsciiCasecmp(ext, ".htm"))){
1487 ctype = "text/html";
1488 }
1489
1490 if (data->len == 0) {
1491 dStr_append(data, "--");
1492 dStr_append(data, boundary);
1493 }
1494 dStr_sprintfa(data,
1495 "\r\n"
1496 "Content-Disposition: form-data; name=\"%s\"; "
1497 "filename=\"", name);
1498 /*
1499 * Replace the characters that are the most likely to damage things.
1500 * For a while, there was some momentum to standardize on an encoding,
1501 * but HTML5/Ian Hickson/his Google masters are, as of late 2012,
1502 * evidently standing in opposition to all of that for some reason.
1503 */
1504 for (int i = 0; char c = filename[i]; i++) {
1505 if (c == '\"' || c == '\r' || c == '\n')
1506 c = '_';
1507 dStr_append_c(data, c);
1508 }
1509 dStr_sprintfa(data,
1510 "\"\r\n"
1511 "Content-Type: %s\r\n"
1512 "\r\n", ctype);
1513
1514 dStr_append_l(data, file->str, file->len);
1515
1516 dStr_sprintfa(data,
1517 "\r\n"
1518 "--%s", boundary);
1519 }
1520}
1521
1525void DilloHtmlForm::inputMultipartAppend(Dstr *data,
1526 const char *boundary,
1527 const char *name,
1528 const char *value)
1529{
1530 if (name && name[0]) {
1531 if (data->len == 0) {
1532 dStr_append(data, "--");
1533 dStr_append(data, boundary);
1534 }
1535 dStr_sprintfa(data,
1536 "\r\n"
1537 "Content-Disposition: form-data; name=\"%s\"\r\n"
1538 "\r\n"
1539 "%s\r\n"
1540 "--%s",
1541 name, value, boundary);
1542 }
1543}
1544
1548void DilloHtmlForm::imageInputUrlencodeAppend(Dstr *data, Dstr *name, Dstr *x,
1549 Dstr *y)
1550{
1551 if (name->len) {
1552 strUrlencodeAppend(data, name->str);
1553 dStr_sprintfa(data, ".x=%s&", x->str);
1554 strUrlencodeAppend(data, name->str);
1555 dStr_sprintfa(data, ".y=%s&", y->str);
1556 } else
1557 dStr_sprintfa(data, "x=%s&y=%s&", x->str, y->str);
1558}
1559
1563void DilloHtmlForm::imageInputMultipartAppend(Dstr *data, const char *boundary,
1564 Dstr *name, Dstr *x, Dstr *y)
1565{
1566 int orig_len = name->len;
1567
1568 if (orig_len)
1569 dStr_append_c(name, '.');
1570 dStr_append_c(name, 'x');
1571
1572 inputMultipartAppend(data, boundary, name->str, x->str);
1573 dStr_truncate(name, name->len - 1);
1574 dStr_append_c(name, 'y');
1575 inputMultipartAppend(data, boundary, name->str, y->str);
1576 dStr_truncate(name, orig_len);
1577}
1578
1583void DilloHtmlForm::reset ()
1584{
1585 int size = inputs->size();
1586 for (int i = 0; i < size; i++)
1587 inputs->get(i)->reset();
1588}
1589
1593void DilloHtmlForm::display_hiddens(bool display)
1594{
1595 int size = inputs->size();
1596 for (int i = 0; i < size; i++) {
1597 DilloHtmlInput *input = inputs->get(i);
1598 if (input->type == DILLO_HTML_INPUT_HIDDEN) {
1599 input->embed->setDisplayed(display);
1600 }
1601 }
1602 showing_hiddens = display;
1603}
1604
1605void DilloHtmlForm::setEnabled(bool enabled)
1606{
1607 for (int i = 0; i < inputs->size(); i++)
1608 inputs->get(i)->setEnabled(enabled);
1609}
1610
1614void DilloHtmlForm::addInput(DilloHtmlInput *input, DilloHtmlInputType type)
1615{
1616 input->connectTo (form_receiver);
1617 input->setEnabled (enabled);
1618 int ni = inputs->size ();
1619 inputs->increase ();
1620 inputs->set (ni,input);
1621
1622 /* some stats */
1623 if (type == DILLO_HTML_INPUT_PASSWORD ||
1624 type == DILLO_HTML_INPUT_TEXT) {
1625 num_entry_fields++;
1626 }
1627}
1628
1632DilloHtmlInput *DilloHtmlForm::getInput (Resource *resource)
1633{
1634 if (resource == NULL)
1635 return NULL;
1636
1637 for (int idx = 0; idx < inputs->size(); idx++) {
1638 DilloHtmlInput *input = inputs->get(idx);
1639 Resource *r = input->getResource();
1640 if (r && resource == r)
1641 return input;
1642 }
1643 return NULL;
1644}
1645
1649DilloHtmlInput *DilloHtmlForm::getRadioInput (const char *name)
1650{
1651 for (int idx = 0; idx < inputs->size(); idx++) {
1652 DilloHtmlInput *input = inputs->get(idx);
1653 if (input->type == DILLO_HTML_INPUT_RADIO &&
1654 input->name && !dStrAsciiCasecmp(input->name, name))
1655 return input;
1656 }
1657 return NULL;
1658}
1659
1660/*
1661 * DilloHtmlReceiver
1662 *
1663 * TODO: Currently there's "clicked" for buttons, we surely need "enter" for
1664 * textentries, and maybe the "mouseover, ...." set for Javascript.
1665 */
1666
1667void DilloHtmlReceiver::activate (Resource *resource)
1668{
1669 form->eventHandler(resource, NULL);
1670}
1671
1676void DilloHtmlReceiver::enter (Resource *resource)
1677{
1678 DilloHtml *html = form->html;
1679 DilloHtmlInput *input = form->getInput(resource);
1680 const char *msg = "";
1681
1682 if ((input->type == DILLO_HTML_INPUT_SUBMIT) ||
1683 (input->type == DILLO_HTML_INPUT_IMAGE) ||
1684 (input->type == DILLO_HTML_INPUT_BUTTON_SUBMIT) ||
1685 (input->type == DILLO_HTML_INPUT_INDEX) ||
1686 ((prefs.enterpress_forces_submit || form->num_entry_fields == 1) &&
1687 ((input->type == DILLO_HTML_INPUT_PASSWORD) ||
1688 (input->type == DILLO_HTML_INPUT_TEXT)))) {
1689 /* The control can submit form. Show action URL. */
1690 msg = URL_STR(form->action);
1691 }
1692 a_UIcmd_set_msg(html->bw, "%s", msg);
1693}
1694
1698void DilloHtmlReceiver::leave (Resource *resource)
1699{
1700 DilloHtml *html = form->html;
1701 a_UIcmd_set_msg(html->bw, "");
1702}
1703
1704void DilloHtmlReceiver::clicked (Resource *resource,
1705 EventButton *event)
1706{
1707 form->eventHandler(resource, event);
1708}
1709
1710/*
1711 * DilloHtmlInput
1712 */
1713
1714/*
1715 * Constructor
1716 */
1717DilloHtmlInput::DilloHtmlInput (DilloHtmlInputType type2, Embed *embed2,
1718 const char *name2, const char *init_str2,
1719 bool init_val2)
1720{
1721 type = type2;
1722 embed = embed2; /* May be NULL! */
1723 name = (name2) ? dStrdup(name2) : NULL;
1724 init_str = (init_str2) ? dStrdup(init_str2) : NULL;
1725 init_val = init_val2;
1726 select = NULL;
1727 switch (type) {
1730 select = new DilloHtmlSelect;
1731 break;
1732 default:
1733 break;
1734 }
1735 file_data = NULL;
1736 reset ();
1737}
1738
1739/*
1740 * Destructor
1741 */
1742DilloHtmlInput::~DilloHtmlInput ()
1743{
1744 /* Embed is not released here */
1745 dFree(name);
1746 dFree(init_str);
1747 dStr_free(file_data, 1);
1748 if (select)
1749 delete select;
1750}
1751
1755void DilloHtmlInput::connectTo(DilloHtmlReceiver *form_receiver)
1756{
1757 Resource *resource = getResource();
1758 if (resource) {
1759 resource->connectClicked (form_receiver);
1760 if (type == DILLO_HTML_INPUT_SUBMIT ||
1761 type == DILLO_HTML_INPUT_RESET ||
1764 type == DILLO_HTML_INPUT_IMAGE ||
1765 type == DILLO_HTML_INPUT_FILE ||
1766 type == DILLO_HTML_INPUT_TEXT ||
1767 type == DILLO_HTML_INPUT_PASSWORD ||
1768 type == DILLO_HTML_INPUT_INDEX) {
1769 resource->connectActivate (form_receiver);
1770 }
1771 }
1772}
1773
1777void DilloHtmlInput::activate(DilloHtmlForm *form, int num_entry_fields,
1778 EventButton *event)
1779{
1780 switch (type) {
1782 readFile (form->html->bw);
1783 break;
1786 form->reset();
1787 break;
1790 if (!(prefs.enterpress_forces_submit || num_entry_fields == 1)) {
1791 break;
1792 }
1793 /* fallthrough */
1798 form->submit(this, event);
1799 break;
1800 default:
1801 break;
1802 }
1803}
1804
1808void DilloHtmlInput::readFile (BrowserWindow *bw)
1809{
1810 const char *filename = a_UIcmd_select_file();
1811 if (filename) {
1812 a_UIcmd_set_msg(bw, "Loading file...");
1813 dStr_free(file_data, 1);
1814 file_data = a_Misc_file2dstr(filename);
1815 if (file_data) {
1816 a_UIcmd_set_msg(bw, "File loaded.");
1818 lbr->setLabel(filename);
1819 } else {
1820 a_UIcmd_set_msg(bw, "ERROR: can't load: %s", filename);
1821 }
1822 }
1823}
1824
1828void DilloHtmlInput::appendValuesTo(Dlist *values, bool is_active_submit)
1829{
1830 switch (type) {
1835 {
1836 EntryResource *entryres = (EntryResource*)embed->getResource();
1837 dList_append(values, dStr_new(entryres->getText()));
1838 }
1839 break;
1841 {
1842 MultiLineTextResource *textres =
1844 dList_append(values, dStr_new(textres->getText()));
1845 }
1846 break;
1849 {
1850 ToggleButtonResource *cb_r =
1852 if (name && init_str && cb_r->isActivated()) {
1853 dList_append(values, dStr_new(init_str));
1854 }
1855 }
1856 break;
1859 if (is_active_submit)
1860 dList_append(values, dStr_new(init_str));
1861 break;
1864 {
1865 SelectionResource *sel_res = (SelectionResource*)embed->getResource();
1866 select->appendValuesTo (values, sel_res);
1867 }
1868 break;
1870 {
1872 const char *filename = lbr->getLabel();
1873 if (filename[0] && strcmp(filename, init_str)) {
1874 if (file_data) {
1875 Dstr *file = dStr_sized_new(file_data->len);
1876 dStr_append_l(file, file_data->str, file_data->len);
1877 dList_append(values, file);
1878 } else {
1879 MSG("FORM file input \"%s\" not loaded.\n", filename);
1880 }
1881 }
1882 }
1883 break;
1885 if (is_active_submit) {
1888 Dstr *strX = dStr_new("");
1889 Dstr *strY = dStr_new("");
1890 dStr_sprintf(strX, "%d", cbr->getClickX());
1891 dStr_sprintf(strY, "%d", cbr->getClickY());
1892 dList_append(values, strX);
1893 dList_append(values, strY);
1894 }
1895 break;
1896 default:
1897 break;
1898 }
1899}
1900
1904void DilloHtmlInput::reset ()
1905{
1906 if (embed == NULL || embed->getResource() == NULL)
1907 return;
1908
1909 switch (type) {
1914 {
1915 EntryResource *entryres = (EntryResource*)embed->getResource();
1916 entryres->setText(init_str ? init_str : "");
1917 }
1918 break;
1921 {
1922 ToggleButtonResource *tb_r =
1924 tb_r->setActivated(init_val);
1925 }
1926 break;
1929 if (select != NULL) {
1931 select->reset(sr);
1932 }
1933 break;
1935 if (init_str != NULL) {
1936 MultiLineTextResource *textres =
1938 textres->setText(init_str ? init_str : "");
1939 }
1940 break;
1942 {
1944 lbr->setLabel(init_str);
1945 }
1946 break;
1947 default:
1948 break;
1949 }
1950}
1951
1952/*
1953 * DilloHtmlSelect
1954 */
1955
1956/*
1957 * Constructor
1958 */
1959DilloHtmlSelect::DilloHtmlSelect ()
1960{
1962}
1963
1964/*
1965 * Destructor
1966 */
1967DilloHtmlSelect::~DilloHtmlSelect ()
1968{
1969 int size = opts->size ();
1970 for (int k = 0; k < size; k++)
1971 delete opts->get (k);
1972 delete opts;
1973}
1974
1975DilloHtmlOptbase *DilloHtmlSelect::getCurrentOpt ()
1976{
1977 return opts->get (opts->size() - 1);
1978}
1979
1980void DilloHtmlSelect::addOpt (DilloHtmlOptbase *opt)
1981{
1982 int size = opts->size ();
1983 opts->increase ();
1984 opts->set (size, opt);
1985}
1986
1990void DilloHtmlSelect::ensureSelection()
1991{
1992 int size = opts->size ();
1993 if (size > 0) {
1994 for (int i = 0; i < size; i++) {
1995 DilloHtmlOptbase *opt = opts->get (i);
1996 if (opt->isSelected())
1997 return;
1998 }
1999 for (int i = 0; i < size; i++) {
2000 DilloHtmlOptbase *opt = opts->get (i);
2001 if (opt->select())
2002 break;
2003 }
2004 }
2005}
2006
2007void DilloHtmlSelect::addOptsTo (SelectionResource *res)
2008{
2009 int size = opts->size ();
2010 for (int i = 0; i < size; i++) {
2011 DilloHtmlOptbase *opt = opts->get (i);
2012 opt->addSelf(res);
2013 }
2014}
2015
2016void DilloHtmlSelect::reset (SelectionResource *res)
2017{
2018 int size = opts->size ();
2019 for (int i = 0; i < size; i++) {
2020 DilloHtmlOptbase *opt = opts->get (i);
2021 res->setItem(i, opt->isSelected());
2022 }
2023}
2024
2025void DilloHtmlSelect::appendValuesTo (Dlist *values, SelectionResource *res)
2026{
2027 int size = opts->size ();
2028 for (int i = 0; i < size; i++) {
2029 if (res->isSelected (i)) {
2030 DilloHtmlOptbase *opt = opts->get (i);
2031 const char *val = opt->getValue();
2032
2033 if (val)
2034 dList_append(values, dStr_new(val));
2035 }
2036 }
2037}
2038
2039DilloHtmlOptgroup::DilloHtmlOptgroup (char *label, bool enabled)
2040{
2041 this->label = label;
2042 this->enabled = enabled;
2043}
2044
2045DilloHtmlOptgroup::~DilloHtmlOptgroup ()
2046{
2047 dFree(label);
2048}
2049
2050/*
2051 * DilloHtmlOption
2052 */
2053
2054/*
2055 * Constructor
2056 */
2057DilloHtmlOption::DilloHtmlOption (char *value2, char *label2, bool selected2,
2058 bool enabled2)
2059{
2060 value = value2;
2061 label = label2;
2062 content = NULL;
2063 selected = selected2;
2064 enabled = enabled2;
2065}
2066
2067/*
2068 * Destructor
2069 */
2070DilloHtmlOption::~DilloHtmlOption ()
2071{
2072 dFree(value);
2073 dFree(label);
2074 dFree(content);
2075}
2076
2077/*
2078 * Utilities
2079 */
2080
2084static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize)
2085{
2087 Embed *button = NULL;
2088
2089 assert(a_Html_should_display(html));
2090
2091 html->styleEngine->setPseudoLink ();
2092
2093 /* create new image and add it to the button */
2094 a_Html_common_image_attrs(html, tag, tagsize);
2095 if ((Image = a_Html_image_new(html, tag, tagsize))) {
2096 // At this point, we know that Image->ir represents an image
2097 // widget. Notice that the order of the casts matters, because
2098 // of multiple inheritance.
2099 dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)Image->img_rndr;
2100 dwi->setStyle (html->backgroundStyle ());
2101 ResourceFactory *factory = HT2LT(html)->getResourceFactory();
2102 ComplexButtonResource *complex_b_r =
2103 factory->createComplexButtonResource(dwi, false);
2104 button = new Embed(complex_b_r);
2105 HT2TB(html)->addWidget (button, html->style ());
2106 }
2107 if (!button)
2108 MSG("Html_input_image: unable to create image submit.\n");
2109 return button;
2110}
2111
2112/*
2113 * ?
2114 */
2116{
2117 DilloHtmlInput *input = Html_get_current_input(html);
2118 if (input &&
2119 (input->type == DILLO_HTML_INPUT_SELECT ||
2120 input->type == DILLO_HTML_INPUT_SEL_LIST)) {
2121 DilloHtmlOptbase *opt = input->select->getCurrentOpt ();
2122 opt->setContent (html->Stash->str, html->Stash->len);
2123 }
2124}
#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:28
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:576
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:641
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:690
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:625
void dList_free(Dlist *lp)
Free a list (not its elements)
Definition dlib.c:592
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:669
#define FALSE
Definition dlib.h:31
#define dNew(type, count)
Definition dlib.h:61
#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:4288
void a_Html_stash_init(DilloHtml *html)
Initialize the stash buffer.
Definition html.cc:853
bool a_Html_should_display(DilloHtml *html)
Definition html.cc:4029
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:2143
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:2073
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:4302
char * a_Html_parse_entities(DilloHtml *html, const char *token, int toksize)
Parse all the entities in a token.
Definition html.cc:1080
#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:407
void a_Html_form_display_hiddens2(void *vform, bool display)
Definition form.cc:267
void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:655
void Html_tag_content_textarea(DilloHtml *html, const char *tag, int tagsize)
The textarea tag.
Definition form.cc:665
void Html_tag_close_button(DilloHtml *html)
Handle close <BUTTON>
Definition form.cc:1023
void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:916
static void Html_option_finish(DilloHtml *html)
Definition form.cc:2115
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:279
DilloHtmlForm * a_Html_form_new(DilloHtml *html, DilloHtmlMethod method, const DilloUrl *action, DilloHtmlEnc content_type, const char *charset, bool enabled)
Definition form.cc:238
static int Html_input_get_size(DilloHtml *html, const char *attrbuf)
get size, restrict it to reasonable value
Definition form.cc:418
void Html_tag_open_optgroup(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:856
void a_Html_form_reset2(void *vform)
Definition form.cc:262
void a_Html_form_delete(DilloHtmlForm *form)
Definition form.cc:247
void a_Html_input_delete(DilloHtmlInput *input)
Definition form.cc:252
static DilloHtmlInput * Html_get_current_input(DilloHtml *html)
Get the current input if available.
Definition form.cc:325
void Html_tag_close_select(DilloHtml *html)
Definition form.cc:834
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:614
void Html_tag_close_optgroup(DilloHtml *html)
Definition form.cc:892
void Html_tag_close_textarea(DilloHtml *html)
Close textarea.
Definition form.cc:729
void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:770
static void generate_boundary(Dstr *boundary)
Generate a random boundary.
Definition form.cc:1307
static Embed * Html_input_image(DilloHtml *html, const char *tag, int tagsize)
Create input image for the form.
Definition form.cc:2084
void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
Add a new input to current form.
Definition form.cc:437
void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize)
Definition form.cc:955
void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
Handle <FORM> tag.
Definition form.cc:341
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:302
void a_Html_form_submit2(void *vform)
Definition form.cc:257
void Html_tag_close_option(DilloHtml *html)
Definition form.cc:944
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:113
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:114
Definition url.h:88
Definition dlib.h:144
Definition dlib.h:114
Dstr_char_t * str
Definition dlib.h:117
int len
Definition dlib.h:116
void a_UIcmd_set_msg(BrowserWindow *bw, const char *format,...)
Definition uicmd.cc:1609
void a_UIcmd_form_popup(void *vbw, const DilloUrl *url, void *vform, bool_t showing_hiddens)
Definition uicmd.cc:1333
void a_UIcmd_open_url_nw(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:846
const char * a_UIcmd_select_file()
Definition uicmd.cc:1162
void a_UIcmd_open_url(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:811
void a_UIcmd_open_url_nt(void *vbw, const DilloUrl *url, int focus)
Definition uicmd.cc:862
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