diff options
author | Rodrigo Arias Mallo <rodarima@gmail.com> | 2025-08-30 15:16:14 +0200 |
---|---|---|
committer | Rodrigo Arias Mallo <rodarima@gmail.com> | 2025-08-30 16:08:34 +0200 |
commit | 73e52f3582329a5e222884a5eaea9f3e21c9a321 (patch) | |
tree | 3aa91553ab852ac70a63f8218380922b80dc8ff3 /src/form.cc | |
parent | 79c10b34b38b5e10c2c5d3c7feb6ac6dfb2979fb (diff) |
Avoid new Embed or Resource on invisible inputs
When an input element should not be displayed due to display:none, don't
allocate the Resource or the Embed directly. It won't be added to the
Widget tree either. This prevents allocating Resources that are not tied
to a Widget so they are not leaked when the tree is destroyed.
The Embed or Resource elements won't be needed as the DilloHtmlInput
handles all the form logic.
Diffstat (limited to 'src/form.cc')
-rw-r--r-- | src/form.cc | 213 |
1 files changed, 129 insertions, 84 deletions
diff --git a/src/form.cc b/src/form.cc index fe7376c5..3a93d4c6 100644 --- a/src/form.cc +++ b/src/form.cc @@ -142,9 +142,11 @@ class DilloHtmlInput { // DilloHtmlForm::addInput() calls connectTo() friend class DilloHtmlForm; +private: + Embed *embed; /* May be NULL (think: hidden input) */ + public: //BUG: for now everything is public DilloHtmlInputType type; - Embed *embed; /* May be NULL (think: hidden input) */ char *name; char *init_str; /* note: some overloading - for buttons, init_str is simply the value of the button; for text @@ -166,6 +168,7 @@ public: void appendValuesTo(Dlist *values, bool is_active_submit); void reset(); void setEnabled(bool enabled) {if (embed) embed->setEnabled(enabled); }; + Resource *getResource() {if (embed) { return embed->getResource(); } else { return NULL; } }; }; class DilloHtmlOptbase @@ -464,35 +467,42 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) placeholder = a_Html_get_attr_wdef(html, tag,tagsize,"placeholder",NULL); attrbuf = a_Html_get_attr(html, tag, tagsize, "size"); int size = Html_input_get_size(html, attrbuf); - resource = factory->createEntryResource (size, true, NULL, placeholder); + if (a_Html_should_display(html)) + resource = factory->createEntryResource (size, true, NULL, placeholder); init_str = value; } else if (!dStrAsciiCasecmp(type, "checkbox")) { inp_type = DILLO_HTML_INPUT_CHECKBOX; - resource = factory->createCheckButtonResource(false); + if (a_Html_should_display(html)) + resource = factory->createCheckButtonResource(false); init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL); init_str = (value) ? value : dStrdup("on"); } else if (!dStrAsciiCasecmp(type, "radio")) { inp_type = DILLO_HTML_INPUT_RADIO; - RadioButtonResource *rb_r = NULL; - DilloHtmlInput *input = Html_get_radio_input(html, name); - if (input) - rb_r = (RadioButtonResource*) input->embed->getResource(); - resource = factory->createRadioButtonResource(rb_r, false); + if (a_Html_should_display(html)) { + RadioButtonResource *rb_r = NULL; + DilloHtmlInput *input = Html_get_radio_input(html, name); + if (input && input->getResource()) + rb_r = (RadioButtonResource*) input->getResource(); + resource = factory->createRadioButtonResource(rb_r, false); + } init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL); init_str = value; } else if (!dStrAsciiCasecmp(type, "hidden")) { inp_type = DILLO_HTML_INPUT_HIDDEN; init_str = value; int size = Html_input_get_size(html, NULL); - resource = factory->createEntryResource(size, false, name, NULL); + if (a_Html_should_display(html)) + resource = factory->createEntryResource(size, false, name, NULL); } else if (!dStrAsciiCasecmp(type, "submit")) { inp_type = DILLO_HTML_INPUT_SUBMIT; init_str = (value) ? value : dStrdup("Submit"); - resource = factory->createLabelButtonResource(init_str); + if (a_Html_should_display(html)) + resource = factory->createLabelButtonResource(init_str); } else if (!dStrAsciiCasecmp(type, "reset")) { inp_type = DILLO_HTML_INPUT_RESET; init_str = (value) ? value : dStrdup("Reset"); - resource = factory->createLabelButtonResource(init_str); + if (a_Html_should_display(html)) + resource = factory->createLabelButtonResource(init_str); } else if (!dStrAsciiCasecmp(type, "image")) { if (URL_FLAGS(html->base_url) & URL_SpamSafe) { /* Don't request the image; make a text submit button instead */ @@ -500,11 +510,13 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) attrbuf = a_Html_get_attr(html, tag, tagsize, "alt"); label = attrbuf ? attrbuf : value ? value : name ? name : "Submit"; init_str = dStrdup(label); - resource = factory->createLabelButtonResource(init_str); + if (a_Html_should_display(html)) + resource = factory->createLabelButtonResource(init_str); } else { inp_type = DILLO_HTML_INPUT_IMAGE; /* use a dw_image widget */ - embed = Html_input_image(html, tag, tagsize); + if (a_Html_should_display(html)) + embed = Html_input_image(html, tag, tagsize); init_str = value; } } else if (!dStrAsciiCasecmp(type, "file")) { @@ -526,13 +538,15 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) if (valid) { inp_type = DILLO_HTML_INPUT_FILE; init_str = dStrdup("File selector"); - resource = factory->createLabelButtonResource(init_str); + if (a_Html_should_display(html)) + resource = factory->createLabelButtonResource(init_str); } } else if (!dStrAsciiCasecmp(type, "button")) { inp_type = DILLO_HTML_INPUT_BUTTON; if (value) { init_str = value; - resource = factory->createLabelButtonResource(init_str); + if (a_Html_should_display(html)) + resource = factory->createLabelButtonResource(init_str); } } else { /* Text input, which also is the default */ @@ -540,9 +554,14 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) placeholder = a_Html_get_attr_wdef(html, tag,tagsize,"placeholder",NULL); attrbuf = a_Html_get_attr(html, tag, tagsize, "size"); int size = Html_input_get_size(html, attrbuf); - resource = factory->createEntryResource(size, false, NULL, placeholder); + if (a_Html_should_display(html)) + resource = factory->createEntryResource(size, false, NULL, placeholder); init_str = value; } + + /* Resource should not be set with display:none */ + assert(!resource || a_Html_should_display(html)); + if (resource) embed = new Embed (resource); @@ -551,6 +570,9 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) (init_str) ? init_str : "", init_val); } + /* Embed should not be set with display:none */ + assert(!embed || a_Html_should_display(html)); + if (embed != NULL && inp_type != DILLO_HTML_INPUT_IMAGE && inp_type != DILLO_HTML_INPUT_UNKNOWN) { if (inp_type == DILLO_HTML_INPUT_HIDDEN) { @@ -575,9 +597,7 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) attrbuf); } - /* Don't add to textbox if we are under a display:none element */ - if (a_Html_should_display(html)) - HT2TB(html)->addWidget (embed, html->backgroundStyle()); + HT2TB(html)->addWidget (embed, html->backgroundStyle()); } dFree(type); dFree(name); @@ -594,7 +614,6 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize) { DilloUrl *action; - Embed *embed; const char *attrbuf; if (html->InFlags & IN_FORM) { @@ -611,18 +630,23 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize) html->charset); html->InFlags |= IN_FORM; - HT2TB(html)->addParbreak (9, html->wordStyle ()); + Embed *embed = NULL; + + if (a_Html_should_display(html)) { + HT2TB(html)->addParbreak (9, html->wordStyle ()); - if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt"))) - HT2TB(html)->addText(attrbuf, html->wordStyle ()); + if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt"))) + HT2TB(html)->addText(attrbuf, html->wordStyle ()); - ResourceFactory *factory = HT2LT(html)->getResourceFactory(); - EntryResource *entryResource = factory->createEntryResource (20, false, - NULL, NULL); - embed = new Embed (entryResource); - Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE); + ResourceFactory *factory = HT2LT(html)->getResourceFactory(); + EntryResource *entryResource = factory->createEntryResource (20, false, + NULL, NULL); + embed = new Embed (entryResource); + + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); + } - HT2TB(html)->addWidget (embed, html->backgroundStyle ()); + Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE); a_Url_free(action); html->InFlags &= ~IN_FORM; @@ -679,18 +703,21 @@ void Html_tag_content_textarea(DilloHtml *html, const char *tag, int tagsize) attrbuf = a_Html_get_attr(html, tag, tagsize, "placeholder"); - ResourceFactory *factory = HT2LT(html)->getResourceFactory(); - MultiLineTextResource *textres = - factory->createMultiLineTextResource (cols, rows, attrbuf); + Embed *embed = NULL; + if (a_Html_should_display(html)) { + ResourceFactory *factory = HT2LT(html)->getResourceFactory(); + MultiLineTextResource *textres = + factory->createMultiLineTextResource (cols, rows, attrbuf); - Embed *embed = new Embed(textres); - /* Readonly or not? */ - if (a_Html_get_attr(html, tag, tagsize, "readonly")) - textres->setEditable(false); - Html_add_input(html, DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, false); + embed = new Embed(textres); + /* Readonly or not? */ + if (a_Html_get_attr(html, tag, tagsize, "readonly")) + textres->setEditable(false); - if (a_Html_should_display(html)) HT2TB(html)->addWidget (embed, html->backgroundStyle ()); + } + + Html_add_input(html, DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, false); dFree(name); } @@ -705,7 +732,7 @@ void Html_tag_close_textarea(DilloHtml *html) DilloHtmlInput *input; int i; - if (html->InFlags & IN_TEXTAREA && !S_TOP(html)->display_none) { + if (html->InFlags & IN_TEXTAREA && a_Html_should_display(html)) { /* Remove the line ending that follows the opening tag */ if (html->Stash->str[0] == '\r') dStr_erase(html->Stash, 0, 1); @@ -728,9 +755,10 @@ void Html_tag_close_textarea(DilloHtml *html) input = Html_get_current_input(html); if (input) { input->init_str = str; - ((MultiLineTextResource *)input->embed->getResource ())->setText(str); + Resource *res = input->getResource(); + if (res) + ((MultiLineTextResource *)res)->setText(str); } - } html->InFlags &= ~IN_TEXTAREA; } @@ -750,9 +778,6 @@ void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize) html->InFlags &= ~IN_OPTION; char *name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL); - ResourceFactory *factory = HT2LT(html)->getResourceFactory (); - DilloHtmlInputType type; - SelectionResource *res; bool multi = a_Html_get_attr(html, tag, tagsize, "multiple") != NULL; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size"))) { @@ -763,28 +788,40 @@ void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize) if (rows < 1) rows = multi ? 10 : 1; - if (rows == 1 && multi == false) { - type = DILLO_HTML_INPUT_SELECT; - res = factory->createOptionMenuResource (); - } else { - ListResource::SelectionMode mode; + DilloHtmlInputType type; + if (rows == 1 && multi == false) + type = DILLO_HTML_INPUT_SELECT; + else type = DILLO_HTML_INPUT_SEL_LIST; - mode = multi ? ListResource::SELECTION_MULTIPLE - : ListResource::SELECTION_AT_MOST_ONE; - res = factory->createListResource (mode, rows); - } - Embed *embed = new Embed(res); - if (prefs.show_tooltip && - (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { + Embed *embed = NULL; - html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, - attrbuf); - } + if (a_Html_should_display(html)) { + ResourceFactory *factory = HT2LT(html)->getResourceFactory (); + SelectionResource *res; + + if (type == DILLO_HTML_INPUT_SELECT) { + res = factory->createOptionMenuResource (); + } else { + ListResource::SelectionMode mode; + type = DILLO_HTML_INPUT_SEL_LIST; + mode = multi ? ListResource::SELECTION_MULTIPLE + : ListResource::SELECTION_AT_MOST_ONE; + res = factory->createListResource (mode, rows); + } + + embed = new Embed(res); + + if (prefs.show_tooltip && + (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { + + html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); + } - if (a_Html_should_display(html)) HT2TB(html)->addWidget (embed, html->backgroundStyle ()); + } Html_add_input(html, type, embed, name, NULL, false); a_Html_stash_init(html); @@ -809,7 +846,9 @@ void Html_tag_close_select(DilloHtml *html) // option menu interface requires that something be selected */ select->ensureSelection (); } - select->addOptsTo ((SelectionResource*)input->embed->getResource()); + /* May not have an embed or resource */ + if (input->getResource()) + select->addOptsTo ((SelectionResource*)input->getResource()); } } } @@ -965,12 +1004,7 @@ void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize) HT2TB(html)->addWidget (embed, html->backgroundStyle ()); S_TOP(html)->textblock = html->dw = page; } else { - /* If we are inside a display:none container, instead of - * creating a new hierarchy of elements, add a simple button. */ - Resource *resource = factory->createLabelButtonResource("dummy"); - embed = new Embed(resource); - /* Don't add the embed to the current textblock, it is only - * used to hold the name and value below. */ + embed = NULL; } /* Always add the input element, so is present in the form */ @@ -1197,18 +1231,20 @@ Dstr *DilloHtmlForm::buildQueryData(DilloHtmlInput *active_submit) dList_remove(values, file); /* Get filename and encode it. Do not encode file contents. */ - LabelButtonResource *lbr = - (LabelButtonResource*) input->embed->getResource(); - const char *filename = lbr->getLabel(); - if (filename[0] && strcmp(filename, input->init_str)) { - const char *p = strrchr(filename, '/'); - if (p) - filename = p + 1; /* don't reveal path */ - Dstr *dfilename = dStr_new(filename); - dfilename = encodeText(char_encoder, &dfilename); - filesInputMultipartAppend(DataStr, boundary, name->str, - file, dfilename->str); - dStr_free(dfilename, 1); + if (input->getResource()) { + LabelButtonResource *lbr = + (LabelButtonResource*) input->getResource(); + const char *filename = lbr->getLabel(); + if (filename[0] && strcmp(filename, input->init_str)) { + const char *p = strrchr(filename, '/'); + if (p) + filename = p + 1; /* don't reveal path */ + Dstr *dfilename = dStr_new(filename); + dfilename = encodeText(char_encoder, &dfilename); + filesInputMultipartAppend(DataStr, boundary, name->str, + file, dfilename->str); + dStr_free(dfilename, 1); + } } dStr_free(file, 1); } else if (input->type == DILLO_HTML_INPUT_INDEX) { @@ -1595,10 +1631,13 @@ void DilloHtmlForm::addInput(DilloHtmlInput *input, DilloHtmlInputType type) */ DilloHtmlInput *DilloHtmlForm::getInput (Resource *resource) { + if (resource == NULL) + return NULL; + for (int idx = 0; idx < inputs->size(); idx++) { DilloHtmlInput *input = inputs->get(idx); - if (input->embed && - resource == input->embed->getResource()) + Resource *r = input->getResource(); + if (r && resource == r) return input; } return NULL; @@ -1680,7 +1719,7 @@ DilloHtmlInput::DilloHtmlInput (DilloHtmlInputType type2, Embed *embed2, bool init_val2) { type = type2; - embed = embed2; + embed = embed2; /* May be NULL! */ name = (name2) ? dStrdup(name2) : NULL; init_str = (init_str2) ? dStrdup(init_str2) : NULL; init_val = init_val2; @@ -1702,6 +1741,7 @@ DilloHtmlInput::DilloHtmlInput (DilloHtmlInputType type2, Embed *embed2, */ DilloHtmlInput::~DilloHtmlInput () { + /* Embed is not released here */ dFree(name); dFree(init_str); dStr_free(file_data, 1); @@ -1714,8 +1754,8 @@ DilloHtmlInput::~DilloHtmlInput () */ void DilloHtmlInput::connectTo(DilloHtmlReceiver *form_receiver) { - Resource *resource; - if (embed && (resource = embed->getResource())) { + Resource *resource = getResource(); + if (resource) { resource->connectClicked (form_receiver); if (type == DILLO_HTML_INPUT_SUBMIT || type == DILLO_HTML_INPUT_RESET || @@ -1863,6 +1903,9 @@ void DilloHtmlInput::appendValuesTo(Dlist *values, bool is_active_submit) */ void DilloHtmlInput::reset () { + if (embed == NULL || embed->getResource() == NULL) + return; + switch (type) { case DILLO_HTML_INPUT_TEXT: case DILLO_HTML_INPUT_PASSWORD: @@ -2043,6 +2086,8 @@ static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize) DilloImage *Image; Embed *button = NULL; + assert(a_Html_should_display(html)); + html->styleEngine->setPseudoLink (); /* create new image and add it to the button */ |