changeset 172:765db4e71128

- Implemented the file input control for forms (work in progress).
author jcid
date Fri, 11 Apr 2008 14:51:23 +0200
parents d6eefa9091ee
children e6c3455abb1c
files ChangeLog src/dialog.cc src/dialog.hh src/html.cc src/uicmd.cc src/uicmd.hh
diffstat 6 files changed, 124 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Apr 11 00:05:19 2008 +0200
+++ b/ChangeLog	Fri Apr 11 14:51:23 2008 +0200
@@ -90,6 +90,7 @@
  - Fixed a bug in Cookies_parse_one. Set it to a single return point too!
  - Added dStr_memmem() and dStr_printable() to dlib.
  - Split Html_append_input() into smaller functions.
+ - Implemented the file input control for forms (work in progress).
    Patches: place
 +- Fixed a problem with locally-installed dpis.
  - Added code for optional image loading (nice interface) very advanced!
--- a/src/dialog.cc	Fri Apr 11 00:05:19 2008 +0200
+++ b/src/dialog.cc	Fri Apr 11 14:51:23 2008 +0200
@@ -81,6 +81,21 @@
    return file_chooser(msg, pattern, fname);
 }
 
+/*
+ * Show the select file dialog.
+ *
+ * Return: pointer to chosen filename, or NULL on Cancel.
+ */
+const char *a_Dialog_select_file(const char *msg,
+                                 const char *pattern, const char *fname)
+{
+   /*
+    * FileChooser::type(MULTI) appears to allow multiple files to be selected,
+    * but just follow save_file's path for now.
+    */
+   return a_Dialog_save_file(msg, pattern, fname);
+}
+
 //#include <fltk/FileIcon.h>
 /*
  * Show the open file dialog.
--- a/src/dialog.hh	Fri Apr 11 00:05:19 2008 +0200
+++ b/src/dialog.hh	Fri Apr 11 14:51:23 2008 +0200
@@ -16,6 +16,8 @@
 const char *a_Dialog_input(const char *msg);
 const char *a_Dialog_save_file(const char *msg,
                                const char *pattern, const char *fname);
+const char *a_Dialog_select_file(const char *msg,
+                                 const char *pattern, const char *fname);
 char *a_Dialog_open_file(const char *msg,
                          const char *pattern, const char *fname);
 void a_Dialog_text_window(const char *txt, const char *title);
--- a/src/html.cc	Fri Apr 11 00:05:19 2008 +0200
+++ b/src/html.cc	Fri Apr 11 14:51:23 2008 +0200
@@ -3749,6 +3749,12 @@
          textres->setText(input->init_str ? input->init_str : "");
       }
       break;
+   case DILLO_HTML_INPUT_FILE:
+   {  LabelButtonResource *lbr =
+         (LabelButtonResource *)((Embed*)input->widget)->getResource();
+      lbr->setLabel(input->init_str);
+      break;
+   }
    default:
       break;
    }
@@ -4053,9 +4059,26 @@
 //    }
 //    break;
    case DILLO_HTML_INPUT_FILE:
-      MSG("Data from file input not submitted\n");
-      // If multiple files are submitted, use multipart/mixed.
+   {  LabelButtonResource *lbr =
+         (LabelButtonResource*)((Embed*)input->widget)->getResource();
+      const char *filename = lbr->getLabel();
+      if (filename[0] && strcmp(filename, input->init_str)) {
+         char *buf;
+         int buf_size;
+         char *escaped_name = a_Misc_escape_chars(filename, "% ");
+         DilloUrl *url = a_Url_new(escaped_name, "file:///", 0, 0, 0);
+         if (a_Capi_get_buf(url, &buf, &buf_size)) {
+            Dstr *file = dStr_sized_new(buf_size);
+            dStr_append_l(file, buf, buf_size);
+            dList_append(values, file);
+         } else {
+            MSG("form file input \"%s\" not loaded.\n", filename);
+         }
+         a_Url_free(url);
+         dFree(escaped_name);
+      }
       break;
+   }
    default:
       break;
    }
@@ -4074,7 +4097,7 @@
    Dstr *boundary = dStr_new("");
    char *ret = NULL;
 
-   /* fill DataStr with names and values */
+   /* fill DataStr with names, filenames, and values */
    for (int input_idx = 0; input_idx < form->inputs->size(); input_idx++) {
       Dstr *dstr;
       DilloHtmlInput *input = form->inputs->getRef (input_idx);
@@ -4087,6 +4110,17 @@
          dStr_append_l(DataStr, dstr->str, dstr->len);
          dStr_free(dstr, 1);
       }
