Merge pull request #1112 from oliverschmidt/master

Various improvements of the HTTP client and web browser.
This commit is contained in:
Oliver Schmidt 2015-06-14 16:12:24 +02:00
commit c9edb9006b
15 changed files with 215 additions and 158 deletions

View file

@ -9,7 +9,6 @@ html_a "a\0"
html_body "body\0" html_body "body\0"
html_br "br\0" html_br "br\0"
html_form "form\0" html_form "form\0"
html_frame "frame\0"
html_h1 "h1\0" html_h1 "h1\0"
html_h2 "h2\0" html_h2 "h2\0"
html_h3 "h3\0" html_h3 "h3\0"

View file

@ -31,9 +31,6 @@ const char html_br[4] =
const char html_form[6] = const char html_form[6] =
/* "form\0" */ /* "form\0" */
{0x66, 0x6f, 0x72, 0x6d, 00, }; {0x66, 0x6f, 0x72, 0x6d, 00, };
const char html_frame[7] =
/* "frame\0" */
{0x66, 0x72, 0x61, 0x6d, 0x65, 00, };
const char html_h1[4] = const char html_h1[4] =
/* "h1\0" */ /* "h1\0" */
{0x68, 0x31, 00, }; {0x68, 0x31, 00, };

View file

@ -9,7 +9,6 @@ extern const char html_a[3];
extern const char html_body[6]; extern const char html_body[6];
extern const char html_br[4]; extern const char html_br[4];
extern const char html_form[6]; extern const char html_form[6];
extern const char html_frame[7];
extern const char html_h1[4]; extern const char html_h1[4];
extern const char html_h2[4]; extern const char html_h2[4];
extern const char html_h3[4]; extern const char html_h3[4];

View file

