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