+      if (input->type == DILLO_HTML_INPUT_FILE) {
+         LabelButtonResource *lbr =
+            (LabelButtonResource*)((Embed*)input->widget)->getResource();
+         const char *filename = lbr->getLabel();
+         if (filename[0] && strcmp(filename, input->init_str)) {
+            dstr = dStr_new(filename);
+            dstr = Html_encode_text(encoder, dstr);
+            dStr_append_l(DataStr, dstr->str, dstr->len);
+            dStr_free(dstr, 1);
+         }
+      }
       for (int i = 0; i < dList_length(values); i++) {
          dstr = (Dstr *) dList_nth_data(values, 0);
          dList_remove(values, dstr);
@@ -4151,7 +4185,26 @@
 
          if (input->type == DILLO_HTML_INPUT_FILE &&
              dList_length(values) > 0) {
-            /* nothing at the moment */
+            if (dList_length(values) > 1)
+               MSG_WARN("multiple files per form control not supported\n");
+            Dstr *file = (Dstr *) dList_nth_data(values, 0);
+            dList_remove(values, file);
+
+            /* Get filename and encode it. Do not encode file contents. */
+            LabelButtonResource *lbr =
+               (LabelButtonResource*)((Embed*)input->widget)->getResource();
+            const char *filename = lbr->getLabel();
+            if (filename[0] && strcmp(filename, input->init_str)) {
+               char *p = strrchr(filename, '/');
+               if (p)
+                  filename = p + 1;     /* don't reveal path */
+               Dstr *dfilename = dStr_new(filename);
+               dfilename = Html_encode_text(encoder, dfilename);
+               Html_append_input_multipart_files(DataStr, boundary,
+                                      name->str, file, dfilename->str);
+               dStr_free(dfilename, 1);
+               dStr_free(file, 1);
+            }
          } else {
             for (int i = 0; i < dList_length(values); i++) {
                Dstr *val = (Dstr *) dList_nth_data(values, 0);
@@ -4250,6 +4303,19 @@
 }
 
 /*
+ * Callback used when getting a file for form input.
+ */
+static void Html_get_file_cb(int Op, CacheClient_t *Client)
+{
+   DilloWeb *web = (DilloWeb *)Client->Web;
+   LabelButtonResource *lbr = (LabelButtonResource *)Client->CbData;
+   if (Op) {
+      lbr->setLabel(URL_PATH(Client->Url));
+      a_UIcmd_set_msg(web->bw, "File loaded.");
+   }
+}
+
+/*
  * Handler for events related to forms.
  *
  * TODO: Currently there's "clicked" for buttons, we surely need "enter" for
@@ -4261,6 +4327,7 @@
 {
    int form_index, input_idx = -1, idx;
    DilloHtmlForm *form = NULL;
+   DilloHtmlInput *input;
    DilloHtml *html = (DilloHtml*)data;
 
    MSG("Html_form_event_handler %p %p\n", html, form_receiver);
@@ -4271,7 +4338,7 @@
       if (form->form_receiver == form_receiver) {
          /* form found, let's get the input index for this event */
          for (idx = 0; idx < form->inputs->size(); idx++) {
-            DilloHtmlInput *input = form->inputs->getRef(idx);
+            input = form->inputs->getRef(idx);
             if (input->embed &&
                 v_resource == (void*)((Embed*)input->widget)->getResource()) {
                input_idx = idx;
@@ -4284,7 +4351,24 @@
    if (form_index == html->forms->size()) {
       MSG("a_Html_form_event_handler: ERROR, form not found!\n");
    } else {
-      Html_submit_form2(html, form, input_idx);
+      if (input->type == DILLO_HTML_INPUT_FILE) {
+         /* read the file into cache */
+         const char *filename = a_UIcmd_select_file();
+         if (filename) {
+            LabelButtonResource *lbr =
+               (LabelButtonResource*)((Embed*)input->widget)->getResource();
+            char *escaped_name = a_Misc_escape_chars(filename, "% ");
+            DilloUrl *url = a_Url_new(escaped_name, "file:///", URL_E2EReload,
+                                      0, 0);
+            DilloWeb *web = a_Web_new(url);
+            web->bw = html->bw;
+            a_Capi_open_url(web, Html_get_file_cb, lbr);
+            a_Url_free(url);
+            dFree(escaped_name);
+         }
+      } else {
+         Html_submit_form2(html, form, input_idx);
+      }
    }
 }
 
@@ -4468,9 +4552,13 @@
          MSG("File input ignored in form not using multipart/form-data"
              " encoding\n");
       } else {
-//       inp_type = DILLO_HTML_INPUT_FILE;
-//       init_str = (value) ? value : NULL;
-         MSG("An input of the type \"file\" wasn't rendered!\n");
+         inp_type = DILLO_HTML_INPUT_FILE;
+         init_str = dStrdup("File selector");
+         LabelButtonResource *lbr =
+            HT2LT(html)->getResourceFactory()->
+               createLabelButtonResource(init_str);
+         widget = embed = new Embed (lbr);
+         lbr->connectClicked(form->form_receiver);
       }
    } else if (!dStrcasecmp(type, "button")) {
       inp_type = DILLO_HTML_INPUT_BUTTON;
--- a/src/uicmd.cc	Fri Apr 11 00:05:19 2008 +0200
+++ b/src/uicmd.cc	Fri Apr 11 14:51:23 2008 +0200
@@ -317,6 +317,14 @@
 }
 
 /*
+ * Select a file
+ */
+const char *a_UIcmd_select_file()
+{
+   return a_Dialog_select_file("Select a File", NULL, NULL);
+}
+
+/*
  * Stop network activity on this bw.
  * The stop button was pressed: stop page (and images) downloads.
  */
--- a/src/uicmd.hh	Fri Apr 11 00:05:19 2008 +0200
+++ b/src/uicmd.hh	Fri Apr 11 14:51:23 2008 +0200
@@ -22,6 +22,7 @@
 void a_UIcmd_stop(void *vbw);
 void a_UIcmd_save_link(BrowserWindow *bw, const DilloUrl *url);
 void a_UIcmd_open_file(void *vbw);
+const char *a_UIcmd_select_file();
 void a_UIcmd_open_url_dialog(void *vbw);
 void a_UIcmd_search_dialog(void *vbw);
 void a_UIcmd_book(void *vbw);