@ -119,9 +119,6 @@ G * (<br>, <p>, <h>), the <li> tag (but does not even try to
#define ISO_eq 0x3d #define ISO_eq 0x3d
#define ISO_gt 0x3e #define ISO_gt 0x3e
#define ISO_rbrack 0x5b
#define ISO_lbrack 0x5d
#define MINORSTATE_NONE 0 #define MINORSTATE_NONE 0
#define MINORSTATE_TEXT 1 /* Parse normal text */ #define MINORSTATE_TEXT 1 /* Parse normal text */
#define MINORSTATE_EXTCHAR 2 /* Check for semi-colon */ #define MINORSTATE_EXTCHAR 2 /* Check for semi-colon */
@ -140,7 +137,7 @@ G * (<br>, <p>, <h>), the <li> tag (but does not even try to
#define MAJORSTATE_LINK 2 #define MAJORSTATE_LINK 2
#define MAJORSTATE_FORM 3 #define MAJORSTATE_FORM 3
#define MAJORSTATE_DISCARD 4 #define MAJORSTATE_DISCARD 4
#define MAJORSTATE_SCRIPT 5
struct htmlparser_state { struct htmlparser_state {
@ -151,7 +148,7 @@ struct htmlparser_state {
unsigned char tagattrptr; unsigned char tagattrptr;
char tagattrparam[WWW_CONF_MAX_URLLEN + 1]; char tagattrparam[WWW_CONF_MAX_URLLEN + 1];
unsigned char tagattrparamptr; unsigned char tagattrparamptr;
unsigned char lastchar, quotechar; unsigned char quotechar;
unsigned char majorstate, lastmajorstate; unsigned char majorstate, lastmajorstate;
char linkurl[WWW_CONF_MAX_URLLEN + 1]; char linkurl[WWW_CONF_MAX_URLLEN + 1];
@ -196,33 +193,31 @@ static const char *tags[] = {
html_br, html_br,
#define TAG_FORM 10 #define TAG_FORM 10
html_form, html_form,
#define TAG_FRAME 11 #define TAG_H1 11
html_frame,
#define TAG_H1 12
html_h1, html_h1,
#define TAG_H2 13 #define TAG_H2 12
html_h2, html_h2,
#define TAG_H3 14 #define TAG_H3 13
html_h3, html_h3,
#define TAG_H4 15 #define TAG_H4 14
html_h4, html_h4,
#define TAG_IMG 16 #define TAG_IMG 15
html_img, html_img,
#define TAG_INPUT 17 #define TAG_INPUT 16
html_input, html_input,
#define TAG_LI 18 #define TAG_LI 17
html_li, html_li,
#define TAG_P 19 #define TAG_P 18
html_p, html_p,
#define TAG_SCRIPT 20 #define TAG_SCRIPT 19
html_script, html_script,
#define TAG_SELECT 21 #define TAG_SELECT 20
html_select, html_select,
#define TAG_STYLE 22 #define TAG_STYLE 21
html_style, html_style,
#define TAG_TR 23 #define TAG_TR 22
html_tr, html_tr,
#define TAG_LAST 24 #define TAG_LAST 23
last, last,
}; };
@ -254,7 +249,7 @@ htmlparser_init(void)
{ {
s.majorstate = s.lastmajorstate = MAJORSTATE_DISCARD; s.majorstate = s.lastmajorstate = MAJORSTATE_DISCARD;
s.minorstate = MINORSTATE_TEXT; s.minorstate = MINORSTATE_TEXT;
s.lastchar = 0; s.wordlen = 0;
#if WWW_CONF_FORMS #if WWW_CONF_FORMS
s.formaction[0] = 0; s.formaction[0] = 0;
#endif /* WWW_CONF_FORMS */ #endif /* WWW_CONF_FORMS */
@ -305,10 +300,10 @@ do_word(void)
{ {
if(s.wordlen > 0) { if(s.wordlen > 0) {
if(s.majorstate == MAJORSTATE_LINK) { if(s.majorstate == MAJORSTATE_LINK) {
if(s.word[s.wordlen] != ISO_space) { if(s.word[s.wordlen - 1] != ISO_space) {
add_char(ISO_space); add_char(ISO_space);
} }
} else if(s.majorstate == MAJORSTATE_DISCARD) { } else if(s.majorstate >= MAJORSTATE_DISCARD) {
s.wordlen = 0; s.wordlen = 0;
} else { } else {
s.word[s.wordlen] = '\0'; s.word[s.wordlen] = '\0';
@ -368,13 +363,19 @@ static void
parse_tag(void) parse_tag(void)
{ {
static char *tagattrparam; static char *tagattrparam;
static unsigned char tag;
static unsigned char size; static unsigned char size;
static char dummy; tag = find_tag(s.tag);
/* If we are inside a <script> we mustn't interpret any tags
(inside JavaScript strings) but wait for the </script>. */
if(s.majorstate == MAJORSTATE_SCRIPT && tag != TAG_SLASHSCRIPT) {
return;
}
PRINTF(("Parsing tag '%s' '%s' '%s'\n", s.tag, s.tagattr, s.tagattrparam)); PRINTF(("Parsing tag '%s' '%s' '%s'\n", s.tag, s.tagattr, s.tagattrparam));
switch(find_tag(s.tag)) { switch(tag) {
case TAG_P: case TAG_P:
case TAG_H1: case TAG_H1:
case TAG_H2: case TAG_H2:
@ -386,15 +387,18 @@ parse_tag(void)
case TAG_TR: case TAG_TR:
case TAG_SLASHDIV: case TAG_SLASHDIV:
case TAG_SLASHH: case TAG_SLASHH:
dummy = 0;
newline(); newline();
break; break;
case TAG_LI: case TAG_LI:
newline(); if(s.tagattr[0] == 0) {
add_char(ISO_asterisk); newline();
add_char(ISO_space); add_char(ISO_asterisk);
add_char(ISO_space);
}
break; break;
case TAG_SCRIPT: case TAG_SCRIPT:
switch_majorstate(MAJORSTATE_SCRIPT);
break;
case TAG_STYLE: case TAG_STYLE:
case TAG_SELECT: case TAG_SELECT:
switch_majorstate(MAJORSTATE_DISCARD); switch_majorstate(MAJORSTATE_DISCARD);
@ -408,18 +412,6 @@ parse_tag(void)
case TAG_BODY: case TAG_BODY:
s.majorstate = s.lastmajorstate = MAJORSTATE_BODY; s.majorstate = s.lastmajorstate = MAJORSTATE_BODY;
break; break;
case TAG_FRAME:
if(strncmp(s.tagattr, html_src, sizeof(html_src)) == 0 && s.tagattrparam[0] != 0) {
switch_majorstate(MAJORSTATE_BODY);
newline();
add_char(ISO_rbrack);
do_word();
htmlparser_link((char *)html_frame, (unsigned char)strlen(html_frame), s.tagattrparam);
PRINTF(("Frame [%s]\n", s.tagattrparam));
add_char(ISO_lbrack);
newline();
}
break;
case TAG_IMG: case TAG_IMG:
if(strncmp(s.tagattr, html_alt, sizeof(html_alt)) == 0 && s.tagattrparam[0] != 0) { if(strncmp(s.tagattr, html_alt, sizeof(html_alt)) == 0 && s.tagattrparam[0] != 0) {
add_char(ISO_lt); add_char(ISO_lt);
@ -572,6 +564,15 @@ parse_word(char *data, uint8_t dlen)
} }
break; break;
case MINORSTATE_TAG: case MINORSTATE_TAG:
/* If we are inside a <srcipt> we mustn't mistake a JavaScript
equation with a '<' as a tag. So we check for the very next
character to be a '/' as we're only interested in parsing
the </script>. */
if(s.majorstate == MAJORSTATE_SCRIPT && data[0] != ISO_slash) {
s.minorstate = MINORSTATE_TEXT;
break;
}
/* We are currently parsing within the name of a tag. We check /* We are currently parsing within the name of a tag. We check
for the end of a tag (the '>' character) or whitespace (which for the end of a tag (the '>' character) or whitespace (which
indicates that we should parse a tag attr argument indicates that we should parse a tag attr argument

View file

@ -1,4 +1,5 @@
http_http "http://" http_http "http://"
http_https "https://"
http_200 "200 " http_200 "200 "
http_301 "301 " http_301 "301 "
http_302 "302 " http_302 "302 "
@ -10,3 +11,4 @@ http_location "location: "
http_host "Host: " http_host "Host: "
http_crnl "\r\n" http_crnl "\r\n"
http_html ".html" http_html ".html"
http_redirect "<body>Redirect to "

View file

@ -1,6 +1,9 @@
const char http_http[8] = const char http_http[8] =
/* "http://" */ /* "http://" */
{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, }; {0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, };
const char http_https[9] =
/* "https://" */
{0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, };
const char http_200[5] = const char http_200[5] =
/* "200 " */ /* "200 " */
{0x32, 0x30, 0x30, 0x20, }; {0x32, 0x30, 0x30, 0x20, };
@ -34,3 +37,6 @@ const char http_crnl[3] =
const char http_html[6] = const char http_html[6] =
/* ".html" */ /* ".html" */
{0x2e, 0x68, 0x74, 0x6d, 0x6c, }; {0x2e, 0x68, 0x74, 0x6d, 0x6c, };
const char http_redirect[19] =
/* "<body>Redirect to " */
{0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, };

View file

@ -1,4 +1,5 @@
extern const char http_http[8]; extern const char http_http[8];
extern const char http_https[9];
extern const char http_200[5]; extern const char http_200[5];
extern const char http_301[5]; extern const char http_301[5];
extern const char http_302[5]; extern const char http_302[5];
@ -10,3 +11,4 @@ extern const char http_location[11];
extern const char http_host[7]; extern const char http_host[7];
extern const char http_crnl[3]; extern const char http_crnl[3];
extern const char http_html[6]; extern const char http_html[6];
extern const char http_redirect[19];

View file

@ -49,7 +49,7 @@
#define HTTPFLAG_NONE 0 #define HTTPFLAG_NONE 0
#define HTTPFLAG_OK 1 #define HTTPFLAG_OK 1
#define HTTPFLAG_MOVED 2 #define HTTPFLAG_MOVED 2
#define HTTPFLAG_ERROR 3 #define HTTPFLAG_HTTPS 3
#define ISO_nl 0x0a #define ISO_nl 0x0a
@ -63,11 +63,11 @@ struct webclient_state {
uint16_t port; uint16_t port;
char host[40]; char host[40];
char file[WWW_CONF_MAX_URLLEN]; char file[WWW_CONF_MAX_URLLEN - 10]; // URL - "http://<host>/"
uint16_t getrequestptr; uint16_t getrequestptr;
uint16_t getrequestleft; uint16_t getrequestleft;
char httpheaderline[200]; char httpheaderline[WWW_CONF_MAX_URLLEN + 10]; // URL + "Location: "
uint16_t httpheaderlineptr; uint16_t httpheaderlineptr;
char mimetype[32]; char mimetype[32];
@ -327,13 +327,12 @@ parse_headers(uint16_t len)
char *cptr; char *cptr;
static unsigned char i; static unsigned char i;
while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) { while(len > 0) {
s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata; s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
uip_appdata = (char *)uip_appdata + 1; uip_appdata = (char *)uip_appdata + 1;
--len; --len;
if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) { if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
/* We have an entire HTTP header line in s.httpheaderline, so /* We reached the end of an HTTP header line. */
we parse it. */
if(s.httpheaderline[0] == ISO_cr) { if(s.httpheaderline[0] == ISO_cr) {
/* This was the last header line (i.e., and empty "\r\n"), so /* This was the last header line (i.e., and empty "\r\n"), so
we are done with the headers and proceed with the actual we are done with the headers and proceed with the actual
@ -342,46 +341,53 @@ parse_headers(uint16_t len)
return len; return len;
} }
s.httpheaderline[s.httpheaderlineptr - 1] = 0; if(s.httpheaderlineptr < sizeof(s.httpheaderline) - 1) {
/* Check for specific HTTP header fields. */ /* We have an entire HTTP header line in s.httpheaderline, so
if(casecmp(s.httpheaderline, http_content_type, we parse it. */
sizeof(http_content_type) - 1) == 0) { s.httpheaderline[s.httpheaderlineptr - 1] = 0;
/* Found Content-type field. */ /* Check for specific HTTP header fields. */
cptr = strchr(s.httpheaderline, ';'); if(casecmp(s.httpheaderline, http_content_type,
if(cptr != NULL) { sizeof(http_content_type) - 1) == 0) {
*cptr = 0; /* Found Content-type field. */
} cptr = strchr(s.httpheaderline, ';');
strncpy(s.mimetype, s.httpheaderline + if(cptr != NULL) {
sizeof(http_content_type) - 1, sizeof(s.mimetype)); *cptr = 0;
} else if(casecmp(s.httpheaderline, http_location,
sizeof(http_location) - 1) == 0) {
cptr = s.httpheaderline +
sizeof(http_location) - 1;
if(strncmp(cptr, http_http, 7) == 0) {
cptr += 7;
for(i = 0; i < s.httpheaderlineptr - 7; ++i) {
if(*cptr == 0 ||
*cptr == '/' ||
*cptr == ' ' ||
*cptr == ':') {
s.host[i] = 0;
break;
}
s.host[i] = *cptr;
++cptr;
} }
} strncpy(s.mimetype, s.httpheaderline +
strncpy(s.file, cptr, sizeof(s.file)); sizeof(http_content_type) - 1, sizeof(s.mimetype));
/* s.file[s.httpheaderlineptr - i] = 0;*/ } else if(casecmp(s.httpheaderline, http_location,
} sizeof(http_location) - 1) == 0) {
cptr = s.httpheaderline +
sizeof(http_location) - 1;
if(strncmp(cptr, http_https, sizeof(http_https) - 1) == 0) {
s.httpflag = HTTPFLAG_HTTPS;
} else if(strncmp(cptr, http_http, 7) == 0) {
cptr += 7;
for(i = 0; i < s.httpheaderlineptr - 7; ++i) {
if(*cptr == 0 ||
*cptr == '/' ||
*cptr == ' ' ||
*cptr == ':') {
s.host[i] = 0;
break;
}
s.host[i] = *cptr;
++cptr;
}
}
strncpy(s.file, cptr, sizeof(s.file));
/* s.file[s.httpheaderlineptr - i] = 0;*/
}
}
/* We're done parsing, so we reset the pointer and start the /* We're done parsing, so we reset the pointer and start the
next line. */ next line. */
s.httpheaderlineptr = 0; s.httpheaderlineptr = 0;
} else { } else {
++s.httpheaderlineptr; if(s.httpheaderlineptr < sizeof(s.httpheaderline) - 1) {
++s.httpheaderlineptr;
}
} }
} }
return len; return len;
@ -403,7 +409,7 @@ newdata(void)
} }
if(len > 0 && s.state == WEBCLIENT_STATE_DATA && if(len > 0 && s.state == WEBCLIENT_STATE_DATA &&
s.httpflag != HTTPFLAG_MOVED) { s.httpflag == HTTPFLAG_OK) {
webclient_datahandler((char *)uip_appdata, len); webclient_datahandler((char *)uip_appdata, len);
} }
} }
@ -441,7 +447,6 @@ webclient_appcall(void *state)
return; return;
} }
/* The acked() and newdata() functions may alter the uip_appdata /* The acked() and newdata() functions may alter the uip_appdata
ptr, so we need to store it in the "dataptr" variable so that we ptr, so we need to store it in the "dataptr" variable so that we
can restore it before the senddata() function is called. */ can restore it before the senddata() function is called. */
@ -474,10 +479,18 @@ webclient_appcall(void *state)
if(uip_closed()) { if(uip_closed()) {
tcp_markconn(uip_conn, NULL); tcp_markconn(uip_conn, NULL);
if(s.httpflag != HTTPFLAG_MOVED) { switch(s.httpflag) {
case HTTPFLAG_HTTPS:
/* Send some info to the user. */
webclient_datahandler((char *)http_redirect, sizeof(http_redirect) - 1);
webclient_datahandler(s.file, strlen(s.file));
webclient_datahandler((char *)http_crnl, sizeof(http_crnl) - 1);
/* FALLTHROUGH */
case HTTPFLAG_OK:
/* Send NULL data to signal EOF. */ /* Send NULL data to signal EOF. */
webclient_datahandler(NULL, 0); webclient_datahandler(NULL, 0);
} else { break;
case HTTPFLAG_MOVED:
/* conn = uip_connect(uip_conn->ripaddr, s.port); /* conn = uip_connect(uip_conn->ripaddr, s.port);
if(conn != NULL) { if(conn != NULL) {
dispatcher_markconn(conn, NULL); dispatcher_markconn(conn, NULL);
@ -489,6 +502,7 @@ webclient_appcall(void *state)
} }
#endif /* UIP_UDP */ #endif /* UIP_UDP */
webclient_get(s.host, s.port, s.file); webclient_get(s.host, s.port, s.file);
break;
} }
} }
} }

View file

@ -125,7 +125,7 @@ static struct ctk_button wgetyesbutton =
#if WWW_CONF_HISTORY_SIZE > 0 #if WWW_CONF_HISTORY_SIZE > 0
/* The char arrays that hold the history of visited URLs. */ /* The char arrays that hold the history of visited URLs. */
static char history[WWW_CONF_HISTORY_SIZE][WWW_CONF_MAX_URLLEN]; static char history[WWW_CONF_HISTORY_SIZE][WWW_CONF_MAX_URLLEN];
static char history_last; static unsigned char history_last;
#endif /* WWW_CONF_HISTORY_SIZE > 0 */ #endif /* WWW_CONF_HISTORY_SIZE > 0 */
struct linkattrib { struct linkattrib {
@ -170,17 +170,19 @@ static struct inputattrib *currptr;
#define ISO_nl 0x0a #define ISO_nl 0x0a
#define ISO_space 0x20 #define ISO_space 0x20
#define ISO_hash 0x23
#define ISO_ampersand 0x26 #define ISO_ampersand 0x26
#define ISO_plus 0x2b #define ISO_plus 0x2b
#define ISO_slash 0x2f #define ISO_slash 0x2f
#define ISO_eq 0x3d #define ISO_eq 0x3d
#define ISO_questionmark 0x3f #define ISO_questionmark 0x3f
/* The state of the rendering code. */ /* The state of the rendering code. */
static char *webpageptr; static char *webpageptr;
static unsigned char x, y; static unsigned char x, y;
static unsigned char loading; static unsigned char loading;
static unsigned short firsty, pagey; static unsigned short firsty, pagey;
static unsigned char newlines;
static unsigned char count; static unsigned char count;
static char receivingmsgs[4][23] = { static char receivingmsgs[4][23] = {
@ -194,7 +196,7 @@ PROCESS(www_process, "Web browser");
AUTOSTART_PROCESSES(&www_process); AUTOSTART_PROCESSES(&www_process);
static void CC_FASTCALL formsubmit(struct formattrib *form); static void CC_FASTCALL formsubmit(struct inputattrib *trigger);
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* make_window() /* make_window()
@ -277,6 +279,7 @@ start_loading(void)
loading = 1; loading = 1;
x = y = 0; x = y = 0;
pagey = 0; pagey = 0;
newlines = 0;
webpageptr = webpage; webpageptr = webpage;
clear_page(); clear_page();
@ -305,10 +308,13 @@ open_url(void)
static uip_ipaddr_t addr; static uip_ipaddr_t addr;
/* Trim off any spaces in the end of the url. */ /* Trim off any spaces in the end of the url. */
urlptr = url + strlen(url) - 1; urlptr = url + strlen(url);
while(*urlptr == ' ' && urlptr > url) { while(urlptr > url) {
*urlptr = 0; if(*(urlptr - 1) == ' ') {
--urlptr; *--urlptr = 0;
} else {
break;
}
} }
/* Don't even try to go further if the URL is empty. */ /* Don't even try to go further if the URL is empty. */
@ -376,7 +382,6 @@ open_url(void)
} else { } else {
show_statustext("Connecting..."); show_statustext("Connecting...");
} }
redraw_window();
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* set_link(link): /* set_link(link):
@ -510,15 +515,17 @@ PROCESS_THREAD(www_process, ev, data)
firsty = 0; firsty = 0;
start_loading(); start_loading();
--history_last; --history_last;
/* Note: history_last is unsigned ! */
if(history_last > WWW_CONF_HISTORY_SIZE) { if(history_last > WWW_CONF_HISTORY_SIZE) {
history_last = WWW_CONF_HISTORY_SIZE - 1; history_last = WWW_CONF_HISTORY_SIZE - 1;
} }
memcpy(url, history[(int)history_last], WWW_CONF_MAX_URLLEN); memcpy(url, history[(int)history_last], WWW_CONF_MAX_URLLEN);
*history[(int)history_last] = 0;
open_url(); open_url();
CTK_WIDGET_FOCUS(&mainwindow, &backbutton); CTK_WIDGET_FOCUS(&mainwindow, &backbutton);
#endif /* WWW_CONF_HISTORY_SIZE > 0 */ #endif /* WWW_CONF_HISTORY_SIZE > 0 */
} else if(w == (struct ctk_widget *)&downbutton) { } else if(w == (struct ctk_widget *)&downbutton) {
firsty = pagey + WWW_CONF_WEBPAGE_HEIGHT - 4; firsty = pagey + WWW_CONF_WEBPAGE_HEIGHT - 2;
start_loading(); start_loading();
open_url(); open_url();
CTK_WIDGET_FOCUS(&mainwindow, &downbutton); CTK_WIDGET_FOCUS(&mainwindow, &downbutton);
@ -557,9 +564,8 @@ PROCESS_THREAD(www_process, ev, data)
#if WWW_CONF_FORMS #if WWW_CONF_FORMS
} else { } else {
/* Assume form widget. */ /* Assume form widget. */
struct inputattrib *input = (struct inputattrib *) formsubmit((struct inputattrib *)
(((char *)w) - offsetof(struct inputattrib, widget)); (((char *)w) - offsetof(struct inputattrib, widget)));
formsubmit(input->formptr);
#endif /* WWW_CONF_FORMS */ #endif /* WWW_CONF_FORMS */
} }
} else if(ev == ctk_signal_hyperlink_activate) { } else if(ev == ctk_signal_hyperlink_activate) {
@ -670,8 +676,6 @@ webclient_connected(void)
{ {
start_loading(); start_loading();
clear_page();
show_statustext("Request sent..."); show_statustext("Request sent...");
set_url(webclient_hostname(), webclient_port(), webclient_filename()); set_url(webclient_hostname(), webclient_port(), webclient_filename());
@ -731,6 +735,8 @@ add_pagewidget(char *text, unsigned char size, char *attrib, unsigned char type,
char *wptr; char *wptr;
static unsigned char maxwidth; static unsigned char maxwidth;
newlines = 0;
if(!loading) { if(!loading) {
return; return;
} }
@ -770,49 +776,49 @@ add_pagewidget(char *text, unsigned char size, char *attrib, unsigned char type,
wptr[size + border] = ' '; wptr[size + border] = ' ';
switch(type) { switch(type) {
case CTK_WIDGET_HYPERLINK: { case CTK_WIDGET_HYPERLINK: {
struct linkattrib *linkptr = struct linkattrib *linkptr =
(struct linkattrib *)add_pageattrib(sizeof(struct linkattrib) /* incl 1 attrib char */ + attriblen); (struct linkattrib *)add_pageattrib(sizeof(struct linkattrib) /* incl 1 attrib char */ + attriblen);
if(linkptr != NULL) { if(linkptr != NULL) {
CTK_HYPERLINK_NEW(&linkptr->hyperlink, x, y + 3, size, wptr, linkptr->url); CTK_HYPERLINK_NEW(&linkptr->hyperlink, x, y + 3, size, wptr, linkptr->url);
strcpy(linkptr->url, attrib); strcpy(linkptr->url, attrib);
CTK_WIDGET_SET_FLAG(&linkptr->hyperlink, CTK_WIDGET_FLAG_MONOSPACE); CTK_WIDGET_SET_FLAG(&linkptr->hyperlink, CTK_WIDGET_FLAG_MONOSPACE);
CTK_WIDGET_ADD(&mainwindow, &linkptr->hyperlink); CTK_WIDGET_ADD(&mainwindow, &linkptr->hyperlink);
}
break;
} }
break;
}
#if WWW_CONF_FORMS #if WWW_CONF_FORMS
case CTK_WIDGET_BUTTON: { case CTK_WIDGET_BUTTON: {
struct submitattrib *submitptr = struct submitattrib *submitptr =
(struct submitattrib *)add_pageattrib(sizeof(struct submitattrib) /* incl 1 attrib char */ + attriblen); (struct submitattrib *)add_pageattrib(sizeof(struct submitattrib) /* incl 1 attrib char */ + attriblen);
if(submitptr != NULL) { if(submitptr != NULL) {
CTK_BUTTON_NEW((struct ctk_button *)&submitptr->button, x, y + 3, size, wptr); CTK_BUTTON_NEW((struct ctk_button *)&submitptr->button, x, y + 3, size, wptr);
add_forminput((struct inputattrib *)submitptr); add_forminput((struct inputattrib *)submitptr);
submitptr->formptr = formptr; submitptr->formptr = formptr;
strcpy(submitptr->name, attrib); strcpy(submitptr->name, attrib);
CTK_WIDGET_SET_FLAG(&submitptr->button, CTK_WIDGET_FLAG_MONOSPACE); CTK_WIDGET_SET_FLAG(&submitptr->button, CTK_WIDGET_FLAG_MONOSPACE);
CTK_WIDGET_ADD(&mainwindow, &submitptr->button); CTK_WIDGET_ADD(&mainwindow, &submitptr->button);
}
break;
} }
case CTK_WIDGET_TEXTENTRY: { break;
struct textattrib *textptr = }
(struct textattrib *)add_pageattrib(sizeof(struct textattrib) /* incl 1 attrib char */ + attriblen case CTK_WIDGET_TEXTENTRY: {
+ (size ? WWW_CONF_MAX_INPUTVALUELEN : strlen(text)) + 1); struct textattrib *textptr =
if(textptr != NULL) { (struct textattrib *)add_pageattrib(sizeof(struct textattrib) /* incl 1 attrib char */ + attriblen
CTK_TEXTENTRY_NEW((struct ctk_textentry *)&textptr->textentry, x, y + 3, size, 1, + (size ? WWW_CONF_MAX_INPUTVALUELEN : strlen(text)) + 1);
textptr->name + attriblen + 1, WWW_CONF_MAX_INPUTVALUELEN); if(textptr != NULL) {
add_forminput((struct inputattrib *)textptr); CTK_TEXTENTRY_NEW((struct ctk_textentry *)&textptr->textentry, x, y + 3, size, 1,
textptr->formptr = formptr; textptr->name + attriblen + 1, WWW_CONF_MAX_INPUTVALUELEN);
strcpy(textptr->textentry.text, text); add_forminput((struct inputattrib *)textptr);
strcpy(textptr->name, attrib); textptr->formptr = formptr;
if(size) { strcpy(textptr->textentry.text, text);
CTK_WIDGET_SET_FLAG(&textptr->textentry, CTK_WIDGET_FLAG_MONOSPACE); strcpy(textptr->name, attrib);
CTK_WIDGET_ADD(&mainwindow, &textptr->textentry); if(size) {
} CTK_WIDGET_SET_FLAG(&textptr->textentry, CTK_WIDGET_FLAG_MONOSPACE);
CTK_WIDGET_ADD(&mainwindow, &textptr->textentry);
} }
break;
} }
break;
}
#endif /* WWW_CONF_FORMS */ #endif /* WWW_CONF_FORMS */
} }
} }
@ -837,6 +843,10 @@ htmlparser_newline(void)
{ {
char *wptr; char *wptr;
if(++newlines > 2) {
return;
}
if(pagey < firsty) { if(pagey < firsty) {
++pagey; ++pagey;
x = 0; x = 0;
@ -863,6 +873,8 @@ htmlparser_newline(void)
void void
htmlparser_word(char *word, unsigned char wordlen) htmlparser_word(char *word, unsigned char wordlen)
{ {
newlines = 0;
if(loading) { if(loading) {
if(wordlen + 1 > WWW_CONF_WEBPAGE_WIDTH - x) { if(wordlen + 1 > WWW_CONF_WEBPAGE_WIDTH - x) {
htmlparser_newline(); htmlparser_newline();
@ -886,7 +898,12 @@ htmlparser_word(char *word, unsigned char wordlen)
void void
htmlparser_link(char *text, unsigned char textlen, char *url) htmlparser_link(char *text, unsigned char textlen, char *url)
{ {
add_pagewidget(text, textlen, url, CTK_WIDGET_HYPERLINK, 0); /* No link for https or fragment-only as we would't be able to handle it anyway. */
if(url[0] == ISO_hash || strncmp(url, http_https, sizeof(http_https) - 1) == 0) {
htmlparser_word(text, textlen);
} else {
add_pagewidget(text, textlen, url, CTK_WIDGET_HYPERLINK, 0);
}
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
#if WWW_CONF_FORMS #if WWW_CONF_FORMS
@ -946,23 +963,36 @@ add_query(char delimiter, char *string)
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
static void CC_FASTCALL static void CC_FASTCALL
formsubmit(struct formattrib *form) formsubmit(struct inputattrib *trigger)
{ {
struct inputattrib *inputptr; struct inputattrib *input;
struct formattrib *form = trigger->formptr;
char delimiter = ISO_questionmark; char delimiter = ISO_questionmark;
set_link(form->action); set_link(form->action);
for(inputptr = form->nextptr; inputptr != NULL; inputptr = inputptr->nextptr) { /* No button pressed so prepare to look for default button. */
if(trigger->widget.type == CTK_WIDGET_TEXTENTRY) {
trigger = NULL;
}
for(input = form->nextptr; input != NULL; input = input->nextptr) {
char *name; char *name;
char *value; char *value;
if(inputptr->widget.type == CTK_WIDGET_BUTTON) { if(input->widget.type == CTK_WIDGET_TEXTENTRY) {
name = ((struct submitattrib *)inputptr)->name; name = ((struct textattrib *)input)->name;
value = ((struct submitattrib *)inputptr)->button.text; value = ((struct textattrib *)input)->textentry.text;
} else { } else {
name = ((struct textattrib *)inputptr)->name; /* Consider first button as default button. */
value = ((struct textattrib *)inputptr)->textentry.text; if(trigger == NULL) {
trigger = input;
}
if(input != trigger) {
continue;
}
name = ((struct submitattrib *)input)->name;
value = ((struct submitattrib *)input)->button.text;
} }
add_query(delimiter, name); add_query(delimiter, name);

View file

@ -44,7 +44,7 @@
#define WWW_CONF_HISTORY_SIZE 10 #define WWW_CONF_HISTORY_SIZE 10
#endif #endif
#ifndef WWW_CONF_MAX_URLLEN #ifndef WWW_CONF_MAX_URLLEN
#define WWW_CONF_MAX_URLLEN 300 #define WWW_CONF_MAX_URLLEN 255
#endif #endif
#ifndef WWW_CONF_PAGEATTRIB_SIZE #ifndef WWW_CONF_PAGEATTRIB_SIZE
#define WWW_CONF_PAGEATTRIB_SIZE 2000 #define WWW_CONF_PAGEATTRIB_SIZE 2000

View file

@ -1,4 +1,5 @@
http_http "http://" http_http "http://"
http_https "https://"
http_200 "200 " http_200 "200 "
http_301 "301 " http_301 "301 "
http_302 "302 " http_302 "302 "
@ -32,4 +33,4 @@ http_gif ".gif"
http_jpg ".jpg" http_jpg ".jpg"
http_text ".text" http_text ".text"
http_txt ".txt" http_txt ".txt"
http_redirect "<body>Redirect to "

View file

@ -1,6 +1,9 @@
const char http_http[8] = const char http_http[8] =
/* "http://" */ /* "http://" */
{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, }; {0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, };
const char http_https[9] =
/* "https://" */
{0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, };
const char http_200[5] = const char http_200[5] =
/* "200 " */ /* "200 " */
{0x32, 0x30, 0x30, 0x20, }; {0x32, 0x30, 0x30, 0x20, };
@ -100,3 +103,6 @@ const char http_text[6] =
const char http_txt[5] = const char http_txt[5] =
/* ".txt" */ /* ".txt" */
{0x2e, 0x74, 0x78, 0x74, }; {0x2e, 0x74, 0x78, 0x74, };
const char http_redirect[19] =
/* "<body>Redirect to " */
{0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, };

View file

@ -1,4 +1,5 @@
extern const char http_http[8]; extern const char http_http[8];
extern const char http_https[9];
extern const char http_200[5]; extern const char http_200[5];
extern const char http_301[5]; extern const char http_301[5];
extern const char http_302[5]; extern const char http_302[5];
@ -32,3 +33,4 @@ extern const char http_gif[5];
extern const char http_jpg[5]; extern const char http_jpg[5];
extern const char http_text[6]; extern const char http_text[6];
extern const char http_txt[5]; extern const char http_txt[5];
extern const char http_redirect[19];

View file

@ -72,7 +72,6 @@ typedef unsigned short uip_stats_t;
#define UIP_CONF_LLH_LEN 14 #define UIP_CONF_LLH_LEN 14
#define RESOLV_CONF_SUPPORTS_MDNS 0 #define RESOLV_CONF_SUPPORTS_MDNS 0
#define RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION 0 #define RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION 0
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 1
#define LOADER_CONF_ARCH "lib/unload.h" #define LOADER_CONF_ARCH "lib/unload.h"

View file

@ -56,11 +56,8 @@ typedef long s32_t;
typedef unsigned short uip_stats_t; typedef unsigned short uip_stats_t;
#define UIP_CONF_MAX_CONNECTIONS 40
#define UIP_CONF_MAX_LISTENPORTS 40
#define UIP_CONF_LLH_LEN 14 #define UIP_CONF_LLH_LEN 14
#define UIP_CONF_BUFFER_SIZE 1514 #define UIP_CONF_BUFFER_SIZE 1514
#define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN
#define UIP_CONF_TCP_SPLIT 1 #define UIP_CONF_TCP_SPLIT 1
#define UIP_CONF_LOGGING 1 #define UIP_CONF_LOGGING 1
#define UIP_CONF_UDP_CHECKSUMS 1 #define UIP_CONF_UDP_CHECKSUMS 1
@ -77,6 +74,8 @@ typedef unsigned short uip_stats_t;
#define UIP_CONF_IP_FORWARD 1 #define UIP_CONF_IP_FORWARD 1
#endif #endif
#define RESOLV_CONF_SUPPORTS_MDNS 0
#define RESOLV_CONF_SUPPORTS_RECORD_EXPIRATION 0
#include <ctype.h> #include <ctype.h>
#define ctk_arch_isprint isprint #define ctk_arch_isprint isprint