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