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 | |
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.
-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 */ |